Re: pre11b and CardBus Bridges :-(

Martin Mares (mj@atrey.karlin.mff.cuni.cz)
Thu, 30 Apr 1998 15:05:16 +0200


Hi,

> Bad news :-( Neither pre11b nor pre10 recognize my TI 1131 Cardbus Bridge
> and so PCMCIA services don't work.

My fault, it seems -- my "alien header type" detection considered CardBus
Bridge headers alien :-(

The following patch should fix it (please check /proc/pci as well).
[As a side effect, it removes bogus base addresses for PCI-to-PCI bridges
in /proc/pci, too.]

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
"If NT is the answer, you didn't understand the question."

--- ./drivers/pci/pci.c.mj Thu Apr 30 14:38:14 1998 +++ ./drivers/pci/pci.c Thu Apr 30 14:48:20 1998 @@ -892,15 +892,16 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size) { unsigned long base; - unsigned int l, class_rev, bus, devfn; + unsigned int l, class_rev, bus, devfn, last_reg; unsigned short vendor, device, status; - unsigned char bist, latency, min_gnt, max_lat; + unsigned char bist, latency, min_gnt, max_lat, hdr_type; int reg, len = 0; const char *str; bus = dev->bus->number; devfn = dev->devfn; + pcibios_read_config_byte (bus, devfn, PCI_HEADER_TYPE, &hdr_type); pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev); pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor); pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device); @@ -979,7 +980,17 @@ len += sprintf(buf + len, "Max Lat=%d.", max_lat); } - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { + switch (hdr_type & 0x7f) { + case 0: + last_reg = PCI_BASE_ADDRESS_5; + break; + case 1: + last_reg = PCI_BASE_ADDRESS_1; + break; + default: + last_reg = 0; + } + for (reg = PCI_BASE_ADDRESS_0; reg <= last_reg; reg += 4) { if (len + 40 > size) { return -1; } @@ -1072,7 +1083,7 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) { unsigned int devfn, l, max; - unsigned char cmd, tmp, hdr_type, is_multi = 0; + unsigned char cmd, tmp, hdr_type, ht, is_multi = 0; struct pci_dev_info *info; struct pci_dev *dev; struct pci_bus *child; @@ -1146,10 +1157,20 @@ /* * Check if the header type is known and consistent with - * device type. Bridges should have hdr_type 1, all other - * devices 0. + * device type. PCI-to-PCI Bridges should have hdr_type 1, + * CardBus Bridges 2, all other devices 0. */ - if ((dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) != (hdr_type & 0x7f)) { + switch (dev->class >> 8) { + case PCI_CLASS_BRIDGE_PCI: + ht = 1; + break; + case PCI_CLASS_BRIDGE_CARDBUS: + ht = 2; + break; + default: + ht = 0; + } + if (ht != (hdr_type & 0x7f)) { printk(KERN_WARNING "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", bus->number, dev->devfn, dev->vendor, dev->device, dev->class, hdr_type); continue;

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