Page 1 of 1
ATA IDENTIFY returning garbage - but only on one machine
Posted: Sat Sep 06, 2008 4:33 am
by JamesM
Hi guys,
I know I haven't been active for a while - that'll fix when I get my home internet sorted (I need to take over the line from a tenant before me who didn't terminate their line rental contract, GRR!!)
But anyway, onto the question. I have an ATA driver that is common to all architectures my OS supports. I have IDENTIFY and PIO working on x86, and also on PowerPC via the PearPC emulation program, however when getting it to work on real PowerPC hardware (an apple iBook), I'm getting problems.
Initial status read is fine - 0x50. I send the IDENTIFY command, receive back a status of 0xd0, also good, and the status changes eventually to not busy, buffer needs servicing. I then read in from the data port - but get only garbage.
Once I've read, the "buffer needs servicing" flag in the status register gets cleared, but that happens even before I've read an entire sector (256 16-bit words) - is that normal?
Because I'm getting the right status but rubbish data, my initial assumption was that the drive was set by the firmware to some DMA mode that it is still in, and so the identify data is being sent somewhere via DMA, but the wiki article [wiki]ATA/ATAPI_using_DMA[/wiki] says a bit has to be explicitly set before each DMA request, so that couldn't be the case.
Is there anyone out there with a good enough knowledge of ATA that they know what's going on? I'd be very grateful!
Cheers,
James
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sat Sep 06, 2008 8:29 am
by JamesM
For anyone who cares, I'm part way through solving this problem.
I installed and ran "hdparm -Istdout" on my iBook, giving me a hexdump of the correct identify response. I discovered that what I was getting was every 4th 16-bit integer from the "real" IDENT response, so for example if the real response looked like
A B C D E F G H I J K
Where each letter is a 16-bit int, I would receive A E I. I need to grep the linux source code again to work out where the other three words are stored!
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sat Sep 06, 2008 1:53 pm
by bewing
Well, I wrote that article, and I'm glad it helped some -- but you've stumped me. Initially as I was reading your post, I was thinking "timing problem" -- but with your second post, my assumption is obviously not right. So I am very confused, along with you. Good luck.
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sat Sep 06, 2008 3:09 pm
by Brendan
Hi,
JamesM wrote:I installed and ran "hdparm -Istdout" on my iBook, giving me a hexdump of the correct identify response. I discovered that what I was getting was every 4th 16-bit integer from the "real" IDENT response, so for example if the real response looked like
A B C D E F G H I J K
Where each letter is a 16-bit int, I would receive A E I. I need to grep the linux source code again to work out where the other three words are stored!
This is just a silly random guess (I don't know anything about PowerPC hardware), but I'm wondering - is it possible to read 64-bits at a time instead of 16-bits? Maybe you're getting the lowest 16-bits of each 64-bit piece of data because the hardware is expecting a 64-bit read...
Cheers,
Brendan
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sat Sep 06, 2008 9:56 pm
by bewing
That's certainly a possibility, but it would be a 100% violation of the ATA standard -- the standard insists on 16 bits per.
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sun Sep 07, 2008 1:56 am
by xyzzy
I've been reading through the Darwin IOATAFamily driver code - see
http://www.opensource.apple.com/darwinsource/10.5.4/ - It's definitely reading 16-bits at a time rather than 64. However, one thing you might want to try: after each read from the data register it calls OSSynchronizeIO(), which, on PowerPC, executes an
eieio instruction to force in-order execution.
EDIT: The IOATAFamily code makes references to some IOKit and kernel stuff - they're in the XNU source on the same page.
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Sun Sep 07, 2008 3:06 am
by JamesM
Brendan wrote:Hi,
JamesM wrote:I installed and ran "hdparm -Istdout" on my iBook, giving me a hexdump of the correct identify response. I discovered that what I was getting was every 4th 16-bit integer from the "real" IDENT response, so for example if the real response looked like
A B C D E F G H I J K
Where each letter is a 16-bit int, I would receive A E I. I need to grep the linux source code again to work out where the other three words are stored!
This is just a silly random guess (I don't know anything about PowerPC hardware), but I'm wondering - is it possible to read 64-bits at a time instead of 16-bits? Maybe you're getting the lowest 16-bits of each 64-bit piece of data because the hardware is expecting a 64-bit read...
Cheers,
Brendan
Hi Brendan,
Yes, that thought occurred to me too. I attempted that and ended up with zeroes in the next 48 bits - "A 0 0 0", so it's not expecting that.
Alex: You've just put an idea in my head as to what the problem could be. On every read (at the moment) I invalidate the relevant cache line, which obviously forces a read from memory. Perhaps that cache line is being invalidated multiple times? The safest option would be to mark the memory cache-disabled, which I should have done in the first place.
I'll look into eieio as well - I totally forgot about that!
Grepping the internet for data is hard when you don't have a web connection at home - I come into the software labs all geared up for google but having forgotten half of what I needed to search for!
Cheers Alex!
James
Re: ATA IDENTIFY returning garbage - but only on one machine
Posted: Mon Sep 08, 2008 5:25 am
by JamesM
This problem is now fixed - thanks to all who tried to help!
The problem was that my MemoryMappedIO class wasn't correctly passing the CacheDisable flag to the virtual memory manager when setting up its MemoryRegion. The result was that the cache wasn't being bypassed for IO, resulting in strangeness.
Cheers guys!
James