Hi,
lemonyii wrote:as to the break, i remember a book referred that if you got 0xffffffff in vendor id and device id, it is a null slot and you may regard it as the end of you emuration.
and i think that it does not matter if i emurate by BFS or DFS if a check all the devices, right?
thx
For PCI there's up to 256 buses, up to 32 devices per bus and up to 8 functions per device. If you scan all functions in all devices on all buses it'll add up to 65536 checks and take far too long (because even for PCI devices, accessing I/O ports isn't fast), and in some cases you'll get wrong information for using information that doesn't exist (e.g. trying to get information for a device's second function when the device is a "single function" device).
For PCI devices, there's a flag in configuration space (bit 7 in the "Header Type" field) that says if the device is a multi-function device or not. If this bit isn't set then there's only one function and you don't need to check for any more (and shouldn't attempt to check for more functions). If the bit is set, then you check the functions in order and stop at the first unimplemented function.
For the PCI buses, there's host controller/s and PCI bridges. You start checking with the host controller/s PCI bus number, and when you find a PCI bridge you find the "secondary bus number" from it's configuration space and scan that PCI bus too. In that way you discover all PCI buses without checking any PCI buses that don't exist. The first PCI host controller is always "bus 0, device 0, function 0", and if this device is a multi-function device then additional host controllers will be part of the same device.
For devices within a bus, you do have to check all 32 of them.
It's usually easier to use at least 2 pieces of code for this - one piece to scan each device on a specific bus and determine if each device is multi-function or not, and one to determine if a specific function on a specific device on a specific bus is a PCI bridge or host controller (and call the first "scan_bus(secondary_bus_number)" piece of code if it is).
For example:
Code: Select all
void scan_PCI_bus(uint8_t bus_number) {
uint8_t device_number;
uint8_t function_number;
for(device_number = 0; device_number < 32; device_number++) {
if( device_exists ) {
function_number = 0;
if( device_is_multifunction ) {
while( (handle_PCI_function(bus_number, device_number, function_number) == 0) && (function_number < 7) {
function_number++;
}
} else { // Device is single-function
handle_PCI_function(bus_number, device_number, function_number);
}
}
}
}
int handle_PCI_function(uint8_t bus_number, uint8_t device_number, uint8_t function_number) {
uint8_t secondary_bus_number;
if( function_exists ) {
// Do other stuff here (display information about the device??)
if( (device_is_host_controller) || (device_is_PCI_to_PCI_bridge) ) {
secondary_bus_number = get_secondary_bus_number(bus_number, device_number, function_number);
scan_PCI_bus(secondary_bus_number);
}
return 0;
} else {
return 1;
}
}
Cheers,
Brendan