Page 1 of 1
I can't get classID of PCI device.
Posted: Sat Apr 18, 2020 8:13 pm
by Shvets04
hi, i write pci driver. but my function get_class_id returns 0x0 for all detected device.
Code: Select all
u16 get_class_id(u16 bus, u16 device, u16 function)
{
u32 r0 = pci_read_word(bus,device,function,0xa);
return (r0 & ~0x00FF) >> 8;
}
full code -
https://github.com/s04v/OSv1.0/blob/mas ... vers/pci.c
how to solve this problem?
Re: I can't get classID of PCI device.
Posted: Sat Apr 18, 2020 9:13 pm
by nullplan
That is a misaligned read. The offset always needs to be divisible by 4, meaning in hex it always has to end in 0, 4, 8, or C. In your case:
Code: Select all
u16 get_class_id(u16 bus, u16 device, u16 function)
{
u32 r0 = pci_read_word(bus,device,function,0x8);
return (r0 >> 24) & 0xFF;
}
Re: I can't get classID of PCI device.
Posted: Sat Apr 18, 2020 11:56 pm
by Octocontrabass
You shouldn't copy someone else's code if you don't understand it.
I suspect this mistake originates
in the wiki, where the example function reads 16-bit words despite configuration mechanism 1 functioning exclusively in 32-bit dwords.
Re: I can't get classID of PCI device.
Posted: Sun Apr 19, 2020 3:17 am
by Shvets04
nullplan wrote:That is a misaligned read. The offset always needs to be divisible by 4, meaning in hex it always has to end in 0, 4, 8, or C. In your case:
Code: Select all
u16 get_class_id(u16 bus, u16 device, u16 function)
{
u32 r0 = pci_read_word(bus,device,function,0x8);
return (r0 >> 24) & 0xFF;
}
It's not working correctly
Re: I can't get classID of PCI device.
Posted: Sun Apr 19, 2020 3:22 am
by Shvets04
where can i find correct function definition?
I take it there's a problem with this line?
Code: Select all
tmp = (u16)((inw(0xCFC) >> ((offset & 2) * 8)) & 0xffff);
Re: I can't get classID of PCI device.
Posted: Sun Apr 19, 2020 10:26 pm
by rkennedy9064
Shvets04 wrote:
where can i find correct function definition?
I take it there's a problem with this line?
Code: Select all
tmp = (u16)((inw(0xCFC) >> ((offset & 2) * 8)) & 0xffff);
My guess would probably be inw, which is defined as u16 inw(u16 port) in your port.h. Those ports read and write 32 bits, so you read the full int and then break it up. This is how I do it in my OS, but my code isn't C/C++.
Code: Select all
let (device_id, vendor_id) = read_2_words(address, 0x00);
fn read_2_words(address: u32, offset: u32) -> (u16, u16) {
let value = read_offset(address, offset);
let high_word = (value >> 16) as u16;
let low_word = value as u16;
(high_word, low_word)
}
fn read_offset(mut address: u32, offset: u32) -> u32 {
let mut config_address = Port::new(CONFIG_ADDRESS);
let mut data_address = Port::new(DATA_ADDRESS);
address |= offset & 0xFC;
unsafe {
config_address.write(address);
data_address.read()
}
}
Re: I can't get classID of PCI device.
Posted: Mon May 04, 2020 8:03 am
by Klakap
Code: Select all
u16 pci_read_word(u8 bus, u8 slot, u8 func, u8 offset)
{
u32 address;
u32 lbus = (u32)bus;
u32 lslot = (u32)slot;
u32 lfunc = (u32)func;
u16 tmp = 0;
address = (u32)((lbus << 16) | (lslot << 11) |
(lfunc << 8) | (offset & 0xfc) | ((u32)0x80000000));
outw(0xCF8, address);
tmp = (u16)((inw(0xCFC) >> ((offset & 2) * 8)) & 0xffff);
return (tmp);
}
You must use outl and inl functions.