[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