765 Floppy Disk Driver Design Notes

  1. There are 2 entries into the driver that can cause disk operations. Both are invoked by FileCore, these being: a) DiscOp
    b) Mount
  2. DiscOp calls are routed to either FlpLowLevel or WinLowLevel, depending on the drive number (0..3=floppy, 4..7=winchester). These operations can result in data transfer and/or read/write head movement.
  3. Mount calls are similarly routed to either FlpMount or WinMount, depending on the drive number. The operation requires the driver to read the free space map on the disk, to determine the format, and to construct a disk record from the data read.
  4. In summary the following "high level" operations will be required:
            a) Read sectors
            b) Write sectors
            c) Format track
            d) Restore to track 0
            e) Seek
    

    5) To perform these functions the following operations are needed

               
            a) Select a drive
            b) Start spindle motor
            c) Time motor startup
            d) Calculate track/head/sector
            e) Seek/restore to track
            f) Verify track no. - optional
            g) Time head settling
            h) Issue '765 command
            i) Get '765 status
            j) Setup pseudo DMA under FIQ
            k) Read sector(s) in a track
            l) Write sector(s) in a track 
            m) Format a track
            n) Implement command timeout
            o) Set bit rate (125/250/500/1000 Kbps)
            p) Reset '765
            q) Read/reset disk changed
            r) Count index pulses
    

    Note that because Acorn L,D and E format disks start from sector no. 0 it will not be possible to use the "multitrack" function of the '765 controller. In addition because L format disks use 16x256 byte sectors per track (ECMA format - no IAM field), the '765 will not be able to format these disks exactly because of the IBM compatible IAM being written. Still it may be possible, like BEEBDOS, to format these disks by overwriting the IAM with the last sector. Some thought needs to go into gap sizes etc.

    6) In order to sequence these operations a finite state system (state machine) will be used. It is essential to arbitrate access to the state machine (by foreground/background accesses) because it is a single threaded construct. The objective of the machine is to sequence motor start, head settling and command completion.

    7) The following events will be recognized:

           
            a) TimeOut
            b) Index pulse
            c) FDC interrupt (Command done, seek done, ready)
            d) Disk changed, interrupt or polled?
    

    7a) The following requests will be recognized:

            a) Seek request(track 0..79 or any)
            b) Reset request, reset '765 restore head
            c) Lock drive
            d) Unlock drive
    

    7b) The following messages will be passed to pending commands:

            a) Track(0..79 or unknown)
            b) TimeOut
            c) DiskChanged
            d) FDC interrupt
    

    8) The following states will exist

            a) Drives idle
            b) Motor started, motor speeding up
            c) Motor ready, motor up to speed
            d) Seeking, head being stepped
            e) Settling, head settling after seek
            f) Drive ready
            g) Drive busy, read/write pending.  Is this necessary?
    

    9) What about retries? Handled by command processor. 9a) Retry algorithm?

            a) Retry operation (disable VIDC if over/underrun)
            b) Step out, step in, retry operation
            c) Restore, seek, retry operation
    

    10) Scatter list updated after each transfer request (1 track max)

    11) A general disk command processor entry point, passed a pointer to a disk control block (DCB) structured as follows:

    +00 BufferAddress & 1 ; Data buffer pointer

    +04  BufferSize & 1     ; Data buffer size
    +08  StaticBase & 1     ; R12 for post routine
    
    +0c PostRoutine & 1 ; Address to call on command completion +10 CommandStatus & 1 ; -1 = pending, 0= no error else an error ptr
    +14  TimeOut & 1        ; Command timeout in centiseconds, 0= none
    +18  Retries = 1        ; Retries, 0= none
    +19  ParamCount = 1     ; 0..13 bytes.  Bit7 = NoWait command
    
    +1a Command = 1
    +1b Parameters = 0d ; Command specific
    +28  Results = 08       ; 1..8 bytes, command specific
    +30  Link & 1           ; Reserved, ptr to next DCB
    
    +34 MessageHandler & 1 ; Reserved, ptr to message handler for this command
    +38  Reserved = 08      ; Reserved for driver
    

    Total size 64 bytes

    In addition to device specific commands a "Cancel" function is necessary to cancel a pending DCB. In this case "BufferAddress" -> DCB to cancel.

    Command processor action:

            a) Check command valid, add MessageHandler address
            b) Queue the DCB (sorted by track), status= pending
            c) Call the DCB message handler with MessageIdle
            d) MessageIdle will result in handler generating SeekRequest(n) to state m/c
            e) State system starts drive motor and performs seek if required
            f) State system generates EventTrack(n)
            g) Message handler claims event if track ok and issues command
            h) State system generates EventResult
            i) Message handler reads '765 status
            j) Command completed, post routine called
            k) MessageIdle sent to pending DCB's, next DCB starts processing
    
            Under interrupt the following happens:
    
    Parameter format:
            a) Arranged like '765 command block.
            b) Implied seek is bit 7 set of 1st parameter
    

    Supported commands:

            a) Read/write data/deleted data inc. multitrack
            b) Read track
            c) Read ID
            d) Format track
            e) Scan
            f) Seek, recalibrate -> state system
            g) Sense interrupt status
            h) Sense drive status
            i) Specify
            j) Invalid
    
            Determine source of FIQ (DRQ/IRQ), branch to Flp765IRQ if IRQ
            a) Read block - FlpFIQread
            b) Write block - FlpFIQwrite
            c) Verify (read and throw away) - FlpFIQverify
    
            d) All start:
            LDRB    Temp, [IOCfiq, #IOCFIQSTA]      ; Read FIQ status from IOC
            TSTS    Temp, IoDrqBit                  ; DRQ?
            BEQ     Flp765IRQ                       ; No then jump, check IRQ
    
            LDRB    Temp, [FDCdack], # 1            ; Read data with DACK/TC, FDCdack++
    
            Call DCB's with MessageIRQ, this allows DCB's to get results
            Queue next DCB from scatter list if required
            Downgrade FIQ to IRQ if no DCB's 
            Release FIQ to FileCore if all commands done.
    
            Read '765 status register.  If RQM and DIO are set then read results
              else issue sense interrupt to get ST0
    

    NOTES

    1. When mounting a new disk the calling sequence with the current 1772 driver is:
      i) DoPollChanged -> Maybe changed if no disk change support ii) Mount
      iii) DoPollChanged -> Maybe changed. WHY? - motor still on iv) DoPollChanged -> Not changed v) Mount
      vi) DoLockDrive. !!This should precede mount!! vii) DoPollChanged -> Not Changed viii) FlpLowLevel
      ix) FlpLowLevel to sector 0, ignore escape x) FlpLowLevel to sector 2, no escape, no timeout!
    2. FDC interrupts cause FIQ, in addition FDC data requests cause FIQ. Reading IOC &3200034 FIQ request register has bit 0 set for DRQ's and bit 1 set for real IRQ's. FIQ's can be downgraded to IRQ's by setting bit 7 in &3200018 which forces an IRQ and results in a call to the routine registered for device 7 (FIQ downgrade).
    3. After format operation remember the double step and alternate side parameters from the disk record provided so that at mount time after format can use these to fill in disk record. If motors stop then invalidate these values and use values in mount command.
    4. Disk record construction:
      Start at MFM 500K, MFM 250K, FM 125K, MFM 1000K Read ID headers, 1st attempt let 765 abort on 2nd index pulse (or timeout), subsequent attempts abort on next index pulse. When density recognized determine max/min sector numbers and construct disk record State system:
      a) Queued command comes to top of queue, do drive select. When ready state system sends "FlpMsgDrvRdy" to command message handler. b) Command tests implied seek bit and issues seek request if required. '765 goes busy, then settling then idle and sends "FlpMsgSeekDone". c) Command handler sends command to '765. d) Interrupt calls command handler with "FlpMsgCmdDone" or "FlpMsgTimeOut" as required.
      e) "FlpMsgCmdDone" invokes status read to get results. f) "FlpMsgTimeOut" invokes Flp765reset to abort operation.