[LV] TURBOchannel support -- success!

Maciej W. Rozycki macro at linux-mips.org
Mon Feb 26 15:58:30 CET 2007


Hi Kenn,

> Yes.  A lot of that was just doing the minimum required to get things to
> boot.  Not having a sparse system address space is a bit of a pain.

 Quite a reasonable approach actually and with a project like this it is 
important to get past the point usefulness exceeds the amount of pain, so 
that actual users may be attracted.  Unfortunately I fear we haven't got 
there yet.

 I guess for useful work I will not get away without userland for long, so 
I'll have a look into what is missing to get glibc ~2.5 going first...  I 
think using the standard Linux libc is essential.

> The problem is the number of "struct page"s we need.  Last time I looked,
> struct page was about 44 bytes.  If we had one struct page for each
> 512-byte hardware page, we'd be losing 8% of our RAM to the mem_map
> array.

 Good point and something to investigate at one stage...

> I saw two possible approaches to interrupt priority handling:
> 
> 1. The easy way - we run at either IPL 0 or IPL 31 (interrupts enabled
>    or disabled).  This fits well with the local_irq_enable/disable API.
>    When I started looking at the VAX port, we were back at kernel 2.0,
>    where the linux interrupt model seemed to be like this anyway.

 It is not going to work unless you are able to mask the coming interrupt 
at the issuing interrupt controller.  Which is possible for the VAXstation 
4000/90 and other systems using the CEAC chip, but may not necessarily be 
available elsewhere (this is at least what I gather -- I do not claim I 
know anything about any VAX computers beside the 4000/90 ;-) ).  This fits 
the Linux model.  Low latency handlers (with the IRQF_DISABLED flag) run 
with interrupts disabled (IPL 31) and the others run with interrupts 
enabled (IPL 0).

> 2. The harder way - each device driver knows the IPL that its device
>    uses and raises IPL to that level (or leaves IPL as-is if already
>    greater).  This allows higher priority devices to interrupt the
>    drivers for lower-priority devices.  However, could this lead to
>    re-entrancy issues within core code?  Driver A raises IPL to 16,
>    calls into some core subsystem, gets interrupted by device B at
>    IPL 17 which calls into the same subsystem.  Perhaps these days
>    all the core code is re-entrant enough for this?

 The core is certainly reentrant and actually the whole Linux interrupt 
model expects most handlers will actually run with interrupts enabled 
(i.e. the majority of handlers do not set the IRQF_DISABLED flag).  I 
think for systems that do not have an external interrupt mask register we 
should use the model used as a workaround for a bug ;-) in one of the 
Alpha systems -- handlers with IRQF_DISABLED run at IPL 31 and others run 
at the original priority which is stored upon entry in a variable to be 
used by local_irq_enable() and irqs_disabled() as required.  I do not 
expect device drivers generally "know" what IPL they should be running at 
beside the IRQF_DISABLED flag.  Complex processing should not be done in 
the interrupt context anyway.

 I suppose this model should be the default unless a system has an 
interrupt mask register and can support the other one.

> I would be interested to see the diffs to support TURBOchannel.

 OK, I am a bit busy these days, and I am going for a short holiday by the 
end of the next week.  I'll try to get these bits in order before I am 
off, but otherwise please ping me if I don't get back within a month.  I 
am sending the raw version I have now just in case so it does not get 
lost.  You can call it version 0.epsilon if you like.  The change to the 
SPT_MAX_IOMAP definition is needed because the generic TC layer ioremap()s 
the whole slot space for each.  Eventually there should be no hardcoded 
size limit for ioremap() anyway.

 BTW, I tried a PMAGD-C framebuffer board and it works for the console 
without any additional changes -- the penguin is there!  Of course for 
that you require the TURBOchannel update for the tgafb driver that got 
dropped by Andrew Morton a while ago because of the patch stack overflow. 
;-)  Framebuffers using other drivers may be problematic as they assume 
the board to be used has been initialized by the firmware, which with the 
VAXstation is most likely not the case (though running "t tc0 init" under 
the REX emulator may be a workaround).

 Here are some relevant bits (with some rubbish filtered out).  A patch 
follows.

  Maciej

SCSI subsystem initialized
tc: TURBOchannel rev. 1 at 12.5 MHz (without parity)
tc0: DEC      PMAGD    BL2.1
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 4096 bind 2048)
TCP reno registered
Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Console: switching to colour frame buffer device 160x64
tgafb: SFB+ detected, rev=0x03
fb0: Digital ZLX-E3 frame buffer device at 0x30000000
Real Time Clock Driver v1.12ac

patch-mips-2.6.18-20060920-vax-tc-0
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/arch/vax/Kconfig linux-mips-2.6.18-20060920-vax-all/arch/vax/Kconfig
--- linux-mips-2.6.18-20060920-vax-base/arch/vax/Kconfig	2007-01-11 00:00:00.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/arch/vax/Kconfig	2007-01-28 04:51:22.000000000 +0000
@@ -143,6 +143,25 @@ config CONS_PREVM_KA52
 	default n
 endmenu
 
+menu "VAX Bus support"
+config QBUS
+	bool "Support for Q-bus"
+	default n
+
+config VSBUS
+	bool "Support for VAXstation bus"
+	default n
+
+config TC
+	bool "TURBOchannel support"
+	depends on CPU_KA46 || CPU_KA49
+	help
+	  TurboChannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS
+	  processors.  Documentation on writing device drivers for TurboChannel
+	  is available at:
+	  <http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PS3HD-TET1_html/TITLE.html>.
+endmenu
+
 source "init/Kconfig"
 
 # It's needed for FB console, but if we compile in VT support,
@@ -157,16 +176,6 @@ source "drivers/video/Kconfig"
 source "fs/Kconfig.binfmt"
 source "mm/Kconfig"
 
-menu "VAX Bus support"
-config QBUS
-	bool "Support for Q-bus"
-	default n
-
-config VSBUS
-	bool "Support for VAXstation bus"
-	default n
-endmenu
-
 source "kernel/Kconfig.hz"
 source "drivers/block/Kconfig"
 source "net/Kconfig"
@@ -192,6 +201,8 @@ endmenu
 endif
 
 
+source "drivers/net/Kconfig"
+
 source "drivers/scsi/Kconfig"
 
 if SCSI
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/arch/vax/kernel/cpu_ka49.c linux-mips-2.6.18-20060920-vax-all/arch/vax/kernel/cpu_ka49.c
--- linux-mips-2.6.18-20060920-vax-base/arch/vax/kernel/cpu_ka49.c	2007-01-11 00:00:00.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/arch/vax/kernel/cpu_ka49.c	2007-02-19 02:05:09.000000000 +0000
@@ -11,10 +11,13 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
+#include <asm/clock.h>   /* for clock_init routines */
+#include <asm/io.h>
 #include <asm/mtpr.h>
 #include <asm/mv.h>
+#include <asm/system.h>
 #include <asm/vaxcpu.h>
-#include <asm/clock.h>   /* for clock_init routines */
+
 #include <asm/bus/vsbus.h>
 
 static void ka49_post_vm_init(void)
@@ -123,7 +126,38 @@ static const char *ka49_cpu_type_str(voi
 
 static void ka49_init_devices(void)
 {
+unsigned long flags;
 	printk ("ka49: init_devices\n");
+local_irq_save(flags);
+{
+int i = 256;
+	volatile u16 *ceac = ioremap(0x25c00000, 0x10);
+#if 0
+printk("CEAC: IMR: %04x, IPR: %04x\n", ceac[4], ceac[6]);
+#endif
+	ceac[4] |= 0x01;
+#if 0
+while(i--)
+printk("CEAC: IMR: %04x, IPR: %04x\n", ceac[4], ceac[6]);
+#endif
+i = 256;
+#if 0
+while(i--)
+printk("CEAC: IMR: %04x, IPR: %04x\n", ceac[4], ceac[6]);
+#endif
+	iounmap(ceac);
+}
+
+{
+	volatile u32 *pta_csr = ioremap(0x36800000, 0x4);
+#if 0
+printk("PTA: CSR: %08x\n", pta_csr[4]);
+#endif
+	pta_csr[0] &= 0x0900f;
+	pta_csr[0] |= 0x09000;
+	iounmap(pta_csr);
+}
+local_irq_restore(flags);
 }
 
 struct vax_mv mv_ka49 = {
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/drivers/net/Kconfig linux-mips-2.6.18-20060920-vax-all/drivers/net/Kconfig
--- linux-mips-2.6.18-20060920-vax-base/drivers/net/Kconfig	2007-02-26 14:12:34.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/drivers/net/Kconfig	2007-02-26 14:13:03.000000000 +0000
@@ -1817,7 +1817,7 @@ config SGISEEQ
 
 config DECLANCE
 	tristate "DEC LANCE ethernet controller support"
-	depends on NET_ETHERNET && MACH_DECSTATION
+	depends on NET_ETHERNET && (TC || MACH_DECSTATION)
 	select CRC32
 	help
 	  This driver is for the series of Ethernet controllers produced by
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/drivers/net/declance.c linux-mips-2.6.18-20060920-vax-all/drivers/net/declance.c
--- linux-mips-2.6.18-20060920-vax-base/drivers/net/declance.c	2006-12-17 02:28:50.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/drivers/net/declance.c	2007-01-28 04:51:22.000000000 +0000
@@ -63,6 +63,7 @@
 #include <linux/tc.h>
 #include <linux/types.h>
 
+#ifdef CONFIG_MACH_DECSTATION
 #include <asm/addrspace.h>
 #include <asm/system.h>
 
@@ -72,6 +73,9 @@
 #include <asm/dec/kn01.h>
 #include <asm/dec/machtype.h>
 #include <asm/dec/system.h>
+#else
+#define iob() do {} while (0)
+#endif
 
 static char version[] __devinitdata =
 "declance.c: v0.011 by Linux MIPS DECstation task force\n";
@@ -722,6 +726,7 @@ out:
 	spin_unlock(&lp->lock);
 }
 
+#ifdef CONFIG_MACH_DECSTATION
 static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
 				      struct pt_regs *regs)
 {
@@ -730,6 +735,7 @@ static irqreturn_t lance_dma_merr_int(co
 	printk("%s: DMA error\n", dev->name);
 	return IRQ_HANDLED;
 }
+#endif
 
 static irqreturn_t lance_interrupt(const int irq, void *dev_id,
 				   struct pt_regs *regs)
@@ -815,6 +821,7 @@ static int lance_open(struct net_device 
 		printk("%s: Can't get IRQ %d\n", dev->name, dev->irq);
 		return -EAGAIN;
 	}
+#ifdef CONFIG_MACH_DECSTATION
 	if (lp->dma_irq >= 0) {
 		unsigned long flags;
 
@@ -836,6 +843,7 @@ static int lance_open(struct net_device 
 		fast_mb();
 		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
 	}
+#endif
 
 	status = init_restart_lance(lp);
 	return status;
@@ -853,6 +861,7 @@ static int lance_close(struct net_device
 	writereg(&ll->rap, LE_CSR0);
 	writereg(&ll->rdp, LE_C0_STOP);
 
+#ifdef CONFIG_MACH_DECSTATION
 	if (lp->dma_irq >= 0) {
 		unsigned long flags;
 
@@ -868,6 +877,7 @@ static int lance_close(struct net_device
 
 		free_irq(lp->dma_irq, dev);
 	}
+#endif
 	free_irq(dev->irq, dev);
 	return 0;
 }
@@ -1075,6 +1085,7 @@ static int __init dec_lance_probe(struct
 
 	lp->type = type;
 	switch (type) {
+#ifdef CONFIG_MACH_DECSTATION
 	case ASIC_LANCE:
 		dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
 
@@ -1118,6 +1129,7 @@ static int __init dec_lance_probe(struct
 			     CPHYSADDR(dev->mem_start) << 3);
 
 		break;
+#endif
 #ifdef CONFIG_TC
 	case PMAD_LANCE:
 		dev_set_drvdata(bdev, dev);
@@ -1132,7 +1144,11 @@ static int __init dec_lance_probe(struct
 			goto err_out_dev;
 		}
 
+#if 0
 		dev->mem_start = CKSEG1ADDR(start);
+#else
+		dev->mem_start = (ulong)ioremap(start, len);
+#endif
 		dev->mem_end = dev->mem_start + 0x100000;
 		dev->base_addr = dev->mem_start + 0x100000;
 		dev->irq = to_tc_dev(bdev)->interrupt;
@@ -1159,6 +1175,7 @@ static int __init dec_lance_probe(struct
 
 		break;
 #endif
+#ifdef CONFIG_MACH_DECSTATION
 	case PMAX_LANCE:
 		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
 		dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
@@ -1189,6 +1206,7 @@ static int __init dec_lance_probe(struct
 		}
 
 		break;
+#endif
 
 	default:
 		printk(KERN_ERR "%s: declance_init called with unknown type\n",
@@ -1303,12 +1321,16 @@ static void __exit dec_lance_remove(stru
 	resource_size_t start, len;
 
 	unregister_netdev(dev);
+#if 1
+	iounmap((void *)dev->mem_start);
+#endif
 	start = to_tc_dev(bdev)->resource.start;
 	len = to_tc_dev(bdev)->resource.end - start + 1;
 	release_mem_region(start, len);
 	free_netdev(dev);
 }
 
+#ifdef CONFIG_MACH_DECSTATION
 /* Find all the lance cards on the system and initialize them */
 static int __init dec_lance_platform_probe(void)
 {
@@ -1338,6 +1360,7 @@ static void __exit dec_lance_platform_re
 		free_netdev(dev);
 	}
 }
+#endif
 
 #ifdef CONFIG_TC
 static int __init dec_lance_tc_probe(struct device *dev);
@@ -1380,14 +1403,18 @@ static int __init dec_lance_init(void)
 	int status;
 
 	status = tc_register_driver(&dec_lance_tc_driver);
+#ifdef CONFIG_MACH_DECSTATION
 	if (!status)
 		dec_lance_platform_probe();
+#endif
 	return status;
 }
 
 static void __exit dec_lance_exit(void)
 {
+#ifdef CONFIG_MACH_DECSTATION
 	dec_lance_platform_remove();
+#endif
 	tc_unregister_driver(&dec_lance_tc_driver);
 }
 
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/drivers/vax/bus/Makefile linux-mips-2.6.18-20060920-vax-all/drivers/vax/bus/Makefile
--- linux-mips-2.6.18-20060920-vax-base/drivers/vax/bus/Makefile	2007-01-11 00:00:00.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/drivers/vax/bus/Makefile	2007-01-28 04:51:22.000000000 +0000
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_QBUS) += qbus.o cqbic.o
 obj-$(CONFIG_VSBUS) += vsbus.o vsbus-ka4x.o
-
+obj-$(CONFIG_TC) += tc.o
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/drivers/vax/bus/tc.c linux-mips-2.6.18-20060920-vax-all/drivers/vax/bus/tc.c
--- linux-mips-2.6.18-20060920-vax-base/drivers/vax/bus/tc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/drivers/vax/bus/tc.c	2007-02-26 14:15:22.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ *	TURBOchannel architecture calls.
+ *
+ *	Copyright (c) 2007  Maciej W. Rozycki
+ *
+ *	This file is subject to the terms and conditions of the GNU
+ *	General Public License.  See the file "COPYING" in the main
+ *	directory of this archive for more details.
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/mv.h>
+
+/*
+ * Protected read byte from TURBOchannel slot space.
+ */
+int tc_preadb(u8 *valp, void __iomem *addr)
+{
+	*valp = readb(addr);
+	return 0;
+}
+
+/*
+ * Get TURBOchannel bus information as specified by the spec, plus
+ * the slot space base address and the number of slots.
+ */
+int __init tc_bus_get_info(struct tc_bus *tbus)
+{
+	if (!is_ka46() && !is_ka49())
+		return -ENXIO;
+
+	tbus->info.revision = 1;			/* whatever */
+	tbus->info.clk_period = 80;			/* 12.5 MHz */
+	tbus->info.slot_size = 128;			/* 128 MB */
+	tbus->info.io_timeout = 128;			/* 128 ~sel cycles */
+	tbus->info.dma_range = 128;			/* 0 - 128 MB */
+	tbus->info.max_dma_burst = 128;			/* 128/rd, 512/wr */
+	tbus->info.parity = 0;				/* unsupported */
+
+	tbus->slot_base = 0x30000000;
+	tbus->num_tcslots = 1;
+
+	return 0;
+}
+
+/*
+ * Get the IRQ for the specified slot.
+ */
+void __init tc_device_get_irq(struct tc_dev *tdev)
+{
+	tdev->interrupt = 0x51;
+}
diff -up --recursive --new-file linux-mips-2.6.18-20060920-vax-base/include/asm-vax/mm/pgtable.h linux-mips-2.6.18-20060920-vax-all/include/asm-vax/mm/pgtable.h
--- linux-mips-2.6.18-20060920-vax-base/include/asm-vax/mm/pgtable.h	2007-01-11 00:00:00.000000000 +0000
+++ linux-mips-2.6.18-20060920-vax-all/include/asm-vax/mm/pgtable.h	2007-01-28 04:51:22.000000000 +0000
@@ -42,7 +42,7 @@
  * alloc a real page of RAM and hijack its SPTE.
  */
 
-#define SPT_MAX_IOMAP	(16 * 1024)
+#define SPT_MAX_IOMAP	(128 * 1024)
 #define SPT_MAX_VMALLOC	4096
 /* entries is (1024 * 1024) >> PAGELET_SIZE */
 #define SPT_HWPTES_IOMAP (SPT_MAX_IOMAP<<1)
_______________________________________________
Linux-Vax mailing list
Linux-Vax at pergamentum.com
http://www.pergamentum.com/mailman/listinfo/linux-vax




More information about the Vax-linux mailing list