patch-1.3.22 linux/arch/alpha/kernel/bios32.c
Next file: linux/arch/alpha/kernel/entry.S
Previous file: linux/arch/alpha/kernel/apecs.c
Back to the patch index
Back to the overall index
- Lines: 350
- Date:
Tue Aug 29 10:15:48 1995
- Orig file:
v1.3.21/linux/arch/alpha/kernel/bios32.c
- Orig date:
Fri Jun 16 22:02:54 1995
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
@@ -49,7 +49,7 @@
#define GB (1024*MB)
#define MAJOR_REV 0
-#define MINOR_REV 2
+#define MINOR_REV 3
/*
* Align VAL to ALIGN, which must be a power of two.
@@ -209,6 +209,19 @@
}
}
/* enable device: */
+ if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
+ dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
+ dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
+ dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+ {
+ /*
+ * All of these (may) have I/O scattered all around
+ * and may not use i/o-base address registers at all.
+ * So we just have to always enable I/O to these
+ * devices.
+ */
+ cmd |= PCI_COMMAND_IO;
+ }
pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
cmd | PCI_COMMAND_MASTER);
}
@@ -355,27 +368,202 @@
return mem_start;
}
+/*
+ * The SRM console *disables* the IDE interface, this code ensures its
+ * enabled.
+ *
+ * This code bangs on a control register of the 87312 Super I/O chip
+ * that implements parallel port/serial ports/IDE/FDI. Depending on
+ * the motherboard, the Super I/O chip can be configured through a
+ * pair of registers that are located either at I/O ports 0x26e/0x26f
+ * or 0x398/0x399. Unfortunately, autodetecting which base address is
+ * in use works only once (right after a reset). The Super I/O chip
+ * has the additional quirk that configuration register data must be
+ * written twice (I believe this is a saftey feature to prevent
+ * accidental modification---fun, isn't it?).
+ */
+static inline void enable_ide(long ide_base)
+{
+ int data;
+
+ outb(0, ide_base); /* set the index register for reg #0 */
+ data = inb(ide_base+1); /* read the current contents */
+ outb(0, ide_base); /* set the index register for reg #0 */
+ outb(data | 0x40, ide_base+1); /* turn on IDE */
+ outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
+}
/*
- * Fixup configuration for Noname boards (AXPpci33).
+ * 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.
*/
-static void noname_fixup(void)
+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;
+ unsigned char pin;
+ /*
+ * 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 PCI_MODIFY
+ /* tell the device: */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
+#endif
+ }
+ 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)
+{
+ char irq_tab[5][5] = {
+ {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);
+}
+
+
+/*
+ * 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)
+{
+ char irq_tab[5][5] = {
+ { 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)
+{
+ char irq_tab[5][5] = {
+ {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 Noname boards (AXPpci33).
+ */
+static inline void noname_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). I don't have any information yet as
* to how INTB, INTC, and INTD get routed (4/12/95,
- * [email protected]).
+ * [email protected]). 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][4] = {
- { 3, -1, -1, -1}, /* slot 6 (53c810) */
- {-1, -1, -1, -1}, /* slot 7 (PCI/ISA bridge) */
- { 2, -1, -1, -1}, /* slot 8 (slot closest to ISA) */
- { 1, -1, -1, -1}, /* slot 9 (middle slot) */
- { 0, -1, -1, -1}, /* slot 10 (slot furthest from ISA) */
+ static const char pirq_tab[7][5] = {
+ { 3, 3, -1, -1, -1}, /* idsel 6 (53c810) */
+ {-1, -1, -1, -1, -1}, /* idsel 7 (PCI/ISA bridge) */
+ { 2, 2, -1, -1, -1}, /* idsel 8 (slot closest to ISA) */
+ {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
+ {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+ { 0, 0, -1, -1, -1}, /* idsel 11 (slot furthest from ISA) */
+ { 1, 1, -1, -1, -1}, /* idsel 12 (middle slot) */
};
/*
* route_tab selects irq routing in PCI/ISA bridge so that:
@@ -399,7 +587,7 @@
for (dev = pci_devices; dev; dev = dev->next) {
dev->irq = 0;
if (dev->bus->number != 0 ||
- PCI_SLOT(dev->devfn) < 6 || PCI_SLOT(dev->devfn) > 10)
+ PCI_SLOT(dev->devfn) < 6 || PCI_SLOT(dev->devfn) > 12)
{
printk("noname_set_irq: no dev on bus %d, slot %d!!\n",
dev->bus->number, PCI_SLOT(dev->devfn));
@@ -408,17 +596,7 @@
pcibios_read_config_byte(dev->bus->number, dev->devfn,
PCI_INTERRUPT_PIN, &pin);
- if (!pin) {
- if (dev->vendor == PCI_VENDOR_ID_S3 &&
- (dev->device == PCI_DEVICE_ID_S3_864_1 ||
- dev->device == PCI_DEVICE_ID_S3_864_2))
- {
- pin = 1;
- } else {
- continue; /* no interrupt line */
- }
- }
- pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin - 1];
+ pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin];
if (pirq < 0) {
continue;
}
@@ -450,47 +628,7 @@
}
#endif /* !PCI_MODIFY */
- /*
- * The SRM console *disables* the IDE interface, this code *
- * enables it. With the miniloader, this may not be necessary
- * but it shouldn't hurt either.
- *
- * This code bangs on a control register of the 87312 Super
- * I/O chip that implements parallel port/serial
- * ports/IDE/FDI. Depending on the motherboard, the Super I/O
- * chip can be configured through a pair of registers that are
- * located either at I/O ports 0x26e/0x26f or 0x398/0x399.
- * Unfortunately, autodetecting which base address is in use
- * works only once (right after a reset). On the other hand,
- * the Noname board hardwires the I/O ports to 0x26e/0x26f so
- * we just use those. The Super I/O chip has the additional
- * quirk that configuration register data must be written
- * twice (I believe this is a saftey feature to prevent
- * accidental modification---happy PC world...).
- */
- {
- long flags;
- int data;
-
- /* update needs to be atomic: */
-
- save_flags(flags);
- cli();
-
- outb(0, 0x26e); /* set the index register for reg #0 */
- data = inb(0x26f); /* read the current contents */
-#ifdef DEBUG
- printk("base @ 0x26e: reg#0 0x%x\n", data);
-#endif
- outb(0, 0x26e); /* set the index register for reg #0 */
- outb(data | 0x40, 0x26f); /* turn on IDE */
- outb(data | 0x40, 0x26f); /* yes, we really mean it... */
-#ifdef DEBUG
- outb(0, 0x26e); data = inb(0x26f);
- printk("base @ 0x26e: reg#0 0x%x\n", data);
-#endif
- restore_flags(flags);
- }
+ enable_ide(0x26e);
}
@@ -506,19 +644,22 @@
/*
* Now is the time to do all those dirty little deeds...
*/
- switch (hwrpb->sys_type) {
- case ST_DEC_AXPPCI_33: noname_fixup(); break;
-
- default:
- printk("pcibios_fixup: don't know how to fixup sys type %ld\n",
- hwrpb->sys_type);
- break;
- }
+#if defined(CONFIG_ALPHA_NONAME)
+ noname_fixup();
+#elif defined(CONFIG_ALPHA_CABRIOLET)
+ cabriolet_fixup();
+#elif defined(CONFIG_ALPHA_EB66)
+ eb66_and_eb64p_fixup();
+#elif defined(CONFIG_ALPHA_EB64P)
+ eb66_and_eb64p_fixup();
+#else
+# error You must tell me what kind of platform you want.
+#endif
return mem_start;
}
-char *pcibios_strerror (int error)
+const char *pcibios_strerror (int error)
{
static char buf[80];
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen, [email protected]
with Sam's (original) version of this