I can't get classID of PCI device.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Shvets04
Member
Member
Posts: 28
Joined: Wed Feb 13, 2019 3:07 pm

I can't get classID of PCI device.

Post 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?
nullplan
Member
Member
Posts: 1792
Joined: Wed Aug 30, 2017 8:24 am

Re: I can't get classID of PCI device.

Post 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;
}
Carpe diem!
Octocontrabass
Member
Member
Posts: 5575
Joined: Mon Mar 25, 2013 7:01 pm

Re: I can't get classID of PCI device.

Post 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.
Shvets04
Member
Member
Posts: 28
Joined: Wed Feb 13, 2019 3:07 pm

Re: I can't get classID of PCI device.

Post 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
Shvets04
Member
Member
Posts: 28
Joined: Wed Feb 13, 2019 3:07 pm

Re: I can't get classID of PCI device.

Post by Shvets04 »

Octocontrabass wrote: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.

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);
rkennedy9064
Member
Member
Posts: 36
Joined: Wed Sep 01, 2010 3:54 pm

Re: I can't get classID of PCI device.

Post by rkennedy9064 »

Shvets04 wrote:
Octocontrabass wrote: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.

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()
    }
}
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: I can't get classID of PCI device.

Post 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.
Post Reply