PCI IDE bus mastering DMA question
Posted: Mon Feb 15, 2016 12:40 pm
I've implemented a PCI IDE driver that supports bus mastering DMA, following the specification here. The instructions on page 99 are quite clear and allowed me to get things up and running under Bochs fairly quickly.
However, I noticed something odd yesterday: adding a line of trace logging between submitting the READ DMA command to the disk and engaging the bus master function on the PCI controller caused things to not work (the drive would never signal an interrupt). Without the logging, things worked perfectly. After some investigation I've determined that it has nothing to do with logging; adding a simple delay between submitting the READ DMA command and engaging bus mastering causes things to not work.
Now the above linked spec is quite clear that the sequence of actions should be submitting the READ DMA command first, and then engaging bus mastering. However, this seems to be problematic under Bochs. So I added a bit of additional logging to the Bochs source (in iodev/harddrv.cc and iodev/pci_ide.cc) to track what's going on. Here's an extract from the Bochs log showing a successful DMA transfer:
And here's an extract from when the transfer hangs:
Note that in the successful case, the actions sequence shows up as re-ordered so that the bus mastering is engaged before the device command--despite the fact that my code is actually submitting the commands in the opposite order (following the spec).
In the problematic case, the READ DMA and bus mastering commands appear in the intended order. And that doesn't seem to work. I've also checked that re-ordering the commands in my driver source allows things to work. However, I don't want to do that since the intended ordering is stated quite clearly in the spec.
So I'm wondering: is this a bug in Bochs? Or am I missing something? Would appreciate any thoughts/suggestions. Also happy to share more details from the code if it would be helpful.
However, I noticed something odd yesterday: adding a line of trace logging between submitting the READ DMA command to the disk and engaging the bus master function on the PCI controller caused things to not work (the drive would never signal an interrupt). Without the logging, things worked perfectly. After some investigation I've determined that it has nothing to do with logging; adding a simple delay between submitting the READ DMA command and engaging bus mastering causes things to not work.
Now the above linked spec is quite clear that the sequence of actions should be submitting the READ DMA command first, and then engaging bus mastering. However, this seems to be problematic under Bochs. So I added a bit of additional logging to the Bochs source (in iodev/harddrv.cc and iodev/pci_ide.cc) to track what's going on. Here's an extract from the Bochs log showing a successful DMA transfer:
Code: Select all
00065821496d[PIDE ] BM-DMA read command register, channel 0, value = 0x08
00065821498d[PIDE ] BM-DMA write command register, channel 0, value = 0x09
00065821571d[HD ] READ DMA command for channel 0, device 0
00065831498d[PIDE ] READ DMA to addr=0x001cd000, size=0x00000200
00065831498d[HD ] raising interrupt 14 {DISK}
Code: Select all
00068106692d[HD ] READ DMA command for channel 0, device 0
00068106897d[PIDE ] BM-DMA read command register, channel 0, value = 0x08
00068106899d[PIDE ] BM-DMA write command register, channel 0, value = 0x09
00068116899d[PIDE ] Data is not ready for channel 0 READ DMA
In the problematic case, the READ DMA and bus mastering commands appear in the intended order. And that doesn't seem to work. I've also checked that re-ordering the commands in my driver source allows things to work. However, I don't want to do that since the intended ordering is stated quite clearly in the spec.
So I'm wondering: is this a bug in Bochs? Or am I missing something? Would appreciate any thoughts/suggestions. Also happy to share more details from the code if it would be helpful.