                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Write Routines
;>
;>      This module contains all but the very most primitive of
;>      of procedures ( the routines that are resident are listed
;>      in the external spec's ) that concern themselves with performing
;>      a read operation.
;>
;>      FUNCTION WriteBlock( Parent : BYTE { !r8 } ) :
;>                         BOOLEAN
;>                         Status : BYTE { !r0 }
;>                         WrErrCnt : BYTE { !r1 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: WriteBlock
;>
;>      This function assumes that the heads are positioned over the
;>      correct track and writes the block of data whose header
;>      matches the header that is made up of the cylinder, head
;>      and sector information that is stored in memory.
;>
;>      Inputs:
;>              Parent : BYTE { !r8 }
;>
;>      Outputs:
;>              WriteBlock : BOOLEAN { Zero flag, true if error in ReadBlock }
;>              Status     : BYTE { !r0 }
;>              WrErrCnt   : BYTE { !r1 }
;>
;>      Global Variables Used:
;>              Cylinder, Head, Sector, Recovery
;>
;>      Local Variables Used:
;>              WrRetryCnt : BYTE { !r8 }
;>              WrError    : BOOLEAN { !r9/bit 7 }
;>              WrExcept   : BOOLEAN { !r9/bit 6 }
;>              WrSuccess  : BOOLEAN { !r9/bit 5 }
;>              NoHeaderFound : BOOLEAN { !r9/bit 4 }
;>              SectorsRead: BYTE { !rA }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       SetDeadManTimer( WriteBlock, Parent )
;>       WrRetryCnt := 10
;>       WrErrCnt := 0
;>       WrError := False
;>       WrExcept := False
;>       NoHeaderFound := False
;>       REPEAT
;>         WHeader[ 1 ] := HiCylinder
;>         WHeader[ 2 ] := LoCylinder
;>         WHeader[ 3 ]/bits 7:6 := Head
;>         WHeader[ 3 ]/bits 5:0 := Sector
;>         WHeader[ 4 ] := Invert( WHeader[ 1 ] )
;>         WHeader[ 5 ] := Invert( WHeader[ 2 ] )
;>         WHeader[ 6 ] := Invert( WHeader[ 3 ] )
;>         WDataSync := $0001
;>       _
;>      /
;>   R  |  Set-up external ram address counter for WRITE
;>   E  |  Msel0:1 := Disk <--> Mem
;>   S  |  WHILE SectorMark DO BEGIN END
;>   I  |  StartL := True
;>   D  |  WHILE NOT( SectorDnL ) DO BEGIN END
;>   E  |  Status := Status_Port
;>   N  |  StartL := False
;>   T  |  Msel0:1 := Z8 <--> Mem
;>      \_
;>
;>         CASE Status.State OF
;>              NormalEndState        : WrStat.WrSuccessful := True
;>
;>              NoMatchingHeaderFound : WrStat.WrSuccessful := False
;>                                      WrStat.WrError := True
;>                                      WrStat.NoHeaderFound := True
;>
;>              AbnormalState         : Reset_StateMachine
;>                                      Abort
;>
;>         IF Status.ServoErr OR NOT( Status.ServoRdy )
;>          THEN
;>               WrStat.WrError := True
;>               WrStat.Except := True
;>
;>         IF Status.WrtNvldL  AND WrSuccessful
;>          THEN
;>              WrStat.WrError := True
;>              WrStat.WrErrCnt := WrErrCnt + 1
;>              WrRetryCnt := WrRetryCnt - 1
;>          ELSE
;>              RdRetryCnt := 0
;>
;>       UNTIL NOT( Recovery ) OR NOT( WrError ) OR ( WrRetryCnt = 0 ) OR
;>                      WrExcept OR ( NoHeaderFound )
;>       ClearDeadManTimer
;>      END
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
WriteBlock:
                Clr     !r9     ;clear booleans
                Ld      !r8,#10 ;WrRetryCnt := 10
                Clr     !rB     ;ErrCnt := 0
                Or      DiskStat,#Wr_Op ;make certain we are writing
                 
WrBlk_Rpt:       Ld     !r2,#.HIBYTE. WHeader ;initialize gaps
                 Ld     !r3,#.LOWBYTE. WHeader
                Call    Load_Header

                Ld      !r0,#0
                Ld      !r1,#( WDataSync - WDataGap )
WrGap_Lp:       Lde     @!!r2,!r0
                Inc     !r3
                Djnz    !r1,WrGap_Lp
                
                Ld      !r0,#01
                Lde     @!!r2,!r0       ;first byte of sync
                Inc     !r3
                Ld      !r0,#$00
                Lde     @!!r2,!r0       ;second byte of sync
                Jr      Do_Write

Write_Fast:     Clr     !r9     ;clear booleans
                Ld      !r8,#10 ;WrRetryCnt := 10
                Clr     !rB     ;ErrCnt := 0
                Or      DiskStat,#Wr_Op ;make certain we are writing
                 
                Ld      !r2,#.HIBYTE. ( WHeader+2 ) ;get Sector location
                Ld      !r3,#.LOWBYTE. ( WHeader+2 )
                Lde     !r0,@!!r2 ;get current Head/Sector Value
                And     !r0,#$C0 ;mask ols sector value
                Or      !r0,Sector ;merge new sector value
                Lde     @!!r2,!r0 ;store it in header
                Add     !r3,#3 ;get location of Inverse Sector
                Com     !r0
                Lde     @!!r2,!r0 ;and store it!
                
Do_Write:       Call    Wr_Resident     ;go internal to the Z8

                Ld      !r1,!r0         ;CASE Status.State
                And     !r1,#$0F
                Or      !rA,!rA
                Jr      Z,WrBlk_NoHdr
                Cp      !r1,#Norm_State
                Jr      Nz,WrBlk_AbNorm
                
WrBlk_Norm:     Or      !r9,#WrSuccess

                Ld      !r1,!r0         ;IF ServorErr OR NOT( ServoRdy )
                Tm      !r1,#ServoErr
                Jr      Nz,Wr_ServoErr
                Tm      !r1,#ServoRdy
                Jr      Z,Wr_ServoErr
                
Wr_ServoOk:     Tm      !r0,#WrtNvldL    ;IF Status.WrtNtVldL
                Jr      Z,WrBlk_NVld
                
                And     !r9,#$FF-WrError
                
WrBlk_Until:    Tm      Excpt_Status,#Recovery
                Jr      Z,WrBlk_End
                Tm      !r9,#WrError
                Jr      Z,WrBlk_End
                Djnz    !r8,WrB_Rpt1
                
WrBlk_End:      Ld      WrErrCnt,!rB
                Ld      !r0,!r9 ;send status back to caller
                Ld      WrStat,!r9
                Tcm     !r0,#WrError ;set zero flag if error
                Ret
                
                
WrB_Rpt1:        Ld     !r2,#.HIBYTE. ZeroHeader
                 Ld     !r3,#.LOWBYTE. ZeroHeader
                Call    Bank_Call
                Jr      WrBlk_Rpt
                
WrBlk_AbNorm:    Call   Reset_StMach
                 Ld     !rA,!r0
                Call    Abort
                
WrBlk_NoHdr:    And     !r9,#$FF-WrSuccess
Wr_HdrErr:      Or      !r9,#WrNoHdrFnd + WrError
                Or      !rB,#Hdr_MisMatch
                Jr      WrBlk_End
                
Wr_ServoErr:    Or      !r9,#WrError + WrSrvoErr ; THEN WrError AND WrSrvoErr
                Jr      WrBlk_End
                
WrBlk_NVld:     Or      !r9,#WrError    ; ELSE
                Inc     !rB
                Jr      WrBlk_Until
                
                .LSTOFF
               
