PCI on real hardware

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
nhruo123
Posts: 3
Joined: Mon Apr 06, 2020 5:06 am

PCI on real hardware

Post by nhruo123 »

Hey, I started working on a toy OS, I was working on a E1000 driver and I found a weird issue that if I don't print to the screen the packet won't appear in Qemu network dump and the NIC won't raise an interrupt after moving the head pointer ( It does raise it if I print ). I wasn't sure what causes the issue so after extensive debugging I decided to test read hardware ( naively thinking the e1000 on Qemu is bugged ), but when I booted up my OS on an old laptop it didn't find my network card ( I am pretty sure I have a E1000 "like" card in there ), but what's weirder is that all the PCI devices I found where vendor id 0x8086 and device id 0x8086, but the class codes and header types where correct. I tried another old PC I had laying around and to nobody surprise it printed the same PCI logs, all the entries are vendor id 0x8086 and device id 0x8086.
So right now I am really stuck I have no idea why all the PCI devices are showing up weird like that, I am sure I have done something wrong but I can't figure out what, because in the only environment I can debug( Qemu ) everything is working as expected ( beside the e1000 but I don't care about that right now ) so I am not sure how to approach this issue.
I am totally lost :( , so I came here for advice, if you have any idea on how to tackle this issue or if you faced something similar to this I would love to hear about it.

My repo: https://github.com/nhruo123/MonkaOS/tree/master
Funny print that makes e1000 work: https://github.com/nhruo123/MonkaOS/blo ... od.rs#L144


Real hardware showing funny PCI values:
My Laptop showing weird PCI values
My Laptop showing weird PCI values
Qemu showing sane PCI values:
Qemu showing sane PCI values
Qemu showing sane PCI values
nullplan
Member
Member
Posts: 1643
Joined: Wed Aug 30, 2017 8:24 am

Re: PCI on real hardware

Post by nullplan »

To my knowledge, you can only use doubleword aligned accesses with the port access method. You should keep the low two bits of PCI_ADDRESS clear and access PCI_DATA with doubleword accesses only. To that end, don't use a template method. You can only read and write three data types here, and they are all different. I personally am only ever using 32-bit methods with either the port or MMIO access method, to reduce the amount of differences.
Carpe diem!
nhruo123
Posts: 3
Joined: Mon Apr 06, 2020 5:06 am

Re: PCI on real hardware

Post by nhruo123 »

nullplan wrote:To my knowledge, you can only use doubleword aligned accesses with the port access method. You should keep the low two bits of PCI_ADDRESS clear and access PCI_DATA with doubleword accesses only. To that end, don't use a template method. You can only read and write three data types here, and they are all different. I personally am only ever using 32-bit methods with either the port or MMIO access method, to reduce the amount of differences.
Hey wow thanks for the quick reply! you where on point, I totally missed the fact that you can only read and write double word aligned data from the PCI config space, fixing that solved the issue instantly!
And I also found the issue with the network driver, the Transmission Descriptor List was unaligned #-o , I am kinda new to rust and for some reason rust won't let you put packed and aligned on a struct so I assumed packed implies aligned as well. Fixed that and now it works 100% of the times!

And on the topic of my old laptop, I found out I have an Intel 82562GT, but I couldn't find a manual for it, after a bit of extra searching I found this site https://linux-hardware.org/?id=pci:8086-10c4-103c-30d7 that claims that the Linux e1000 driver can works with the 82562GT so I added an entry for that card in my driver array and it seems to work ( the transmit head moved after writing to the tail ).
But I don't want to make more false assumptions, do you know if they are compatible and/or how to find the 82562GT manual?

FYI I follow this spec for my e1000 https://pdos.csail.mit.edu/6.828/2023/r ... Be_SDM.pdf
nullplan
Member
Member
Posts: 1643
Joined: Wed Aug 30, 2017 8:24 am

Re: PCI on real hardware

Post by nullplan »

nhruo123 wrote:I am kinda new to rust
See, I don't know Rust at all. I only know C well. I am passable at C++ and other C-based languages (e.g. C#), but the language I use for everything is C. I like Haskell, but I'm terrible at it. But still I could understand enough of your code to see that the PCI accesses were misaligned.
nhruo123 wrote:and for some reason rust won't let you put packed and aligned on a struct so I assumed packed implies aligned as well.
I seriously dislike the packed attribute. Better to just understand padding rules and use the correct data types. E.g my TSS type is just

Code: Select all

struct splitptr {
    uint32_t low, high;
};

struct tss {
    uint32_t res0;
    struct splitptr
        rsp0,
        rsp1,
        rsp2,
        res1,
        ist1,
        ist2,
        ist3,
        ist4,
        ist5,
        ist6,
        ist7,
        res2;
    uint16_t res3, ioploff;
};
No alignment or packing directive required.
nhruo123 wrote:I found out I have an Intel 82562GT, but I couldn't find a manual for it,
I found a manual that says the card is part of the IO controller hub. I would search for a data sheet for that one. They often have all of the registers.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5218
Joined: Mon Mar 25, 2013 7:01 pm

Re: PCI on real hardware

Post by Octocontrabass »

nullplan wrote:To my knowledge, you can only use doubleword aligned accesses with the port access method. You should keep the low two bits of PCI_ADDRESS clear and access PCI_DATA with doubleword accesses only.
It's a good idea to stick to dword accesses, but PCI_DATA allows byte and word accesses to any subset of the dword selected by PCI_ADDRESS if you really can't find a way to make it work with the whole dword.
Post Reply