fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / ppc / platforms / prep_pci.c
index 58775fc..c627ba4 100644 (file)
@@ -6,7 +6,6 @@
  * The motherboard routes/maps will disappear shortly. -- Cort
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -43,16 +42,16 @@ static unsigned long        *ProcInfo;
 /* Tables for known hardware */
 
 /* Motorola PowerStackII - Utah */
-static char Utah_pci_IRQ_map[23] __prepdata =
+static char Utah_pci_IRQ_map[23] =
 {
         0,   /* Slot 0  - unused */
         0,   /* Slot 1  - unused */
         5,   /* Slot 2  - SCSI - NCR825A  */
         0,   /* Slot 3  - unused */
-        1,   /* Slot 4  - Ethernet - DEC2114x */
+        3,   /* Slot 4  - Ethernet - DEC2114x */
         0,   /* Slot 5  - unused */
-        3,   /* Slot 6  - PCI Card slot #1 */
-        4,   /* Slot 7  - PCI Card slot #2 */
+        2,   /* Slot 6  - PCI Card slot #1 */
+        3,   /* Slot 7  - PCI Card slot #2 */
         5,   /* Slot 8  - PCI Card slot #3 */
         5,   /* Slot 9  - PCI Bridge */
              /* added here in case we ever support PCI bridges */
@@ -72,7 +71,7 @@ static char Utah_pci_IRQ_map[23] __prepdata =
         0,   /* Slot 22 - unused */
 };
 
-static char Utah_pci_IRQ_routes[] __prepdata =
+static char Utah_pci_IRQ_routes[] =
 {
         0,   /* Line 0 - Unused */
         9,   /* Line 1 */
@@ -84,7 +83,7 @@ static char Utah_pci_IRQ_routes[] __prepdata =
 
 /* Motorola PowerStackII - Omaha */
 /* no integrated SCSI or ethernet */
-static char Omaha_pci_IRQ_map[23] __prepdata =
+static char Omaha_pci_IRQ_map[23] =
 {
         0,   /* Slot 0  - unused */
         0,   /* Slot 1  - unused */
@@ -111,7 +110,7 @@ static char Omaha_pci_IRQ_map[23] __prepdata =
         0,
 };
 
-static char Omaha_pci_IRQ_routes[] __prepdata =
+static char Omaha_pci_IRQ_routes[] =
 {
         0,   /* Line 0 - Unused */
         9,   /* Line 1 */
@@ -121,7 +120,7 @@ static char Omaha_pci_IRQ_routes[] __prepdata =
 };
 
 /* Motorola PowerStack */
-static char Blackhawk_pci_IRQ_map[19] __prepdata =
+static char Blackhawk_pci_IRQ_map[19] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -144,7 +143,7 @@ static char Blackhawk_pci_IRQ_map[19] __prepdata =
        3,      /* Slot P5 */
 };
 
-static char Blackhawk_pci_IRQ_routes[] __prepdata =
+static char Blackhawk_pci_IRQ_routes[] =
 {
        0,      /* Line 0 - Unused */
        9,      /* Line 1 */
@@ -154,7 +153,7 @@ static char Blackhawk_pci_IRQ_routes[] __prepdata =
 };
 
 /* Motorola Mesquite */
-static char Mesquite_pci_IRQ_map[23] __prepdata =
+static char Mesquite_pci_IRQ_map[23] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -182,7 +181,7 @@ static char Mesquite_pci_IRQ_map[23] __prepdata =
 };
 
 /* Motorola Sitka */
-static char Sitka_pci_IRQ_map[21] __prepdata =
+static char Sitka_pci_IRQ_map[21] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -208,7 +207,7 @@ static char Sitka_pci_IRQ_map[21] __prepdata =
 };
 
 /* Motorola MTX */
-static char MTX_pci_IRQ_map[23] __prepdata =
+static char MTX_pci_IRQ_map[23] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -237,7 +236,7 @@ static char MTX_pci_IRQ_map[23] __prepdata =
 
 /* Motorola MTX Plus */
 /* Secondary bus interrupt routing is not supported yet */
-static char MTXplus_pci_IRQ_map[23] __prepdata =
+static char MTXplus_pci_IRQ_map[23] =
 {
         0,      /* Slot 0  - unused */
         0,      /* Slot 1  - unused */
@@ -264,13 +263,13 @@ static char MTXplus_pci_IRQ_map[23] __prepdata =
         0,      /* Slot 22 - unused */
 };
 
-static char Raven_pci_IRQ_routes[] __prepdata =
+static char Raven_pci_IRQ_routes[] =
 {
        0,      /* This is a dummy structure */
 };
 
 /* Motorola MVME16xx */
-static char Genesis_pci_IRQ_map[16] __prepdata =
+static char Genesis_pci_IRQ_map[16] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -290,7 +289,7 @@ static char Genesis_pci_IRQ_map[16] __prepdata =
        0,      /* Slot 15 - unused */
 };
 
-static char Genesis_pci_IRQ_routes[] __prepdata =
+static char Genesis_pci_IRQ_routes[] =
 {
        0,      /* Line 0 - Unused */
        10,     /* Line 1 */
@@ -299,7 +298,7 @@ static char Genesis_pci_IRQ_routes[] __prepdata =
        15      /* Line 4 */
 };
 
-static char Genesis2_pci_IRQ_map[23] __prepdata =
+static char Genesis2_pci_IRQ_map[23] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -327,7 +326,7 @@ static char Genesis2_pci_IRQ_map[23] __prepdata =
 };
 
 /* Motorola Series-E */
-static char Comet_pci_IRQ_map[23] __prepdata =
+static char Comet_pci_IRQ_map[23] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -354,7 +353,7 @@ static char Comet_pci_IRQ_map[23] __prepdata =
        0,
 };
 
-static char Comet_pci_IRQ_routes[] __prepdata =
+static char Comet_pci_IRQ_routes[] =
 {
        0,      /* Line 0 - Unused */
        10,     /* Line 1 */
@@ -364,7 +363,7 @@ static char Comet_pci_IRQ_routes[] __prepdata =
 };
 
 /* Motorola Series-EX */
-static char Comet2_pci_IRQ_map[23] __prepdata =
+static char Comet2_pci_IRQ_map[23] =
 {
        0,      /* Slot 0  - unused */
        0,      /* Slot 1  - unused */
@@ -391,7 +390,7 @@ static char Comet2_pci_IRQ_map[23] __prepdata =
        0,
 };
 
-static char Comet2_pci_IRQ_routes[] __prepdata =
+static char Comet2_pci_IRQ_routes[] =
 {
        0,      /* Line 0 - Unused */
        10,     /* Line 1 */
@@ -405,7 +404,7 @@ static char Comet2_pci_IRQ_routes[] __prepdata =
  * This is actually based on the Carolina motherboard
  * -- Cort
  */
-static char ibm8xx_pci_IRQ_map[23] __prepdata = {
+static char ibm8xx_pci_IRQ_map[23] = {
         0, /* Slot 0  - unused */
         0, /* Slot 1  - unused */
         0, /* Slot 2  - unused */
@@ -431,7 +430,7 @@ static char ibm8xx_pci_IRQ_map[23] __prepdata = {
         2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
 };
 
-static char ibm8xx_pci_IRQ_routes[] __prepdata = {
+static char ibm8xx_pci_IRQ_routes[] = {
         0,      /* Line 0 - unused */
         15,     /* Line 1 */
         15,     /* Line 2 */
@@ -443,7 +442,7 @@ static char ibm8xx_pci_IRQ_routes[] __prepdata = {
  * a 6015 ibm board
  * -- Cort
  */
-static char ibm6015_pci_IRQ_map[23] __prepdata = {
+static char ibm6015_pci_IRQ_map[23] = {
         0, /* Slot 0  - unused */
         0, /* Slot 1  - unused */
         0, /* Slot 2  - unused */
@@ -469,7 +468,7 @@ static char ibm6015_pci_IRQ_map[23] __prepdata = {
         2, /* Slot 22 -  */
 };
 
-static char ibm6015_pci_IRQ_routes[] __prepdata = {
+static char ibm6015_pci_IRQ_routes[] = {
         0,      /* Line 0 - unused */
         13,     /* Line 1 */
         15,     /* Line 2 */
@@ -479,7 +478,7 @@ static char ibm6015_pci_IRQ_routes[] __prepdata = {
 
 
 /* IBM Nobis and Thinkpad 850 */
-static char Nobis_pci_IRQ_map[23] __prepdata ={
+static char Nobis_pci_IRQ_map[23] ={
         0, /* Slot 0  - unused */
         0, /* Slot 1  - unused */
         0, /* Slot 2  - unused */
@@ -498,7 +497,7 @@ static char Nobis_pci_IRQ_map[23] __prepdata ={
         0, /* Slot 15 - unused */
 };
 
-static char Nobis_pci_IRQ_routes[] __prepdata = {
+static char Nobis_pci_IRQ_routes[] = {
         0, /* Line 0 - Unused */
         13, /* Line 1 */
         13, /* Line 2 */
@@ -510,7 +509,7 @@ static char Nobis_pci_IRQ_routes[] __prepdata = {
  * IBM RS/6000 43p/140  -- paulus
  * XXX we should get all this from the residual data
  */
-static char ibm43p_pci_IRQ_map[23] __prepdata = {
+static char ibm43p_pci_IRQ_map[23] = {
         0, /* Slot 0  - unused */
         0, /* Slot 1  - unused */
         0, /* Slot 2  - unused */
@@ -536,7 +535,7 @@ static char ibm43p_pci_IRQ_map[23] __prepdata = {
         1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
 };
 
-static char ibm43p_pci_IRQ_routes[] __prepdata = {
+static char ibm43p_pci_IRQ_routes[] = {
         0,      /* Line 0 - unused */
         15,     /* Line 1 */
         15,     /* Line 2 */
@@ -559,7 +558,7 @@ struct powerplus_irq_list
  * are routed to OpenPIC inputs 5-8.  These values are offset by
  * 16 in the table to reflect the Linux kernel interrupt value.
  */
-struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
+struct powerplus_irq_list Powerplus_pci_IRQ_list =
 {
        {25, 26, 27, 28},
        {21, 22, 23, 24}
@@ -572,7 +571,7 @@ struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
  * are routed to OpenPIC inputs 12-15. These values are offset by
  * 16 in the table to reflect the Linux kernel interrupt value.
  */
-struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
+struct powerplus_irq_list Mesquite_pci_IRQ_list =
 {
        {24, 25, 26, 27},
        {28, 29, 30, 31}
@@ -582,7 +581,7 @@ struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
  * This table represents the standard PCI swizzle defined in the
  * PCI bus specification.
  */
-static unsigned char prep_pci_intpins[4][4] __prepdata =
+static unsigned char prep_pci_intpins[4][4] =
 {
        { 1, 2, 3, 4},  /* Buses 0, 4, 8, ... */
        { 2, 3, 4, 1},  /* Buses 1, 5, 9, ... */
@@ -622,12 +621,12 @@ static unsigned char prep_pci_intpins[4][4] __prepdata =
 #define MIN_DEVNR      11
 #define MAX_DEVNR      22
 
-static int __prep
+static int
 prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
                 int len, u32 *val)
 {
        struct pci_controller *hose = bus->sysdata;
-       volatile unsigned char *cfg_data;
+       volatile void __iomem *cfg_data;
 
        if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
            || DEVNO(devfn) > MAX_DEVNR)
@@ -640,24 +639,24 @@ prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
        cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
        switch (len) {
        case 1:
-               *val = in_8((u8 *)cfg_data);
+               *val = in_8(cfg_data);
                break;
        case 2:
-               *val = in_le16((u16 *)cfg_data);
+               *val = in_le16(cfg_data);
                break;
        default:
-               *val = in_le32((u32 *)cfg_data);
+               *val = in_le32(cfg_data);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int __prep
+static int
 prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
                  int len, u32 val)
 {
        struct pci_controller *hose = bus->sysdata;
-       volatile unsigned char *cfg_data;
+       volatile void __iomem *cfg_data;
 
        if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
            || DEVNO(devfn) > MAX_DEVNR)
@@ -670,13 +669,13 @@ prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
        cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
        switch (len) {
        case 1:
-               out_8((u8 *)cfg_data, val);
+               out_8(cfg_data, val);
                break;
        case 2:
-               out_le16((u16 *)cfg_data, val);
+               out_le16(cfg_data, val);
                break;
        default:
-               out_le32((u32 *)cfg_data, val);
+               out_le32(cfg_data, val);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
@@ -804,7 +803,7 @@ struct mot_info {
        void            (*map_non0_bus)(struct pci_dev *);      /* For boards with more than bus 0 devices. */
        struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
        unsigned char   secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
-} mot_info[] __prepdata = {
+} mot_info[] = {
        {0x300, 0x00, 0x00, "MVME 2400",                        Genesis2_pci_IRQ_map,   Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
        {0x010, 0x00, 0x00, "Genesis",                          Genesis_pci_IRQ_map,    Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
        {0x020, 0x00, 0x00, "Powerstack (Series E)",            Comet_pci_IRQ_map,      Comet_pci_IRQ_routes, NULL, NULL, 0x00},
@@ -836,52 +835,59 @@ struct mot_info {
 void __init
 ibm_prep_init(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-       u32 addr, real_addr, len;
-       PPC_DEVICE *mpic;
-       PnP_TAG_PACKET *pkt;
-
-       /* Use the PReP residual data to determine if an OpenPIC is
-        * present.  If so, get the large vendor packet which will
-        * tell us the base address and length in memory.
-        * If we are successful, ioremap the memory area and set
-        * OpenPIC_Addr (this indicates that the OpenPIC was found).
-        */
-       mpic = residual_find_device(-1, NULL, SystemPeripheral,
-                           ProgrammableInterruptController, MPIC, 0);
-       if (!mpic)
-               return;
+       if (have_residual_data) {
+               u32 addr, real_addr, len, offset;
+               PPC_DEVICE *mpic;
+               PnP_TAG_PACKET *pkt;
+
+               /* Use the PReP residual data to determine if an OpenPIC is
+                * present.  If so, get the large vendor packet which will
+                * tell us the base address and length in memory.
+                * If we are successful, ioremap the memory area and set
+                * OpenPIC_Addr (this indicates that the OpenPIC was found).
+                */
+               mpic = residual_find_device(-1, NULL, SystemPeripheral,
+                                   ProgrammableInterruptController, MPIC, 0);
+               if (!mpic)
+                       return;
 
-       pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
-                       mpic->AllocatedOffset, 9, 0);
+               pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+                               mpic->AllocatedOffset, 9, 0);
 
-       if (!pkt)
-               return;
+               if (!pkt)
+                       return;
 
 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
-       if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
-               return; /* not a 32-bit memory address */
+               if (p.PPCData[1] == 32) {
+                       switch (p.PPCData[0]) {
+                               case 1:  offset = PREP_ISA_IO_BASE;  break;
+                               case 2:  offset = PREP_ISA_MEM_BASE; break;
+                               default: return; /* Not I/O or memory?? */
+                       }
+               }
+               else
+                       return; /* Not a 32-bit address */
 
-       real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
-       if (real_addr == 0xffffffff)
-               return;
+               real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+               if (real_addr == 0xffffffff)
+                       return;
 
-       /* Adjust address to be as seen by CPU */
-       addr = real_addr + PREP_ISA_MEM_BASE;
+               /* Adjust address to be as seen by CPU */
+               addr = real_addr + offset;
 
-       len = ld_le32((unsigned int *) (p.PPCData + 12));
-       if (!len)
-               return;
+               len = ld_le32((unsigned int *) (p.PPCData + 12));
+               if (!len)
+                       return;
 #undef p
-       OpenPIC_Addr = ioremap(addr, len);
-       ppc_md.get_irq = openpic_get_irq;
+               OpenPIC_Addr = ioremap(addr, len);
+               ppc_md.get_irq = openpic_get_irq;
 
-       OpenPIC_InitSenses = prep_openpic_initsenses;
-       OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+               OpenPIC_InitSenses = prep_openpic_initsenses;
+               OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
 
-       printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
-              "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
-#endif
+               printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+                      "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+       }
 }
 
 static void __init
@@ -900,6 +906,17 @@ ibm43p_pci_map_non0(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 }
 
+void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+       if (have_residual_data) {
+               Motherboard_map_name = res->VitalProductData.PrintableModel;
+               Motherboard_map = NULL;
+               Motherboard_routes = NULL;
+               residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+       }
+}
+
 void __init
 prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
 {
@@ -1011,21 +1028,31 @@ prep_route_pci_interrupts(void)
                }
        } else if ( _prep_type == _PREP_IBM ) {
                unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+               unsigned short irq_edge_mask;
+               int i;
 
                setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
 
                outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
                outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+               irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+               for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+                       if (irq_edge_mask & 1)
+                               irq_desc[i].status |= IRQ_LEVEL;
        } else {
                printk("No known machine pci routing!\n");
                return;
        }
 
        /* Set up mapping from slots */
-       for (i = 1;  i <= 4;  i++)
-               ibc_pirq[i-1] = Motherboard_routes[i];
-       /* Enable PCI interrupts */
-       *ibc_pcicon |= 0x20;
+       if (Motherboard_routes) {
+               for (i = 1;  i <= 4;  i++)
+                       ibc_pirq[i-1] = Motherboard_routes[i];
+
+               /* Enable PCI interrupts */
+               *ibc_pcicon |= 0x20;
+       }
 }
 
 void __init
@@ -1041,7 +1068,7 @@ prep_pib_init(void)
                 * Perform specific configuration for the Via Tech or
                 * or Winbond PCI-ISA-Bridge part.
                 */
-               if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+               if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                        PCI_DEVICE_ID_VIA_82C586_1, dev))) {
                        /*
                         * PPCBUG does not set the enable bits
@@ -1052,7 +1079,7 @@ prep_pib_init(void)
                        reg |= 0x03; /* IDE: Chip Enable Bits */
                        pci_write_config_byte(dev, 0x40, reg);
                }
-               if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+               if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                                PCI_DEVICE_ID_VIA_82C586_2,
                                                dev)) && (dev->devfn = 0x5a)) {
                        /* Force correct USB interrupt */
@@ -1061,7 +1088,7 @@ prep_pib_init(void)
                                        PCI_INTERRUPT_LINE,
                                        dev->irq);
                }
-               if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+               if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
                                        PCI_DEVICE_ID_WINBOND_83C553, dev))) {
                         /* Clear PCI Interrupt Routing Control Register. */
                        short_reg = 0x0000;
@@ -1072,9 +1099,10 @@ prep_pib_init(void)
                                pci_write_config_byte(dev, 0x43, reg);
                        }
                }
+               pci_dev_put(dev);
        }
 
-       if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+       if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
                                   PCI_DEVICE_ID_WINBOND_82C105, dev))){
                if (OpenPIC_Addr){
                        /*
@@ -1093,6 +1121,7 @@ prep_pib_init(void)
                        pci_write_config_dword(dev, 0x40, 0x10ff08a1);
                }
        }
+       pci_dev_put(dev);
 }
 
 static void __init
@@ -1171,38 +1200,57 @@ void __init
 prep_pcibios_fixup(void)
 {
         struct pci_dev *dev = NULL;
+       int irq;
+       int have_openpic = (OpenPIC_Addr != NULL);
 
        prep_route_pci_interrupts();
 
        printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-       if (OpenPIC_Addr) {
-               /* PCI interrupts are controlled by the OpenPIC */
-               while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-                       if (dev->bus->number == 0) {
-                                       dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-                               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-                       } else {
-                               if (Motherboard_non0 != NULL)
-                                       Motherboard_non0(dev);
-                       }
+
+       /* Iterate through all the PCI devices, setting the IRQ */
+       for_each_pci_dev(dev) {
+               /*
+                * If we have residual data, then this is easy: query the
+                * residual data for the IRQ line allocated to the device.
+                * This works the same whether we have an OpenPic or not.
+                */
+               if (have_residual_data) {
+                       irq = residual_pcidev_irq(dev);
+                       dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
                }
+               /*
+                * If we don't have residual data, then we need to use
+                * tables to determine the IRQ.  The table organisation
+                * is different depending on whether there is an OpenPIC
+                * or not.  The tables are only used for bus 0, so check
+                * this first.
+                */
+               else if (dev->bus->number == 0) {
+                       irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+                       dev->irq = have_openpic ? openpic_to_irq(irq)
+                                               : Motherboard_routes[irq];
+               }
+               /*
+                * Finally, if we don't have residual data and the bus is
+                * non-zero, use the callback (if provided)
+                */
+               else {
+                       if (Motherboard_non0 != NULL)
+                               Motherboard_non0(dev);
 
-               /* Setup the Winbond or Via PIB */
-               prep_pib_init();
+                       continue;
+               }
 
-               return;
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
        }
 
-       dev = NULL;
-       while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               /*
-                * Use our old hard-coded kludge to figure out what
-                * irq this device uses.  This is necessary on things
-                * without residual data. -- Cort
-                */
-               unsigned char d = PCI_SLOT(dev->devfn);
-               dev->irq = Motherboard_routes[Motherboard_map[d]];
-       }
+       /* Setup the Winbond or Via PIB - prep_pib_init() is coded for
+        * the non-openpic case, but it breaks (at least) the Utah
+        * (Powerstack II Pro4000), so only call it if we have an
+        * openpic.
+        */
+       if (have_openpic)
+               prep_pib_init();
 }
 
 static void __init
@@ -1218,12 +1266,13 @@ prep_pcibios_after_init(void)
         * instead of 0xc0000. vgacon.c (for example) is completely unaware of
         * this little quirk.
         */
-       dev = pci_find_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
+       dev = pci_get_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
        if (dev) {
                dev->resource[1].end -= dev->resource[1].start;
                dev->resource[1].start = 0;
                /* tell the hardware */
                pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0);
+               pci_dev_put(dev);
        }
 #endif
 }
@@ -1262,14 +1311,15 @@ prep_find_bridges(void)
                           PREP_ISA_IO_BASE + 0xcfc);
 
        printk("PReP architecture\n");
-#ifdef CONFIG_PREP_RESIDUAL
-       {
+
+       if (have_residual_data) {
                PPC_DEVICE *hostbridge;
 
                hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
                        BridgeController, PCIBridge, -1, 0);
                if (hostbridge &&
-                       hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+                       ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+                        (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
                        PnP_TAG_PACKET * pkt;
                        pkt = PnP_find_large_vendor_packet(
                                res->DevicePnPHeap+hostbridge->AllocatedOffset,
@@ -1284,7 +1334,6 @@ prep_find_bridges(void)
                                setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
                }
        }
-#endif /* CONFIG_PREP_RESIDUAL */
 
        ppc_md.pcibios_fixup = prep_pcibios_fixup;
        ppc_md.pcibios_after_init = prep_pcibios_after_init;