patch-2.2.17 linux/arch/ppc/kernel/prep_pci.c
Next file: linux/arch/ppc/kernel/prep_setup.c
Previous file: linux/arch/ppc/kernel/ppc_ksyms.c
Back to the patch index
Back to the overall index
- Lines: 362
- Date:
Mon Sep 4 18:39:16 2000
- Orig file:
v2.2.16/arch/ppc/kernel/prep_pci.c
- Orig date:
Mon Sep 4 18:37:47 2000
diff -u --recursive --new-file v2.2.16/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
@@ -8,6 +8,7 @@
*/
#include <linux/types.h>
+#include <linux/string.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -36,7 +37,7 @@
unsigned char *Motherboard_routes;
void (*Motherboard_non0)(struct pci_dev *);
-void Mesquite_Map_Non0(struct pci_dev *);
+void Powerplus_Map_Non0(struct pci_dev *);
/* Used for Motorola to store system config register */
static unsigned long *ProcInfo;
@@ -508,6 +509,51 @@
13 /* Line 4 */
};
+/* Motorola PowerPlus architecture PCI IRQ tables */
+/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
+
+struct powerplus_irq_list
+{
+ unsigned char primary[4]; /* INT A-D */
+ unsigned char secondary[4]; /* INT A-D */
+};
+
+/*
+ * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
+ * OpenPIC inputs 9-12. PCI INTs A-D from the on board P2P bridge
+ * 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 =
+{
+ {25, 26, 27, 28},
+ {21, 22, 23, 24}
+};
+
+/*
+ * For the MCP750 (system slot board), bus 0 PCI INTs A-D are routed
+ * to OpenPIC inputs 8-11. PCI INTs A-D from the on board P2P bridge
+ * 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 =
+{
+ {24, 25, 26, 27},
+ {28, 29, 30, 31}
+};
+
+/*
+ * This table represents the standard PCI swizzle defined in the
+ * PCI bus specification.
+ */
+static unsigned char prep_pci_intpins[4][4] =
+{
+ { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */
+ { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */
+ { 3, 4, 1, 2}, /* Buses 2, 6, 10 ... */
+ { 4, 1, 2, 3}, /* Buses 3, 7, 11 ... */
+};
+
/* We have to turn on LEVEL mode for changed IRQ's */
/* All PCI IRQ's need to be level mode, so this should be something
* other than hard-coded as well... IRQ's are individually mappable
@@ -685,8 +731,7 @@
#define MOT_RAVEN_PRESENT 0x1
#define MOT_HAWK_PRESENT 0x2
-/* Keyboard present flag */
-int prep_kbd_present = 1; /* Keyboard present by default */
+int mot_entry = -1;
int MotMPIC = 0;
int mot_multi = 0;
@@ -751,13 +796,17 @@
mot_multi = 1;
}
- /* This is a hack. If this is a 2300 or 2400 mot board then there is
- * no keyboard controller and we have to indicate that.
+ /*
+ * If a Motorola MVME2300, 2400, or MCPN750 board is detected
+ * disable keyboard controller initialization to avoid system
+ * hangs.
*/
base_mod = inb(MOTOROLA_BASETYPE_REG);
if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
- (base_mod == 0xFA) || (base_mod == 0xE1))
- prep_kbd_present = 0;
+ (base_mod == 0xFA) || (base_mod == 0xE1)) {
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+ }
return 1;
}
@@ -771,33 +820,35 @@
unsigned char *map;
unsigned char *routes;
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[] = {
- {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, NULL},
- {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL},
- {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes, NULL},
- {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes, NULL},
- {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes, NULL},
- {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes, NULL},
- {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Mesquite_Map_Non0},
- {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL},
- {0x000, 0x00, 0x00, "", NULL, NULL, NULL}
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {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},
+ {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0x00},
+ {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
+ {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+ {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+ {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x000, 0x00, 0x00, "", NULL, NULL, NULL, 0x00}
};
__initfunc(unsigned long prep_route_pci_interrupts(void))
@@ -812,7 +863,6 @@
unsigned char cpu_type;
unsigned char base_mod;
int entry;
- int mot_entry = -1;
cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
base_mod = inb(MOTOROLA_BASETYPE_REG);
@@ -989,91 +1039,91 @@
return 0;
}
-static unsigned int pci_localpirqs[4] =
-{
- 24,
- 25,
- 26,
- 27
-};
-
-static unsigned int pci_remotepirqs[4] =
-{
- 28,
- 29,
- 30,
- 31
-};
-
-static unsigned int pci_remotedev = 0xc0;
-
+/*
+ * Remove a device from the kernel PCI device list based on its
+ * devfn identifier.
+ */
+__initfunc(
void
-Mesquite_Map_Non0(struct pci_dev *pdev)
+prep_exclude_pci_device(unsigned char devfn)
+)
{
- struct pci_bus *pbus; /* Parent Bus Structure Pointer */
- unsigned int devnum; /* Accumulated Device Number */
- unsigned int irq; /* IRQ Value */
-
- /*
- ** Device Interrupt Line register initialization.
- ** The IRQ line number will be generated after
- ** taking into account all the PCI-2-PCI bridge
- ** devices between the device and the Host Bridge.
- */
- devnum = PCI_SLOT(pdev->devfn);
- pbus = pdev->bus;
+ struct pci_dev *dev, *pdev = NULL;
- while ((pbus->parent)->primary != (pbus->parent)->secondary)
- {
- devnum += PCI_SLOT((pbus->self)->devfn);
+ /* Walk the pci device list */
+ for(dev=pci_devices; dev; dev=dev->next) {
+ if (dev->devfn == devfn)
+ {
+ /*
+ * If we find a matching device, adjust
+ * the list to remove the device.
+ */
+ if (pdev != NULL)
+ pdev->next = dev->next;
+ else
+ pci_devices = dev->next;
- pbus = pbus->parent;
+ break;
+ }
+ pdev = dev;
}
+}
- devnum &= 0x03;
-
- /*
- ** By default, get the PCI local domain IRQ value.
- */
- irq = pci_localpirqs[devnum];
-
- /*
- ** Determine if the device is located in the
- ** remote domain or not. We must find the
- ** domain's bridge device located on bus 0.
- */
- pbus = pdev->bus;
+void
+Powerplus_Map_Non0(struct pci_dev *dev)
+{
+ struct pci_bus *pbus; /* Parent bus structure pointer */
+ struct pci_dev *tdev; /* Temporary device structure */
+ unsigned int devnum; /* Accumulated device number */
+ unsigned char intline; /* Linux interrupt value */
+ unsigned char intpin; /* PCI interrupt pin */
+
+ /* Check for valid PCI dev pointer */
+ if (dev == NULL) return;
+
+ /* Fill our temporary device, and get the device number */
+ *tdev = *dev;
+ devnum = PCI_SLOT(tdev->devfn);
+
+ /* Read the interrupt pin of the device and adjust for indexing */
+ pcibios_read_config_byte(tdev->bus->number, tdev->devfn,
+ PCI_INTERRUPT_PIN, &intpin);
- while (pbus->primary != 0)
- pbus = pbus->parent;
+ /* If device doesn't request an interrupt, return */
+ if ( (intpin < 1) || (intpin > 4) )
+ return;
- /*
- ** Check the device/function of domain's bridge
- ** device against the remote device/function.
- ** If the same, then the device is located in
- ** the remote domain. Thus, get the PCI remote
- ** domain IRQ value.
- */
- if ((pbus->self)->devfn == pci_remotedev)
- irq = pci_remotepirqs[devnum];
+ intpin--;
- /*
- ** Validate the IRQ number.
- */
- if (irq <= 255)
+ /* Walk up to bus 0, adjusting the interrupt pin for the standard
+ PCI bus swizzle. */
+ do {
+ intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+ pbus = tdev->bus; /* up one level */
+ tdev = pbus->self;
+ devnum = PCI_SLOT(tdev->devfn);
+ } while(tdev->bus->number);
+
+ /* Use the primary interrupt inputs by default */
+ intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+
+ /* If the board has secondary interrupt inputs, walk the bus and
+ note the devfn of the bridge from bus 0. If it is the same as
+ the devfn of the bus bridge with secondary inputs, use those. */
+ if (mot_info[mot_entry].secondary_bridge_devfn)
{
- /*
- ** Set the device's Interrupt Line register
- ** to the IRQ number and save it in the
- ** device's structure.
- */
-
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, (u8)irq);
-
- pdev->irq = irq;
-
+ pbus = dev->bus;
+
+ while (pbus->primary != 0)
+ pbus = pbus->parent;
+
+ if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
+ intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
}
- return;
+
+ /* Write calculated interrupt value to header and device list */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)intline);
+ dev->irq = intline;
}
int motopenpic_to_irq(int n)
@@ -1137,6 +1187,15 @@
prep_route_pci_interrupts();
+ /*
+ * If MTX+, exclude the SL82C105 IDE controller so the driver
+ * doesn't hang.
+ */
+ if ( _prep_type == _PREP_Motorola )
+ if ( strstr(mot_info[mot_entry].name, "MTX Plus") )
+ /* On MTX+, SL82C105 is at IDSEL 0xb function 0x1 */
+ prep_exclude_pci_device(PCI_DEVFN(0xb, 0x1));
+
prep_pib_init();
printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
@@ -1150,7 +1209,7 @@
motopenpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, dev->irq);
+ PCI_INTERRUPT_LINE, dev->irq);
} else {
if (Motherboard_non0 != NULL)
Motherboard_non0(dev);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)