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;
 }
