Index: arch/parisc/kernel/drivers.c =================================================================== RCS file: /var/cvs/linux/arch/parisc/kernel/drivers.c,v retrieving revision 1.32 diff -u -p -r1.32 drivers.c --- arch/parisc/kernel/drivers.c 2001/10/23 21:02:53 1.32 +++ arch/parisc/kernel/drivers.c 2001/10/27 06:35:50 @@ -292,6 +292,13 @@ alloc_pa_dev(unsigned long hpa, struct h return NULL; dev = find_parisc_device(mod_path); + if (dev->id.hw_type != HPHW_FAULTY) { + char p[64]; + print_hwpath(mod_path, p); + printk("Two devices have hardware path %s. Please file a bug with HP.\n" + "In the meantime, you could try rearranging your cards.\n", p); + return NULL; + } dev->id.hw_type = iodc_data[3] & 0x1f; dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4); @@ -343,7 +350,7 @@ int register_parisc_device(struct parisc #define NATIVE_DEVICE_OFFSET 0x1000 /** - * do_native_bus_walk -- Probe a bus for devices + * walk_native_bus -- Probe a bus for devices * @addr: Base address of this bus. * * A native bus (eg Runway or GSC) may have up to 64 devices on it, Index: arch/parisc/kernel/pci.c =================================================================== RCS file: /var/cvs/linux/arch/parisc/kernel/pci.c,v retrieving revision 1.29 diff -u -p -r1.29 pci.c --- arch/parisc/kernel/pci.c 2001/10/11 23:43:27 1.29 +++ arch/parisc/kernel/pci.c 2001/10/27 06:35:50 @@ -51,7 +51,7 @@ int pci_post_reset_delay = 50; struct pci_port_ops *pci_port; struct pci_bios_ops *pci_bios; -int pci_hba_count = 0; +int pci_hba_count = 1; /* ** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. @@ -479,7 +480,6 @@ pcibios_setup_host_bridge(struct pci_bus } -#ifdef __LP64__ /* ** Mostly copied from drivers/pci/setup-bus.c:pci_assign_unassigned_resources() */ @@ -498,7 +498,6 @@ pcibios_assign_unassigned_resources(stru ranges.found_vga = 0; pbus_assign_resources(bus, &ranges); } -#endif /* ** PARISC specific (unfortunately) Index: drivers/gsc/dino.c =================================================================== RCS file: /var/cvs/linux/drivers/gsc/dino.c,v retrieving revision 1.45 diff -u -p -r1.45 dino.c --- drivers/gsc/dino.c 2001/10/23 21:02:54 1.45 +++ drivers/gsc/dino.c 2001/10/27 06:35:50 @@ -151,10 +151,6 @@ struct dino_device int irq; /* Virtual IRQ dino uses */ struct irq_region *dino_region; /* region for this Dino */ -/* REVISIT - replace these hba.io_space and hba.memspace? */ - unsigned long mmio_addr; /* FIXME: card-mode support */ - u32 ioport_addr; /* card-mode support */ - u32 imr; /* IRQ's which are enabled */ #ifdef DINO_DEBUG unsigned int dino_irr0; /* save most recent IRQ line stat */ @@ -180,7 +176,7 @@ struct dino_device #define DINO_CFG_RD(type, size, mask) \ static int dino_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \ { \ - struct dino_device *d = DINO_DEV(dev->bus->sysdata); \ + struct dino_device *d = DINO_DEV(dev->sysdata); \ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ u32 v = DINO_CFG_TOK(local_bus, dev->devfn, (pos&~3)); \ unsigned long flags; \ @@ -207,7 +203,7 @@ DINO_CFG_RD(l, 32, 0) #define DINO_CFG_WR(type, size, mask) \ static int dino_cfg_write##size (struct pci_dev *dev, int pos, u##size data) \ { \ - struct dino_device *d = DINO_DEV(dev->bus->sysdata); \ + struct dino_device *d = DINO_DEV(dev->sysdata); \ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ u32 v = DINO_CFG_TOK(local_bus, dev->devfn, (pos&~3)); \ unsigned long flags; \ @@ -293,9 +289,6 @@ struct pci_port_ops dino_port_ops = { outl: dino_out32 }; - - - static void dino_mask_irq(void *irq_dev, int irq) { @@ -405,23 +398,20 @@ ilr_again: int irq; /* - ** Perform a binary search on set bits - ** INT 8 & 9 are not supported. - */ - if (mask & (PCIINTA | PCIINTC | PCIINTE | GSCEXTINT | RS232INT)) - { - if (mask & (PCIINTA | PCIINTC)) { - irq = (mask & PCIINTA) ? 0 : 2; + * Perform a binary search on set bits. + * `Less than Fatal' and PS2 interupts aren't supported. + */ + if (mask & 0xf) { + if (mask & 0x3) { + irq = (mask & 0x1) ? 0 : 1; /* PCI INT A, B */ } else { - if (mask & (PCIINTE | GSCEXTINT)) { - irq = (mask & PCIINTE) ? 4 : 6; - } else irq = 10; /* RS232 INTERRUPT */ + irq = (mask & 0x4) ? 2 : 3; /* PCI INT C, D */ } } else { - if (mask & (PCIINTB | PCIINTD)) { - irq = (mask & PCIINTB) ? 1 : 3; + if (mask & 0x30) { + irq = (mask & 0x10) ? 4 : 5; /* PCI INT E, F */ } else { - irq = (mask & PCIINTF) ? 5 : 7; + irq = (mask & 0x40) ? 6 : 10; /* GSC, RS232 */ } } @@ -442,10 +432,11 @@ ilr_again: ** device drivers may assume lines are level triggered (and not ** edge triggered like EISA/ISA can be). */ - if (0 != (mask = gsc_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr)) - { - --ilr_loop; - goto ilr_again; + mask = gsc_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr; + if (mask) { + if (--ilr_loop > 0) + goto ilr_again; + printk("Dino: stuck interrupt %d\n", mask); } } @@ -467,64 +458,42 @@ dino_bios_init(void) { DBG("dino_bios_init\n"); } - +/* + * dino_card_setup - Set up the memory space for a Dino in card mode. + * @bus: the bus under this dino + * + * Claim an 8MB chunk of unused IO space and call the generic PCI routines + * to set up the addresses of the devices on this bus. + */ +#define _8MB 0x00800000 static void __init -dino_set_bars(struct pci_dev *dev) +dino_card_setup(struct pci_bus *bus, unsigned long base_addr) { - struct dino_device *dino_dev = DINO_DEV(dev->bus->sysdata); int i; + struct dino_device *dino_dev = DINO_DEV(bus->sysdata); + struct resource *res = &dino_dev->hba.lmmio_space; - /* Adjust the I/O Port space addresses */ - for (i=0; i<6; i++) - { - u32 bar_val = 0; - - /* - ** Calculate next properly aligned address. - */ - if (dev->resource[i].flags & IORESOURCE_IO) - { - unsigned long sz = dev->resource[i].end - - dev->resource[i].start; - - /* Round up to nearest "sz" alignment */ - dino_dev->ioport_addr += (u32) sz; - dino_dev->ioport_addr &= (u32) ~sz; - bar_val = dino_dev->ioport_addr; - - /* point to next unused addr */ - dino_dev->ioport_addr += (u32) sz + 1; - - dev->resource[i].start = bar_val; - dev->resource[i].end = bar_val + sz; - DBG(KERN_WARNING __FUNCTION__ " %0x:%0x [%d] ioport %x start 0x%x sz %lx\n", - dev->bus->number, dev->devfn, i, - dino_dev->ioport_addr, bar_val, sz); - } else { - /* NOT SUPPORTED */ - dev->resource[i].start = dev->resource[i].end = - bar_val = 0; - } + res->name = "PCI %d"; + res->flags = IORESOURCE_MEM; - /* Write the new address */ - dino_cfg_write32(dev, (i*4)+0x10, bar_val); + if (allocate_resource(&iomem_resource, res, _8MB, 0xf0000000 | _8MB, + 0xffffffff &~ _8MB, _8MB, NULL, NULL) < 0) { + printk(KERN_WARNING "Dino: Failed to allocate memory region\n"); + return; } + bus->resource[1] = res; + /* Now tell dino what range it has */ + for (i = 1; i < 31; i++) { + if (res->start == (0xf0000000 | i * _8MB)) + break; + } + gsc_writel(1 << (31 - i), base_addr + DINO_IO_ADDR_EN); - /* - ** Enable the command register - ** - ** FIXME: This is put here because PCI subsystem could - ** be doing all of this for us. - */ - dino_cfg_write32(dev, PCI_COMMAND, - PCI_COMMAND_SERR | - PCI_COMMAND_PARITY | PCI_COMMAND_INVALIDATE | - PCI_COMMAND_MASTER | PCI_COMMAND_IO); + pcibios_assign_unassigned_resources(bus); } - static void __init dino_card_fixup(struct pci_dev *dev) { @@ -539,15 +508,6 @@ dino_card_fixup(struct pci_dev *dev) panic("Card-Mode Dino: PCI-PCI Bridge not supported\n"); } -/* -** FIXME: PCI subsystem in linux 2.4 manage and program I/O Port space -** for us if we told it which addresses it could use. -*/ - /* - ** Program the I/O Port space BARs. - */ - dino_set_bars(dev); - /* ** Set Latency Timer to 0xff (not a shared bus) ** Set CACHELINE_SIZE. @@ -564,8 +524,7 @@ dino_card_fixup(struct pci_dev *dev) ** The additional "-1" adjusts for skewing the IRQ<->slot. */ dino_cfg_read8(dev, PCI_INTERRUPT_PIN, &irq_pin); - dev->irq = (irq_pin + (dev->devfn >> 3) - 2) % 4 ; - + dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 2) % 4 ; /* Shouldn't really need to do this but it's in case someone tries ** to bypass PCI services and look at the card themselves. @@ -585,6 +544,10 @@ dino_fixup_bus(struct pci_bus *bus) DBG(KERN_WARNING __FUNCTION__ "(0x%p) bus %d sysdata 0x%p\n", bus, bus->secondary, bus->sysdata); + /* Firmware doesn't set up card-mode dino, so we have to */ + if (is_card_dino(dino_dev->hba.iodc_info)) + dino_card_setup(bus, dino_dev->hba.base_addr); + /* If this is a PCI-PCI Bridge, read the window registers etc */ if (bus->self) pci_read_bridge_bases(bus); @@ -612,7 +575,7 @@ dino_fixup_bus(struct pci_bus *bus) } #ifdef __LP64__ /* Sign Extend MMIO addresses */ - if (res->flags & IORESOURCE_MEM) { + else if (res->flags & IORESOURCE_MEM) { res->start |= 0xffffffff00000000UL; res->end |= 0xffffffff00000000UL; } @@ -662,10 +625,6 @@ dino_card_init(struct dino_device *dino_ */ gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_IO_ADDR_EN); - dino_dev->ioport_addr = 0x00001000; /* Make believe */ - dino_dev->mmio_addr = 0xf0800000; /* FIXME: Make believe */ - dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ - gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_DAMODE); gsc_writel(0x00222222, dino_dev->hba.base_addr+DINO_PCIROR); gsc_writel(0x00222222, dino_dev->hba.base_addr+DINO_PCIWOR); @@ -680,7 +639,7 @@ dino_card_init(struct dino_device *dino_ gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_PAMR); /* - ** Dino ERS encourage to enable FBB (0x6f). + ** Dino ERS encourages enabling FBB (0x6f). ** We can't until we know *all* devices below us can support it. ** (Something in device configuration header tells us). */ @@ -726,7 +685,6 @@ dino_bridge_init(struct dino_device *din return result; } - dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ return 0; } @@ -737,30 +695,31 @@ dino_common_init(struct parisc_device *d u32 eim; struct gsc_irq gsc_irq; struct resource *res; - struct busdevice *dino_busdevice; - int ret; - - pcibios_register_hba(&dino_dev->hba); - pci_bios = &dino_bios_ops; /* used by pci_scan_bus() */ - pci_port = &dino_port_ops; - + int ret; - /* Needed for the serial port to work. */ + /* Support the serial port which is sometimes attached on built-in + * Dino / Cujo chips. + */ dino_busdevice = kmalloc(sizeof(struct busdevice), GFP_KERNEL); - if(!dino_busdevice) + if (!dino_busdevice) return -ENOMEM; - + dino_busdevice->name = "Dino"; dino_busdevice->hpa = dev->hpa; + + pcibios_register_hba(&dino_dev->hba); + pci_bios = &dino_bios_ops; /* used by pci_scan_bus() */ + pci_port = &dino_port_ops; + /* ** Note: SMP systems can make use of IRR1/IAR1 registers ** But it won't buy much performance except in very ** specific applications/configurations. Note Dino - ** still only has 11 IRQ input lines - just map some them + ** still only has 11 IRQ input lines - just map some of them ** to a different processor. */ dino_dev->irq = gsc_alloc_irq(&gsc_irq); @@ -772,18 +731,17 @@ dino_common_init(struct parisc_device *d ** Dino needs a PA "IRQ" to get a processor's attention. ** arch/parisc/kernel/irq.c returns an EIRR bit. */ - if(dino_dev->irq < 0) - { + if (dino_dev->irq < 0) { printk(KERN_WARNING "Dino %lx: gsc_alloc_irq() failed\n", - (long) dino_dev->hba.base_addr); - return(1); + dino_dev->hba.base_addr); + return 1; } status = request_irq(dino_dev->irq, dino_isr, 0,"dino", dino_dev); if(status) { printk(KERN_WARNING "Dino %lx: request_irq() failed with %d\n", - (long) dino_dev->hba.base_addr,status); - return(1); + dino_dev->hba.base_addr, status); + return 1; } /* @@ -793,10 +751,10 @@ dino_common_init(struct parisc_device *d dino_dev->dino_region = alloc_irq_region( DINO_IRQS, &dino_irq_ops, IRQ_REG_MASK|IRQ_REG_DIS, "dino", dino_dev); - if(NULL == dino_dev->dino_region) { + if (NULL == dino_dev->dino_region) { printk(KERN_WARNING "Dino %lx: alloc_irq_region() failed\n", - (long) dino_dev->hba.base_addr); - return(1); + dino_dev->hba.base_addr); + return 1; } /* Register busdevice for the serial port */ @@ -832,7 +790,7 @@ dino_common_init(struct parisc_device *d ** Some platforms don't clear Dino's IRR0 register at boot time. ** Reading will clear it now. */ - (void) gsc_readl(dino_dev->hba.base_addr+DINO_IRR0); + gsc_readl(dino_dev->hba.base_addr+DINO_IRR0); /* allocate I/O Port resource region */ res = &dino_dev->hba.io_space; @@ -844,7 +802,6 @@ dino_common_init(struct parisc_device *d res->start = HBA_PORT_BASE(dino_dev->hba.hba_num); res->end = res->start + (HBA_PORT_SPACE_SIZE - 1); res->flags = IORESOURCE_IO; /* do not mark it busy ! */ - res->child = NULL; if (request_resource(&ioport_resource, res) < 0) { printk(KERN_ERR "DINO: request I/O Port region failed 0x%lx/%lx (hpa 0x%lx)\n" , res->start, res->end, dino_dev->hba.base_addr); @@ -945,6 +902,7 @@ dino_driver_callback(struct parisc_devic dino_dev->hba.iodc_info = &dev->id; dino_dev->hba.base_addr = dev->hpa; /* faster access */ + dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ dino_dev->dinosaur_pen = SPIN_LOCK_UNLOCKED; dino_dev->hba.iommu = ccio_get_iommu(dev); @@ -961,7 +919,8 @@ dino_driver_callback(struct parisc_devic ** It's not used to avoid chicken/egg problems ** with configuration accessor functions. */ - dino_dev->hba.hba_bus = pci_scan_bus(dino_dev->hba.hba_num, &dino_cfg_ops, (void *) dino_dev); + dino_dev->hba.hba_bus = pci_scan_bus(dino_dev->hba.hba_num, + &dino_cfg_ops, dino_dev); return 0; }