While Intel documentation lists PCI capability as 32 bit entities,

the PCI specifications lists it as two 8 bit entities, followed by
a unknown number of vendor specific data. It should be better to do
two 8 bit reads, instead of one 16 or 32 bit access.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@479 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2002-07-27 20:24:45 +00:00
parent ef831f3638
commit 3fe5330ccb

View File

@ -433,7 +433,7 @@ static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
uint8 *offs)
{
uint16 status;
uint32 reg_data;
uint8 cap_data;
uint8 hdr_type;
uint8 ofs;
int maxcount;
@ -458,27 +458,33 @@ static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
return 0;
}
/* the 192 bytes vendor defined configuration space
* can hold as maximum 48 times a 32 bit capability
/* the 192 bytes vendor defined configuration space can
* hold as maximum 48 times a 32 bit aligned capability,
* we use this as abort condition to avoid lock up by
* searching in a circular loop on bad hardware
*/
maxcount = 48;
ofs = read_pci_config(bus, dev, func, ofs, 1);
while (maxcount-- != 0 && ofs != 0) {
/* mask off potentially wrong bits */
/* mask off low two bits, demanded by PCI standard */
ofs &= ~3;
/* capabilities must be read as 32bit access */
reg_data = read_pci_config(bus, dev, func, ofs, 4);
/* PCI specification 2.2, section 6.8.1.1 and following
* describe capability ID and next capability position as
* two 8 bit values, the "capability ID" is at the 32 bit
* aligned position, after it the "next pointer" follows.
*/
/* lower 8 bit (0 to 7) contain the capability */
if ((reg_data & 0xff) == cap) {
/* read the 8 bit capability id is at the 32bit aligned ofs position */
cap_data = read_pci_config(bus, dev, func, ofs, 1);
if (cap_data == cap) {
if (offs)
*offs = ofs;
return 1;
}
/* bit 8 to 15 contain next capability position */
ofs = (reg_data >> 8) & 0xff;
/* at ofs + 1, we can read the next capability position */
ofs = read_pci_config(bus, dev, func, ofs + 1, 1);
}
return 0;
}