Code: Select all
uint32_t read_pci ( const uint8_t bus, const uint8_t device, const uint8_t func, const uint8_t port /*, const uint8_t len */ ) {
uint32_t ret;
const uint32_t val = 0x80000000 | ( bus << 16 ) | ( device << 11 ) | ( func << 8 ) | ( port & 0xFC );
outd ( 0x0CF8, val );
extern uint32_t ind( uint32_t in_port );
/* ret = ind( 0x0CFC + ( port & 0x3) ); */
/* ret &= ( 0xFFFFFFFF >> ( ( 4 - len ) * 8 ) ); */
ret = ( ( ind ( 0xCFC ) >> ( ( port & 2 ) * 8 ) ) & 0xFFFF );
return ret;
}
/*
Scan all pci busses, devices and functions
*/
void enumerate_pci () {
uint8_t bus = 0;
uint8_t device = 0;
uint8_t func = 0;
uint32_t vendor_id;
uint32_t device_id;
uint32_t sub_class;
uint32_t class;
for ( bus = 0; bus < 255; bus++ ) {
for ( device = 0; device < 32; device++ ) {
for ( func = 0; func < 8; func++ ) {
/* vendor id at offset 0 */
vendor_id = read_pci ( bus, device, func, 0 );
/* vendor found check for device id, subclass and class */
if ( vendor_id != 0xFFFF ) {
/* vendor id at offset 2 */
device_id = read_pci ( bus, device, func, 2 );
/* subclass at offset 0x0A */
sub_class = read_pci ( bus, device, func, 0x0A );
/* class at offset 0x0B */
class = read_pci ( bus, device, func, 0x0B );
log(DEBUG, "Vend: %p did: %p sub: %p c: %p", vendor_id, device_id, sub_class, class);
}
}
}
}
}
Here's the output (on QEMU)
Vend: 00008086 did: 00001237 sub: 00000600 c: 00000600
Vend: 00008086 did: 00007000 sub: 00000601 c: 00000601
Vend: 00008086 did: 00007010 sub: 00000101 c: 00000101
Vend: 00008086 did: 00007113 sub: 00000680 c: 00000680
Vend: 00001013 did: 000000B8 sub: 00000300 c: 00000300
Vend: 00008086 did: 0000100E sub: 00000200 c: 00000200
Seems that the sub class and class are the same.