PCI Configuration & 82371SB
PCI Configuration & 82371SB
First, I would like to say that this is a great website and I learned a lot here.
I am developing my own OS to educate myself about the inner workings of the x86 platform. Now I am at the stage to implement some PCI functionality.
I decided to start this by writing a driver (sort of) for the Intel 82371SB chip, which seems to be a good idea because it is the inbuilt PCI IDE interface in Bochs and I would need to handle IDE anyway sooner or later. I think I could have done this by using PIO but if I understand correctly that would put heavy loads on the CPU during I/O operations. Handling IDE through the classic way of ISA DMA would require me to be able to allocate memory strictly under the 16 MByte barrier, and that wouldn't play nicely along with my memory handling (paging) routines. It is my understanding DMA with PCI doesn't have that limitation, but since I don't know much about DMA yet I might be wrong. In that case, please feel free to correct me.
I have decided to use the BIOS32 & PCI BIOS (in protected mode) to read & write the PCI registers because it can handle both mode 1 and mode 2.
I have succesfully enumerated the PCI devices by enumerating through the buses, slots and functions and reading the vendor IDs. After the enumeration, my OS loops through the identified functions and tries to start the appropriate drivers. It recognizes the 82371SB chip (vendor = 8086 & device = 7010), time to start the driver. First, the driver reads the command register of the device (0x04). That's where my problems begin: the chip's datasheet states the bits 0 and 1 should be hardwired to 1 but my OS reads 0x1 for the whole register, which means that only the first bit is set by default. Then I tried to read the BAR registers. If I understand correctly, PCI IDE interfaces shouldn't map to memory space but only to IO space, so the first bit of the BAR registers should be hardwired to one. Unfortunately, my OS reads 0x00000000 when asked to read the BAR registers.
Is that normal? Is it the job of the OS to set up the BAR registers, even the "hardwired" bits? Do I get something wrong? I have no idea what to do next. I would really appreciate if somebody with more experience than me could give me some hints.
Thanks.
I am developing my own OS to educate myself about the inner workings of the x86 platform. Now I am at the stage to implement some PCI functionality.
I decided to start this by writing a driver (sort of) for the Intel 82371SB chip, which seems to be a good idea because it is the inbuilt PCI IDE interface in Bochs and I would need to handle IDE anyway sooner or later. I think I could have done this by using PIO but if I understand correctly that would put heavy loads on the CPU during I/O operations. Handling IDE through the classic way of ISA DMA would require me to be able to allocate memory strictly under the 16 MByte barrier, and that wouldn't play nicely along with my memory handling (paging) routines. It is my understanding DMA with PCI doesn't have that limitation, but since I don't know much about DMA yet I might be wrong. In that case, please feel free to correct me.
I have decided to use the BIOS32 & PCI BIOS (in protected mode) to read & write the PCI registers because it can handle both mode 1 and mode 2.
I have succesfully enumerated the PCI devices by enumerating through the buses, slots and functions and reading the vendor IDs. After the enumeration, my OS loops through the identified functions and tries to start the appropriate drivers. It recognizes the 82371SB chip (vendor = 8086 & device = 7010), time to start the driver. First, the driver reads the command register of the device (0x04). That's where my problems begin: the chip's datasheet states the bits 0 and 1 should be hardwired to 1 but my OS reads 0x1 for the whole register, which means that only the first bit is set by default. Then I tried to read the BAR registers. If I understand correctly, PCI IDE interfaces shouldn't map to memory space but only to IO space, so the first bit of the BAR registers should be hardwired to one. Unfortunately, my OS reads 0x00000000 when asked to read the BAR registers.
Is that normal? Is it the job of the OS to set up the BAR registers, even the "hardwired" bits? Do I get something wrong? I have no idea what to do next. I would really appreciate if somebody with more experience than me could give me some hints.
Thanks.
It seems you have old motherboard/ide controller.
BAR of 0x00000000 means your ide is in 'Compability' mode and you should use fixed IO addresses 1f0h-1f7h, 3f6h, 170h-177h, 376h and IRQs 14 & 15.
Search the forum for further explanation of these #s. You are not reading correct documents probably.
You need to read PCI ClassCode it'll tell you for certain which channels are in compability mode.
The 16bit command register has first bit set. Thats fine. You can't do DMA(BusMaster bit=0), and MemIO bit=0(more than normal).
I did google for your "PIIX3 IDE Interface", seems like Linux people have some problem with the device. I got no idea if thats related.(might have same problems in the future)
The numbers you read from pci config space seem fine.
BAR of 0x00000000 means your ide is in 'Compability' mode and you should use fixed IO addresses 1f0h-1f7h, 3f6h, 170h-177h, 376h and IRQs 14 & 15.
Search the forum for further explanation of these #s. You are not reading correct documents probably.
You need to read PCI ClassCode it'll tell you for certain which channels are in compability mode.
The 16bit command register has first bit set. Thats fine. You can't do DMA(BusMaster bit=0), and MemIO bit=0(more than normal).
I did google for your "PIIX3 IDE Interface", seems like Linux people have some problem with the device. I got no idea if thats related.(might have same problems in the future)
The numbers you read from pci config space seem fine.
I am also running bochs trying to get some PCI IDE loving, but having no joy. I can read the BAR, and it's an I/O bar (as expected), base address is 0xC000 as given to me (which is fine), IRQ 0x0, the problem is, in the class code it reports the programming interface as 0x80 (bit 7 set) which means it's the primary IDE controller (which it is), but it has the rest of the bits clear, which means neither the master nor the slave support PCI, only 'compatibility'. According to the PCI IDE docs, this means the device cannot be put into PCI mode, since these bits aren't set. Am I missing a setting in bochs, or does it really not support PCI mode (odd considering it returns a size and memory address).
To the AP, the value's i get for the address registers are not 0x000, so you must be doing something wrong, it only gets ONE valid bar from bochs, so expect a few of them to be 0x000, but not all. Specificallly BAR4 (starting at BAR0) contains the address 0xC000 under my version of Bochs, so don't assuem because BAR0 is 0x000 that there is no information for you.
To the AP, the value's i get for the address registers are not 0x000, so you must be doing something wrong, it only gets ONE valid bar from bochs, so expect a few of them to be 0x000, but not all. Specificallly BAR4 (starting at BAR0) contains the address 0xC000 under my version of Bochs, so don't assuem because BAR0 is 0x000 that there is no information for you.
from PCI IDE Cntrl Spec Rev 1.0 3/4/94Ready4Dis wrote:I am also running bochs trying to get some PCI IDE loving, but having no joy. I can read the BAR, and it's an I/O bar (as expected), base address is 0xC000 as given to me (which is fine), IRQ 0x0, the problem is, in the class code it reports the programming interface as 0x80 (bit 7 set) which means it's the primary IDE controller (which it is), but it has the rest of the bits clear, which means neither the master nor the slave support PCI, only 'compatibility'. According to the PCI IDE docs, this means the device cannot be put into PCI mode, since these bits aren't set. Am I missing a setting in bochs, or does it really not support PCI mode (odd considering it returns a size and memory address).
"When a channel in 'compatibility' mode ... Any values in the associated Base Address are ignored"
Besides, this is an emulator.
That's the only way to do it. I got bar0-3 =0 & bar4 & 5 set to some value while cntrl operate in compatibility on some Intel965P mombo.exkor wrote:You need to read PCI ClassCode it'll tell you for certain which channels are in compability mode.
- zaleschiemilgabriel
- Member
- Posts: 232
- Joined: Mon Feb 04, 2008 3:58 am
I had the exact reverse of this problem once, when I tried to access the first disk on my test box using the compatibility mode I/O ports. My motherboard has only one ATA connector and lots of SATA connectors, and I think only the IDE ATA controller gets to use compatibility mode. There is no way to make the SATA ones work in compatibility mode, so I'm assuming that compatibility mode is slowly dying. My previous motherboard had two IDE ATA connectors. Maybe the next one I get will have none. Anyway, I thought that SATA controllers supported compatibility mode, otherwise how will I run DOS?
- zaleschiemilgabriel
- Member
- Posts: 232
- Joined: Mon Feb 04, 2008 3:58 am
Right, I forgot about that.
For those interested in the subject, int 13h also has some extensions that can be used to enumerate hard disks without using PCI. It uses BIOS disk numbers (80h, 81h etc.) so it is useful, for example to find out the I/O ports for the boot disk (80h) and for mapping physical disks to BIOS disk numbers...
Here's the spec: int 13h EDD
For those interested in the subject, int 13h also has some extensions that can be used to enumerate hard disks without using PCI. It uses BIOS disk numbers (80h, 81h etc.) so it is useful, for example to find out the I/O ports for the boot disk (80h) and for mapping physical disks to BIOS disk numbers...
Here's the spec: int 13h EDD
Well, the 82371SB documentation says that the PI byte is always 0x80. I guess that means that the 82371SB isn't capable of running in native PCI mode. At least it can do Bus Mastering.Ready4Dis wrote:... in the class code it reports the programming interface as 0x80 (bit 7 set) which means it's the primary IDE controller (which it is), but it has the rest of the bits clear, which means neither the master nor the slave support PCI, only 'compatibility'. According to the PCI IDE docs, this means the device cannot be put into PCI mode, since these bits aren't set.
Re: PCI Configuration & 82371SB
I was under this misimpression, too, when I started coding my disk drivers -- but it is totally wrong.drjokepu wrote: Handling IDE through the classic way of ISA DMA would require me to be able to allocate memory strictly under the 16 MByte barrier ....
ATA disks do not use ISA DMA. They use PCI Busmastering DMA. Those are two totally different things. PCI Busmastering DMA does not have the 16MB limitation. You can use 4K scatter/gather DMA operations to write directly into any set of pages in physical memory. You just need to store the target memory addresses in the PRD entries of the PRDT. However, it sounds like Bochs is not giving you a good BAR for your
BusMaster Register, so you will not be able to use DMA either.
But you may want to read my wiki article anyway: http://www.osdev.org/wiki/ATA/ATAPI_using_DMA
Hi,
Nice article and I certainly learned something. Having always reserved some low memory for DMA operations, it looks like this may be redundant. If adding legacy floppy support, just use single-sector transfer and the need for 8-16bit DMA seems redundant.
Do you happen to know if modern sound cards still use 'old' DMA? If not, I guess the need for having a DMA driver and reserved memory is gone completely.
Cheers,
Adam
Nice article and I certainly learned something. Having always reserved some low memory for DMA operations, it looks like this may be redundant. If adding legacy floppy support, just use single-sector transfer and the need for 8-16bit DMA seems redundant.
Do you happen to know if modern sound cards still use 'old' DMA? If not, I guess the need for having a DMA driver and reserved memory is gone completely.
Cheers,
Adam
I am not completly sure about this, but PCI devices can't/shouldn't use legacy DMA, but some PCI cards require physically continuous memory though.AJ wrote:Do you happen to know if modern sound cards still use 'old' DMA? If not, I guess the need for having a DMA driver and reserved memory is gone completely.
No not all do, some support a kind of scatter gather approach, e.g. the AMD PCNet network card has say n receive/transmit descriptors. For each of these descriptors you can set a different physical memory regions, so you don't need more than 4k physically continuous.jal wrote:Don't they all?
The RTL8139 however uses one physically continuous buffer.
That is correct.The card has only knowledge of physical memory, it does not and cannot know about paging and such
My point more or less is that for some cards a normal non-continous page allocator is sufficient and for some it is not.
Yay! Thanks for the props. It's still mostly a stub ... just wait until I really fill it out.AJ wrote: I certainly learned something.
It is. AFAIK bluecode is almost entirely correct. Everything in your machine today is controlled by PCI devices. They have the capability (for legacy reasons) of doing legacy ISA DMA (your current everything-on-one-chip PCI controller also handles your floppy drive's ISA DMA) -- but all current devices (except the floppy, serial, lpt) should have PCI Busmastering DMA, or hardware memory mapped access modes. The ones that do not will probably all use IO port data access, instead.If adding legacy floppy support, just use single-sector transfer and the need for 8-16bit DMA seems redundant.
The main question is, if someone tries to read/write a floppy -- are you content to let the rest of the system slow to an unbearable crawl during that time (using single sector transfer) -- or do you want to make it only slow down to an almost-bearable crawl (by writing ISA DMA code, and reserving ISA DMA memory for that one device only).
They do not, in general. They might have a legacy mode that supports it, that you should not use.Do you happen to know if modern sound cards still use 'old' DMA?
PCI Busmastering DMA does not specify a fixed size for transfers. It's easiest to just do all your contiguous DMA transfers in individual 4K chunks to de-mapped individual physical pages yourself. The overhead on PCI DMA transfers is pretty low. You don't gain much by creating a special large contiguous physical buffer, doing a big DMA transfer to it, and then having to copy all the data into destination 4K pages -- if creating large contiguous physical buffers is a problem.jal wrote: Don't they all? The card has only knowledge of physical memory, it does not and cannot know about paging and such.