Page 1 of 1

ATA DMA data arriving late

Posted: Thu Jul 18, 2024 3:11 pm
by Octacone
Hello, I'm back after a long break and I gotta say this new forum theme is quite hard to get used to.
It needs a better contrast.

Anyways, I've been having this problem for years: whenever I receive an interrupt, I have to wait approx. 37 * 400ns in order to be able to see the data in memory, otherwise the buffer is empty.
Inside the interrupt handler, everything checks out, bus master status register bit 2 is set, bit 0 and 1 are clear.
I also read the status register to acknowledge the interrupt and I stop the DMA transfer.

I experience this behavior in all emulators.
Has anybody ever encountered a similar issue?

Re: ATA DMA data arriving late

Posted: Fri Jul 19, 2024 9:19 am
by Octacone
Interrupt: This bit is set by the rising edge of the IDE interrupt line. This bit is cleared when a
'1' is written to it by software. Software can use this bit to determine if an IDE device has
asserted its interrupt line. When this bit is read as a one, all data transfered from the drive is
visible in system memory.


Yeah, that is not happening...

Re: ATA DMA data arriving late

Posted: Fri Jul 19, 2024 11:39 am
by Octocontrabass
I've never heard of anyone else having that problem, so I can only assume it's a bug in your code, but I can't think of anything that would cause the exact behavior you're seeing.

QEMU can log some events that might help you find the problem.

Re: ATA DMA data arriving late

Posted: Sat Jul 20, 2024 8:39 am
by Octacone
My FAT 32 code uses malloc all around.
Could this thing be caused by crossing the 64 KB boundary.
Let's say my malloc returned 0x24F202C, and I needed to read 8 sectors 512 bytes each.
The resulting address would be 0x24F302C which would not be compliant with this:

"The data buffers cannot cross a 64K boundary, and must be contiguous in physical memory (ie. they can't be "virtual" data buffers). The byte count on the data buffers must match the number of sectors transferred by the disk. If not, the controller will error out in various ways."

Right?

Edit:
This is ridiculous!
It sometimes randomly works. Like every 50 times.
I also fixed the boundary issue, but it didn't help.

Edit 2:
When I start Qemu for the first time it doesn't work, but when I tell Qemu to reboot it works almost every time.

Re: ATA DMA data arriving late

Posted: Sun Jul 21, 2024 6:43 pm
by Octocontrabass
Octacone wrote: Sat Jul 20, 2024 8:39 amCould this thing be caused by crossing the 64 KB boundary.
Probably not. I would expect either memory corruption or no problem at all, data arriving late just doesn't make sense.
Octacone wrote: Sat Jul 20, 2024 8:39 amWhen I start Qemu for the first time it doesn't work, but when I tell Qemu to reboot it works almost every time.
Sounds like the problem is timing-related, but I still can't imagine what it could be if it only affects IDE DMA and nothing else.

Re: ATA DMA data arriving late

Posted: Mon Jul 22, 2024 8:29 am
by Octacone
This driver might as well be a random number generator. :D
I think the interrupts are to blame.
I always get a spurious interrupt on Qemu and a fake one (interrupt bit clear) on Bochs.

Reading or not reading the command register when stopping the transfer appears to have a big impact...

Re: ATA DMA data arriving late

Posted: Mon Jul 22, 2024 11:22 am
by Octocontrabass
Octacone wrote: Mon Jul 22, 2024 8:29 amI think the interrupts are to blame.
I always get a spurious interrupt on Qemu and a fake one (interrupt bit clear) on Bochs.
Well, that definitely points to a bug in your code.

Spurious IDE interrupts can be caused by polling a drive when you should be waiting for an interrupt, or by switching between drives that share an interface without waiting for command completion and acknowledging the interrupt. Spurious interrupts of any kind can be caused by polling a device when you should be waiting for an interrupt, or by incorrectly configuring an interrupt controller, or (if it's something like the PIT) by not responding to the interrupt before the device cancels its interrupt request.

VMs aren't bound by the limits of physical hardware, so I could see how the bug causing spurious interrupts might also cause DMA to appear to complete late instead of aborting the transfer.