                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Data Exception Handling
;>
;>      PROCEDURE: Data_Ex_Handler( ErrorCode : 7 BITS { !r0/Bits 6:0 } )
;>
;>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Data_Ex_Handler { data exception handler }
;>
;>      This procedure is responsible for cleaning up after some sort
;>      of data error ( spareing, bad-blocking, etc. ). It is
;>      assumed that if spareing is going to occur that correct data must
;>      be residing in Buffer2.
;>
;>      Inputs:
;>              ErrorCode : 7 BITS { !r0/Bits 6:0 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       IF NOT( DiskStatus.Wr_Op ) THEN SetStatus( ReadError )
;>       CASE ErrorCode OF
;>        0 : SetStatus( OperationFailed )
;>
;>        2 : Spare( Spare )
;>
;>        4 : Spare( BadBlock )
;>            SetStatus( OperationFailed )
;>
;>        6 : SetStatus( ErrorCount )
;>
;>        8 : SetStatus( NoHeaderFound )
;>            Spare( BadBlock )
;>            SetStatus( OperationFailed )
;>
;>        A : SetStatus( NoHeaderFound )
;>            Spare( Spare )
;>       OTHERWISE Abort
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Data_Ex_Handler:
                Push    !r0 ;save error code
                 
                Call    ExtPush_Vector ;save state
                
                Tm      DiskStat,#Wr_Op
                Jr      Z,Data_Ex_RdErr
                
                 Ld     !r0,#3 ;load status byte 3
                 Ld     !r1,WrErrCnt
                Call    SetStatus
                Jr      Data_Ex_Case
                
Data_Ex_RdErr:  Call    SS_ReadErr
                
Data_Ex_Case:    Ld     !r2,#.HIBYTE. Set_SeekNeeded
                 Ld     !r3,#.LOWBYTE. Set_SeekNeeded
                Call    Bank_Call ;update cache on next Pro/Sys command
                
                Pop     !r1 ;get error code back
                And     !r1,#$7F ;mask off error flag
                Tm      !r1,#01 ;see if error code is odd
                Jr      Nz,Data_Ex_Abort
                Cp      !r1,#Ex_Case_Max ;bounds check
                Jr      Le,Data_Ex_Cmnd
                
Data_Ex_Abort:  Call    Abort
                
Data_Ex_Cmnd:   Ld      !r2,#.HIBYTE. Ex_Jp_Tbl
                Ld      !r3,#.LOWBYTE. Ex_Jp_Tbl
                Add     !r3,!r1 ;add offset
                Adc     !r2,#0
                Ldc     !rE,@!!r2 ;get routine to execute
                Incw    !!r2
                Ldc     !rF,@!!r2
                Jp      @!rE ;go to routine
                
Ex_Jp_Tbl:      .DW     X_Undeter
                .DW     X_Spare
                .DW     X_BadBlock
                .DW     X_ReadErr
                .DW     X_HdrBadBlock
                .DW     X_HdrSpare
                
X_Undeter:      Call    SS_OpFail
                Jr      Except_Return
                
X_Spare:        Ld      !rA,#Spare
X_Spr_Call:     Call    SprBlock
                Jr      Except_Return
                
X_BadBlock:     Ld      !r4,#4 ;retry 4 times
X_BB_Lp:        Push    !r4
                Call    Bad_Recover
                Pop     !r4
                Jr      Nz,X_Spare
                Djnz    !r4,X_BB_Lp
                
                Call    SS_OpFail
                 Ld     !rA,#BadBlock
                Jr      X_Spr_Call
                
X_ReadErr:      Call    SS_ReadErr
                 Ld     !r2,#.HIBYTE. Buf2_To_RBuf
                 Ld     !r3,#.LOWBYTE. Buf2_To_RBuf
                Call    Bank_Call
Except_Return:  Call    ExtPop_Vector
                Jp      Bank_Ret
                
X_HdrBadBlock:  Call    Bad_Recover
                Jr      Nz,X_Spare
                Call    SS_NoHdr
                Call    LocateSector
                 Ld     !r2,#.HIBYTE. ReadHdr
                 Ld     !r3,#.LOWBYTE. ReadHdr
                Call    Bank_Call
                Jr      Z,X_Hdr_Crct
                 
                 Ld     !r2,#.HIBYTE. RBuf_To_Buf2
                 Ld     !r3,#.LOWBYTE. RBuf_To_Buf2
                Call    Bank_Call
                Jr      X_Spare
                
X_Hdr_Crct:      Ld     !r2,#.HIBYTE. Ecc
                 Ld     !r3,#.LOWBYTE. Ecc
                Call    Bank_Call
                Jr      Z,X_BadBlock

X_HdrSpare:     Call    SS_NoHdr
                Jr      X_Spare
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Bad_Recover
;>
;>      This function is called when a block can not be read, either the
;>      header can not be found or there is a hard data error. The purpose
;>      here is to use the auto offset capabilities of the servo controller
;>      and reread the block.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Bad_Recover: BOOLEAN { zero flag set if failure on retry }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Bad_Recover:
                Tm      DiskStat,#Offset_On ;check for auto_offset
                Jr      Nz,B_Rcvr_Read
                
                Call    ReSeek

B_Rcvr_Read:    Call    Read_Common
                Jr      Nz,Bad_Rcvr_Ret
                
                Cp      !r0,#Error+Ex_ReadErr
                Jr      Z,Bad_Rc_Spr
                
                Cp      !r0,#Error+Ex_BadBlock
                Jr      Z,Bad_Rc_Ecc
                
                Cp      !r0,#Error+Ex_SprBlock
                Jr      Z,Bad_Rc_Spr
                
                Ld      !r0,#0
Bad_Rc_Set:     Or      !r0,!r0
                Jr      Bad_Rcvr_Ret
                
Bad_Rc_Spr:     Ld      !r0,#1
                Jr      Bad_Rc_Set
                
Bad_Rc_Ecc:      Ld     !r2,#.HIBYTE. Ecc
                 Ld     !r3,#.LOWBYTE. Ecc
                Call    Bank_Call
                
Bad_Rcvr_Ret:   Ret
                
                .LSTOFF
                
