On Sunday 07 December 2003 13:47, Tony Duell wrote:
Therer's also no seek-complete or equivalent
signal for head
switches. There is a 'settling time' in the ST506 spec, but it's
short. So you have to be able to switch heads (i.e. between tracks on
the same cylinder) without transfering data to/from the modern disk.
There just isn't time to do that.
So you have to buffer an entire cylinder's-worth of data in the
emulator, and keep on squirting out that part that corresponds to the
selected 'head'. When the classic steps to a new cylinder, you have
to save one or more of the 'tracks' in the emulator's RAM buffer (you
can flag writes to particular tracks, since there is a write gate
line, but you also have to assume that it's possible the classic has
written to all 16 tracks in the cylinder -- it certainly would when
formatting). Then you have to reload all 16 tracks-worth of data from
the modern hard disk, and then assert seek-complete to tell the
classic that the drive (emulator) is outputting the data for the new
Now, I am not sure what the seek times are for ST506 drives, but I
would guess a few ms for the voice-coil ones. Transferring 4Mbytes of
data (2M from the emulator, 2M to the emulator) in 10Ms is a
400Mbyte/s data rate. Which is fast by modern standards. Very fast.
Here's an idea. You DON'T need to transfer that much in the 'cylinder
First, you can double the size of the original buffer (to 4MB), and have
two separate buffers. When you switch heads, all you have to do is
"swap" buffers (preferally by updating a memory pointer, or using by
bank switching it - not by copying it). Now all you have to do is have
time to read one buffer (2MB) in during the 'cylinder change' time,
which halves your necessary data transfer rate. You can then write out
the other buffer "in the background" to the disk, which has only to
take less time than the drive spends lingering on the current cylinder.
Step two. Add a 'dirty' word to each cylinder that has one bit per
cylinder. Clear these before reading in the new cylinder, and set them
only if the host asserts its write gate signal. In the common case,
this will greatly reduce the amount of data you need to write back to
disk. In addition, if no dirty bits are set, you can just 'junk' the
data in memory, and NOT write it to disk. This keeps you from having
to flush out the data you need to write to disk when the controller is
just stepping the drive through cylinders. However, you have to be
careful to wait for the 'to be written' data in the background buffer
to be completely written before allowing the cylinder change to finish
if you have any dirty bits set.
Step three (version 1). While the head can switch tracks at any time,
the disk does _rotate_ linearly. So, if you store the bits on the real
disk in a manner like this: (assuimg 4 heads)
Block #: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
Cylinder: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
Head: 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 ...
Sector: 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 ...
You can start reading this data when you're told to switch tracks, and
assert the 'seek complete' line when you're ready to read the block
correlating to head 0, sector 1. As long as you can read the data from
disk into memory fast enough to keep ahead of the memory position from
which you're sending data to the old controller, you're set. Also,
it's important to selectively write, using the dirty bit scheme. If
you've written to a track, make sure you have the *entire* track read
into memory before you step to a new track and write data out, or
you'll lose data...
Step three-B. Don't write your background/output buffer while reading
new data in, make sure you do this either before or after reading
(after reading should improve speed).
Step three (version 2). Add two more buffers to store data (up to 8MB).
You can at most move one track at a time. After you've written your
data for the previous (dirty) cylinders to disk, prefetch data into a
buffer for the next two possible cylinder choices - moving forward one
and moving back one. Also, don't allow a track switch to finish until
you've completely 1) written out the dirty buffers 2) and read in the
cylinder that's going to be switched to. If you get the signal to
switch cylinders before reading both cylinders, stop reading the one
that's not getting switched to, and only read the one that is getting
switched to. Once you're done reading that, assert the 'seek complete'
signal, and bank-switch the correct buffer into memory.
For version 2, the worst case scenerio will be writing to an entire
cylinder, and then seeking more than one track immediately afterwards,
and will require the full 4MB of data to be moved in the time of two
Version 1 would be faster, but would be more error/bug prone, and you
need to ensure that you can read your data in from disk at least
(#tracks) times faster than you need to output it to the original host
There's still the issue of what to do when the host powers down... you
could perhaps have a timer that automatically writes any changed data
out to disk if the cylinder hasn't changed in the past, say, 500ms, and
clears the dirty bits after it has written the data. Then it's just a
matter of making sure the operator waits at least a few seconds before
powering off the machine, after halting it.
Now, if I could just use things like this email to satify course
requirements at Purdue...
Purdue University ITAP/RCS
Information Technology at Purdue
Research Computing and Storage