                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Cmnd2  { continuation of Cmnd.Assem }
;>
;>      This module contains all the code associated with processing
;>      the System commands.
;>
;>      PROCEDURE Sys_Read
;>      PROCEDURE Sys_Write
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Sys_Read
;>
;>      This procedure is the System Read command for Widget. It
;>      allows the host to read up to 8 sequential blocks without
;>      sending any additional commands. Between each block status
;>      is passed back to the host with the data, and the host must
;>      set CMD before the next block can be read. In general, the protocol
;>      is about the same as in Pro_Read.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Ld_LgclBlk( Wid_Log_Offset )
;>       Count := Ld_Param1.FirstParam
;>       Offset := 0
;>       BlockNumber := Load_Logical
;>       ClrNormStat
;>       Get_Type_Check( BlockNumber + Count )
;>       Seek_Type := Access
;>       DiskStat.Wr_Op := False
;>       OverLap
;>       IF NOT( ReadBlock )
;>        THEN 
;>              SS_RdErr
;>              Goto Pro_Rd_Exit
;>       WHILE Always DO
;>              BlockNumber := BlockNumber + 1
;>              IF NOT( Srch_Cache )
;>               THEN OverLap
;>              IF NOT( Read_Fast )
;>               THEN Goto Pro_Rd_Exit
;>               ELSE
;>                IF BlkStat.Bad_Block
;>                 THEN GoTo Pro_Rd_BB
;>              IF ( Count > 1 )
;>               THEN 
;>                    Command_Pending,IBsy := True, Response := Sys_Rd_Resp
;>                    Rd_Leave2
;>               ELSE Rd_Leave
;>              Count := Count - 1
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Sys_Read:
                 Ld     Wrk_Io+$A,#Sys_Rd_Resp
                Call    Sys_SetUp
                
                
Sys_Rd_Seek:     Ld     Seek_Type,#Access
                 And    DiskStat,#$FF-Wr_Op
                Call    Sys_Rw_Seek
                Call    ReadBlock
                Jr      Nz,Sys_Rd_Next
                Jr      Sys_RdErr
                
Sys_Rd_Lp:      Call    Sys_Inc_Blk
                Jr      Nz,Sys_Rd_Seek
                
                And     !r0,#$3F ;mask off head value
                Ld      Sector,!r0

Sys_Rd_OvrLp:   Call    Read_Fast
                Jr      Z,Sys_Rd_Err

Sys_Rd_Next:    Tm      BlkStat,#B_Block ;check if bad block came back!
                Jr      Nz,Sys_Rd_BB
                
Sys_Rd_N1:      Ld      Wrk_Io+$A,#Sys_Rd_Resp
                Ld      Wrk_Io+$B,#Cmnd_Pending+IBsy
                Djnz    !r4,Sys_Rd_More
                
                Jp      Rd_Leave
                
Sys_Rd_More:    Call    Rd_Leave1
                Jr      Sys_Rd_Lp
                
                .Page
                
Sys_RdErr:      Push    !r4     ;save block count
                Call    Read_Common ;retry for exception handling
Sys_RErr1:      Pop     !r4     ;get block count
                Push    Flags   ;save result
                Push    !r0     ;save return code
                Call    Load_Logical ;restore block number sequence
                Pop     !r0
                Pop     Flags
                Jr      Nz,Sys_Rd_Next
                
                Call    Data_Ex_Handler
                Jr      Sys_Chk_Ftl

Sys_Rd_BB:      Push    !r4             ;save block count
                Call    Pro_Rd_BB
                Jr      Sys_RErr1

Sys_Chk_Ftl:    Call    Chk_FatalStat
                Jp      Nz,Rd_Leave     ;get out if fatal error
                
                Call    ClrNormStat
                Jr      Sys_Rd_N1

Chk_FatalStat:  Ld      !r2,#.HIBYTE. CStatus0
                Ld      !r3,#.LOWBYTE. CStatus0
                Lde     !r0,@!!r2               ;get 1st byte of standard stat
                Tm      !r0,#Op_Failed          ;check if operation failed
                Ret


Sys_SetUp:      Call    Ack_Read
                 
                Call    ClrNormStat
                
                 Ld     !r0,#Sys_Log_Offset
                Call    Ld_LgclBlk
                
                Call    Ld_Param1
                Or      !r0,!r0 ;check for zero count
                Jr      Nz,Sys_Set1
                
                Call    Abort
                
Sys_Set1:       Ld      !r4,!r0 ;Count := ...

                Call    Load_Logical
                Ld      !r0,!r4
                Dec     !r0 ;account for numbering 1..n
                Add     !rE,!r0
                Adc     !rD,#0
                Adc     !rC,#0
                 Ld     !r2,#.HIBYTE. Get_Type_Check
                 Ld     !r3,#.LOWBYTE. Get_Type_Check
                Call    Bank_Call
                
                Call    Load_Logical
                
                Ld      Data_Type,#User_Type
                
                Ld      Wrk_Io+$C,#.HIBYTE. WBuffer1 ;get ready for more writes
                Ld      Wrk_Io+$D,#.LOWBYTE. WBuffer1
                
                Ret
                
Sys_Rw_Seek:     Push   !r4 ;save state
                 Ld     !r2,#.HIBYTE. OverLap
                 Ld     !r3,#.LOWBYTE. OverLap
                Call    Bank_Call
                 Pop    !r4
                Call    Load_Logical
                Ret
                 
Sys_Inc_Blk:    Add     !rE,#$01 ;BlockNumber := BlockNumber + 1
                Adc     !rD,#0
                Adc     !rC,#0
                 Ld     !r2,#.HIBYTE. LogicalBlock
                 Ld     !r3,#.LOWBYTE. LogicalBlock
                 Ld     !r1,#3
                 Ld     !r0,#Wrk_Sys+$0C
Sys_Inc_Lp:     Ldei    @!!r2,@!r0
                Djnz    !r1,Sys_Inc_Lp
                
                Call    Srch_Cache      ;get the new physical adr
                Tm      BlkStat,#CachSeek+CachHdChg ;check for Head change
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Sys_Write
;>
;>      This procedure is the System Write command for Widget. In 
;>      general it is a major departure from the ProFile write
;>      protocol: Status is not sent back to the host unless
;>      there is useful information in that status - the fact that
;>      there were no errors in a block transfer is communicated
;>      to the host via Response Byte that is handshaken across
;>      at CMD/BSY time. If an error has occured, than the host
;>      is to recognize this state and come back to read the status
;>      from the controller, otherwise it is assumed that the next
;>      thing that the controller wants is write data. Note that
;>      the second handshake ( data received acknowledgment )
;>      has been removed from this protocol.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Ld_LgclBlk( Wid_Log_Offset )
;>       Count := Ld_Param1.FirstParam
;>       BlockNumber := Load_Logical
;>       ClrNormStat
;>       BlockNumber := BlockNumber
;>       Get_Type_Check( BlockNumber + Count )
;>       Seek_Type := Access_Offset
;>       DiskStat.Wr_Op := True
;>       OverLap
;>       IF NOT( ReadBlock )
;>        THEN 
;>              SS_RdErr
;>              Goto Pro_Rd_Exit
;>       WHILE Always DO
;>              BlockNumber := BlockNumber + 1
;>              IF NOT( Srch_Cache )
;>               THEN OverLap
;>              IF NOT( Write_Common )
;>               THEN Data_Ex_Handler( Wr_Common.Error.Code )
;>              IF NOT( Read_Fast )
;>               THEN Goto Pro_Rd_Exit
;>               ELSE
;>                IF BlkStat.Bad_Block
;>                 THEN GoTo Pro_Rd_BB
;>              IF ( Count > 1 )
;>               THEN 
;>                    Command_Pending,IBsy := True, Response := Sys_Wr_Resp
;>                    Rd_Leave2
;>               ELSE Rd_Leave
;>              Count := Count - 1
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Sys_Write:
                 Ld     Wrk_Io+$A,#Sys_Wr_Resp
                Call    Sys_SetUp
                
Sys_Wr_Seek:     Ld     Seek_Type,#Access+Offset
                 Or     DiskStat,#Wr_Op
                Call    Sys_Rw_Seek
                Tm      BlkStat,#B_Block ;check if bad block
                Jr      Nz,Sys_Wr_BB
                
                Call    WriteBlock
                Jr      Nz,Sys_Wr_Next
                Jr      Sys_WrErr
                
Sys_Wr_Lp:      Call    Sys_Inc_Blk
                Jr      Nz,Sys_Wr_Seek
                
                Tm      DiskStat,#Offset_On ;check for offset on all writes
                Jr      Z,Sys_Wr_Seek
                
                And     !r0,#$3F ;mask off head value
                Ld      Sector,!r0

Sys_Wr_OvrLp:   Tm      BlkStat,#B_Block ;check if bad block
                Jp      Nz,Sys_Wr_BB
                
                Call    Write_Fast
                Jr      Z,Sys_WrErr
                
Sys_Wr_Next:    Ld      Wrk_Io+$A,#Sys_Wr_Resp
                Ld      Wrk_Io+$B,#Cmnd_Pending+IBsy+MultiWr
                Ld      Wrk_Io+$C,#.HIBYTE. WBuffer1
                Ld      Wrk_Io+$D,#.LOWBYTE. WBuffer1
                Djnz    !r4,Sys_Wr_More
                
                 Ld     Wrk_Io+$A,#Sys_WrEnd_Resp
Sys_Wr_HS:       Ld     Wrk_Io+$B,#Cmnd_Pending+IBsy
                Call    Rd_Leave2
                Jp      Rd_Leave
                
Sys_Wr_More:    Call    Clr_Bsy
                Jr      Sys_Wr_Lp
                
                
Sys_WrErr:      Call    Wr_Common ;retry for exception handling
                Jr      Nz,Sys_Wr_Next
                
                Call    Data_Ex_Handler
Sys_WrChk:      Call    Chk_FatalStat
                Jr      Nz,Sys_WrE1
                
                Call    ClrNormStat
                Jr      Sys_Wr_Next

Sys_WrE1:       Ld      Wrk_Io+$A,#Sys_WrEx_Resp
                Jr      Sys_Wr_HS

Sys_Wr_BB:      Call    Wr_BBlock
                Jr      Sys_WrChk
                
                .LSTOFF

