patch-2.1.95 linux/arch/i386/kernel/bios32.c
Next file: linux/arch/i386/kernel/irq.c
Previous file: linux/arch/alpha/kernel/bios32.c
Back to the patch index
Back to the overall index
- Lines: 118
- Date:
Thu Apr 9 13:16:18 1998
- Orig file:
v2.1.94/linux/arch/i386/kernel/bios32.c
- Orig date:
Wed Apr 8 19:36:24 1998
diff -u --recursive --new-file v2.1.94/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
@@ -834,44 +834,52 @@
__initfunc(void pcibios_fixup(void))
{
struct pci_dev *dev;
- int i, has_io;
+ int i, has_io, has_mem;
+ unsigned short cmd;
+ unsigned char pin;
for(dev = pci_devices; dev; dev=dev->next) {
/*
- * There are probably some buggy BIOSes that forget to assign I/O port
- * addresses to several devices. We probably should assign new addresses
- * to such devices, but we need to gather some information first. [mj]
+ * There are buggy BIOSes that forget to enable I/O and memory
+ * access to PCI devices. We try to fix this, but we need to
+ * be sure that the BIOS didn't forget to assign an address
+ * to the device. [mj]
*/
- has_io = 0;
+ has_io = has_mem = 0;
for(i=0; i<6; i++) {
unsigned long a = dev->base_address[i];
if (a & PCI_BASE_ADDRESS_SPACE_IO) {
- has_io = 1;
+ has_io |= 1;
a &= PCI_BASE_ADDRESS_IO_MASK;
- if (!a || a == PCI_BASE_ADDRESS_IO_MASK)
+ if (!a || a == PCI_BASE_ADDRESS_IO_MASK) {
printk(KERN_WARNING "PCI: BIOS forgot to assign address #%d to device %02x:%02x,"
" please report to <mj@ucw.cz>\n", i, dev->bus->number, dev->devfn);
- }
+ has_io |= 2;
+ }
+ } else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+ has_mem = 1;
}
- /*
- * Check if the I/O space access is allowed. If not, moan loudly. [mj]
- */
- if (has_io) {
- unsigned short cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (!(cmd & PCI_COMMAND_IO))
- printk(KERN_WARNING "PCI: BIOS forgot to enable I/O for device %02x:%02x,"
- " please report to <mj@ucw.cz>\n", dev->bus->number, dev->devfn);
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (has_io == 1 && !(cmd & PCI_COMMAND_IO)) {
+ printk("PCI: Enabling I/O for device %02x:%02x\n",
+ dev->bus->number, dev->devfn);
+ cmd |= PCI_COMMAND_IO;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
+ if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+ printk("PCI: Enabling memory for device %02x:%02x\n",
+ dev->bus->number, dev->devfn);
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
#ifdef __SMP__
/*
* Recalculate IRQ numbers if we use the I/O APIC
*/
{
- unsigned char pin;
int irq;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin) {
pin--; /* interrupt pins are numbered starting from 1 */
irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
@@ -884,10 +892,13 @@
}
#endif
/*
- * Fix out-of-range IRQ numbers.
+ * Fix out-of-range IRQ numbers and report bogus IRQ.
*/
if (dev->irq >= NR_IRQS)
dev->irq = 0;
+ if (pin && !dev->irq)
+ printk(KERN_WARNING "PCI: Bogus IRQ for device %02x:%02x [pin=%x], please report to <mj@ucw.cz>\n",
+ dev->bus->number, dev->devfn, pin);
}
}
@@ -919,25 +930,25 @@
{
if (!strncmp(str, "off", 3)) {
pci_probe = 0;
- return str+3;
+ return NULL;
}
#ifdef CONFIG_PCI_BIOS
else if (!strncmp(str, "bios", 4)) {
pci_probe = PCI_PROBE_BIOS;
- return str+4;
+ return NULL;
} else if (!strncmp(str, "nobios", 6)) {
pci_probe &= ~PCI_PROBE_BIOS;
- return str+6;
+ return NULL;
}
#endif
#ifdef CONFIG_PCI_DIRECT
else if (!strncmp(str, "conf1", 5)) {
pci_probe = PCI_PROBE_CONF1;
- return str+5;
+ return NULL;
}
else if (!strncmp(str, "conf2", 5)) {
pci_probe = PCI_PROBE_CONF2;
- return str+5;
+ return NULL;
}
#endif
return str;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov