More PCI patches

Martin Mares (mj@atrey.karlin.mff.cuni.cz)
Fri, 17 Apr 1998 19:58:33 +0200


Hi,

Next round of PCI patches...

- When both BIOS and direct access are available, prefer direct
access.

- When BIOS is available (and even if using direct access), sort the
pci_dev list according to BIOS order.

- If BIOS forgets to assign I/O addresses to a device, assign them.
Removed kludges doing this in ide-{pci,dma}.c.

- Don't report bogus interrupts as they happen very frequently.

- Added few new options.

- Moved initialization of PCI procfs to drivers/pci/proc.c. This makes
Ultra/AX happy.

- Latency timer setting is gone (it confuses several broken devices).
Drivers needing latency timer and bus mastering enable to be set
should call pci_set_master().

- pcibios_error() is gone. It wasn't SMP safe and almost nobody checks
the error codes anyway (I've changed the few drivers that did use it
to write numeric error codes instead which are comparably comprehensible
to an ordinary user as the original messages were.)

- If expansion ROMs are mapped, record their addresses.

- Minor bug fixes.

If you have the init order fixes by DaveM, don't apply the last chunk of this
patch.

Known problems to be solved:

- Multi-bus PCI chipsets (waiting for detailed information)

- CardBus etc. (hot-pluggable PCI cards)

Have a nice fortnight

-- 
Martin `MJ' Mares   <mj@ucw.cz>   http://atrey.karlin.mff.cuni.cz/~mj/
Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth
"Linux hackers are funny people -- they count the time in patchlevels."

--- linux-2.1.96/drivers/block/ide-pci.c Thu Apr 2 19:12:22 1998 +++ linux/drivers/block/ide-pci.c Thu Apr 16 15:42:57 1998 @@ -116,31 +116,6 @@ {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }}; /* - * Search for an (apparently) unused block of I/O space - * of "size" bytes in length. Ideally we ought to do a pass - * through pcicfg space to eliminate ports already allocated - * by the BIOS, to avoid conflicts later in the init cycle, - * but we don't. FIXME - */ -unsigned long ide_find_free_region (unsigned short size) /* __init */ -{ - static unsigned short base = 0x5800; /* it works for me */ - unsigned short i; - - for (; base > 0; base -= 0x200) { - if (!check_region(base,size)) { - for (i = 0; i < size; i++) { - if (inb(base+i) != 0xff) - goto next; - } - return base; /* success */ - } - next: - } - return 0; /* failure */ -} - -/* * Match a PCI IDE port against an entry in ide_hwifs[], * based on io_base port if possible. */ @@ -197,7 +172,6 @@ __initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)) { - unsigned int base, readback; byte reg, progif = 0; /* @@ -218,16 +192,11 @@ /* * Setup base registers for IDE command/control spaces for each interface: */ - if (!(base = ide_find_free_region(32))) - return 1; - for (reg = 0; reg < 4; reg++, base += 8) { - (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, base | PCI_BASE_ADDRESS_SPACE_IO); - if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, &readback) || - readback != (base | PCI_BASE_ADDRESS_SPACE_IO)) { - printk("%s: readback failed for basereg 0x%02x: wrote 0x%04x, read 0x%x04\n", name, reg, base, readback); + for (reg = 0; reg < 4; reg++) + if (!dev->base_address[reg]) { + printk("%s: Missing I/O address #%d, please report to <mj@ucw.cz>\n", name, reg); return 1; } - } return 0; } --- linux-2.1.96/drivers/block/ide-dma.c Thu Apr 2 19:12:22 1998 +++ linux/drivers/block/ide-dma.c Thu Apr 16 15:26:58 1998 @@ -341,19 +341,7 @@ dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) { printk("%s: dma_base is invalid (0x%04lx, BIOS problem), please report to <mj@ucw.cz>\n", name, dma_base); - new = ide_find_free_region(16 + extra); - hwif->no_autodma = 1; /* default DMA off if we had to configure it here */ - if (new) { - printk("%s: setting dma_base to 0x%04lx\n", name, new); - new |= PCI_BASE_ADDRESS_SPACE_IO; - (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, new); - dma_base = 0; - (void) pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, (unsigned int *) &dma_base); - if (dma_base != new) { - printk("%s: Operation failed, DMA disabled\n", name); - dma_base = 0; - } - } + dma_base = 0; } } if (dma_base) { --- linux-2.1.96/arch/i386/kernel/bios32.c Thu Apr 9 22:16:18 1998 +++ linux/arch/i386/kernel/bios32.c Fri Apr 17 18:38:40 1998 @@ -1,7 +1,7 @@ /* * bios32.c - Low-Level PCI Access * - * $Id: bios32.c,v 1.26 1998/02/18 15:21:09 mj Exp $ + * $Id: bios32.c,v 1.29 1998/04/17 16:31:15 mj Exp $ * * Sponsored by * iX Multiuser Multitasking Magazine @@ -73,6 +73,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/page.h> #include <asm/segment.h> @@ -86,6 +87,14 @@ #include "irq.h" +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + /* * Generic PCI access -- indirect calls according to detected HW. */ @@ -158,11 +167,13 @@ return access_pci->write_config_dword(bus, device_fn, where, value); } -static unsigned int pci_probe = ~0; - #define PCI_PROBE_BIOS 1 #define PCI_PROBE_CONF1 2 #define PCI_PROBE_CONF2 4 +#define PCI_NO_SORT 0x100 +#define PCI_BIOS_SORT 0x200 + +static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2; /* * Direct access to PCI hardware... @@ -596,8 +607,10 @@ return (int) (ret & 0xff00) >> 8; } -static int pci_bios_find_device (unsigned short vendor, unsigned short device_id, - unsigned short index, unsigned char *bus, unsigned char *device_fn) +#endif + +__initfunc(static int pci_bios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, unsigned char *device_fn)) { unsigned short bx; unsigned short ret; @@ -621,8 +634,6 @@ return (int) (ret & 0xff00) >> 8; } -#endif - static int pci_bios_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value) { @@ -803,13 +814,13 @@ check->fields.revision, check); continue; } - printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check); + DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check); if (check->fields.entry >= 0x100000) { - printk("PCI: BIOS32 entry in high memory, cannot use.\n"); + printk("PCI: BIOS32 entry (0x%p) in high memory, cannot use.\n", check); return NULL; } else { bios32_entry = check->fields.entry; - printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); bios32_indirect.address = bios32_entry + PAGE_OFFSET; if (check_pcibios()) return &pci_bios_access; @@ -817,18 +828,104 @@ break; /* Hopefully more than one BIOS32 cannot happen... */ } - /* - * If we were told to use the PCI BIOS and it's not present, avoid - * touching the hardware. - */ - pci_probe = 0; return NULL; } +/* + * Sort the device list according to PCI BIOS. + */ + +__initfunc(void pcibios_sort(void)) +{ + struct pci_dev *dev = pci_devices; + struct pci_dev **last = &pci_devices; + struct pci_dev *d, **dd, *e; + int idx; + unsigned char bus, devfn; + + DBG("PCI: Sorting device list...\n"); + while ((e = dev)) { + idx = 0; + while (pci_bios_find_device(e->vendor, e->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) { + idx++; + for(dd=&dev; (d = *dd); dd = &d->next) { + if (d->bus->number == bus && d->devfn == devfn) { + *dd = d->next; + *last = d; + last = &d->next; + break; + } + } + if (!d) + printk("PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn); + } + if (!idx) { + printk("PCI: Device %02x:%02x not found by BIOS\n", + dev->bus->number, dev->devfn); + d = dev; + dev = dev->next; + *last = d; + last = &d->next; + } + } + *last = NULL; +} + #endif /* - * Arch-dependent fixups. + * Several BIOS'es forget to assign addresses to I/O ranges. + * We try to fix it here, expecting there are free addresses + * starting with 0x5800. Ugly, but until we come with better + * resource management, it's the only simple solution. + */ + +static int pci_last_io_addr __initdata = 0x5800; + +__initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx)) +{ + unsigned short cmd; + unsigned int reg = PCI_BASE_ADDRESS_0 + 4*idx; + unsigned int size, addr, try; + unsigned int bus = dev->bus->number; + unsigned int devfn = dev->devfn; + + if (!pci_last_io_addr) { + printk("PCI: Unassigned I/O space for %02x:%02x\n", bus, devfn); + return; + } + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + pcibios_write_config_dword(bus, devfn, reg, ~0); + pcibios_read_config_dword(bus, devfn, reg, &size); + size = (~(size & PCI_BASE_ADDRESS_IO_MASK) & 0xffff) + 1; + addr = 0; + if (!size || size > 0x100) + printk("PCI: Unable to handle I/O allocation for %02x:%02x (%04x), tell <mj@ucw.cz>\n", bus, devfn, size); + else { + do { + addr = (pci_last_io_addr + size - 1) & ~(size-1); + pci_last_io_addr = addr + size; + } while (check_region(addr, size)); + printk("PCI: Assigning I/O space %04x-%04x to device %02x:%02x\n", addr, addr+size-1, bus, devfn); + pcibios_write_config_dword(bus, devfn, reg, addr | PCI_BASE_ADDRESS_SPACE_IO); + pcibios_read_config_dword(bus, devfn, reg, &try); + if ((try & PCI_BASE_ADDRESS_IO_MASK) != addr) { + addr = 0; + printk("PCI: Address setup failed, got %04x\n", try); + } else + dev->base_address[idx] = try; + } + if (!addr) { + pcibios_write_config_dword(bus, devfn, reg, 0); + dev->base_address[idx] = 0; + } + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); +} + +/* + * Arch-dependent fixups. We need to fix here base addresses, I/O + * and memory enables and IRQ's as the PCI BIOS'es are buggy as hell. */ __initfunc(void pcibios_fixup(void)) @@ -836,7 +933,6 @@ struct pci_dev *dev; int i, has_io, has_mem; unsigned short cmd; - unsigned char pin; for(dev = pci_devices; dev; dev=dev->next) { /* @@ -849,18 +945,15 @@ 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) { - 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; - } + if (!a || a == PCI_BASE_ADDRESS_IO_MASK) + pcibios_fixup_io_addr(dev, i); } else if (a & PCI_BASE_ADDRESS_MEM_MASK) has_mem = 1; } pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (has_io == 1 && !(cmd & PCI_COMMAND_IO)) { + if (has_io && !(cmd & PCI_COMMAND_IO)) { printk("PCI: Enabling I/O for device %02x:%02x\n", dev->bus->number, dev->devfn); cmd |= PCI_COMMAND_IO; @@ -872,14 +965,15 @@ 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 */ { int irq; + unsigned char pin; + 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); @@ -896,30 +990,38 @@ */ 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); } + +#ifdef CONFIG_PCI_BIOS + if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) + pcibios_sort(); +#endif } /* - * Initialization. Try all known PCI access methods. + * Initialization. Try all known PCI access methods. Note that we support + * using both PCI BIOS and direct access: in such cases, we use I/O ports + * to access config space, but we still keep BIOS order of cards to be + * compatible with 2.0.X. This should go away in 2.3. */ __initfunc(void pcibios_init(void)) { - struct pci_access *a = NULL; + struct pci_access *bios = NULL; + struct pci_access *dir = NULL; #ifdef CONFIG_PCI_BIOS - if (pci_probe & PCI_PROBE_BIOS) - a = pci_find_bios(); + if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) + pci_probe |= PCI_BIOS_SORT; #endif #ifdef CONFIG_PCI_DIRECT - if (!a && (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))) - a = pci_check_direct(); + if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) + dir = pci_check_direct(); #endif - if (a) - access_pci = a; + if (dir) + access_pci = dir; + else if (bios) + access_pci = bios; } #if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT) @@ -928,25 +1030,35 @@ __initfunc(char *pcibios_setup(char *str)) { - if (!strncmp(str, "off", 3)) { + if (!strcmp(str, "off")) { pci_probe = 0; return NULL; + } else if (!strncmp(str, "io=", 3)) { + char *p; + unsigned int x = simple_strtoul(str+3, &p, 16); + if (p && *p) + return str; + pci_last_io_addr = x; + return NULL; } #ifdef CONFIG_PCI_BIOS - else if (!strncmp(str, "bios", 4)) { + else if (!strcmp(str, "bios")) { pci_probe = PCI_PROBE_BIOS; return NULL; - } else if (!strncmp(str, "nobios", 6)) { + } else if (!strcmp(str, "nobios")) { pci_probe &= ~PCI_PROBE_BIOS; return NULL; + } else if (!strcmp(str, "nosort")) { + pci_probe |= PCI_NO_SORT; + return NULL; } #endif #ifdef CONFIG_PCI_DIRECT - else if (!strncmp(str, "conf1", 5)) { + else if (!strcmp(str, "conf1")) { pci_probe = PCI_PROBE_CONF1; return NULL; } - else if (!strncmp(str, "conf2", 5)) { + else if (!strcmp(str, "conf2")) { pci_probe = PCI_PROBE_CONF2; return NULL; } --- linux-2.1.96/drivers/pci/pci.c Thu Apr 9 22:16:18 1998 +++ linux/drivers/pci/pci.c Fri Apr 17 18:32:48 1998 @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.71 1998/03/30 11:14:35 mj Exp $ + * $Id: pci.c,v 1.79 1998/04/17 16:25:24 mj Exp $ * * PCI Bus Services * @@ -17,44 +17,19 @@ #include <asm/page.h> +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + struct pci_bus pci_root; struct pci_dev *pci_devices = NULL; static struct pci_dev **pci_last_dev_p = &pci_devices; static int pci_reverse __initdata = 0; -#undef DEBUG - -const char *pcibios_strerror(int error) -{ - static char buf[32]; - - switch (error) { - case PCIBIOS_SUCCESSFUL: - case PCIBIOS_BAD_VENDOR_ID: - return "SUCCESSFUL"; - - case PCIBIOS_FUNC_NOT_SUPPORTED: - return "FUNC_NOT_SUPPORTED"; - - case PCIBIOS_DEVICE_NOT_FOUND: - return "DEVICE_NOT_FOUND"; - - case PCIBIOS_BAD_REGISTER_NUMBER: - return "BAD_REGISTER_NUMBER"; - - case PCIBIOS_SET_FAILED: - return "SET_FAILED"; - - case PCIBIOS_BUFFER_TOO_SMALL: - return "BUFFER_TOO_SMALL"; - - default: - sprintf (buf, "PCI ERROR 0x%x", error); - return buf; - } -} - - struct pci_dev * pci_find_slot(unsigned int bus, unsigned int devfn) { @@ -93,6 +68,28 @@ } +void +pci_set_master(struct pci_dev *dev) +{ + unsigned short cmd; + unsigned char lat; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (! (cmd & PCI_COMMAND_MASTER)) { + printk("PCI: Enabling bus mastering for device %02x:%02x\n", + dev->bus->number, dev->devfn); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) { + printk("PCI: Increasing latency timer of device %02x:%02x to 64\n", + dev->bus->number, dev->devfn); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + } +} + + __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus)) { unsigned int devfn, l, max, class; @@ -101,10 +98,7 @@ struct pci_bus *child; int reg; -#ifdef DEBUG - printk("pci_scan_bus for bus %d\n", bus->number); -#endif - + DBG("pci_scan_bus for bus %d\n", bus->number); max = bus->secondary; for (devfn = 0; devfn < 0xff; ++devfn) { if (PCI_FUNC(devfn) && !is_multi) { @@ -161,6 +155,8 @@ pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l); dev->base_address[reg] = (l == 0xffffffff) ? 0 : l; } + pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); + dev->rom_address = (l == 0xffffffff) ? 0 : l; break; case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ if (class >> 8 != PCI_CLASS_BRIDGE_PCI) @@ -169,6 +165,8 @@ pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l); dev->base_address[reg] = (l == 0xffffffff) ? 0 : l; } + pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); + dev->rom_address = (l == 0xffffffff) ? 0 : l; break; case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ if (class >> 16 != PCI_BASE_CLASS_BRIDGE) @@ -185,10 +183,7 @@ continue; } -#ifdef DEBUG - printk("PCI: %02x:%02x [%04x/%04x]\n", - bus->number, dev->devfn, dev->vendor, dev->device); -#endif + DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device); /* * Put it into the global PCI device chain. It's used to @@ -209,16 +204,15 @@ dev->sibling = bus->devices; bus->devices = dev; +#if 0 /* - * In case the latency timer value is less than 32, - * which makes everything very sllooowww, set it to - * 32. Pciutils should be used to fine-tune it later. - * Note that we don't check if the device is a bus-master: - * if it isn't, write to the latency timer should be ignored. + * Setting of latency timer in case it was less than 32 was + * a great idea, but it confused several broken devices. Grrr. */ pcibios_read_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, &tmp); if (tmp < 32) pcibios_write_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, 32); +#endif /* * If it's a bridge, scan the bus behind it. @@ -303,9 +297,7 @@ * * Return how far we've got finding sub-buses. */ -#ifdef DEBUG - printk("PCI: pci_scan_bus returning with max=%02x\n", max); -#endif + DBG("PCI: pci_scan_bus returning with max=%02x\n", max); return max; } @@ -330,26 +322,16 @@ #ifdef CONFIG_PCI_OPTIMIZE pci_quirks_init(); #endif - -#ifdef CONFIG_PROC_FS - proc_bus_pci_init(); -#ifdef CONFIG_PCI_OLD_PROC - proc_old_pci_init(); -#endif -#endif } __initfunc(void pci_setup (char *str, int *ints)) { - str = pcibios_setup(str); while (str) { char *k = strchr(str, ','); if (k) *k++ = 0; - if (*str) { - if (!(str = pcibios_setup(str)) || !*str) - continue; + if (*str && (str = pcibios_setup(str)) && *str) { if (!strcmp(str, "reverse")) pci_reverse = 1; else printk(KERN_ERR "PCI: Unknown option `%s'\n", str); --- linux-2.1.96/drivers/pci/pcisyms.c Thu Apr 2 19:12:24 1998 +++ linux/drivers/pci/pcisyms.c Fri Apr 17 18:41:44 1998 @@ -1,5 +1,5 @@ /* - * $Id: pcisyms.c,v 1.2 1998/02/16 10:35:57 mj Exp $ + * $Id: pcisyms.c,v 1.4 1998/04/17 16:34:19 mj Exp $ * * PCI Bus Services -- Exported Symbols * @@ -16,11 +16,12 @@ EXPORT_SYMBOL(pcibios_write_config_byte); EXPORT_SYMBOL(pcibios_write_config_word); EXPORT_SYMBOL(pcibios_write_config_dword); -EXPORT_SYMBOL(pcibios_strerror); EXPORT_SYMBOL(pci_devices); +EXPORT_SYMBOL(pci_root); EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_slot); +EXPORT_SYMBOL(pci_set_master); /* Backward compatibility */ --- linux-2.1.96/drivers/pci/proc.c Thu Apr 2 19:12:24 1998 +++ linux/drivers/pci/proc.c Thu Apr 16 22:54:33 1998 @@ -1,5 +1,5 @@ /* - * $Id: proc.c,v 1.8 1998/03/12 14:32:51 mj Exp $ + * $Id: proc.c,v 1.10 1998/04/16 20:48:30 mj Exp $ * * Procfs interface for the PCI bus. * @@ -250,6 +250,13 @@ "\t%016lx", #endif dev->base_address[i]); + len += sprintf(buf+len, +#if BITS_PER_LONG == 32 + "\t%08lx", +#else + "\t%016lx", +#endif + dev->rom_address); buf[len++] = '\n'; at += len; if (at >= pos) { @@ -298,7 +305,7 @@ } } -__initfunc(void proc_bus_pci_init(void)) +__initfunc(void pci_proc_init(void)) { struct proc_dir_entry *proc_pci; @@ -307,4 +314,8 @@ proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus); proc_register(proc_pci, &proc_pci_devices); proc_bus_pci_add(&pci_root, proc_pci); + +#ifdef CONFIG_PCI_OLD_PROC + proc_old_pci_init(); +#endif } --- linux-2.1.96/include/linux/pci.h Sat Apr 11 20:19:34 1998 +++ linux/include/linux/pci.h Thu Apr 16 22:54:37 1998 @@ -1,5 +1,5 @@ /* - * $Id: pci.h,v 1.62 1998/03/15 13:50:05 ecd Exp $ + * $Id: pci.h,v 1.67 1998/04/16 20:48:33 mj Exp $ * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt @@ -105,10 +105,10 @@ #define PCI_CARDBUS_CIS 0x28 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c #define PCI_SUBSYSTEM_ID 0x2e -#define PCI_ROM_ADDRESS 0x30 /* 32 bits */ -#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM, - bits 31..11 are address, - 10..2 are reserved */ +#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 +#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) + /* 0x34-0x3b are reserved */ #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ @@ -178,8 +178,8 @@ #define PCI_CB_IO_LIMIT_1_HI 0x3a /* 0x3c-0x3d are same as for htype 0 */ /* 0x3e-0x3f are same as for htype 1 */ -#define PCI_CB_SUBSYSTEM_ID 0x40 -#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x42 +#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 +#define PCI_CB_SUBSYSTEM_ID 0x42 #define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ /* 0x48-0x7f reserved */ @@ -979,8 +978,7 @@ #ifdef __KERNEL__ /* - * Error values that may be returned by the PCI bios. Use - * pcibios_strerror() to convert to a printable string. + * Error values that may be returned by the PCI bios. */ #define PCIBIOS_SUCCESSFUL 0x00 #define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 @@ -1008,7 +1006,6 @@ unsigned char where, unsigned short val); int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned int val); -const char *pcibios_strerror (int error); /* Don't use these in new code, use pci_find_... instead */ @@ -1051,6 +1048,7 @@ * pcibios_fixup() as necessary. */ unsigned long base_address[6]; + unsigned long rom_address; }; struct pci_bus { @@ -1076,8 +1074,9 @@ void pci_setup(char *str, int *ints); void pci_quirks_init(void); unsigned int pci_scan_bus(struct pci_bus *bus); -void proc_bus_pci_init(void); +void pci_proc_init(void); void proc_old_pci_init(void); +int get_pci_list(char *buf); struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from); struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from); @@ -1090,8 +1089,7 @@ #define pci_write_config_byte(dev, where, val) pcibios_write_config_byte(dev->bus->number, dev->devfn, where, val) #define pci_write_config_word(dev, where, val) pcibios_write_config_word(dev->bus->number, dev->devfn, where, val) #define pci_write_config_dword(dev, where, val) pcibios_write_config_dword(dev->bus->number, dev->devfn, where, val) - -int get_pci_list (char *buf); +void pci_set_master(struct pci_dev *); #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ --- linux-2.1.96/drivers/block/ide-proc.c Tue Apr 7 16:48:54 1998 +++ linux/drivers/block/ide-proc.c Thu Apr 16 15:09:48 1998 @@ -226,7 +226,7 @@ restore_flags(flags); printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", msg, dev->bus->number, dev->devfn, reg, val); - printk("proc_ide_write_config: %s\n", pcibios_strerror(rc)); + printk("proc_ide_write_config: error %d\n", rc); return -EIO; } #endif /* CONFIG_BLK_DEV_IDEPCI */ @@ -271,7 +271,7 @@ if (rc) { printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n", dev->bus->number, dev->devfn, reg); - printk("proc_ide_read_config: %s\n", pcibios_strerror(rc)); + printk("proc_ide_read_config: error %d\n", rc); return -EIO; out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n'); } else --- linux-2.1.96/drivers/scsi/53c7,8xx.c Sat Apr 11 20:13:25 1998 +++ linux/drivers/scsi/53c7,8xx.c Wed Apr 15 16:18:38 1998 @@ -5143,8 +5124,8 @@ pci_status &= ~PCI_STATUS_PARITY; } } else { - printk ("scsi%d : couldn't read status register : %s\n", - host->host_no, pcibios_strerror (tmp)); + printk ("scsi%d : couldn't read status register : error %d\n", + host->host_no, tmp); retry = NEVER; } } --- linux-2.1.96/drivers/scsi/gdth.c Sat Apr 11 20:13:25 1998 +++ linux/drivers/scsi/gdth.c Wed Apr 15 16:39:35 1998 @@ -73,7 +91,7 @@ * Initial revision * * - * $Id: gdth.c,v 1.3 1998/02/25 23:52:32 ecd Exp $ + * $Id: gdth.c,v 1.4 1998/04/15 14:35:26 mj Exp $ ************************************************************************/ #ifdef MODULE @@ -473,8 +489,7 @@ if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_ROM_ADDRESS, (int *) &pcistr->bios))) { - printk("GDT-PCI: error %s reading configuration space", - pcibios_strerror(error)); + printk("GDT-PCI: error %d reading configuration space", error); return -1; } pcistr->irq = pdev->irq; @@ -499,8 +514,7 @@ GDTH_BASEP&pcistr->bios)) || (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn, PCI_INTERRUPT_LINE,&pcistr->irq))) { - printk("GDT-PCI: error %s reading configuration space", - pcibios_strerror(error)); + printk("GDT-PCI: error %d reading configuration space", error); return -1; } #endif --- linux-2.1.96/Documentation/pci.txt Thu Apr 2 19:12:22 1998 +++ linux/Documentation/pci.txt Wed Apr 15 16:15:21 1998 @@ -53,8 +53,13 @@ 4. Obsolete functions ~~~~~~~~~~~~~~~~~~~~~ - <linux/bios32.h> is obsolete and should not be included in new code. pcibios_find_(device|class) are also obsolete and should be replaced by pci_find_(device|class). + +5. Bus mastering +~~~~~~~~~~~~~~~~ + If you need to setup a bus-mastering card, just call pci_set_master(). It +should set PCI_COMMAND_MASTER in the command register and adjust the latency +timer if needed. --- linux-2.1.96/drivers/block/ide-dma.c Fri Apr 17 19:06:25 1998 +++ linux/drivers/block/ide-dma.c Fri Apr 17 19:06:28 1998 @@ -333,7 +333,7 @@ */ __initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name)) { - unsigned long new, dma_base = 0; + unsigned long dma_base = 0; if (hwif->mate && hwif->mate->dma_base) { dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); --- linux-2.1.96/drivers/pci/pci.c Fri Apr 17 19:28:29 1998 +++ linux/drivers/pci/pci.c Fri Apr 17 19:30:44 1998 @@ -322,6 +322,10 @@ #ifdef CONFIG_PCI_OPTIMIZE pci_quirks_init(); #endif + +#ifdef CONFIG_PROC + pci_proc_init(); +#endif }

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu