home *** CD-ROM | disk | FTP | other *** search
-
- This text contains some background technical info. It is not a manual,
- but it fills in some data regarding the problems with disk control and
- how things are implemented. (And I love to talk about it after all this
- work)
-
-
- INTRODUCTION
-
- The rotational speed of an Amiga disk is 300 rpm. The time of one
- revolution is .2 seconds. Data is sampled at .5 MHz. So a track on an
- Amiga floppy disk contains 100000 bits. This can vary a little due to
- motor speed variations. Alas we cannot put any desired pattern in these
- bits. Therefore data is converted to patterns which are allowed. This
- conversion, called MFM-encoding, has an efficiency of 50 percent. For
- every bit of data two bits of the magnetic track are used. We can
- picture an encoded sector as follows:
-
- 4 bytes inter sector gap
- 4 bytes sync pattern
- 8 bytes sector ID
- 32 bytes label
- 8 bytes checksum over sector ID and label
- 8 bytes checksum over data block
- 1024 bytes data block
-
- Therefore the size of a sector is 1088*8=8704 bits. 100000/8704=11,
- remainder 4256. Thus we can store 11 sectors. We have 4256 bits left we
- do not use for storage. Instead these bits allow us to accept a motor
- speed increase of 4.25 %. If we allow the same speed decrease, we must
- be able to supply a non used space of roughly 8500 bits or 1100 bytes.
- In fact, Trackdisk is prepared for an unused space of 1660 bytes. (Why
- that much?)
-
- Trackdisk does not write separate sectors as found on other systems.
- Instead it writes out a complete track, actually reformatting the track.
- That is why blocks can be so tight together. (On the other systems you
- need gaps between the sectors and between sector ID and data block to
- allow soft and hardware to synchronize) If Trackdisk writes out a track,
- it begins with the 1660 bytes gap, followed by the sectors. Although
- the sectors are written out in order, the first sector can be any of the
- eleven. The last sector is written over the begin of the gap, thus
- effectively removing old data and patterns. Although Trackdisk allows
- for synchronization with the disk index, this is normally not used;
- Trackdisk just starts writing when it is ready to do so.
-
- Reading is something else. If Trackdisk should wait for the gap to
- pass, average halve a tracktime is done nothing. Therefore reading is
- started, ignoring where the head is in the track. To ensure that all
- sectors are read, the readsize must be one sector larger than the number
- of available sectors. And the gap must be read too. This results in a
- readsize of 12*1088+1660=14716 bytes or 117728 bits, 18% more than a
- physical track. Usually the read is started somewhere within a sector,
- continues until the gap, the gap itself and enough sectors after the gap
- to cover the whole track. Reading and writing is done by DMA (Direct
- Memory Access) and word wide (16 bits). Therefore data read from disk
- can be in memory shifted up to 15 bits. The part behind the gap has no
- exact relation in position and shift to the first read part. To recover
- the track, a search is started for a sync pattern. If found, this
- informs us about the shift. Knowing the shift, the following sector id
- can be decoded. This sector id has the following form and are all
- bytes:
-
- $ff (formatbyte)
- tracknumber
- sectornumber
- number of sectors until gap
-
- The last item "number of sectors until gap" tells us how large the part
- is with the current shift. This part is shifted and moved to the begin
- of the data part of the trackbuffer. Then a second search for a
- syncword is done, starting behind the first part. The remaining
- sectors are found and moved and shifted tight behind the first part.
- Now there is in the buffer a block of 11 sectors and after updating the
- last items of the sector id's, "number of sectors until gap", the track
- is ready to be written again.
- But before that a lot can go wrong. If some syncword or intersector gap
- is distorted, or one of the 22 checksums is wrong, Trackdisk stops and
- returns an error. If the error concerns a syncword or a gap, or if a
- faulting checksum belongs to a sector ID, it is likely that all data can
- be recovered (except for the label, but that is not used by Dos). And if
- the checksum belongs to a data block, but this data block is not
- requested, then the other blocks could be read without a problem. Of
- course a track with an error must not be written back to disk.
-
-
- SALVE FUNCTION
-
- The salve function of TrackSalve reads data from disk in such a large
- buffer, that there will be an uninterrupted array of sectors in this
- buffer. If one sector can be found with a good checksum over its
- header, all data to calculate the position of the other sectors is
- available. The data and label blocks are copied to the original buffer,
- this time with sector 0 in the first position. If the checksum of the
- current block is correct, a corresponding bit is cleared in a word that
- is initiated with 11 ones. Such a word exists as well for the data as
- the label blocks. There is a byte that contains normally the number of
- the first sector, but it will contain an error number if the track is
- bad. The Trackdisk errors start at 20, so if the byte is larger than
- 10, the track is bad. Somewhere within trackdisk this is tested and as
- result the tracknumber is set to -1, meaning "trackbuffer not valid".
- Therefore any subsequent read request will result in a seek and several
- read retries of the track. If the salve function is active, this
- invalidation of the tracknumber is prevented. Instead the first sector
- byte is tested at a read request and if this indicates an error, the
- bitpattern with bad blocks are tested. As soon as the request concerns
- a bad block, the error value and the number of transferred bytes is set
- and fixed, but transfers continues until the number of requested bytes
- are copied. There is no difference between the original behavior of
- trackdisk and the salve function other than the bonus of the extra
- transferred data (IO_ERROR contains the error and IO_ACTUAL contains the
- number of bytes without error). If label transfers is switched on,
- IO_ACTUAL presents the number of sectorbytes transferred until an error
- is encountered in a label OR sector. Some specialized recovery program
- can use this info to recover more data at the cost of accuracy, which
- may be acceptable in some cases. A write to the same track still will
- set this tracknumber to -1, and the normal retry scheme will be used.
- The salve function is rather introvert and will at a priority of +5
- disturb the feeling of the Amiga. So the priority is lowered to -2
- during track salvage.
-
-
- MFM FLAW
-
- How heavy the tests are on the track read from disk, there is a serious
- gap (to my opinion) in these integrity checks. As stated earlier, not
- every pattern is allowed in the magnetic track. A MFM encoded data
- block exist of true data bits and timing bits. The databits are always
- valid: these are not coded, but the timing bits, these are to be found
- between the data bits, are meaningless as data. They are just there to
- prevent too much and to less subsequent magnetic transitions. Too much
- is beyond the bandwidth of the medium and too less may lead to loss of
- synchronization and gives noise a chance. The used recording technique
- is a transition on a one and no transition on a zero. MFM coding
- defines patterns where a one always is followed by a zero, and there are
- never more than three subsequent zeros. What happens if there are two
- subsequent ones? Or more than three zeros? The system is not that
- sensitive that this immediately will lead to bad reads of the data
- containing bits. And Trackdisk maintains checksums over encoded data,
- or..? But ONLY over the data bits, NOT over the timing bits! If a
- timing bit is read wrong from disk, this will not be detected. The
- sector is copied to a new position in the trackbuffer, and if an other
- sector is changed, it will be written back to disk with the faulting
- timing bit! If the sector is not updated (eg belonging to a program)
- this faulting bit will stay forever. Slowly all timing bits can
- disappear due to the retry scheme of trackdisk. At a moment the track
- will be unreadable. Especially the roottrack is sensitive for this
- phenomena.
- TrackSalve has modified Trackdisk in such way that just before a track
- is written to disk, all timing bits are set according to the MFM
- standard. This takes very little time because it is all done by the
- blitter. Now that it is ensured that the track is MFM updated before it
- goes to disk, the encoding routines can ignore these bits, and that
- saves cpu time. Because the encoding routines were rewritten, it was
- easy to allow non chip memory for IO buffers. Non-chip buffers are
- copied by the cpu at the most efficient way (cribbed from exec's
- CopyMem()), although CopyMem() is used if it is replaced.
-
-
- BUGS IN TRACKDISK
-
- I knew of two bugs and found a third. These all are repaired in
- TrackSalve.
-
- Raw read and write had problems because IO_LENGTH was compared with
- $8000 instead of #$8000. The difference is that IO_LENGTH should be
- compared with the value 8000 hex. Instead it was compared with some
- value that was at memory location 8000 hex.
-
- In a multitasking environment the hardware must be shared between the
- concurrent tasks. There can be up to four drives connected to the
- Amiga. For each drive a Trackdisk task is started (all executing the
- same code but with separate data area's). These four drives are
- controlled by one piece of hardware (some custom chip I forgot the name
- but I know its address). The TD-tasks use it to control their particular
- drives. The tasks ask permission to the disk.resource to access this
- chip directly by a call named GetUnit(). If the task is ready with it,
- this is told to the disk.resource by a call named GiveUnit(). Another
- TD-task that perhaps was waiting for it, gets access permission. There
- is a nasty bug in Trackdisk which could disturb the permission scheme.
- Because a branch was too far, a call to GetUnit() was missed if that
- drive was empty. The task assumed permission, did some access and called
- GiveUnit(). This is not as bad as it looks, because the time of violated
- hardware access is very short, and was very short after a permitted
- access. But if another TD-task had got permission (and the more drives
- the more likely this will happen), the turnips are cooked. The other
- tasks commands to the hardware are possibly destroyed and to make
- matters worse, it looses its permission to access by the first tasks
- call to GiveUnit(). So now this ignorant task is violating the rules.
- The patch done by the setpatch program modifies disk.resource in such
- way that only GiveUnits() are valid from tasks that did the GetUnit().
- The access violation was not repaired.
-
- During the tests with special Trackdisk IO programs, some strange
- behavior of Trackdisk came up. Dos is very precise in its IO with
- Trackdisk, but a Trackdisk tester is not. That must explain why this
- was not disturbing more general. If a write to a protected disk was
- done, this disk became unreadable for all other tracks than that was
- just written to. Reads via Dos resulted in a Read/Write error requester
- although retry selection solved the problem (CMD_CLEAR). A new bug in
- Trackdisk? Yes! If you write a sector to a protected disk, first the
- track is read into the trackbuffer, followed by a copy of the sector
- into this buffer, replacing the original, and a flag is set, meaning
- "trackbuffer changed". If you want to read a sector from another track,
- trackdisk tries to flush (write to disk) its trackbuffer. The disk is
- protected and the attempt will fail. So you cannot read another track!
- But it is even worse if you want to read from the track currently in the
- buffer. You think the data is coming from disk, but it might be the
- never updated sector! What is the problem? Trackdisk does not check
- the protect status before letting a CMD_WRITE modify the trackbuffer.
-
-
- AUTO UPDATE FUNCTION
-
- There were times when I used Sectorama (I still use this nice program
- from the hand of David Joiner), I did not understand why sometimes a
- modified and written sector would not stick on disk. Now I know this is
- because Trackdisk needs some help. It must be told to flush its
- buffers, although this is automatic done if some data is requested
- from another track. Trackdisk also does not switch off its drive motor.
- If not be told to switch it off, the motor runs forever. Dos knows
- about Td's lack of updating and does some special commands: CMD_UPDATE
- and TD_MOTOR. Dos does this well within five seconds. But programs
- that directly access Td, may not be aware and leave the motor running
- and the buffers unflushed.
- There are a lot of timers in Trackdisk, so why does not Td do it by
- it self? I do not know, but if you have the function switched on,
- Td flushes a modified trackbuffer and switch the motor off after
- five seconds idling.
-
-
- NOCLICK FUNCTION
-
- The presence of a disk in a drive is reflected by a line called CHNG.
- This line is asserted if there is no disk in the drive. It stays that
- way until a disk in the drive and the head is stepped (and the drive is
- selected of course). I assume this is done this way to give the
- opportunity to acknowledge an disk extraction. If the line directly
- reflects the disk presence state, an extraction can be missed. Well, it
- is a way, I know some other, and I know too that the sound of an empty
- drive generally is experienced to be annoying. The step direction is
- each time reversed, so the head will stay about the same position. This
- reverse is done by a CPU instruction "bchg", bitchange. Therefore is
- was very simple to implement the noclick function, just change the
- instruction into "bset", bit set. Then the head steps to the outside of
- the disk and once arrived, it stops because it is blocked there. This
- can be by a pillow or by an electrical switch, the latter effectively
- preventing stepping. When Kickstart got in rom, this was not that easy
- anymore. TrackSalve executes Trackdisk in ram, and the patch is simple
- again. But should you have noclick on every drive? Some drives still
- make noise, this time not as regular as well in time as in sound. Even
- more disturbing! Apart from the fact that I believe that these drives
- are not suitable for this method.
- For disk absence detection it is not needed to step the head. Therefore
- disk absence check is done every .5 seconds and presence check every
- 2.5 seconds. Now that the heads do not actually step, the interval of
- the presence check can be reduced to .5 seconds.
-
-
- VERIFY FUNCTION
-
- A drawback of this whole track read/write system is that a simple verify
- is not possible. It is not enough to verify the just written sector,
- because ten more sectors are written to disk. These sectors have
- probably no connection with the writing program, and a more general
- warning must be made. It is the particular Trackdisk task that does a
- request and the user must reply on it. The AutoRequest() has been
- proven unreliable in low memory situations. It returns "Cancel" if the
- function could not be carried out, where it should return "Retry". The
- same is true for an Alert(). Therefore TrackSalve build its own
- requester.
- My mouse is often hard to find, and if found, I have to search for a
- surface for it (the screen would be nice but it's too steep). So I like
- keyboard shortcuts. This is well implemented in the system requester.
- If you build your own requester, suddenly all input is blocked, and I
- found no way (other than an special inputhandler, which is beyond I am
- willing to implement in a patch) to receive shortcuts. What is a
- requester other than a window with some gadgets? Then I can receive
- everything I like. But this time Dmouse does not recognize the
- requester as a requester. Sigh. It doesn't get any easier with
- Intuition.
- Do the verify, the track is read back into another buffer and then
- compared with the original. This is broken in two parts, because the
- data in the verify buffer probably begins with another sector. The
- comparison is done by the blitter, xor-ing both buffers.
- The motor is switched off before the requester is displayed. The
- writing program however is not notified and may not switch off a motor
- of a source. The standard diskcopy is a good example. If you use
- diskcopy without its verify function, but with TrackSalve verifying
- (which is faster), and a verify error happens, the destination drive
- will stop turning. Diskcopy does not know and does not switch off its
- source drive. This is a good reason to enable the auto update function
- in TrackSalve, which will stop the source's motor.
-
-
- BUGS?
-
- The preceding release of TrackSalve (1.0) had a bug in it, although it
- was extremely unlikely that the buggy code would be executed. This
- unlikeliness was the reason that the bug slipped through the
- debugging phase. It brought me to an improved debugging administration
- and every single branch is executed under debug control, how trivial a
- branch might look. Pieces of code that could behave unexpectable
- because of special combinations of parameters, have been run under
- simulators producing all possible combinations. This time I would like
- to qualify the debugging as "extreme". Again: This program is extremely
- debugged!
-
-
- CONCLUSION
-
- With this patch Trackdisk becomes more efficient in its CPU use,
- although slightly slower (well under 2%) in its writing, because of the
- MFM update. A lot features are added, which are fully transparent.
- Trackdisk has come closer to what I think a floppy disk device driver
- should be. Better requires a complete rewrite. (Sorry Commodore,
- but disk drivers are my favorite pastime, yours too?).
-