Just checked back - It's good to see that the conversation has finally
turned back to useful persuits.
I grew up with the WD controllers, and found the
8272/765 a real
disapointment after those :-)
Here we are in complete agreement.
You can
analyze MOST formats by trying to read a 256 byte, a 512 byte, and
a 1024 byte sector, such as #2, and then trying the numbers up and down to
find first and last. Won't work for sectors whose numbering don't start
with 0 or 1, or ones with invalid headers (such as side B of Kaypro)
IIRC the sector number is a single byte, so presumably you could try
reading each sector in turn (0..255) in each size to see what gave no
errors. I'd thought of doing it that way, but it's going to be terribly
slow...
FWIW, this is what I did:
During the "Full analysis" performed at the beginning, or any time the
format appears to have changed, I :
First hunt for the correct data-rate (250/300/500) and mode (FM/MFM) by
reprograming the controller and issuing read-id until I find it (You can see
this if you watch the indicators at the top of the screen) - then I intentionally
reprogram the FDC to "wrong" values and issue a read-id, which will fail at
the second occurance of the index hole. This gets me to the physical start
of the track. Also note that this will get you the sector size, although you don't
actually need it during analysis (you will need it for later reading).
I then reprogram the FDC to the correct data-rate/format, and begin reading
ID's as quickly as possible and building a list of the ID's and the order in
which
they occur.
Some formats are "on the edge" of what the PC can read (or sometimes the
disk/drive is unreliable), so you cannot guarantee that you will see all of the
IDs reliably. What I do to detect this is to continue reading IDs for several
revolutions keeping count of how many of each ID has been seen. I then
check the ID counts and make a decision as to how reliable the sector list
is - if I deem it to be unreliable, I issue the warning "Unable to determine
interleave", and reorder the sector ID's according to "best guess" (see
below)
if it was configured for "As Read".
Once I have the sector list, I process it according to the configured interleave
settings:
"As Read" (the default setting) means that I take the sector list exactly as it
was
observed on the disk.
"Best guess" means that I sort the IDs and work out the average spacing of
adjacent IDs in my sorted list against the original ID list (I use the sorted list
to make it independant of actual logical sector numbering - I've found some formats
which have gaps in the sector numbering - ie: use even or odd numbers only).- Then
I re-interleave the sector numbers based on this calculated average.
"fixed number" means I simply re-interleave the sectors frojm the lowest
according
the specified spacing no matter what order I actually found them in.
(btw, this interleave process is done for both reading or writing, so you can write
a disk with different interleave than it was read if you wish).
The whole process is a bit more complex than this, because I also maintain head
numbering maps and cylinder numbering maps so that I can deal with other odd
disk formats - for example, some disks record the side2 sectors as continued sector
numbering on side1 (!). - This gives it "different" sector numbers and
"wrong" head
numbers on side2. Btw, I maintain two separate control blocks which track the format
information for both sides of the disk independantly.
Unless you have turned on "Full analysis", I do not repeat this procedure as
long
as all of the information I have collected continues to result in complete and successful
track reads - in the event that an operation fails, I will perform another full analysis
on the track. To accomodate any "really odd" disks which change the format
subtly
from track to track, I provide the "Full
analysis" option which goes through the entire
process for every single track.
The above process has two "real time" critical operations. Getting the first
read-id
going after the intentionally failed read, and getting on with the next read-id after
each one has returned it's results.
In my program, I use interrupts only when waiting for the completion of seeks and
DMA transfers. In particular, I am not currently using interrupts to control the read-ID
command - even where I do use interrupts, I am using it only to signal that the FDC
has entered it's result phase. This works well under a non-multitasking system,
however under Linix or any other such system, it could be an issue to these real-time
critical points as has been noted.
Bringing the system up in single-user mode would probably help, as would eliminating
all the background activity that you can... however this is not a definitive solution.
I think a better approach would be to move much of the above logic into the interrupt
handler - this could be done with a small state machine:
- When the initial read-id fails (and generates an interrupt), you could switch modes
and issue the first "real" read-id command directly from within the interrupt
handler.
- As each read-id completes and an interrupt is generated, you can store the information
and issue the next read-id command from within the interrupt handler - you need only
set a "done" flag when you determine the analysis is complete.
This would reduce your real-time concerns to the latency at which the system can service
and interrupt, and as long as your mainline tasks are not doing something
"unfriendly"
like disabling interrupts for extended periods of time, it should work OK even on a
multitasking system.
Regards,
Dave
--
dave04a (at) Dave Dunfield
dunfield (dot) Firmware development services & tools:
www.dunfield.com
com Collector of vintage computing equipment:
http://www.parse.com/~ddunfield/museum/index.html