Code: Select all
for(int bus = 0; bus <= 0xFF; bus++) {
for(int dev = 0; dev <= 0x1F; dev++) {
for(int fnc = 0; fnc <= 0x07; fnc++) {
pci_cfg = pci::read_pci(bus, dev, fnc);
}
}
}
regards
Code: Select all
for(int bus = 0; bus <= 0xFF; bus++) {
for(int dev = 0; dev <= 0x1F; dev++) {
for(int fnc = 0; fnc <= 0x07; fnc++) {
pci_cfg = pci::read_pci(bus, dev, fnc);
}
}
}
For each PCI bridge there's a "primary bus" and a "secondary bus" where the secondary bus is the bus on the other side of the bridge. Because PCI is a hierarchy of buses, you can start at the top (which is always "bus 0") and find all other buses without checking every bus number.os64dev wrote:Currently i am trying to enumerate all the pci devices with the following code. It is kind a raw i guess because it scans all the posibble combinations. pci::read_pci returns a pointer to the configuration header of a device or null if there is no device at that location.
Very roughly, it'd go something like:os64dev wrote:now my question is because i find a lot of pci bridges how do i detect de devices behind the bridges, do i have to program the bridge device? or does the above code find all the device.
Code: Select all
void main(void) {
scanPCIbus(0);
}
void scanPCIbus(int bus) {
int device;
int function;
for(device = 0; device < 32; device ++) {
if( checkIfMultifunction(bus, device) == MULTI_FUNCTION) {
for(function = 0; function < 7; function++) {
scanPCIfunction(bus, device, function);
}
} else {
scanPCIfunction(bus, device, 0);
}
}
}
void scanPCIfunction(int bus, int device, int function) {
int type;
if( (bus == 0) && (device == 0) ) {
handlePCIhostController(bus, device, function);
} else {
type = getPCIdeviceType();
switch(type) {
case PCI_TO_PCI_BRIDGE:
handlePCItoPCIbridge(bus, device, function);
break;
/* More device types here */
}
}
}
void handlePCIhostController(int bus, int device, int function) {
scanPCIbus( getSecondaryBus(bus, device, function) );
}
void handlePCItoPCIbridge(int bus, int device, int function); {
scanPCIbus( getSecondaryBus(bus, device, function) );
}
To determine if the device is a multi-function device, you need to check bit 7 of the "header type" field in the devices PCI configuration space (set = multifunction, clear = single function).os64dev wrote:@brendanthanks for the explanation, i see that i get all the devices though in a very inefficient way. Your code example explains a lot and shows a lot of similarities with a new version i've implemented but i seem to get stuck at the function getSecondaryBus how is this implemented and where can i obtain more information about it and please another answer then pcisig
Code: Select all
mov ax, 0xb101
int 0x1a ; get PCI bus info
jc short nopci
; check signature bytes
cmp dx, 0x4350
jne short nopci
; check for error code, AH=00 is good
test ah, ah
jne short nopci
; info is here, then. CL is the PCI bus count -1
; BH is the PCI major version number of the chipset
; BL is the PCI minor version number
; AL bit 0 means "use configuration method 1" -- should always be set
; bit 1 means "use config method 2" -- should never be set
; bit 4 means use special cycle method 1
; bit 5 means use special cycle method 2
As said above, your code finds all the devices, because the BIOS programmed and initialized all the PCI devices (including bridges) during bootup.os64dev wrote:how do i detect the devices behind the bridges, do i have to program the bridge device?
for the sequential busses thingy i'll have to check that because i think it skipped a bus on my amd64 x2 4400+. i also don't use grub fro the same reasons.bewing wrote:If you are not using GRUB, then while you are still in real mode, you can do an INT call to get the total number of PCI busses, and shorten your loop to only what is used. Busses are always supposed to be sequential -- no skips.
(This is one reason why I don't use GRUB, and wrote my own bootloader -- GRUB doesn't pass me enough info from real mode.)