Implement searching for multiple PCI devices matching a pattern.

This commit is contained in:
Jonas 'Sortie' Termansen 2014-03-25 00:31:25 +01:00
parent 400eb2238f
commit 50ee8ca323
3 changed files with 28 additions and 17 deletions

View File

@ -100,7 +100,7 @@ addr_t DetectBGAFramebuffer()
memset(&pcifind, 255, sizeof(pcifind));
pcifind.vendorid = 0x1234;
pcifind.deviceid = 0x1111;
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
if ( (devaddr = PCI::SearchForDevices(pcifind, 0)) )
return ParseDevBar0(devaddr);
// Search for a generic VGA compatible device.
@ -108,7 +108,7 @@ addr_t DetectBGAFramebuffer()
pcifind.classid = 0x03;
pcifind.subclassid = 0x00;
pcifind.progif = 0x00;
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
if ( (devaddr = PCI::SearchForDevices(pcifind)) )
return ParseDevBar0(devaddr);
return 0;

View File

@ -92,7 +92,7 @@ void Write32(uint32_t devaddr, uint8_t off, uint32_t val); // Host endian
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val); // PCI endian
pciid_t GetDeviceId(uint32_t devaddr);
pcitype_t GetDeviceType(uint32_t devaddr);
uint32_t SearchForDevice(pcifind_t pcifind);
uint32_t SearchForDevices(pcifind_t pcifind, uint32_t last = 0);
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar);
pcibar_t GetExpansionROM(uint32_t devaddr);
void EnableExpansionROM(uint32_t devaddr);

View File

@ -139,35 +139,46 @@ static bool MatchesSearchCriteria(uint32_t devaddr, pcifind_t pcifind)
return true;
}
static uint32_t SearchForDeviceOnBus(uint8_t bus, pcifind_t pcifind)
// TODO: This iterates the whole PCI device tree on each call!
static uint32_t SearchForDevicesOnBus(uint8_t bus, pcifind_t pcifind, uint32_t last = 0)
{
for ( unsigned slot = 0; slot < 32; slot++ )
bool found_any_device = false;
uint32_t next_device = 0;
for ( unsigned int slot = 0; slot < 32; slot++ )
{
unsigned numfuncs = 1;
for ( unsigned func = 0; func < numfuncs; func++ )
unsigned int num_functions = 1;
for ( unsigned int function = 0; function < num_functions; function++ )
{
uint32_t devaddr = MakeDevAddr(bus, slot, func);
if ( MatchesSearchCriteria(devaddr, pcifind) )
return devaddr;
uint32_t devaddr = MakeDevAddr(bus, slot, function);
if ( last < devaddr &&
(!found_any_device || devaddr < next_device) &&
MatchesSearchCriteria(devaddr, pcifind) )
next_device = devaddr, found_any_device = true;
uint8_t header = Read8(devaddr, 0x0D); // Secondary Bus Number.
if ( header & 0x80 ) // Multi function device.
numfuncs = 8;
num_functions = 8;
if ( (header & 0x7F) == 0x01 ) // PCI to PCI bus.
{
uint8_t subbusid = Read8(devaddr, 0x1A);
uint32_t recret = SearchForDeviceOnBus(subbusid, pcifind);
if ( recret )
return recret;
uint32_t recret = SearchForDevicesOnBus(subbusid, pcifind, last);
if ( last < recret &&
(!found_any_device || recret < next_device) )
next_device = recret, found_any_device = true;
}
}
}
return 0;
if ( !found_any_device )
return 0;
return next_device;
}
uint32_t SearchForDevice(pcifind_t pcifind)
uint32_t SearchForDevices(pcifind_t pcifind, uint32_t last)
{
// Search on bus 0 and recurse on other detected busses.
return SearchForDeviceOnBus(0, pcifind);
return SearchForDevicesOnBus(0, pcifind, last);
}
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar)