                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: SrvoUtils
;>
;>      BANK 1 MODULE
;>
;>      This module holds those routines that make up most of the
;>      auxillary servo commands.
;>
;>      PROCEDURE ServoCmnd( CommandString : 4 BYTES { !r0:3 } )
;>      PROCEDURE ServoStatus( CommandString : 4 BYTES { !r0:3 }
;>                             BufferPtr : PTR { !!rE }
;>                           )
;>      FUNCTION ServoStore : BOOLEAN
;>      FUNCTION ServoLoad( BufferPtr : PTR { !!r2 } ) : BOOLEAN
;>      FUNCTION Restore( RecalType : BYTE { !r0 } ) : BOOLEAN
;>      PROCEDURE SrvoRcvry
;>      PROCEDURE Load_SrvoCmnd
;>      PROCEDURE Park_Heads
;>      PROCEDURE ResetServo
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: ServoCmnd  { Send the Servo a command }
;>
;>      Inputs:
;>              CommandString : 4 BYTES { !r0:3 }
;>
;>      Outputs: { none }
;>
;>      Global Variables Changed:
;>              SrvoCmndBuffer
;>
;>      Local Variables:
;>              SioRetry : BYTE { !r8 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       SrvoCmndBuffer[ CommandByte ] := !r0
;>       SrvoCmndBuffer[ LoDiffByte ] := !r1
;>       SrvoCmndBuffer[ OffsetByte ] := !r2
;>       SrvoCmndBuffer[ StatusByte ] := !r3
;>       SioRetry := 4
;>       WHILE NOT( ServoStore( CommandString ) ) AND ( SioRetry > 0 ) DO
;>              SioRetry := SioRetry - 1
;>       IF ( SioRetry = 0 ) ABORT
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
ServoCmnd:      
                Srp     #Wrk_Sys2
                Call    Load_SrvoCmnd
                
Srv_C_Lp1:      Ld      !r8,#4  ;SioRetry := 4
                
                Ld      !r4,ScrReg0 ;save command
                Ld      !r5,ScrReg1
                Ld      !rA,ScrReg2
                Ld      !rB,ScrReg3
                
Srv_C_Lp:       Call    ServoStore
                Jr      Nz,Srv_C_End
                
                Ld      ScrReg0,!r4 ;restore command
                Ld      ScrReg1,!r5
                Ld      ScrReg2,!rA
                Ld      ScrReg3,!rB
                
                Djnz    !r8,Srv_C_Lp

Srv_C_Abort:    Call    Abort
                
Srv_C_End:      Srp     #Wrk_Sys
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: ServoStatus  { Read a status location from the servo }
;>
;>      Inputs:
;>              CommandString : 4 BYTES { !r0:3 }
;>
;>      Outputs: { none }
;>
;>      Global Variables Changed:
;>              SrvoCmndBuffer
;>
;>      Algorithm:
;>
;>      BEGIN
;>       ServoCmnd
;>       IF NOT( ServoLoad( BufferPtr ) ) THEN ABORT
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
ServoStatus:
                Push    !r8 ;save for caller
                Ld      !r8,#4 ;retry 4 times
                
Srv_St_Lp1:     Call    ServoCmnd
Srv_St_Else:    Call    ServoLoad
                Jr      Z,Srv_St_End
                
                Ld      ScrReg0,Wrk_Sys2+$04
                Ld      ScrReg1,Wrk_Sys2+$05
                Ld      ScrReg2,Wrk_Sys2+$0A
                Ld      ScrReg3,Wrk_Sys2+$0B
                Djnz    !r8,Srv_St_Lp1
                
                Call Abort
                
Srv_St_End:     Pop     !r8
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: ServoStore
;>
;>      The function of this routine is to transmit a command string
;>      to the Servo Processor. The command string is expected to
;>      reside in the global variable
;>      SrvoCmndBuffer ( thus providing a record of the last command
;>      sent to the servo ). ServoStore then attempts to complete the
;>      transmission to the Servo, and returns a boolean variable
;>      indicating whether the transmission was completed or not.
;>
;>      Inputs:
;>              Parent : BYTE { !r1 }
;>
;>      Outputs:
;>              ServoStore : BOOLEAN { Zero flag; True if transmission failed }
;>
;>      Local Variables:
;>              Retry : BYTE { !r6 }
;>              i     : BYTE { !r4 }
;>              j     : BYTE { !r5 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       SrvoCmndBuffer[ CheckByte ] := GenerateCheckByte(
;>                                              PTR( SrvoCmndBuffer ),
;>                                              Length( SrvoCmndBuffer ) )
;>       Retry := 10
;>       REPEAT
;>         FOR i := 1 TO 5 DO
;>              WHILE ( IRQ.SerialOutput = False ) OR NOT( SioReady ) DO
;>                      BEGIN
;>                      END
;>              Sio.Data := SrvoCmndBuffer[ i ]
;>         Retry := Retry - 1
;>         FOR j := 1 TO ( value for wait of 250 usec ) DO BEGIN END
;>       UNTIL NOT( SioReady ) OR ( Retry = 0 )
;>       FOR j := 1 TO ( value for wait of 400 usec ) DO BEGIN END
;>       IF ( Retry = 0 )
;>        THEN ServoStore := False
;>        ELSE ServoStore := True
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

ServoStore:     Push    Rp ;save context
                Srp     #Wrk_Scr
                
                 Ld     !rE,#.HIBYTE. SrvoCmndBuffer
                 Ld     !rF,#.LOWBYTE. SrvoCmndBuffer
                 Ld     !r8,#S_Cmnd_Len - 1
                Call    Gen_Chk_Byte
                
                Ld      !r6,#10 ;Retry := 10
                
Srvo_St_Rpt:    Ld      !rE,#.HIBYTE. SrvoCmndBuffer
                Ld      !rF,#.LOWBYTE. SrvoCmndBuffer
                
                Ld      !r4,#S_Cmnd_Len
                
Srvo_St_1:      Tm      Port2,#SioRdy   ; WHILE NOT( SioReady )
                Jr      Z,Srvo_St_1
                
                And     Irq,#$FF-Serial_Out-Serial_In     ;clear old interrupts
                
                Lde     !r0,@!!rE       ;get a command byte
                Ld      Sio,!r0         ;send it to Servo
                
                Incw    !rE             ;point to next command byte
                
Srvo_St_2:      Tm      Irq,#Serial_Out ;WHILE ( IRQ.SerialOut = False )
                Jr      Z,Srvo_St_2
                
                Djnz    !r4,Srvo_St_1   ;loop 'til all command bytes are sent
                
                And     Irq,#$FF-Serial_Out     ;clear old interrupts
                
                Ld      !r5,#80         ;do a 250 usec wait
Srvo_Wt_1:      Djnz    !r5,Srvo_Wt_1

                Tm      Port2,#SioRdy   ;if NOT( SioReady ) then Servo 
                Jr      Z,Srvo_St_Exit  ; took the bytes and is munchin' on 'em
                
                Djnz    !r6,Srvo_St_Rpt ;Retry := Retry - 1
                
Srvo_St_Exit:   Or      !r6,!r6         ;test for Retry = 0
                Pop     Rp ;return to original context
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: ServoLoad
;>
;>      This function is responsible for reading a status response back 
;>      from the servo. The bytes that it receives are stored into a
;>      buffer that is passed into the routine in the form of a PTR.
;>      ServoLoad passes back to the caller a BOOLEAN variable describing
;>      whether the checkbyte was valid ( i.e., the transmission was a
;>      success.
;>
;>      Inputs:
;>              Parent : BYTE { !r1 }
;>              BufferPtr : PTR { !r2:3 }
;>
;>      Outputs:
;>              ServoLoad : BOOLEAN { Zero flag, true if checkbyte mismatch }
;>
;>      Global Variables Changed:
;>              Buffer pointed to by !!r2
;>
;>      Local Variables:
;>              i : BYTE { !r4 }
;>              TempBufPtr : PTR { !!rA }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 1 TO 5 DO
;>         WHILE NOT( Irq.SerialInput ) DO BEGIN END
;>         Buffer[ i ] := Sio.Data
;>       ServoLoad := Check_Check_Byte( PTR( Buffer ), 5 )
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

ServoLoad:
                Push    Rp      ;save context
                Srp     #Wrk_Scr  ;context switch
                
                Ld      !rE,#.HIBYTE. SStatus0
                Ld      !rF,#.LOWBYTE. SStatus0
                
                Ld      !r4,#5  ;load i
                
Srvo_Ld_Wt:     Tm      Irq,#Serial_In
                Jr      Z,Srvo_Ld_Wt
                
                And     Irq,#$FF-Serial_In      ;clear old interrupts
                
                Ld      !r0,Sio         ;read SIO
                Lde     @!!rE,!r0       ; and store in buffer
                
                Incw    !!rE            ;point to next location in buffer
                
                Djnz    !r4,Srvo_Ld_Wt  ;loop 'til all bytes are read
                
                 Ld     !rE,#.HIBYTE. SStatus0 ;get original buffer ptr
                 Ld     !rF,#.LOWBYTE. SStatus0
                 Ld     !r8,#4          ;length of buffer
                Call   Chk_Chk_Byte
                Pop     Rp              ;context switch
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Restore
;>
;>      This procedure performs a Recal operation on the servo.
;>      Normally, a ReadHeader operation is to be performed after 
;>      the Servo comes ready, and the current cylinder is to be 
;>      subsequently updated. This mechanism ( doing the ReadHeader )
;>      can be turned off by clearing the RdHdrRecal bit in the
;>      exception working register set.
;>
;>      Inputs:
;>              RecalType : BYTE { !r0 }
;>
;>      Outputs:
;>              Restore : BOOLEAN { zero flag is true if NOT( ServoRdy ) }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       ServoCmnd( RecalType, 0, 0, 57.6K Baud )
;>       WHILE NOT( ServoRdy ) AND 2 seconds hasn't gone by DO BEGIN END
;>       IF ( DiskStat.RdHdrRecal ) AND ServoRdy
;>        THEN IF NOT( UpDate_Cur_Cyl ) THEN Abort
;>        ELSE
;>         IF ( RecalType = DataRecal )
;>          THEN Cur_Cyl := Init_Cyl
;>          ELSE Cur_Cyl := Max_Cyl
;>       Restore := ServoRdy
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Restore:
                 Push   !r0 ;save RecalType for later
                 Call   Ext_Push
                 
                 Call   Set_Dmt
                 
                 Srp    #Wrk_Scr
                 Pop    !r0 ;save RecalType for later
                 Push   !r0
                 Clr    !r1
                 Clr    !r2
                 Ld     !r3,#S_Rate_57_6
                 Srp    #Wrk_Sys
                Call    ServoCmnd
                Call    Clr_Dmt
                And     DiskStat,#$FF-On_Track
                Call    Set_SeekNeeded
                
                Ld      Cur_Cyl,#HiMaxCyl ;assume FormatRecal
                Ld      Cur_Cyl+1,#LoMaxCyl
                
                Pop     !r6 ;load RecalType from storage
                Cp      !r6,#FrmtRecal
                Jr      Z,Rest_Up2
                
                Ld      Cur_Cyl,#Init_HiCyl ;otherwise DataRecal
                Ld      Cur_Cyl+1,#Init_LoCyl

Rest_Up2:       Clr     !r5
                Ld      !r4,#$D5 ;max time to wait is two seconds
                
Restore_Lp:     Call    LoadStatus
                Tm      !r0,#ServoRdy
                Jr      Nz,Rest_UpDate
                Decw    !!r4
                Jr      Nz,Restore_Lp
                
                Clr     !r0             ;pass error status to exit
                Jr      Restore_End
                
Rest_UpDate:    Tm      DiskStat,#RdHdrRecal
                Jr      Z,Rest_Up1
                Cp      !r6,#FrmtRecal ;don't try to read headers here!
                Jr      Z,Rest_Up1
                
                Call    UpDate_Cur_Cyl
                Jr      Nz,Rest_Up1 ;leave if positioned correctly
                
                Call    SS_NoHdr ;header err here is bad news!
                Call    Abort

Rest_Up1:       Ld      !r0,#1
Restore_End:    Push    !r0 ;save result
                Call    Ext_Pop
                And     DiskStat,#$FF-Offset_On-Parked-On_Track
                Or      DiskStat,#SeekComplete
                Pop     !r0
                Or      !r0,!r0 ;set zero flag
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: SrvoRcvry { ServoRecovery }
;>
;>      This procedure's responsiblity is to do everything within reason
;>      to make certain that the Servo Processor is Healthy, Wealthy, and
;>      Wise; and if it can't then there is no point in using the Servo.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Local Variables:
;>              i       : BYTE { !r8 }
;>              Error   : BOOLEAN { !r9 }
;>
;>      Global Variables Changed:
;>              On_Track, Cur_Cyl
;>
;>      Global Variables Used:
;>              Cylinder, Head, Sector
;>
;>      Algorithm:
;>
;>      BEGIN
;>       i := 8
;>       REPEAT
;>        Zero_Header
;>        Error := False
;>        IF ServoError
;>         THEN Error := NOT( ServoOk )
;>         ELSE
;>              Error := NOT( ReadHdr )
;>              IF NOT( Error )
;>               THEN
;>                IF ReadHdr.Cylinder <> Cylinder
;>                 THEN
;>                      Cur_Cyl := ReadHdr.Cylinder
;>                      On_Track := False
;>        IF NOT( On_Track ) THEN Seek( Cylinder, Head, Sector )
;>       UNTIL ( i = 0 ) OR NOT( Error )
;>       IF ( i = 0 ) THEN Abort
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

SrvoRcvry:
                Call    Ext_Push    ;save caller's stuff
                
                Ld      !r8,#4  ;i := 8
                
Srvo_R_Rpt:     Call    Zero_Header
                Call    Chk_SStat
                Jr      Nz,Srvo_R_Sok
                
                Call    ServoOk
                
Srvo_R_Sok:     Call    UpDate_Hdr ; IF ReadHdr.Cylinder <> Cylinder...
                Jr      Nz,Srvo_R_Leave
                
                 Ld     !r0,#1 ;byte1
                 Ld     !r1,#Stat_Seek
                Call    Set_Status
                
                Call    ReSeek
                 
Srvo_DecI:      Djnz    !r8,Srvo_R_Rpt

Srvo_R_Leave:   Call    Ext_Pop     ;get user's stuff back
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Load_SrvoCmnd  { Load Servo Command Buffer }
;>
;>      This procedure loads the global array ServoCmndBuffer
;>      with the information contained within !r0:3
;>
;>      Inputs:
;>              SrvoCmndBuffer[ 0 ] : BYTE { !r0 }
;>              SrvoCmndBuffer[ 1 ] : BYTE { !r1 }
;>              SrvoCmndBuffer[ 2 ] : BYTE { !r2 }
;>              SrvoCmndBuffer[ 3 ] : BYTE { !r3 }
;>
;>      Outputs: { none }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Load_SrvoCmnd:
                Ld      !r2,#.HIBYTE. SrvoCmndBuf
                Ld      !r3,#.LOWBYTE. SrvoCmndBuf
                Ld      !r1,#4 ;load 4 bytes
                Ld      !r0,#ScrReg0 ;start with what's in ScrReg0
                
Ld_S_Cmnd_Lp:   Ldei    @!!r2,@!r0
                Djnz    !r1,Ld_S_Cmnd_Lp
                
                Ret
                
                .LSTOFF
                .DO     External
                .LSTOFF
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Park_Heads
;>
;>      This procedure moves the heads in a closed-loop fashion
;>      ( access command vs. Park command ) to a location away from the
;>      user data area. The attempt here is to provide some additional
;>      protection from power failures, and the such, from accidentally
;>      writing bogus data on the disk.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Seek( HiParkCylinder, LowParkCylinder, 0, 0 )
;>       Set_SeekNeeded
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Park_Heads:
                 Ld     SeekType,#Access
                 Ld     !rC,#HiParkCyl
                 Ld     !rD,#LowParkCyl
                 Clr    !rE
                 Clr    !rF
                Call    Seek
                
                Or      DiskStat,#Parked
                And     DiskStat,#$FF-On_Track
                Call    Set_SeekNeeded
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: ResetServo
;>
;>      This procedure is responsible for performing all the 
;>      necessary tasks in resetting the servo. This includes
;>      setting the correct Baud rates ( the servo comes up
;>      at 19.2k baud, but normally runs at 57.6k baud ) and
;>      positioning the heads over the data field and keeping 
;>      the world straight about it ( cylinder is set to
;>      MaxDataCylinder because a DataRecal positions the heads
;>      at the closest data cylinder to the inside ).
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       ServoRst := True
;>       Wait for 18 instructions ( about ) to make certain that Reset is valid
;>       ServoRst := False
;>       Wait for 2 secs to allow motor and servo to get ready
;>       IF NOT( ServoRdy ) OR ServoError THEN Abort
;>       Baud Rate := 19.2k
;>       IF NOT( ServoStore( ReadStatus, x, x, BaudRate57.6 + NormalStatus ) )
;>        THEN Abort
;>       IF NOT( ServoLoad( NormalReadStatusBuffer ) )
;>        THEN Abort
;>       Baud Rate := 57.6K
;>       IF NOT( Restore( DataRecal ) ) THEN Abort
;>       DiskStatus.On_Track := False
;>      END
;>
;>      Global Variables Changed:
;>              Cylinder
;>
;>              
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

ResetServo:
                And     Port0,#$FF-Not_ServoRst ;set Servo Reset
                
S_Rst_Lp1:       Ld     !r2,#.HIBYTE. 5 ;busy wait for 50 msec
                 Ld     !r3,#.LOWBYTE. 5
                Call    MsWait
                
                Or      Port0,#Not_ServoRst ;clear Servo Reset

                 Ld     !r2,#.HIBYTE. 100 ;busy wait for 1 sec
                 Ld     !r3,#.LOWBYTE. 100
                Call    MsWait
                
S_Rst_1:        Call    LoadStatus ;get servo status
                Tm      !r0,#ServoErr
                Jr      Z,S_Rst_Bd1
                
S_Rst_Abt1:      Ld     !rA,!r0
                Call    Abort
                
S_Rst_Bd1:      And     Tmr,#$FF-T0_CntEn        ;halt T0
                Ld      Pre0,#$D ;Pre0 := Mod-64,continuous;go to 19.2k baud
                Ld      T0,#1   ;interrupt after 1 byte
                Or      Tmr,#T0_CntEn + T0_Load
                
                Call    Set_Dmt
                 Srp    #Wrk_Scr
                 Ld     !r0,#ReadStatus  ;try talking to the Servo
                 Clr    !r1
                 Clr    !r2
                 Ld     !r3,#S_Norm_Status + S_Rate_57_6
                 Srp    #Wrk_Sys
                Call    Load_SrvoCmnd
                Call    ServoStore
                Jr      Z,S_Rst_Comm
                Call    Load_Status
                Tm      !r0,#ServoErr
                Jr      Z,S_Rst_Ld
                
S_Rst_Comm:      Ld     !rA,#S_Store
S_Rst_Abt2:      Ld     !r8,#S_Rst_Abort
                Call   Abort
                
S_Rst_Ld:       Call    ServoLoad
                 Ld     !r7,#S_Load
                Jr      Nz,S_Rst_Abt2
                Call    Clr_Dmt

                And     Tmr,#$FF-T0_CntEn        ;halt T0
                Ld      Pre0,#$5 ;Pre0 := 1,continuous run ;go to 57.6k baud
                Ld      T0,#1
                Or      Tmr,#T0_CntEn + T0_Load
                
S_Rst_2:        Jp      Bank_Ret

                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Set_SeekNeeded
;>
;>      This procedure acts in much the same fashion for the
;>      LogicalBlockCache as DiskStat.On_Track does for simple
;>      seeks. It keeps a legitimate seeks between tow requests
;>      for the same block number from returning a bogus result.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 1 TO CacheLength DO
;>        CachStat[ i ].SeekNeeded := True
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Set_SeekNeeded:
                Ld      !r2,#.HIBYTE. CachStat
                Ld      !r3,#.LOWBYTE. CachStat
                Ld      !r1,#CacheLength

S_SeekN_Lp:     Lde     !r0,@!!r2 ;get array value
                Or      !r0,#CachSeek
                Lde     @!!r2,!r0
                Incw    !!r2
                Djnz    !r1,S_SeekN_Lp
                
                Jp      Bank_Ret
                
                .LSTOFF
                
