On 24/04/2020 02:23, Benjamin David Lunt wrote:
> "James Harris" <
james.h...@gmail.com> wrote in message
> news:r7s4eq$j24$1...@dont-email.me...
>> On 23/04/2020 04:38, Benjamin David Lunt wrote:
...
>>> This technique has worked on about 95% of the hardware I have tested
>>> it on, and I have not yet run into a 4096-byte only drive with it.
>>
>> You know the obvious question that throws up: Why did it not work on the
>> other 5%? It looked to me as though your method should have provided 100%
>> coverage.
>
> I don't remember why. I don't remember if it was the technique that failed
> or if it was reading from some drives with the commands I was using that
> failed. However, every once in a while, this function would return zero
> for the sector size. It has been so long since I worked on that part
> that I have totally forgotten why. I just remember it failing once in
> a while. Hence the 95% statement, instead of stating 100%.
I've acquired a number of test machines over the years, usually chosen
because although they are 'IBM compatible' they were unusual in some
way, and I have found that code of mine which works on most of them runs
into a snag or two on the others. That's why I bought them. I wanted to
have to get my code working with a variety of hardware.
Actually, having said that, I should correct it and say that I suspect
that most of the faults are not really hardware but them trapping to SMM
and the SMM code not doing everything it's supposed to - such as setting
status bits.
>
>> An option I thought of was to read the same sector to two buffers. If we
>> had pre-filled each buffer with different values then it would be easy to
>> work out how many bytes were overwritten. Simply count the number of bytes
>> which matched (and for extra checking ensure that those which followed had
>> not been altered).
>>
>> That should resolve it to byte level and would work with both PIO and DMA
>> although the latter would require either the pre-allocation of buffers
>> which were 'big enough' or page protection to guard against unbounded
>> writes.
>
> I agree here. Though with PIO, you as the programmer, can tell exactly
> how many words you read since you use an explicet inpw instruction on
> each read, while checking for the DRQ bit. As you stated, this should
> work 100% of the time.
I have at least one machine which fails to set a status bit when it
should. I suspect SMM in that case. Not sure if it could apply to the
ATA interface. Perhaps not. But I have another machine where slowness to
effect an update is a potential cause of problems. It's a Toshiba Tecra
which you may remember gave Linux problems over the A20 gate. I found
that is just a bit slow to enable the A20 gate. From memory I think it
takes only about 68uS to enable the gate so it's not long in real terms
but an OS must wait for the change to take effect before starting to use
memory above 1M.
It's partly because of seeing a machine take a while to effect a setting
that I had reservations about checking the DRQ bit. I just wasn't sure
how long it would take DRQ to change on the slowest machine.
>
> With the DMA method, yes, you would have to make sure the buffer was
> 'big enough'.
>
> The only coveat I would see with the DMA method is if you preset the
> buffer with a value and happened to read the exact same value, how
> would you know where the read stopped? However, this would be very
> minimal I think.
That's why I was thinking there would be /two/ buffers pre-filled with
different contents. To make a manageable example say the blocks on the
disk are just 4 bytes (not 4k) long and we set up two buffers, each 8
bytes long. We could pre-fill the buffers with (in hex)
00 00 00 00 00 00 00 00
FF FF FF FF FF FF FF FF
Then say the block we are going to read for this test contains (also in
hex) 22 22 22 22. After reading the block in to both buffers they would
hold
22 22 22 22 00 00 00 00
22 22 22 22 FF FF FF FF
A count of initial matches between the two buffers would yield 4, the
size of the block.
Even if some of the data read from the disk were to match what was in
one of the buffers the technique should still work. Say the block read
from disk contained 00 FF 00 FF so that its last byte matches what we
pre-loaded into the second buffer. Then after the reads the two buffers
would hold
00 FF 00 FF 00 00 00 00
00 FF 00 FF FF FF FF FF
Even though the block read from the disk ended with the same value as
was already in the second buffer (i.e. FF) a count of the number of
matched bytes would still yield a block size of 4.
And the rest of the buffers could be compare with their initial contents
as a sanity check.
At least, that's the idea. :-)
--
James Harris