I am attempting to enumerate the pci configuration space (on qemu, if that matters, I haven't had a chance to try on real hardware), but the ID always comes out as 0x1111, and the vendor always comes out as 0.
my pci code looks like this
Code: Select all
#define PCI_ADDR 0x0CF8
#define PCI_DATA 0x0CFC
// port is the byte offset from 0x00
unsigned char pci_read_byte(const int bus, const int dev, const int func, const int port) {
const int shift = ((port & 3) * 8);
const unsigned int val = 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (port & 0xFC);
outl(PCI_ADDR, val);
return (inl(PCI_DATA) >> shift) & 0xFF;
}
// port is the byte offset from 0x00
unsigned short pci_read_word(const int bus, const int dev, const int func, const int port) {
if ((port & 3) <= 2) {
const int shift = ((port & 3) * 8);
const unsigned int val = 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (port & 0xFC);
outl(PCI_ADDR, val);
return (inl(PCI_DATA) >> shift) & 0xFFFF;
} else
return (pci_read_byte(bus, dev, func, port + 1) << 8) | pci_read_byte(bus, dev, func, port);
}
// port is the byte offset from 0x00
unsigned int pci_read_dword(const int bus, const int dev, const int func, const int port) {
if ((port & 3) == 0) {
const unsigned int val = 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (port & 0xFC);
outl(PCI_ADDR, val);
return inl(PCI_DATA);
} else
return (pci_read_word(bus, dev, func, port + 2) << 16) | pci_read_word(bus, dev, func, port);
}
Code: Select all
/// max pci buses to enumerate
pub const PCI_MAX_BUS: i32 = 256;
/// max number of devices to enumerate in a bus
pub const PCI_MAX_DEV: i32 = 32;
/// max number of functions to enumerate in a device
pub const PCI_MAX_FUNC: i32 = 8;
pub unsafe fn probe() {
let mut found = false;
let mut nonzero = false;
// enumerate pci buses
for bus in 0..PCI_MAX_BUS {
for dev in 0..PCI_MAX_DEV {
for func in 0..PCI_MAX_FUNC {
// read the first 16 bytes of the function
// if it is not 0xFFFF, then it's a valid function
let id = pci::pci_read_dword(bus, dev, func, 0x00);
// vendor is bits 31:16
let vendor = (id & 0xFFFF0000) << 15;
dbgln!(
"[{}][{}][{}] -> id: {i:b} ({i:x}), vendor: {v:b} ({v:x})",
bus,
dev,
func,
i = id,
v = vendor
);
if vendor != 0xFFFF {
// 0x09 is CC - Class Code
// see 2.1.5 of the intel serial ata spec
let class_code = pci::pci_read_dword(bus, dev, func, 0x09);
// base class code, bits 23:16
let bcc = (class_code & 0x0000FF00) << 15;
// sub class code, bits 15:08
let scc = (class_code & 0x00FF0000) << 7;
dbgln!("[{}][{}][{}] -> class code: {:b}, base class code: {:b}, sub class code: {:b}", bus, dev, func, class_code, bcc, scc);
if bcc == 0x01 && scc == 0x06 {
found = true;
}
if bcc != 0 || scc != 0 {
nonzero = true;
}
}
}
}
}
dbgln!(
"found a suitable drive: {}\nany values nonzero? : {}",
found,
nonzero
);
}
Code: Select all
[1][12][0] -> class code: 10001000000000000000000010001, base class code: 0, sub class code: 0
[1][12][1] -> id: 1000100010001 (1111), vendor: 0 (0)
[1][12][1] -> class code: 10001000000000000000000010001, base class code: 0, sub class code: 0
[1][12][2] -> id: 1000100010001 (1111), vendor: 0 (0)
[1][12][2] -> class code: 10001000000000000000000010001, base class code: 0, sub class code: 0
[1][12][3] -> id: 1000100010001 (1111), vendor: 0 (0)
[1][12][3] -> class code: 10001000000000000000000010001, base class code: 0, sub class code: 0
[1][12][4] -> id: 1000100010001 (1111), vendor: 0 (0)
[1][12][4] -> class code: 10001000000000000000000010001, base class code: 0, sub class code: 0
thank you,
skylar alexandra bleed