patch-1.3.84 linux/arch/alpha/kernel/bios32.c
Next file: linux/drivers/char/pcxx.c
Previous file: linux/arch/alpha/defconfig
Back to the patch index
Back to the overall index
- Lines: 173
- Date:
Thu Apr 4 09:17:19 1996
- Orig file:
v1.3.83/linux/arch/alpha/kernel/bios32.c
- Orig date:
Sun Mar 31 00:13:16 1996
diff -u --recursive --new-file v1.3.83/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
@@ -81,7 +81,11 @@
#if PCI_MODIFY
+#if 0
static unsigned int io_base = 64*KB; /* <64KB are (E)ISA ports */
+#else
+static unsigned int io_base = 0xb000;
+#endif
#if defined(CONFIG_ALPHA_XL)
/*
@@ -318,15 +322,18 @@
if (bus->self) {
struct pci_dev *bridge = bus->self;
/*
- * Set up the top and bottom of the I/O memory segment
+ * Set up the top and bottom of the PCI I/O segment
* for this bus.
*/
pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
0x1c, &l);
- l = l | (bio >> 8) | ((tio - 1) & 0xf000);
+ l = (l & 0xffff0000) | (bio >> 8) | ((tio - 1) & 0xf000);
pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
0x1c, l);
-
+ /*
+ * Set up the top and bottom of the PCI Memory segment
+ * for this bus.
+ */
l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
0x20, l);
@@ -445,6 +452,47 @@
outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
}
+/*
+ * A small note about bridges and interrupts. The DECchip 21050 (and later chips)
+ * adheres to the PCI-PCI bridge specification. This says that the interrupts on
+ * the other side of a bridge are swizzled in the following manner:
+ *
+ * Dev Interrupt Interupt
+ * Pin on Pin on
+ * Device Connector
+ *
+ * 4 A A
+ * B B
+ * C C
+ * D D
+ *
+ * 5 A B
+ * B C
+ * C D
+ * D A
+ *
+ * 6 A C
+ * B D
+ * C A
+ * D B
+ *
+ * 7 A D
+ * B A
+ * C B
+ * D C
+ *
+ * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
+ * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
+ *
+ * The following code is somewhat simplistic as it assumes only one bridge.
+ * I will fix it later (david.rusling@reo.mts.dec.com).
+ */
+static inline unsigned char bridge_swizzle(unsigned char pin, unsigned int slot)
+{
+ /* swizzle */
+ return (((pin-1) + slot) % 4) + 1 ;
+}
+
/*
* Most evaluation boards share most of the fixup code, which is isolated here.
* This function is declared "inline" as only one platform will ever be selected
@@ -457,40 +505,64 @@
{
struct pci_dev *dev;
unsigned char pin;
+ unsigned char slot ;
/*
* Go through all devices, fixing up irqs as we see fit:
*/
for (dev = pci_devices; dev; dev = dev->next) {
- dev->irq = 0;
- /*
- * Ignore things not on the primary bus - I'll figure
- * this out one day - Dave Rusling
- */
- if (dev->bus->number != 0)
- continue;
-
- /* read the pin */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
- if (irq_tab[PCI_SLOT(dev->devfn) - min_idsel][pin] != -1)
- dev->irq = irq_tab[PCI_SLOT(dev->devfn) - min_idsel][pin];
+ if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) {
+ dev->irq = 0;
+ /*
+ * This device is not on the primary bus, we need to figure out which
+ * interrupt pin it will come in on. We know which slot it will come
+ * in on 'cos that slot is where the bridge is. Each time the interrupt
+ * line passes through a PCI-PCI bridge we must apply the swizzle function
+ * (see the inline static routine above).
+ */
+ if (dev->bus->number != 0) {
+ struct pci_dev *curr = dev ;
+ /* read the pin and do the PCI-PCI bridge interrupt pin swizzle */
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ /* cope with 0 */
+ if (pin == 0) pin = 1 ;
+ /* follow the chain of bridges, swizzling as we go */
+ do {
+ /* swizzle */
+ pin = bridge_swizzle(pin, PCI_SLOT(curr->devfn)) ;
+ /* move up the chain of bridges */
+ curr = curr->bus->self ;
+ } while (curr->bus->self) ;
+ /* The slot is the slot of the last bridge. */
+ slot = PCI_SLOT(curr->devfn) ;
+ } else {
+ /* work out the slot */
+ slot = PCI_SLOT(dev->devfn) ;
+ /* read the pin */
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ }
+ if (irq_tab[slot - min_idsel][pin] != -1)
+ dev->irq = irq_tab[slot - min_idsel][pin];
#if PCI_MODIFY
- /* tell the device: */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
+ /* tell the device: */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
#endif
- /*
- * if its a VGA, enable its BIOS ROM at C0000
- */
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- pcibios_write_config_dword(dev->bus->number, dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+ /*
+ * if its a VGA, enable its BIOS ROM at C0000
+ */
+ if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+ pcibios_write_config_dword(dev->bus->number, dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+ }
+ }
+
+ if (ide_base) {
+ enable_ide(ide_base);
}
- }
- if (ide_base) {
- enable_ide(ide_base);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this