patch-2.1.116 linux/arch/alpha/kernel/bios32.c
Next file: linux/arch/alpha/kernel/bios32.h
Previous file: linux/arch/alpha/kernel/apecs.c
Back to the patch index
Back to the overall index
- Lines: 2380
- Date:
Sun Aug 9 12:09:05 1998
- Orig file:
v2.1.115/linux/arch/alpha/kernel/bios32.c
- Orig date:
Tue Jul 21 00:15:29 1998
diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
@@ -31,9 +31,15 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <asm/pci.h>
#include <asm/dma.h>
-#if 0
+#include "proto.h"
+#include "bios32.h"
+
+#define DEBUG_DEVS 0
+
+#if DEBUG_DEVS
# define DBG_DEVS(args) printk args
#else
# define DBG_DEVS(args)
@@ -43,161 +49,288 @@
asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
+void reset_for_srm(void) { }
#else /* CONFIG_PCI */
#include <linux/malloc.h>
#include <linux/mm.h>
-#include <asm/hwrpb.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/system.h>
-
-#define KB 1024
-#define MB (1024*KB)
-#define GB (1024*MB)
+/*
+ * PCI public interfaces.
+ */
#define MAJOR_REV 0
+#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */
-/* minor revision 4, add multi-PCI handling */
-#define MINOR_REV 4
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+int
+pcibios_present(void)
+{
+ return alpha_mv.pci_read_config_byte != NULL;
+}
+void __init
+pcibios_init(void)
+{
+ printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+ if (alpha_use_srm_setup)
+ printk(" NOT modifying existing (SRM) PCI configuration\n");
-/*
- * On multiple PCI bus machines, create a handle from the bus number.
- */
-#if defined(CONFIG_ALPHA_MCPCIA) /* || defined(CONFIG_ALPHA_TSUNAMI) */
-extern struct linux_hose_info *bus2hose[256];
-#define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32)
-#define DEV_IS_ON_PRIMARY(dev) \
- (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
-#else
-#define HANDLE(b) (0)
-#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0)
-#endif
+ /* FIXME: Scan for multiple PCI busses here. */
+}
-/*
- * PCI_MODIFY
- *
- * Temporary internal macro. If this 0, then do not write to any of
- * the PCI registers, merely read them (i.e., use configuration as
- * determined by SRM). The SRM seem do be doing a less than perfect
- * job in configuring PCI devices, so for now we do it ourselves.
- * Reconfiguring PCI devices breaks console (RPB) callbacks, but
- * those don't work properly with 64 bit addresses anyways.
- *
- * The accepted convention seems to be that the console (POST
- * software) should fully configure boot devices and configure the
- * interrupt routing of *all* devices. In particular, the base
- * addresses of non-boot devices need not be initialized. For
- * example, on the AXPpci33 board, the base address a #9 GXE PCI
- * graphics card reads as zero (this may, however, be due to a bug in
- * the graphics card---there have been some rumor that the #9 BIOS
- * incorrectly resets that address to 0...).
- */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-#define PCI_MODIFY 0
-static struct pci_dev *irq_dev_to_reset[16];
-static unsigned char irq_to_reset[16];
-static int irq_reset_count = 0;
-static struct pci_dev *io_dev_to_reset[16];
-static unsigned char io_reg_to_reset[16];
-static unsigned int io_to_reset[16];
-static int io_reset_count = 0;
-#else /* SRM_SETUP */
-#define PCI_MODIFY 1
-#endif /* SRM_SETUP */
-
-extern struct hwrpb_struct *hwrpb;
-
-/* Forward declarations for some extra fixup routines for specific hardware. */
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-extern int SMC93x_Init(void);
-#endif
-extern int SMC669_Init(void);
-#ifdef CONFIG_ALPHA_MIATA
-static int es1888_init(void);
-#endif
+char * __init
+pcibios_setup(char *str)
+{
+ return str;
+}
+
+void __init
+pcibios_fixup(void)
+{
+ alpha_mv.pci_fixup();
+}
-#if PCI_MODIFY
+void __init
+pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
-/*
- * NOTE: we can't just blindly use 64K for machines with EISA busses; they
- * may also have PCI-PCI bridges present, and then we'd configure the bridge
- * incorrectly.
- *
- * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
- * IO space areas allocated *before* 0xC000; this is because certain
- * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
- * accesses to probe the bus. If a device's registers appear at 0xC000,
- * it may see an INx/OUTx at that address during BIOS emulation of the
- * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
- *
- * Note that we may need this stuff for SRM_SETUP also, since certain
- * SRM consoles screw up and allocate I/O space addresses > 64K behind
- * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, AFAIK.
- */
-#if defined(CONFIG_ALPHA_EISA)
-#define DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
-#else
-#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
-#endif
-static unsigned int io_base;
+int
+pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_byte)
+ r = alpha_mv.pci_read_config_byte(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_word)
+ r = alpha_mv.pci_read_config_word(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_dword)
+ r = alpha_mv.pci_read_config_dword(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_byte)
+ r = alpha_mv.pci_write_config_byte(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_word)
+ r = alpha_mv.pci_write_config_word(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_dword)
+ r = alpha_mv.pci_write_config_dword(bus, dev, where, value);
+ return r;
+}
+
+asmlinkage int
+sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ubyte = 0xff;
+ put_user(ubyte, buf);
+ break;
+ case 2:
+ err = pcibios_read_config_word(bus, dfn, off, &ushort);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ushort = 0xffff;
+ put_user(ushort, (unsigned short *)buf);
+ break;
+ case 4:
+ err = pcibios_read_config_dword(bus, dfn, off, &uint);
+ if (err != PCIBIOS_SUCCESSFUL)
+ uint = 0xffffffff;
+ put_user(uint, (unsigned int *)buf);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
+
+asmlinkage int
+sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = get_user(ubyte, buf);
+ if (err)
+ break;
+ err = pcibios_write_config_byte(bus, dfn, off, ubyte);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 2:
+ err = get_user(ushort, (unsigned short *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_word(bus, dfn, off, ushort);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 4:
+ err = get_user(uint, (unsigned int *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_dword(bus, dfn, off, uint);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
-#if defined(CONFIG_ALPHA_XL)
-/*
- * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
- * that get passed through the PCI<->ISA bridge chip. Although this causes
- * us to set the PCI->Mem window bases lower than normal, we still allocate
- * PCI bus devices' memory addresses *below* the low DMA mapping window,
- * and hope they fit below 64Mb (to avoid conflicts), and so that they can
- * be accessed via SPARSE space.
- *
- * We accept the risk that a broken Myrinet card will be put into a true XL
- * and thus can more easily run into the problem described below.
- */
-#define DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
-#elif defined(CONFIG_ALPHA_LCA) || defined(CONFIG_ALPHA_APECS)
/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * However, APECS and LCA have only 34 bits for physical addresses, thus
- * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ * Gory details start here...
*/
-#define DEFAULT_MEM_BASE (64*MB + 2*MB)
-#else
+struct linux_hose_info *bus2hose[256];
+
/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * Because CIA and PYXIS and T2 have more bits for physical addresses,
- * they support an expanded range of SPARSE memory addresses.
+ * Align VAL to ALIGN, which must be a power of two.
*/
-#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+
+
+/*
+ * The following structure records initial configuration of devices
+ * so that we can reset them on shutdown and so enable clean reboots
+ * on SRM. It is more trouble than it iw worth to conditionalize this.
+ */
+
+static struct {
+ struct reset_irq {
+ struct pci_dev *dev;
+ u8 irq;
+ } irq[16];
+ int irq_count;
+
+ struct reset_io {
+ struct pci_dev *dev;
+ u8 reg;
+ u32 io;
+ } io[16];
+ int io_count;
+} srm_resets;
+
+/* Apply the collected reset modifications. */
+
+void
+reset_for_srm(void)
+{
+ struct pci_dev *dev;
+ int i;
+ /* Reset any IRQs that we changed. */
+ for (i = 0; i < srm_resets.irq_count; i++) {
+ dev = srm_resets.irq[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE,
+ srm_resets.irq[i].irq);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IRQ 0x%x changed back from 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.irq[i].irq, dev->irq);
#endif
-static unsigned int mem_base;
+ }
+
+ /* Reset any IO addresses that we changed. */
+ for (i = 0; i < srm_resets.io_count; i++) {
+ dev = srm_resets.io[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ srm_resets.io[i].reg,
+ srm_resets.io[i].io);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IO restored to 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.io[i].io);
+#endif
+ }
+}
+
/*
* Disable PCI device DEV so that it does not respond to I/O or memory
* accesses.
*/
-static void disable_dev(struct pci_dev *dev)
+static void __init
+disable_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -208,12 +341,20 @@
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("disable_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("disable_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
* console code to do the right thing, and ignore it here... :-\
*/
@@ -223,6 +364,19 @@
return;
}
+#if DEBUG_DEVS && 0
+ /* Worse HACK: Don't disable the video card, so I can see where
+ it is *really* falling over. */
+ if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
+ DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n",
+ dev->vendor, dev->device));
+ return;
+ }
+#endif
+
+ DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
+ dev->vendor, dev->device));
+
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
@@ -237,7 +391,11 @@
*/
#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-static void layout_dev(struct pci_dev *dev)
+static unsigned int io_base;
+static unsigned int mem_base;
+
+static void __init
+layout_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -251,12 +409,20 @@
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("layout_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("layout_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
* console code to do the right thing, and ignore it here... :-\
*/
@@ -315,7 +481,7 @@
pcibios_write_config_dword(bus->number, dev->devfn,
off, base | 0x1);
- handle = HANDLE(bus->number) | base | 1;
+ handle = PCI_HANDLE(bus->number) | base | 1;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
@@ -400,7 +566,7 @@
mem_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
off, base);
- handle = HANDLE(bus->number) | base;
+ handle = PCI_HANDLE(bus->number) | base;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
dev->device, handle, size));
@@ -431,8 +597,8 @@
dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
}
-
-static int layout_bus(struct pci_bus *bus)
+static int __init
+layout_bus(struct pci_bus *bus)
{
unsigned int l, tio, bio, tmem, bmem;
struct pci_bus *child;
@@ -543,24 +709,44 @@
return found_vga;
}
-#endif /* !PCI_MODIFY */
-
-
-int pcibios_present(void)
+void __init
+layout_all_busses(unsigned long default_io_base,
+ unsigned long default_mem_base)
{
- return 1;
-}
+ struct pci_bus *cur;
+#if defined(CONFIG_ALPHA_GENERIC)
+ static struct linux_hose_info dummy_hose;
+ int i;
-void __init
-pcibios_init(void)
-{
- printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
-#if !PCI_MODIFY
- printk("...NOT modifying existing (SRM) PCI configuration\n");
+ /*
+ * HACK: Emulate a multi-bus machine to a limited extent
+ * by initializing bus2hose to point to something that
+ * has pci_hose_index & pci_first_busno zero.
+ */
+ for (i = 0; i <= 0xff; i++)
+ bus2hose[i] = &dummy_hose;
#endif
+
+ /*
+ * Scan the tree, allocating PCI memory and I/O space.
+ */
+ /*
+ * Sigh; check_region() will need changing to accept a PCI_HANDLE,
+ * if we allocate I/O space addresses on a per-bus basis.
+ * For now, make the I/O bases unique across all busses, so
+ * that check_region() will not get confused... ;-}
+ */
+ io_base = default_io_base;
+ for (cur = &pci_root; cur; cur = cur->next) {
+ mem_base = default_mem_base;
+ DBG_DEVS(("layout_all_busses: calling layout_bus()\n"));
+ layout_bus(cur);
+ }
+ DBG_DEVS(("layout_all_busses: done.\n"));
}
+
/*
* The SRM console *disables* the IDE interface, this code ensures it's
* enabled.
@@ -575,7 +761,9 @@
* written twice (I believe this is a safety feature to prevent
* accidental modification---fun, isn't it?).
*/
-static inline void enable_ide(long ide_base)
+
+void __init
+enable_ide(long ide_base)
{
int data;
@@ -586,68 +774,29 @@
outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
}
-/*
- * A small note about bridges and interrupts. The DECchip 21050 (and later)
- * 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 Interrupt
- * 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;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* look for mis-configured devices' I/O space addresses behind bridges */
-static void check_behind_io(struct pci_dev *dev)
+/* Look for mis-configured devices' I/O space addresses behind bridges. */
+static void
+check_behind_io(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
unsigned int reg, orig_base, new_base, found_one = 0;
+ struct reset_io *ior;
for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
- /* read the current setting, check for I/O space and >= 64K */
- pcibios_read_config_dword(bus->number, dev->devfn, reg, &orig_base);
+ /* Read the current setting, check for I/O space and >= 64K */
+ pcibios_read_config_dword(bus->number, dev->devfn,
+ reg, &orig_base);
+
if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO))
continue; /* unused or non-IO */
+
if (orig_base < 64*1024) {
#if 1
printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n",
bus->number, PCI_SLOT(dev->devfn), orig_base);
#endif
if (orig_base & ~1)
- continue; /* OK! */
+ continue; /* OK! */
orig_base = 0x12001; /* HACK! FIXME!! */
}
@@ -662,1160 +811,148 @@
pcibios_write_config_dword(bus->number, dev->devfn,
reg, new_base);
- io_dev_to_reset[io_reset_count] = dev;
- io_reg_to_reset[io_reset_count] = reg;
- io_to_reset[io_reset_count] = orig_base;
- io_reset_count++;
+ ior = &srm_resets.io[srm_resets.io_count++];
+ ior->dev = dev;
+ ior->reg = reg;
+ ior->io = orig_base;
found_one++;
- } /* end for-loop */
+ }
- /* if any were modified, gotta hack the bridge IO limits too... */
+ /* If any were modified, gotta hack the bridge IO limits too. */
if (found_one) {
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
- unsigned int l;
- /*
- * 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);
+ if (bus->self) {
+ struct pci_dev *bridge = bus->self;
+ unsigned int l;
+ /*
+ * 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);
#if 1
printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n",
bus->number, PCI_SLOT(bridge->devfn), l);
#endif
- l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, l);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x3c, 0x00040000);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x4, 0xffff0007);
- } else
- printk("check_behind_io: WARNING! bus->self NULL\n");
+ l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn, 0x1c, l);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x3c, 0x00040000);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x4, 0xffff0007);
+ } else
+ printk("check_behind_io: WARNING! bus->self NULL\n");
}
}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
+
/*
- * 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 in any given kernel. If that platform doesn't need this code,
- * we don't want it around as dead code.
+ * Most boards share most of the fixup code, which is isolated here.
*/
-static inline void
-common_fixup(long min_idsel, long max_idsel, long irqs_per_slot,
- char irq_tab[max_idsel - min_idsel + 1][irqs_per_slot],
- long ide_base)
-{
- struct pci_dev *dev, *curr;
- unsigned char pin;
- unsigned char slot;
+
+void __init
+common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
+ int (*swizzle)(struct pci_dev *dev, int *pin))
+{
+ struct pci_dev *dev;
+ u8 pin, slot, irq_orig;
+ int irq;
/*
- * Go through all devices, fixing up irqs as we see fit:
+ * Go through all devices, fixing up irqs as we see fit.
*/
for (dev = pci_devices; dev; dev = dev->next) {
- if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE ||
- dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA) {
- /*
- * HACK: the PCI-to-EISA bridge appears not to identify
- * itself as a bridge... :-(
- */
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82375) {
- DBG_DEVS(("common_fixup: ignoring PCEB...\n"));
- continue;
- }
+ if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
+ (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
+ continue;
- /*
- * 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).
- */
- dev->irq = 0;
- if (!DEV_IS_ON_PRIMARY(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 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- /* follow the chain of bridges, swizzling
- as we go */
- curr = dev;
-#if defined(CONFIG_ALPHA_MIATA)
- /* check first for the built-in bridge */
- if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
- (PCI_SLOT(dev->bus->self->devfn) == 20)) {
- slot = PCI_SLOT(dev->devfn) + 5;
- DBG_DEVS(("MIATA: bus 1 slot %d pin %d"
- " irq %d min_idsel %d\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if ((PCI_SLOT(curr->bus->self->devfn) == 8) ||
- (PCI_SLOT(curr->bus->self->devfn) == 20))
- {
- slot = PCI_SLOT(curr->devfn) + 5;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#elif defined(CONFIG_ALPHA_NORITAKE)
- /* check first for the built-in bridge */
- if (PCI_SLOT(dev->bus->self->devfn) == 8) {
- slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
- DBG_DEVS(("NORITAKE: bus 1 slot %d pin %d"
- "irq %d min_idsel %ld\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if (PCI_SLOT(curr->bus->self->devfn) == 8) {
- slot = PCI_SLOT(curr->devfn) + 15;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#else /* everyone but MIATA and NORITAKE */
- DBG_DEVS(("common_fixup: bus %d slot %d pin %d "
- "irq %d min_idsel %ld\n",
- curr->bus->number,
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- 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);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * must make sure that SRM didn't screw up
- * and allocate an address > 64K for I/O
- * space behind a PCI-PCI bridge
- */
- check_behind_io(dev);
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- } else { /* just a device on a primary bus */
- /* 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);
- DBG_DEVS(("common_fixup: bus %d slot %d"
- " pin %d irq %d min_idsel %ld\n",
- dev->bus->number, slot, pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- /* cope with 0 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- }
- if (irq_tab[slot - min_idsel][pin] != -1)
- dev->irq = irq_tab[slot - min_idsel][pin];
-#ifdef CONFIG_ALPHA_RAWHIDE
- dev->irq +=
- 24 * bus2hose[dev->bus->number]->pci_hose_index;
-#endif /* RAWHIDE */
-#ifdef CONFIG_ALPHA_SRM
- {
- unsigned char irq_orig;
- /* read the original SRM-set IRQ and tell */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_LINE,
- &irq_orig);
- if (irq_orig != dev->irq) {
- DBG_DEVS(("common_fixup: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed to 0x%x\n",
- dev->bus->number,PCI_SLOT(dev->devfn),
- irq_orig, dev->irq));
-#ifdef CONFIG_ALPHA_SRM_SETUP
- irq_dev_to_reset[irq_reset_count] = dev;
- irq_to_reset[irq_reset_count] = irq_orig;
- irq_reset_count++;
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- }
- }
-#endif /* SRM */
+ /*
+ * 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).
+ */
+ dev->irq = 0;
- /* always tell the device, so the driver knows what is
- * the real IRQ to use; the device does not use it.
- */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ /* Cope with 0 and illegal. */
+ if (pin == 0 || pin > 4)
+ pin = 1;
+
+ if (!DEV_IS_ON_PRIMARY(dev)) {
+ /* Follow the chain of bridges, swizzling as we go. */
+
+ int spill = pin;
+ slot = (*swizzle)(dev, &spill);
+ pin = spill;
+
+ /* Must make sure that SRM didn't screw up
+ and allocate an address > 64K for I/O
+ space behind a PCI-PCI bridge. */
+ if (alpha_use_srm_setup)
+ check_behind_io(dev);
+ } else {
+ /* Just a device on a primary bus. */
+ slot = PCI_SLOT(dev->devfn);
+ }
- DBG_DEVS(("common_fixup: bus %d slot 0x%x"
- " VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x"
- " pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- dev->vendor, dev->device,
- slot, pin, dev->irq));
+ irq = (*map_irq)(dev, slot, pin);
- /*
- * if it's a VGA, enable its BIOS ROM at C0000
- */
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
- if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
- (dev->device >= 0x00a0) &&
- (dev->device <= 0x00ac)) {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x00000000);
- } else {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- /*
- * if it's a SCSI, disable its BIOS ROM
- */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
- pcibios_write_config_dword(dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x0000000);
+ DBG_DEVS(("common_pci_fixup: bus %d slot %d "
+ "pin %d irq %d\n",
+ dev->bus->number, slot, pin, irq));
+
+ if (irq != -1)
+ dev->irq = irq;
+
+ if (alpha_using_srm) {
+ /* Read the original SRM-set IRQ and tell. */
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_LINE,
+ &irq_orig);
+
+ if (irq_orig != dev->irq) {
+ struct reset_irq *r;
+
+ DBG_DEVS(("common_pci_fixup: bus %d "
+ "slot 0x%x SRM IRQ 0x%x "
+ "changed to 0x%x\n",
+ dev->bus->number,
+ PCI_SLOT(dev->devfn),
+ irq_orig, dev->irq));
+
+ r = &srm_resets.irq[srm_resets.irq_count++];
+ r->dev = dev;
+ r->irq = irq_orig;
}
}
- }
- if (ide_base) {
- enable_ide(ide_base);
- }
-}
-
-/*
- * The EB66+ is very similar to the EB66 except that it does not have
- * the on-board NCR and Tulip chips. In the code below, I have used
- * slot number to refer to the id select line and *not* the slot
- * number used in the EB66+ documentation. However, in the table,
- * I've given the slot number, the id select line and the Jxx number
- * that's printed on the board. The interrupt pins from the PCI slots
- * are wired into 3 interrupt summary registers at 0x804, 0x805 and
- * 0x806 ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void eb66p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
- {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
- {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
- };
- common_fixup(6, 10, 5, irq_tab, 0x398);
-}
+ /* Always tell the device, so the driver knows what is
+ the real IRQ to use; the device does not use it. */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
-/*
- * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
- * PCI slots, the SIO, PCI/IDE, and USB.
- *
- * Each of the interrupts can be individually masked. This is
- * accomplished by setting the appropriate bit in the mask register.
- * A bit is set by writing a "1" to the desired position in the mask
- * register and cleared by writing a "0". There are 3 mask registers
- * located at ISA address 804h, 805h and 806h.
- *
- * An I/O read at ISA address 804h, 805h, 806h will return the
- * state of the 11 PCI interrupts and not the state of the MASKED
- * interrupts.
- *
- * Note: A write to I/O 804h, 805h, and 806h the mask register will be
- * updated.
- *
- *
- * ISA DATA<7:0>
- * ISA +--------------------------------------------------------------+
- * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- * +==============================================================+
- * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
- * +--------------------------------------------------------------+
- * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
- * +--------------------------------------------------------------+
- * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
- * +--------------------------------------------------------------+
- * * Rsrv = reserved bits
- * Note: The mask register is write-only.
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Saturn I/O
- * 9 32 bit PCI option slot 3
- * 10 USB
- * 11 IDE
- *
- */
-
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-static inline void alphapc164_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
- { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
- { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
- { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
- { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
- };
-
- common_fixup(5, 11, 5, irq_tab, 0);
- SMC93x_Init();
-}
-#endif
-
-/*
- * The AlphaPC64 is very similar to the EB66+ except that its slots
- * are numbered differently. In the code below, I have used slot
- * number to refer to the id select line and *not* the slot number
- * used in the AlphaPC64 documentation. However, in the table, I've
- * given the slot number, the id select line and the Jxx number that's
- * printed on the board. The interrupt pins from the PCI slots are
- * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
- * ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void cabriolet_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
- { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
- { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
- };
-
- common_fixup(5, 9, 5, irq_tab, 0x398);
-}
-
-
-/*
- * Fixup configuration for EB66/EB64+ boards.
- *
- * Both these boards use the same interrupt summary scheme. There are
- * two 8 bit external summary registers as follows:
- *
- * Summary @ 0x26:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line A from slot 1
- * 2 Interrupt Line B from slot 0
- * 3 Interrupt Line B from slot 1
- * 4 Interrupt Line C from slot 0
- * 5 Interrupt line from the two ISA PICs
- * 6 Tulip (slot
- * 7 NCR SCSI
- *
- * Summary @ 0x27
- * Bit Meaning
- * 0 Interrupt Line C from slot 1
- * 1 Interrupt Line D from slot 0
- * 2 Interrupt Line D from slot 1
- * 3 RAZ
- * 4 RAZ
- * 5 RAZ
- * 6 RAZ
- * 7 RAZ
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 5 NCR SCSI controller
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 Intel SIO PCI-ISA bridge chip
- * 9 Tulip - DECchip 21040 Ethernet controller
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void eb66_and_eb64p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
- {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
- {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
-}
-
-
-/*
- * Fixup configuration for MIKASA (AlphaServer 1000)
- *
- * Summary @ 0x536:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line B from slot 0
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 2
- * 9 Interrupt Line B from slot 2
- *10 Interrupt Line C from slot 2
- *11 Interrupt Line D from slot 2
- *12 NCR 810 SCSI
- *13 Power Supply Fail
- *14 Temperature Warn
- *15 Reserved
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 NCR SCSI controller
- * 7 Intel PCI-EISA bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void mikasa_fixup(void)
-{
- static char irq_tab[8][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
- };
- common_fixup(6, 13, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for NORITAKE (AlphaServer 1000A)
- *
- * This is also used for CORELLE (AlphaServer 800)
- * and ALCOR Primo (AlphaStation 600A).
- *
- * Summary @ 0x542, summary register #1:
- * Bit Meaning
- * 0 All valid ints from summary regs 2 & 3
- * 1 QLOGIC ISP1020A SCSI
- * 2 Interrupt Line A from slot 0
- * 3 Interrupt Line B from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line A from slot 2
- * 7 Interrupt Line B from slot 2
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line B from slot 3
- *10 Interrupt Line A from slot 4
- *11 Interrupt Line B from slot 4
- *12 Interrupt Line A from slot 5
- *13 Interrupt Line B from slot 5
- *14 Interrupt Line A from slot 6
- *15 Interrupt Line B from slot 6
- *
- * Summary @ 0x544, summary register #2:
- * Bit Meaning
- * 0 OR of all unmasked ints in SR #2
- * 1 OR of secondary bus ints
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line C from slot 1
- * 5 Interrupt line D from slot 1
- * 6 Interrupt Line C from slot 2
- * 7 Interrupt Line D from slot 2
- * 8 Interrupt Line C from slot 3
- * 9 Interrupt Line D from slot 3
- *10 Interrupt Line C from slot 4
- *11 Interrupt Line D from slot 4
- *12 Interrupt Line C from slot 5
- *13 Interrupt Line D from slot 5
- *14 Interrupt Line C from slot 6
- *15 Interrupt Line D from slot 6
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 7 Intel PCI-EISA bridge chip
- * 8 DEC PCI-PCI bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void noritake_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSELs 16, 17, and 25 are CORELLE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
- { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
- /* the following 5 are actually on PCI bus 1, which is */
- /* across the built-in bridge of the NORITAKE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
- {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
- {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
- {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
- };
- common_fixup(5, 19, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALCOR and XLT (XL-300/366/433)
- *
- * Summary @ GRU_INT_REQ:
- * Bit Meaning
- * 0 Interrupt Line A from slot 2
- * 1 Interrupt Line B from slot 2
- * 2 Interrupt Line C from slot 2
- * 3 Interrupt Line D from slot 2
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 0
- * 9 Interrupt Line B from slot 0
- *10 Interrupt Line C from slot 0
- *11 Interrupt Line D from slot 0
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line D from slot 3
- *17 Interrupt Line D from slot 3
- *18 Interrupt Line D from slot 3
- *19 Interrupt Line D from slot 3
- *20-30 Reserved
- *31 EISA interrupt
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 built-in TULIP (XLT only)
- * 7 PCI on board slot 0
- * 8 PCI on board slot 3
- * 9 PCI on board slot 4
- * 10 PCEB (PCI-EISA bridge)
- * 11 PCI on board slot 2
- * 12 PCI on board slot 1
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void alcor_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSEL 17 is XLT only */
- {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
- { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- };
- common_fixup(6, 12, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
- *
- * Summary Registers (536/53a/53c):
- * Bit Meaning
- *-----------------
- * 0 PCI slot 0
- * 1 NCR810 (builtin)
- * 2 TULIP (builtin)
- * 3 mouse
- * 4 PCI slot 1
- * 5 PCI slot 2
- * 6 keyboard
- * 7 floppy
- * 8 COM2
- * 9 parallel port
- *10 EISA irq 3
- *11 EISA irq 4
- *12 EISA irq 5
- *13 EISA irq 6
- *14 EISA irq 7
- *15 COM1
- *16 EISA irq 9
- *17 EISA irq 10
- *18 EISA irq 11
- *19 EISA irq 12
- *20 EISA irq 13
- *21 EISA irq 14
- *22 NC
- *23 IIC
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 0 TULIP
- * 1 SCSI
- * 2 PCI-EISA bridge
- * 3 none
- * 4 none
- * 5 none
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-/*
- * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
- * with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables
- * in irq.c
- */
-static inline void sable_fixup(void)
-{
- static char irq_tab[9][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
- { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
- { -1, -1, -1, -1, -1}, /* IdSel 3, none */
- { -1, -1, -1, -1, -1}, /* IdSel 4, none */
- { -1, -1, -1, -1, -1}, /* IdSel 5, none */
- { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
- { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
- { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
- };
- common_fixup(0, 8, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for MIATA (EV56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 Fan Fault
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 none
- * 4 CID0 (Riser ID)
- * 5 CID1 (Riser ID)
- * 6 Interval timer
- * 7 PCI-ISA Bridge
- * 8 Ethernet
- * 9 EIDE (deprecated, ISA 14/15 used)
- *10 none
- *11 USB
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line A from slot 5
- *17 Interrupt line B from slot 5
- *18 Interrupt Line C from slot 5
- *19 Interrupt Line D from slot 5
- *20 Interrupt Line A from slot 1
- *21 Interrupt Line B from slot 1
- *22 Interrupt Line C from slot 1
- *23 Interrupt Line D from slot 1
- *24 Interrupt Line A from slot 2
- *25 Interrupt Line B from slot 2
- *26 Interrupt Line C from slot 2
- *27 Interrupt Line D from slot 2
- *27 Interrupt Line A from slot 3
- *29 Interrupt Line B from slot 3
- *30 Interrupt Line C from slot 3
- *31 Interrupt Line D from slot 3
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 3 DC21142 Ethernet
- * 4 EIDE CMD646
- * 5 none
- * 6 USB
- * 7 PCI-ISA bridge
- * 8 PCI-PCI Bridge (SBU Riser)
- * 9 none
- * 10 none
- * 11 PCI on board slot 4 (SBU Riser)
- * 12 PCI on board slot 5 (SBU Riser)
- *
- * These are behind the bridge, so I'm not sure what to do...
- *
- * 13 PCI on board slot 1 (SBU Riser)
- * 14 PCI on board slot 2 (SBU Riser)
- * 15 PCI on board slot 3 (SBU Riser)
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-
-#ifdef CONFIG_ALPHA_MIATA
-static inline void miata_fixup(void)
-{
- static char irq_tab[18][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
- { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
- { -1, -1, -1, -1, -1}, /* IdSel 16, none */
- { -1, -1, -1, -1, -1}, /* IdSel 17, none */
-/* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
- { -1, -1, -1, -1, -1}, /* IdSel 20, none */
- { -1, -1, -1, -1, -1}, /* IdSel 21, none */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
- /* The following are actually on bus 1, which is */
- /* across the builtin PCI-PCI bridge */
- {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */
- {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */
- {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */
- { -1, -1, -1, -1, -1}, /* IdSel 27, none */
- { -1, -1, -1, -1, -1}, /* IdSel 28, none */
- { -1, -1, -1, -1, -1}, /* IdSel 29, none */
- { -1, -1, -1, -1, -1}, /* IdSel 30, none */
- { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
- };
- common_fixup(3, 20, 5, irq_tab, 0);
- SMC669_Init(); /* it might be a GL (fails harmlessly if not) */
- es1888_init();
-}
-#endif
-
-/*
- * Fixup configuration for SX164 (PCA56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 RSVD
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 MBZ
- * 4 RAZ
- * 5 RAZ
- * 6 Interval timer (RTC)
- * 7 PCI-ISA Bridge
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line A from slot 2
- *10 Interrupt Line A from slot 1
- *11 Interrupt Line A from slot 0
- *12 Interrupt Line B from slot 3
- *13 Interrupt Line B from slot 2
- *14 Interrupt Line B from slot 1
- *15 Interrupt line B from slot 0
- *16 Interrupt Line C from slot 3
- *17 Interrupt Line C from slot 2
- *18 Interrupt Line C from slot 1
- *19 Interrupt Line C from slot 0
- *20 Interrupt Line D from slot 3
- *21 Interrupt Line D from slot 2
- *22 Interrupt Line D from slot 1
- *23 Interrupt Line D from slot 0
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Cypress I/O
- * 9 32 bit PCI option slot 3
- *
- */
-
-static inline void sx164_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
- { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
- { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
- { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
- { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
-
-/*
- * Fixup configuration for DP264 (EV6+TSUNAMI)
- *
- * Summary @ TSUNAMI_CSR_DIM0:
- * Bit Meaning
- * 0-17 Unused
- *18 Interrupt SCSI B (Adaptec 7895 builtin)
- *19 Interrupt SCSI A (Adaptec 7895 builtin)
- *20 Interrupt Line D from slot 2 PCI0
- *21 Interrupt Line C from slot 2 PCI0
- *22 Interrupt Line B from slot 2 PCI0
- *23 Interrupt Line A from slot 2 PCI0
- *24 Interrupt Line D from slot 1 PCI0
- *25 Interrupt Line C from slot 1 PCI0
- *26 Interrupt Line B from slot 1 PCI0
- *27 Interrupt Line A from slot 1 PCI0
- *28 Interrupt Line D from slot 0 PCI0
- *29 Interrupt Line C from slot 0 PCI0
- *30 Interrupt Line B from slot 0 PCI0
- *31 Interrupt Line A from slot 0 PCI0
- *
- *32 Interrupt Line D from slot 3 PCI1
- *33 Interrupt Line C from slot 3 PCI1
- *34 Interrupt Line B from slot 3 PCI1
- *35 Interrupt Line A from slot 3 PCI1
- *36 Interrupt Line D from slot 2 PCI1
- *37 Interrupt Line C from slot 2 PCI1
- *38 Interrupt Line B from slot 2 PCI1
- *39 Interrupt Line A from slot 2 PCI1
- *40 Interrupt Line D from slot 1 PCI1
- *41 Interrupt Line C from slot 1 PCI1
- *42 Interrupt Line B from slot 1 PCI1
- *43 Interrupt Line A from slot 1 PCI1
- *44 Interrupt Line D from slot 0 PCI1
- *45 Interrupt Line C from slot 0 PCI1
- *46 Interrupt Line B from slot 0 PCI1
- *47 Interrupt Line A from slot 0 PCI1
- *48-52 Unused
- *53 PCI0 NMI (from Cypress)
- *54 PCI0 SMI INT (from Cypress)
- *55 PCI0 ISA Interrupt (from Cypress)
- *56-60 Unused
- *61 PCI1 Bus Error
- *62 PCI0 Bus Error
- *63 Reserved
- *
- * IdSel
- * 5 Cypress Bridge I/O
- * 6 SCSI Adaptec builtin
- * 7 64 bit PCI option slot 0
- * 8 64 bit PCI option slot 1
- * 9 64 bit PCI option slot 2
- *
- */
-
-static inline void dp264_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
- { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin */
- { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
- { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
- { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
-
-/*
- * Fixup configuration for RAWHIDE
- *
- * Summary @ MCPCIA_PCI0_INT_REQ:
- * Bit Meaning
- *0 Interrupt Line A from slot 2 PCI0
- *1 Interrupt Line B from slot 2 PCI0
- *2 Interrupt Line C from slot 2 PCI0
- *3 Interrupt Line D from slot 2 PCI0
- *4 Interrupt Line A from slot 3 PCI0
- *5 Interrupt Line B from slot 3 PCI0
- *6 Interrupt Line C from slot 3 PCI0
- *7 Interrupt Line D from slot 3 PCI0
- *8 Interrupt Line A from slot 4 PCI0
- *9 Interrupt Line B from slot 4 PCI0
- *10 Interrupt Line C from slot 4 PCI0
- *11 Interrupt Line D from slot 4 PCI0
- *12 Interrupt Line A from slot 5 PCI0
- *13 Interrupt Line B from slot 5 PCI0
- *14 Interrupt Line C from slot 5 PCI0
- *15 Interrupt Line D from slot 5 PCI0
- *16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
- *17-23 NA
- *
- * IdSel
- * 1 EISA bridge (PCI bus 0 only)
- * 2 PCI option slot 2
- * 3 PCI option slot 3
- * 4 PCI option slot 4
- * 5 PCI option slot 5
- *
- */
-
-static inline void rawhide_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 only */
- { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
- { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
- { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
- { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
- };
- common_fixup(1, 5, 5, irq_tab, 0);
-}
-
-/*
- * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
- * 19, and 18 respectively, in the default configuration. They can
- * also be jumpered to slots 8, 7, and 6 respectively, which is fun
- * because the SIO ISA bridge can also be slot 7. However, the SIO
- * doesn't explicitly generate PCI-type interrupts, so we can
- * assign it whatever the hell IRQ we like and it doesn't matter.
- */
-static inline void takara_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
- { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
- };
- common_fixup(6, 20, 5, irq_tab, 0x26e);
-}
-
-/*
- * Fixup configuration for all boards that route the PCI interrupts
- * through the SIO PCI/ISA bridge. This includes Noname (AXPpci33),
- * Avanti (AlphaStation) and Kenetics's Platform 2000.
- */
-static inline void sio_fixup(void)
-{
- struct pci_dev *dev;
- /*
- * The Noname board has 5 PCI slots with each of the 4
- * interrupt pins routed to different pins on the PCI/ISA
- * bridge (PIRQ0-PIRQ3). The table below is based on
- * information available at:
- *
- * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
- *
- * I have no information on the Avanti interrupt routing, but
- * the routing seems to be identical to the Noname except
- * that the Avanti has an additional slot whose routing I'm
- * unsure of.
- *
- * pirq_tab[0] is a fake entry to deal with old PCI boards
- * that have the interrupt pin number hardwired to 0 (meaning
- * that they use the default INTA line, if they are interrupt
- * driven at all).
- */
- static const char pirq_tab[][5] __initlocaldata = {
- /*INT A B C D */
-#ifdef CONFIG_ALPHA_P2K
- { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
- { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
- { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
-#else
- { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 2, 2, -1, -1, -1}, /* idsel 8 (Noname hack: slot closest to ISA) */
- {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
- { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
- { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
- { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
-#endif
- };
- const size_t pirq_tab_len = sizeof(pirq_tab)/sizeof(pirq_tab[0]);
-
- /*
- * route_tab selects irq routing in PCI/ISA bridge so that:
- * PIRQ0 -> irq 15
- * PIRQ1 -> irq 9
- * PIRQ2 -> irq 10
- * PIRQ3 -> irq 11
- *
- * This probably ought to be configurable via MILO. For
- * example, sound boards seem to like using IRQ 9.
- */
-
-#if defined(CONFIG_ALPHA_BOOK1)
- /* for the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15 */
- const unsigned int new_route_tab = 0x0e0f0a0a;
-
-#elif defined(CONFIG_ALPHA_NONAME)
- /*
- * For UDB, the only available PCI slot must not map to IRQ 9,
- * since that's the builtin MSS sound chip. That PCI slot
- * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
- * instead.
- *
- * Unfortunately we have to do this for NONAME as well, since
- * they are co-indicated when the platform type "Noname" is
- * selected... :-(
- */
- const unsigned int new_route_tab = 0x0b0a0f09;
-#else
- const unsigned int new_route_tab = 0x0b0a090f;
-#endif
- unsigned int route_tab, old_route_tab;
- unsigned int level_bits, old_level_bits;
- unsigned char pin, slot;
- int pirq;
-
- pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &old_route_tab);
- DBG_DEVS(("sio_fixup: old pirq route table: 0x%08x\n",
- old_route_tab));
-#if PCI_MODIFY
- route_tab = new_route_tab;
- pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
-#else
- route_tab = old_route_tab;
-#endif
-
- /*
- * Go through all devices, fixing up irqs as we see fit:
- */
- level_bits = 0;
- for (dev = pci_devices; dev; dev = dev->next) {
- if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
- (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
- continue;
-
- dev->irq = 0;
- 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 (slot < 6 || slot >= 6 + pirq_tab_len) {
- printk("bios32.sio_fixup: "
- "weird, found device %04x:%04x in"
- " non-existent slot %d!!\n",
- dev->vendor, dev->device, slot);
- continue;
- }
- pirq = pirq_tab[slot - 6][pin];
+ DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x"
+ " VID 0x%x DID 0x%x\n"
+ " int_slot 0x%x pin 0x%x"
+ " pirq 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ dev->vendor, dev->device,
+ slot, pin, dev->irq));
- DBG_DEVS(("sio_fixup: bus %d slot 0x%x VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor,
- dev->device, slot, pin, pirq));
/*
- * if it's a VGA, enable its BIOS ROM at C0000
+ * If it's a VGA, enable its BIOS ROM at C0000.
*/
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
+ /* But if its a Cirrus 543x/544x DISABLE it,
+ since enabling ROM disables the memory... */
if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
(dev->device >= 0x00a0) &&
(dev->device <= 0x00ac)) {
@@ -1827,401 +964,37 @@
} else {
pcibios_write_config_dword(
dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- continue; /* for now, displays get no IRQ */
- }
-
- if (pirq < 0) {
- DBG_DEVS(("bios32.sio_fixup: "
- "weird, device %04x:%04x coming in on"
- " slot %d has no irq line!!\n",
- dev->vendor, dev->device, slot));
- continue;
- }
-
- dev->irq = (route_tab >> (8 * pirq)) & 0xff;
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* do not set *ANY* level triggers for AlphaBook1 */
- /* must set the PCI IRQs to level triggered */
- level_bits |= (1 << dev->irq);
-#endif /* !CONFIG_ALPHA_BOOK1 */
-
-#if PCI_MODIFY
- /* tell the device: */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-#endif
-
-#ifdef CONFIG_ALPHA_BOOK1
- /*
- * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
- * is sensitive to PCI bus bursts, so we must DISABLE
- * burst mode for the NCR 8xx SCSI... :-(
- *
- * Note that the NCR810 SCSI driver must preserve the
- * setting of the bit in order for this to work. At the
- * moment (2.0.29), ncr53c8xx.c does NOT do this, but
- * 53c7,8xx.c DOES.
- */
- if (dev->vendor == PCI_VENDOR_ID_NCR &&
- (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
- dev->device == PCI_DEVICE_ID_NCR_53C815 ||
- dev->device == PCI_DEVICE_ID_NCR_53C820 ||
- dev->device == PCI_DEVICE_ID_NCR_53C825)) {
- unsigned int io_port;
- unsigned char ctest4;
-
- pcibios_read_config_dword(dev->bus->number,
- dev->devfn,
- PCI_BASE_ADDRESS_0,
- &io_port);
- io_port &= PCI_BASE_ADDRESS_IO_MASK;
- ctest4 = inb(io_port+0x21);
- if (!(ctest4 & 0x80)) {
- printk("AlphaBook1 NCR init: setting"
- " burst disable\n");
- outb(ctest4 | 0x80, io_port+0x21);
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
}
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
- } /* end for-devs */
-
- /*
- * Now, make all PCI interrupts level sensitive. Notice:
- * these registers must be accessed byte-wise. inw()/outw()
- * don't work.
- *
- * Make sure to turn off any level bits set for IRQs 9,10,11,15,
- * so that the only bits getting set are for devices actually found.
- * Note that we do preserve the remainder of the bits, which we hope
- * will be set correctly by ARC/SRM.
- *
- * Note: we at least preserve any level-set bits on AlphaBook1
- */
- old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
- DBG_DEVS(("sio_fixup: old irq level bits: 0x%04x\n",
- old_level_bits));
- level_bits |= (old_level_bits & 0x71ff);
- DBG_DEVS(("sio_fixup: new irq level bits: 0x%04x\n",
- level_bits));
- outb((level_bits >> 0) & 0xff, 0x4d0);
- outb((level_bits >> 8) & 0xff, 0x4d1);
-
-#ifdef CONFIG_ALPHA_BOOK1
- {
- unsigned char orig, config;
- /* On the AlphaBook1, make sure that register PR1
- indicates 1Mb mem */
- outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
- outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
- outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
- if ((config & 0xc0) != 0xc0) {
- printk("AlphaBook1 VGA init: setting 1Mb memory\n");
- config |= 0xc0;
- outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
}
- outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* Do not do IDE init for AlphaBook1 */
- enable_ide(0x26e);
-#endif
-}
-
-
-__initfunc(void
-pcibios_fixup(void))
-{
- struct pci_bus *cur;
-
-#ifdef CONFIG_ALPHA_MCPCIA
- /* must do massive setup for multiple PCI busses here... */
- DBG_DEVS(("pcibios_fixup: calling mcpcia_fixup()...\n"));
- mcpcia_fixup();
-#endif /* MCPCIA */
-
-#ifdef CONFIG_ALPHA_TSUNAMI
- /* must do massive setup for multiple PCI busses here... */
- /* tsunami_fixup(); */
-#endif /* TSUNAMI */
-
-#if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN)
- /*
- * Scan the tree, allocating PCI memory and I/O space.
- */
- /*
- * Sigh; check_region() will need changing to accept a HANDLE,
- * if we allocate I/O space addresses on a per-bus basis.
- * For now, make the I/O bases unique across all busses, so
- * that check_region() will not get confused... ;-}
- */
- io_base = DEFAULT_IO_BASE;
- for (cur = &pci_root; cur; cur = cur->next) {
- mem_base = DEFAULT_MEM_BASE;
- DBG_DEVS(("pcibios_fixup: calling layout_bus()\n"));
- layout_bus(cur);
- }
-#endif
-
- /*
- * Now is the time to do all those dirty little deeds...
- */
-#if defined(CONFIG_ALPHA_NONAME) || defined(CONFIG_ALPHA_AVANTI) || \
- defined(CONFIG_ALPHA_P2K)
- sio_fixup();
-#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164)
- cabriolet_fixup();
-#elif defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
- alphapc164_fixup();
-#elif defined(CONFIG_ALPHA_EB66P)
- eb66p_fixup();
-#elif defined(CONFIG_ALPHA_EB66)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_EB64P)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_fixup();
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_fixup();
-#elif defined(CONFIG_ALPHA_SABLE)
- sable_fixup();
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_fixup();
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_fixup();
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_fixup();
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_fixup();
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_fixup();
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_fixup();
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- /* no fixup needed */
-#else
-# error "You must tell me what kind of platform you want."
-#endif
-}
-
-
-__initfunc(void
-pcibios_fixup_bus(struct pci_bus *bus))
-{
-}
-
-
-asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
- if (err != PCIBIOS_SUCCESSFUL)
- ubyte = 0xff;
- put_user(ubyte, buf);
- break;
- case 2:
- err = pcibios_read_config_word(bus, dfn, off, &ushort);
- if (err != PCIBIOS_SUCCESSFUL)
- ushort = 0xffff;
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- err = pcibios_read_config_dword(bus, dfn, off, &uint);
- if (err != PCIBIOS_SUCCESSFUL)
- uint = 0xffffffff;
- put_user(uint, (unsigned int *)buf);
- break;
- default:
- err = -EINVAL;
- break;
- }
- unlock_kernel();
- return err;
-}
-
-
-asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = get_user(ubyte, buf);
- if (err)
- break;
- err = pcibios_write_config_byte(bus, dfn, off, ubyte);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if (err)
- break;
- err = pcibios_write_config_word(bus, dfn, off, ushort);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if (err)
- break;
- err = pcibios_write_config_dword(bus, dfn, off, uint);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
+ /*
+ * If it's a SCSI, disable its BIOS ROM.
+ */
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
+ pcibios_write_config_dword(dev->bus->number,
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x0000000);
}
- break;
- default:
- err = -EINVAL;
- break;
}
- unlock_kernel();
- return err;
}
-#if (defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164) || \
- defined(CONFIG_ALPHA_SX164) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_CABRIOLET)) && defined(CONFIG_ALPHA_SRM)
+/* Most Alphas have straight-forward swizzling needs. */
-/*
- on the above machines, under SRM console, we must use the CSERVE PALcode
- routine to manage the interrupt mask for us, otherwise, the kernel/HW get
- out of sync with what the PALcode thinks it needs to deliver/ignore
- */
-void
-cserve_update_hw(unsigned long irq, unsigned long mask)
+int __init
+common_swizzle(struct pci_dev *dev, int *pinp)
{
- extern void cserve_ena(unsigned long);
- extern void cserve_dis(unsigned long);
+ int pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
- if (mask & (1UL << irq))
- /* disable */
- cserve_dis(irq - 16);
- else
- /* enable */
- cserve_ena(irq - 16);
- return;
+ /* The slot is the slot of the last bridge. */
+ return PCI_SLOT(dev->devfn);
}
-#endif /* (PC164 || LX164 || SX164 || EB164 || CABRIO) && SRM */
-
-#ifdef CONFIG_ALPHA_MIATA
-/*
- * Init the built-in ES1888 sound chip (SB16 compatible)
- */
-static int __init
-es1888_init(void)
-{
- /* Sequence of IO reads to init the audio controller */
- inb(0x0229);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0220); /* This sets the base address to 0x220 */
-
- /* Sequence to set DMA channels */
- outb(0x01, 0x0226); /* reset */
- inb(0x0226); /* pause */
- outb(0x00, 0x0226); /* release reset */
- while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
- continue;
- inb(0x022a); /* pause */
- outb(0xc6, 0x022c); /* enable extended mode */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x14, 0x022c); /* set IRQ 5 */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb2, 0x022c); /* setup for write to DMA CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x18, 0x022c); /* set DMA channel 1 */
-
- return 0;
-}
-#endif /* CONFIG_ALPHA_MIATA */
-
-__initfunc(char *pcibios_setup(char *str))
-{
- return str;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-void reset_for_srm(void)
-{
- struct pci_dev *dev;
- int i;
-
- /* reset any IRQs that we changed */
- for (i = 0; i < irq_reset_count; i++) {
- dev = irq_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, irq_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed back from 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- irq_to_reset[i], dev->irq);
-#endif
- }
-
- /* reset any IO addresses that we changed */
- for (i = 0; i < io_reset_count; i++) {
- dev = io_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- io_reg_to_reset[i], io_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IO restored to 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- io_to_reset[i]);
-#endif
-}
- /* FIXME: reset the video origin. */
-}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
-
#endif /* CONFIG_PCI */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov