* -pa48 * Stop reserving bus 0 for EISA in order to solve SuckyIO problems * Register drivers in the right order to make the Asp/Wax IRQ region available to the EISA driver; and make sure EISA claims its PCI bus before Dino does. * Fill in ->sibling links for Snake firmware machines. * Choose Asp subdevice IRQs by sversion rather than address (except for the serial ports... oh well :-) * Add an `irq' field to the parisc_device, and fill it in for Asp's children _and siblings_ because Mongoose is a sibling of Asp. * Short-circuit busdevice_alloc_irq if the irq field has been filled in. * The beginnings of irq support in eisa.c itself. Note that this is far from complete and doesn't incorporate all the suggestions from Richard yet. Index: arch/parisc/kernel/inventory.c =================================================================== RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/inventory.c,v retrieving revision 1.40 diff -u -p -r1.40 inventory.c --- arch/parisc/kernel/inventory.c 2001/10/06 19:17:02 1.40 +++ arch/parisc/kernel/inventory.c 2001/10/11 23:18:42 @@ -446,6 +446,7 @@ legacy_create_device(struct pdc_memory_m static int __init snake_inventory(void) { int mod, num = 0; + struct parisc_device *prev = NULL; for (mod = 0; mod < 16; mod++) { struct parisc_device *dev; struct pdc_module_path module_path; @@ -457,10 +458,16 @@ static int __init snake_inventory(void) dev = legacy_create_device(&r_addr, &module_path); if (!dev) continue; + num++; + if (prev) { + prev->sibling = dev; + } - if (dev->id.hw_type != HPHW_BA) + if (dev->id.hw_type != HPHW_BA) { + prev = dev; continue; + } memset(module_path.bc, 0xff, 4); module_path.bc[4] = mod; @@ -474,7 +481,14 @@ static int __init snake_inventory(void) continue; num++; child->parent = dev; + if (!dev->child) { + dev->child = child; + } else { + prev->sibling = child; + } + prev = child; } + prev = dev; } return num; Index: arch/parisc/kernel/lba_pci.c =================================================================== RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/lba_pci.c,v retrieving revision 1.38 diff -u -p -r1.38 lba_pci.c --- arch/parisc/kernel/lba_pci.c 2001/10/10 20:10:10 1.38 +++ arch/parisc/kernel/lba_pci.c 2001/10/11 23:18:42 @@ -1487,7 +1487,7 @@ lba_init_iregs(void *sba_hpa, u32 ibase, */ DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); - for (i = 1; i < pci_hba_count; i++) { + for (i = 0; i < pci_hba_count; i++) { struct pci_hba_data *lba = &parisc_pci_hba[i]; DBG("%s() base_addr %p\n", __FUNCTION__, lba->base_addr); WRITE_REG32( imask, lba->base_addr + LBA_IMASK); Index: arch/parisc/kernel/pci.c =================================================================== RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/pci.c,v retrieving revision 1.28 diff -u -p -r1.28 pci.c --- arch/parisc/kernel/pci.c 2001/10/10 20:10:10 1.28 +++ arch/parisc/kernel/pci.c 2001/10/11 23:18:42 @@ -51,8 +51,7 @@ int pci_post_reset_delay = 50; struct pci_port_ops *pci_port; struct pci_bios_ops *pci_bios; -/* NB: hba 0 is reserved for EISA */ -int pci_hba_count = 1; +int pci_hba_count = 0; /* ** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. @@ -75,8 +74,8 @@ struct pci_hba_data *parisc_pci_hba[PCI_ */ #ifdef CONFIG_EISA -#define EISA_IN(size) if (b == 0) return eisa_in##size(addr) -#define EISA_OUT(size) if (b == 0) return eisa_out##size(d, addr) +#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr) +#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr) #else #define EISA_IN(size) #define EISA_OUT(size) Index: arch/parisc/kernel/setup.c =================================================================== RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/setup.c,v retrieving revision 1.92 diff -u -p -r1.92 setup.c --- arch/parisc/kernel/setup.c 2001/10/10 20:10:10 1.92 +++ arch/parisc/kernel/setup.c 2001/10/11 23:18:42 @@ -208,16 +208,21 @@ void __init parisc_init(void) #if defined(CONFIG_IOMMU_CCIO) ccio_init(); #endif -#if defined(CONFIG_GSC_DINO) - dino_init(); -#endif -#ifdef CONFIG_EISA - eisa_init(); -#endif + /* + * Need to register Asp & Wax before the EISA adapters for the IRQ + * regions. EISA must come before PCI to be sure it gets IRQ region + * 0. + */ #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_DINO) \ || defined(CONFIG_GSC_WAX) busdevices_init(); +#endif +#ifdef CONFIG_EISA + eisa_init(); +#endif +#if defined(CONFIG_GSC_DINO) + dino_init(); #endif #ifdef CONFIG_CHASSIS_LCD_LED Index: drivers/gsc/asp.c =================================================================== RCS file: /home/cvs/parisc/linux/drivers/gsc/asp.c,v retrieving revision 1.11 diff -u -p -r1.11 asp.c --- drivers/gsc/asp.c 2001/10/03 08:06:40 1.11 +++ drivers/gsc/asp.c 2001/10/11 23:18:42 @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -33,30 +34,40 @@ static int asp_find_irq(struct busdevice *busdev_dev, struct parisc_device *dev) { - int irq; - int off = dev->hpa & 0xffff; + int irq = 0; - /* - ** "irq" bits below are numbered relative to most significant bit. - */ - switch (off) { - case 0x1000: irq = 30; break; /* FIXME? (29,30 or 2 !)*/ /* HIL */ - case 0x2000: irq = 25; break; /* RS232 B */ - case 0x3000: irq = 26; break; /* RS232 A */ - case 0x4000: irq = 24; break; /* Centronics/Parallel Port */ - case 0x5000: irq = 22; break; /* SCSI */ - case 0x6000: irq = 23; break; /* LAN */ - - case 0x0000: irq = 18; break; /* Audio ??? */ - case 0x9000: irq = 18; break; /* Audio ??? */ - - case 0xF000: irq = 17; break; /* ASP itself */ - default: irq = -1; break; /* unknown */ + switch (dev->id.sversion) { + case 0x71: irq = 22; break; /* SCSI */ + case 0x72: irq = 23; break; /* LAN */ + case 0x73: irq = 30; break; /* HIL */ + case 0x74: irq = 24; break; /* Centronics */ + case 0x75: if ((dev->hpa & 0xffff) == 0x3000) + irq = 26; /* RS232 A */ + else + irq = 25; /* RS232 B */ + break; + case 0x76: irq = 21; break; /* EISA BA */ + case 0x77: irq = 20; break; /* Graphics1 */ + case 0x7a: irq = 18; break; /* Audio (Bushmaster) */ + case 0x7b: irq = 18; break; /* Audio (Scorpio) */ + case 0x7c: irq = 28; break; /* FW SCSI */ + case 0x7d: irq = 27; break; /* FDDI */ + case 0x7f: irq = 18; break; /* Audio (Outfield) */ } - return irq; } +static void fixup_bus(struct parisc_device *dev, int base) +{ + while (dev) { + int irq = asp_find_irq(NULL, dev); + if (irq) { + dev->irq = base + irq; + } + dev = dev->sibling; + } +} + int __init asp_init_chip(struct parisc_device *dev) { @@ -101,7 +112,10 @@ asp_init_chip(struct parisc_device *dev) ret = register_busdevice(dev, asp); if (ret) goto out; - + + fixup_bus(dev->child, asp->busdev_region->data.irqbase); + fixup_bus(dev, asp->busdev_region->data.irqbase); + /* initialize the chassis LEDs */ #ifdef CONFIG_CHASSIS_LCD_LED register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, Index: drivers/gsc/busdevice.c =================================================================== RCS file: /home/cvs/parisc/linux/drivers/gsc/busdevice.c,v retrieving revision 1.26 diff -u -p -r1.26 busdevice.c --- drivers/gsc/busdevice.c 2001/10/10 20:10:12 1.26 +++ drivers/gsc/busdevice.c 2001/10/11 23:18:42 @@ -53,6 +53,9 @@ int busdevice_alloc_irq(struct parisc_de int irq; int hpa = dev->hpa; + if (dev->irq) + return dev->irq; + if (dev->parent) { hpa = dev->parent->hpa; } Index: drivers/gsc/eisa.c =================================================================== RCS file: /home/cvs/parisc/linux/drivers/gsc/eisa.c,v retrieving revision 1.1 diff -u -p -r1.1 eisa.c --- drivers/gsc/eisa.c 2001/10/10 20:10:12 1.1 +++ drivers/gsc/eisa.c 2001/10/11 23:18:42 @@ -9,7 +9,7 @@ * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard * * There are two distinct EISA adapters. Mongoose is found in machines - * up to the 712; then the Wax ASIC is used. To complicate matters, the + * before the 712; then the Wax ASIC is used. To complicate matters, the * Wax ASIC also includes a PS/2 and RS-232 controller, but those are * dealt with elsewhere; this file is concerned only with the EISA portions * of Wax. @@ -17,9 +17,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -30,7 +32,8 @@ * implementation can be flexed. */ struct eisa_ba { - struct resource mem; + struct pci_hba_data hba; + struct irq_region *region; } eisa_dev; /* Port ops */ @@ -84,21 +87,92 @@ void eisa_out32(u32 data, u16 port) gsc_writel(cpu_to_le32(data), eisa_permute(port)); } +/* Interrupt handling */ + +static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs) +{ + extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); + int irq = gsc_readb(0xfc01f000); + + printk(KERN_DEBUG "EISA irq %d\n", irq); + + do_irq(&eisa_dev.region->action[irq], + eisa_dev.region->data.irqbase + irq, regs); +} + +static void eisa_disable_irq(void *irq_dev, int irq) +{ + return; +} + +static void eisa_enable_irq(void *irq_dev, int irq) +{ + return; +} + +static void eisa_mask_irq(void *irq_dev, int irq) +{ + return; +} + +static void eisa_unmask_irq(void *irq_dev, int irq) +{ + return; +} + +static struct irq_region_ops eisa_irq_ops = { + disable_irq: eisa_disable_irq, + enable_irq: eisa_enable_irq, + mask_irq: eisa_mask_irq, + unmask_irq: eisa_unmask_irq, +}; + +/* Device initialisation */ + +#define is_mongoose(dev) (dev->id.sversion == 0x00076) + static int __devinit eisa_probe(struct parisc_device *dev) { - int result; - char *name = (dev->id.sversion == 0x00076) ? "Mongoose" : "Wax"; + int result, irq; + char *name = is_mongoose(dev) ? "Mongoose" : "Wax"; printk("%s EISA Adapter found at 0x%08lx\n", name, dev->hpa); - eisa_dev.mem.name = "EISA Bus"; - eisa_dev.mem.start = 0xfc000000; - eisa_dev.mem.end = 0xffbfffff; - eisa_dev.mem.flags = IORESOURCE_MEM; - result = request_resource(&iomem_resource, &eisa_dev.mem); + eisa_dev.hba.lmmio_space.name = "EISA"; + eisa_dev.hba.lmmio_space.start = 0xfc000000; + eisa_dev.hba.lmmio_space.end = 0xffbfffff; + eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM; + result = request_resource(&iomem_resource, &eisa_dev.hba.lmmio_space); if (result < 0) { printk(KERN_ERR "EISA: failed to claim EISA Bus address space!\n"); return result; + } + eisa_dev.hba.io_space.name = "EISA"; + eisa_dev.hba.io_space.start = 0; + eisa_dev.hba.io_space.end = 0xffff; + eisa_dev.hba.lmmio_space.flags = IORESOURCE_IO; + result = request_resource(&ioport_resource, &eisa_dev.hba.io_space); + if (result < 0) { + printk(KERN_ERR "EISA: failed to claim EISA Bus port space!\n"); + return result; + } + pcibios_register_hba(&eisa_dev.hba); + + irq = busdevice_alloc_irq(dev); + if (!irq) { + printk(KERN_ERR "EISA: failed to claim IRQ\n"); + return -ENODEV; + } + result = request_irq(irq, eisa_irq, 0, name, NULL); + if (result) { + printk(KERN_ERR "EISA: request_irq failed!\n"); + return result; + } + eisa_dev.region = alloc_irq_region(8, &eisa_irq_ops, + IRQ_REG_MASK|IRQ_REG_DIS, name, NULL); + if (eisa_dev.region == NULL) { + printk(KERN_ERR "EISA: Couldn't allocate IRQ region\n"); + return -ENODEV; } EISA_bus = 1; Index: include/asm-parisc/hardware.h =================================================================== RCS file: /home/cvs/parisc/linux/include/asm-parisc/hardware.h,v retrieving revision 1.23 diff -u -p -r1.23 hardware.h --- include/asm-parisc/hardware.h 2001/10/05 02:43:50 1.23 +++ include/asm-parisc/hardware.h 2001/10/11 23:18:43 @@ -29,6 +29,7 @@ struct parisc_device { struct parisc_device *child; struct parisc_driver *driver; /* Driver for this device */ char name[80]; /* The hardware description */ + int irq; unsigned int hw_path; /* The hardware path on the current bus */ unsigned int num_addrs; /* some devices have additional address ranges. */