                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Cache.B1
;>
;>      BANK 1 MODULE
;>
;>      This module contains those Cache routines that must be located
;>      in Bank 1.
;>
;>      PROCEDURE Load_Cache
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Load_Cache
;>
;>      This procedure loads the 'cache-table' with the next 7
;>      sequential logical blocks ( from the current logical block )
;>      and status' associated with each block ( i.e., if no seek is
;>      required, if a head change is required, etc. ) and the
;>      head and sector number of each logical block ( assuming that
;>      all the blocks are on the same track ). It should be noted that
;>      the status bytes are kept in a seperate table.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Data_Type := User_Type
;>       FOR i := 1 TO CacheLength DO
;>        Cur_Block := LogicalBlock + i
;>        TempCyl, TempHead, TempSector,
;>                      SrchStat, SrchPtr := CnvrtLogical( Cur_Block )
;>        CacheStatus[ i - 1 ].Seek := CalcMagDir( TempCyl )
;>        IF ( TempHead <> Head )
;>         THEN CacheStatus[ i - 1 ].HeadChange := True
;>         ELSE CacheStatus[ i - 1 ].HeadChange := False
;>        CacheArray[ i - 1 ].LogicalBlock := Cur_Block
;>        CacheArray[ i - 1 ].Head := TempHead
;>        CacheArray[ i - 1 ].Sector := TempSector
;>       Cache_Index := 0
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Load_Cache:
                Ld      !r4,#CacheLength
                Ld      !r5,#0 ;clear seekneeded, headchange booleans
                Ld      Data_Type,#User_Type
                
                Ld      !r8,#.HIBYTE. CachStat
                Ld      !r9,#.LOWBYTE. CachStat
                Ld      !rA,#.HIBYTE. CacheArray
                Ld      !rB,#.LOWBYTE. CacheArray
                 
                Call    Load_Logical
                
                 Ld     !r2,#.HIBYTE. TLBlock
                 Ld     !r3,#.LOWBYTE. TLBlock
                Call    St_Blk
                
                Call    Ld_C_Srch
                 Push   Flags   ;save result of spare table search
                 Push   !r0
                 Ld     !r2,#.HIBYTE. PBlock
                 Ld     !r3,#.LOWBYTE. PBlock
                Call    St_Blk
                Call    Cache_Cnvrt
                 Pop    !r0
                 Pop    Flags
                Clr     !r1 ;SeekNeeded,HdChg := False
                Jr      Nz,Ld_Cache_In
                Jp      Ld_C_Enter
                
Ld_Cache_Lp:     Ld     !r2,#.HIBYTE. PBlock
                 Ld     !r3,#.LOWBYTE. PBlock
                Call    Inc_Blk
                 Ld     !r2,#.HIBYTE. TLBlock
                 Ld     !r3,#.LOWBYTE. TLBlock
                Call    Inc_Blk
                
                Call    Ld_C_Srch
                Jr      Z,Cache_NoSpare
                
                 Ld     !r1,#CachSeek
                 Or     !r5,!r1 ;set seekneeded
Ld_Cache_In:    Call    Enter_Cache
                Jr      Ld_Cache_More
                
Cache_NoSpare:  Srp     #Wrk_Sys2
                Ld      !r9,Wrk_Sys+$0C
                Ld      !rA,Wrk_Sys+$0D
                Ld      !rB,Wrk_Sys+$0E
                 Ld     !r2,#.HIBYTE. PBlock
                 Ld     !r3,#.LOWBYTE. PBlock
                 Ld     !r0,#Wrk_Sys2+$0C
                Call    Gt_3_Ldei
                Sub     !rE,!rB ;IF ( TPBlock <> PBlock ) 
                Sbc     !rD,!rA
                Sbc     !rC,!r9
                Or      !rC,!rD
                Or      !rC,!rE
                Push    Flags
                Srp     #Wrk_Sys
                
                 Ld     !r2,#.HIBYTE. PBlock
                 Ld     !r3,#.LOWBYTE. PBlock
                Call    St_Blk
                Pop     Flags
                Jr      Nz,Ld_Cach_Seek
                
                Call    Gt_THS ;load current seek address
                Inc     !rF ;bump the sector address
                Cp      !rF,#NbrSctrs
                Jr      Ge,Ld_Cach_HdChg
                
                Call    St_THS ;save new seek address
                 Clr    !r1 ;CacheSeek, CachHdChg := False
                Jr      Ld_C_Enter
                
Ld_Cach_HdChg:  Ld      !rF,#0 ;start at sector 0
                Cp      !rE,#0 ;check for head 0
                Jr      Nz,Ld_Cach_Seek
                
                 Ld      !rE,#1 ;otherwise go to head 1
                Call    St_THS
                Ld      !r1,#CachHdChg
                Jr      Ld_C_Enter
                
Ld_Cach_Seek:   Ld      !rE,#0 ;start at head 0
                Ld      !rF,#0 ;and sector 0
                Add     !rD,#1 ;bump the track count by 1
                Adc     !rC,#0
                Call    St_THS
                Ld      !r1,#CachSeek

Ld_C_Enter:      Or     !r5,!r1 ;set seekneeded or headchange
                Call    Ld_BlkStat
                
Ld_Cache_More:  Djnz    !r4,Ld_Cache_Lp

Ld_Cache_End:   Clr     Cache_Index
                Jp      Bank_Ret


;************************************


Enter_Cache:    Tm      !r0,#Spare ;check if block is a spare
                Jr      Z,Ld_Blk_BB
                
                Or      !r1,#S_Block ;set Spare Block status
                Jr      Ld_BlkStat
                
Ld_Blk_BB:      Or      !r1,#B_Block ;otherwise it must be a Bad Block
                
Ld_BlkStat:     Or      !r1,!r5 ;merge in global seekneeded or headchange
                Lde     @!!r8,!r1
                
Ld_Cach_Lgcl:    Ld     !r2,#.HIBYTE. TLBlock
                 Ld     !r3,#.LOWBYTE. TLBlock
                Call    Gt_Blk
                
                Ld      !r0,#Wrk_Sys+$C ;load CacheArray.Logical
                Ldei    @!!rA,@!r0
                Ldei    @!!rA,@!r0
                Ldei    @!!rA,@!r0
                
                Incw    !!r8 ;set up for the next go 'round
                
                Call    Gt_THS
                Ld     !r2,#.HIBYTE. Map_Table ;logically remap the sector
                Ld     !r3,#.LOWBYTE. Map_Table
                Add    !r3,!rF
                Adc    !r2,#0
                Lde    !rF,@!!r2
                Swap    !rE ;merge Head with sector
                Rcf
                Rl      !rE
                Rl      !rE
                Or      !rE,!rF
                Lde     @!!rA,!rE
                
                Incw    !!rA ;point to next cache entry
                
                Ret
                

Cache_Cnvrt:     Ld     !r2,#.HIBYTE. PBlock
                 Ld     !r3,#.LOWBYTE. PBlock
                Call    Gt_Blk
                 Ld     !r2,#.HIBYTE. Get_Cyl_H_S
                 Ld     !r3,#.LOWBYTE. Get_Cyl_H_S
                Call    Bank_Call
                Call    St_THS
                Ret
                

St_THS:         Ld      !r2,#.HIBYTE. Cur_THS ;store the current seek address
                Ld      !r3,#.LOWBYTE. Cur_THS
                Ld      !r0,#Wrk_Sys+$0C
                Ldei    @!!r2,@!r0
St_3_Ldei:      Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ret
                
Gt_THS:         Ld      !r2,#.HIBYTE. Cur_THS ;load the current seek address
                Ld      !r3,#.LOWBYTE. Cur_THS
                Ld      !r0,#Wrk_Sys+$0C
                Ldei    @!r0,@!!r2
Gt_3_Ldei:      Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Ret

Inc_Blk:        Ld      !r0,#Wrk_Sys+$0C
                Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Add     !rE,#1
                Adc     !rD,#0
                Adc     !rC,#0
                Sub     !r3,#3 ;get back to original block ptr
                Sbc     !r2,#0
                Ld      !r0,#Wrk_Sys+$0C
                Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ret
                
St_Blk:         Ld      !r0,#Wrk_Sys+$0C
                Jr      St_3_Ldei

Gt_Blk:         Ld      !r0,#Wrk_Sys+$0C
                Jr      Gt_3_Ldei

                
                .PAGE

;***********************************
;
;       Fast search of spare table
;
;***********************************

Ld_C_Srch:      Ld      !r1,!rD ;check if head ptr is NIL
                Ld      !r0,!rC ;but first form a headptr structure
                Rrc     !r0     ;and index into HeadPtr Array
                Rrc     !r1
                Rcf
                Rrc     !r1
                Ld      !r2,#.HIBYTE. SegPtrArray
                Ld      !r3,#.LOWBYTE. SegPtrArray
                Add     !r3,!r1
                Adc     !r2,#0
                Lde     !r0,@!!r2       ;get headptr and check for NIL
                Tm      !r0,#Nil
                Jr      Z,Ld_C_Long ;do a real search if not NIL
                
                .DO     W_10MB
                Ld      !r0,!rD ;save for possible rollover
                Add     !rE,!rD ;Physical Block := LBlock + LBlock DIV 256
                Adc     !rD,#0
                Adc     !rC,#0
                .FIN
                
                Cp      !r0,!rD ;check for rollover
                Jr      Z,Ld_C_S_End
                
                Add     !rE,#1 ;otherwise bump Physical Block
                Adc     !rD,#0
                Adc     !rC,#0
                
Ld_C_S_End:     Xor     !r0,!r0 ;return zero status
Ld_C_S_Ret:     Ret

Ld_C_Long:       Ld     !r2,#.HIBYTE. SrchSpTabl
                 Ld     !r3,#.LOWBYTE. SrchSpTabl
                Call    Bank_Call
                Jr      Ld_C_S_Ret
                 
                .LSTOFF
                
