patch-1.3.65 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: 253
- Date:
Sat Feb 17 09:19:37 1996
- Orig file:
v1.3.64/linux/arch/alpha/kernel/bios32.c
- Orig date:
Fri Feb 16 11:34:03 1996
diff -u --recursive --new-file v1.3.64/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
@@ -85,15 +85,35 @@
static unsigned int io_base = 64*KB; /* <64KB are (E)ISA ports */
static unsigned int mem_base = 16*MB; /* <16MB is ISA memory */
+/*
+ * Disable PCI device DEV so that it does not respond to I/O or memory
+ * accesses.
+ */
+static void disable_dev(struct pci_dev *dev)
+{
+ struct pci_bus *bus;
+ unsigned short cmd;
+
+ bus = dev->bus;
+ pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
+
+ /* hack, turn it off first... */
+ cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
+ pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
+}
+
/*
* Layout memory and I/O for a device:
*/
+#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
+
static void layout_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
unsigned int base, mask, size, reg;
+ unsigned int alignto;
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
@@ -110,6 +130,7 @@
/* this base-address register is unused */
continue;
}
+
/*
* We've read the base address register back after
* writing all ones and so now we must decode it.
@@ -123,7 +144,9 @@
base &= PCI_BASE_ADDRESS_IO_MASK;
mask = (~base << 1) | 0x1;
size = (mask & base) & 0xffffffff;
- base = ALIGN(io_base, size);
+ /* align to multiple of size of minimum base */
+ alignto = MAX(0x400, size) ;
+ base = ALIGN(io_base, alignto );
io_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
reg, base | 0x1);
@@ -133,7 +156,6 @@
* Memory space base address register.
*/
cmd |= PCI_COMMAND_MEMORY;
-
type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
base &= PCI_BASE_ADDRESS_MEM_MASK;
mask = (~base << 1) | 0x1;
@@ -183,7 +205,9 @@
* address space must be accessed through
* dense memory space only!
*/
- base = ALIGN(mem_base, size);
+ /* align to multiple of size of minimum base */
+ alignto = MAX(0x1000, size) ;
+ base = ALIGN(mem_base, alignto);
if (size > 7 * 16*MB) {
printk("bios32 WARNING: slot %d, function %d "
"requests %dB of contiguous address "
@@ -192,15 +216,15 @@
PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), size);
} else {
- if (((base / 16*MB) & 0x7) == 0) {
+ if (((base / (16*MB)) & 0x7) == 0) {
base &= ~(128*MB - 1);
base += 16*MB;
- base = ALIGN(base, size);
+ base = ALIGN(base, alignto);
}
- if (base / 128*MB != (base + size) / 128*MB) {
+ if (base / (128*MB) != (base + size) / (128*MB)) {
base &= ~(128*MB - 1);
base += (128 + 16)*MB;
- base = ALIGN(base, size);
+ base = ALIGN(base, alignto);
}
}
mem_base = base + size;
@@ -222,6 +246,7 @@
*/
cmd |= PCI_COMMAND_IO;
}
+
pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
cmd | PCI_COMMAND_MASTER);
}
@@ -244,6 +269,21 @@
bmem = mem_base = ALIGN(mem_base, 1*MB);
/*
+ * There are times when the PCI devices have already been
+ * setup (e.g., by MILO or SRM). In these cases there is a
+ * window during which two devices may have an overlapping
+ * address range. To avoid this causing trouble, we first
+ * turn off the I/O and memory address decoders for all PCI
+ * devices. They'll be re-enabled only once all address
+ * decoders are programmed consistently.
+ */
+ for (dev = bus->devices; dev; dev = dev->sibling) {
+ if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) {
+ disable_dev(dev) ;
+ }
+ }
+
+ /*
* Allocate space to each device:
*/
for (dev = bus->devices; dev; dev = dev->sibling) {
@@ -405,6 +445,7 @@
{
struct pci_dev *dev;
unsigned char pin;
+
/*
* Go through all devices, fixing up irqs as we see fit:
*/
@@ -489,6 +530,7 @@
{ -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);
}
@@ -549,9 +591,11 @@
/*
- * Fixup configuration for Noname (AXPpci33) and Avanti (AlphaStation 240).
+ * 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 avanti_and_noname_fixup(void)
+static inline void sio_fixup(void)
{
struct pci_dev *dev;
/*
@@ -573,16 +617,24 @@
* driven at all).
*/
static const char pirq_tab[][5] = {
+#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 (slot closest to ISA) */
+ { 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 (slot furthest from ISA) KN25_PCI_SLOT0 */
- { 1, 1, 0, 2, 1}, /* idsel 12 (middle slot) KN25_PCI_SLOT1 */
-#ifdef CONFIG_ALPHA_AVANTI
- { 1, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
-#endif /* CONFIG_ALPHA_AVANTI */
+ { 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 */
+#endif
};
/*
* route_tab selects irq routing in PCI/ISA bridge so that:
@@ -607,12 +659,17 @@
level_bits = 0;
for (dev = pci_devices; dev; dev = dev->next) {
dev->irq = 0;
- if (dev->bus->number != 0 ||
- PCI_SLOT(dev->devfn) < 6 ||
+ if (dev->bus->number != 0) {
+ printk("bios32.sio_fixup: don't know how to fixup devices on bus %d\n",
+ dev->bus->number);
+ continue;
+ }
+ if (PCI_SLOT(dev->devfn) < 6 ||
PCI_SLOT(dev->devfn) >= 6 + sizeof(pirq_tab)/sizeof(pirq_tab[0]))
{
- printk("bios32.avanti_and_noname_fixup: no dev on bus %d, slot %d!!\n",
- dev->bus->number, PCI_SLOT(dev->devfn));
+ printk("bios32.sio_fixup: "
+ "weird, found device %04x:%04x in non-existent slot %d!!\n",
+ dev->vendor, dev->device, PCI_SLOT(dev->devfn));
continue;
}
pcibios_read_config_byte(dev->bus->number, dev->devfn,
@@ -646,31 +703,10 @@
/*
* Now, make all PCI interrupts level sensitive. Notice:
* these registers must be accessed byte-wise. outw() doesn't
- * work, for some reason.
+ * work.
*/
outb((level_bits >> 0) & 0xff, 0x4d0);
outb((level_bits >> 8) & 0xff, 0x4d1);
-
-#if PCI_MODIFY
- {
- unsigned char hostid;
- /*
- * SRM console version X3.9 seems to reset the SCSI
- * host-id to 0 no matter what console environment
- * variable pka0_host_id is set to. Thus, if the
- * host-id reads out as a zero, we set it to 7. The
- * SCSI controller is on the motherboard on bus 0,
- * slot 6
- */
- if (pcibios_read_config_byte(0, PCI_DEVFN(6, 0), 0x84, &hostid)
- == PCIBIOS_SUCCESSFUL && (hostid == 0))
- {
- pcibios_write_config_byte(0, PCI_DEVFN(6, 0),
- 0x84, 7);
- }
- }
-#endif /* !PCI_MODIFY */
-
enable_ide(0x26e);
}
@@ -691,9 +727,9 @@
/*
* Now is the time to do all those dirty little deeds...
*/
-#if defined(CONFIG_ALPHA_NONAME) || defined(CONFIG_ALPHA_AVANTI)
- avanti_and_noname_fixup();
-#elif defined(CONFIG_ALPHA_CABRIOLET)
+#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_EB66P)
eb66p_fixup();
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