                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: SprUtils  { Spare Module's Utilities }
;>
;>      This module contains all the primitive utulitie procedures
;>      used by the module: Spare
;>
;>      FUNCTION Get_HeadPtr( LogicalBlock : 3 BYTES { !rC:E } ) : 
;>                          BOOLEAN
;>                          HeadPtr : BYTE { !r0 }
;>                          ArrayPtr : PTR { !!r2 }
;>      FUNCTION Get_EoList( Start_Ptr : BYTE { !r0 } ) : 
;>                         SparePtr : BYTE { !r0 }
;>                         ElementStatus : BYTE { !r1 }
;>                         Ptr : PTR { !!r2 }
;>                         PreviousPtr : PTR { ScrReg0:1 }
;>      FUNCTION TSC_BitMap( TestBit : BOOLEAN { !rC/bit 7 }
;>                           SetBit : BOOLEAN { !rC/bit 6 }
;>                           ClearBit : BOOLEAN { !rC/bit 5 }
;>                           Location : BYTE { !rD }
;>                         ) : BOOLEAN
;>      FUNCTION Get_Ptr( SparePtr : BYTE { !r0 } ) : Ptr : PTR { !r2 }
;>      FUNCTION Get_Spr_Code : 2 BITS { !r0/Bits 1:0 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Get_HeadPtr
;>
;>      This function searches the SegPtrArray { that array for the
;>      spare table that contains the various head ptrs for the
;>      spare table } and returns the HeadPtr that corresponds to the
;>      list whose elements all have the first 7 bits of the { passed
;>      in } LogicalBlockNumber.
;>
;>      Inputs:
;>              LogicalBlockNumber : 3 BYTES { !rC:E }
;>
;>      Outputs:
;>              Get_HeadPtr : BOOLEAN { zero is set if HeadPtr.Nil is true }
;>              HeadPtr     : BYTE { !r0 }
;>              ArrayPtr    : Ptr { !!r2 } { ptr to location in array }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       HeadPtr :=  SegPtrArray[ LogicalBlockNumber/bits 10:16 ]
;>       Get_HeadPtr := NOT( HeadPtr.Nil )
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Get_HeadPtr:    
                Ld      !r1,!rD         ;bits 8:15 of logical block #
                And     !r1,#$FC
                Ld      !r0,!rC         ;bit 16 of logical block #
                Rrc     !r0             ;put bit 16 into carry flag
                Rrc     !r1             ;shift bits 10:16 into !r1
                Rcf                     ;arithmetic divide by 2
                Rrc     !r1
                
                Ld      !r2,#.HIBYTE. SegPtrArray
                Ld      !r3,#.LOWBYTE. SegPtrArray
                Add     !r3,!r1         ;add in offset to array
                Adc     !r2,#0
                Lde     !r0,@!!r2       ;load HeadPtr
                
                Tcm     !r0,#Nil        ;test for Nil Ptr
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Get_EoList { Get End-Of-List }
;>
;>      This function takes a starting ptr as an input parameter
;>      and follows the list specified by the ptr until the list
;>      terminates. A pointer to the last element of the array is returned
;>      to the caller.
;>
;>      Inputs:
;>              Start_Ptr : BYTE { !r0 }
;>
;>      Outputs:
;>              Ptr : PTR { !!r2 }
;>              SparePtr : BYTE { !r0 }
;>              Element.Status : BYTE { !r1 }
;>              PreviousPtr : PTR { ScrReg0,1 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Ptr := Get_Ptr( Start_Ptr )
;>       WHILE NOT( Get_Ptr( Temp )^.Nil ) DO
;>              PreviousPtr := Get_Ptr( Temp )
;>              Temp := PreviuosPtr^.Ptr
;>              Ptr := Get_Ptr( Temp )
;>              Element.Status := Ptr^.Status
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Get_EoList:     Ld      ScrReg3,!r0
                Call    Get_Ptr         ;create ptr into Spare Table
                Lde     !r1,@!!r2       ;get element status
                Tm      !r1,#Nil        ;IF Nil THEN Exit Loop
                Jr      Nz,EoList_End
                
                Ld      ScrReg0,!r2     ;save Ptr to element i - 1
                Ld      ScrReg1,!r3
                Add     !r3,#3  ;get ptr to next
                Adc     !r2,#0
                Lde     !r0,@!!r2
                Jr      Get_EoList
                
EoList_End:     Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: TSC_BitMap  { Test, Set, Or Clear BitMap Location }
;>
;>      This function performs one of 3 functions: Set a bit location
;>      in the Spare Table bit map; Clear a location in the Spare Table
;>      bit map; or Test a location in the spare table bit map. The
;>      location to test, set, or clear is an integer value between 0
;>      and 75.
;>
;>      Inputs:
;>              TestBit : BOOLEAN {!rC/bit 7 }
;>              SetBit  : BOOLEAN {!rC/bit 6 }
;>              ClearBit : BOOLEAN {!rC/bit 5 }
;>              Location : BYTE {!rD }
;>
;>      Outputs:
;>              TSC_BitMap : BOOLEAN { zero is set if location is zero }
;>
;>      Global Variables Changed:
;>              SpareBitMap
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

TSC_BitMap:     Ld      !r0,!rD
                
                Ld      !r3,#3   ;right hand justify the byte index
TSC_Lp1:        Rcf
                Rrc     !r0
                Djnz    !r3,TSC_Lp1
                
                Ld      !r2,#.HIBYTE. SpareBitMap
                Ld      !r3,#.LOWBYTE. SpareBitMap
                Add     !r3,!r0
                Adc     !r2,#0  ;inc second byte of address if needed
                Lde     !r1,@!!r2 ;load in the byte from bit map
                
                And     !rD,#$07 ;mask off all but MOD 8 of original index
                Ld      !r0,#$80 ;convert index to mask
                Jr      Z,TSC_Map
                
TSC_Lp2:        Rr      !r0
                Djnz    !rD,TSC_Lp2
TSC_Map:        Push    !r0     ;save mask
                
                Tm      !rC,#TestBitMap
                Jr      Nz,TSC_End
                Tm      !rC,#SetBitMap
                Jr      Nz,TSC_Set
                
TSC_Clear:      Com     !r0
                And     !r1,!r0 ;mask out bit
                Jr      TSC_SCEnd
                
TSC_Set:        Or      !r1,!r0 ;merge in bit
TSC_SCEnd:      Lde     @!!r2,!r1 ;update the bit map
TSC_End:        Pop     !r0
                Tm      !r1,!r0 ;test the bit
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Get_Ptr
;>
;>      This function accepts a Spare Table ptr structure and creates
;>      a real ptr into the Spare Table array.
;>
;>      Inputs:
;>              SparePtr : BYTE { !r0 }
;>
;>      Outputs:
;>              SParePtr : BYTE { !r0 } { input is unchanged }
;>              Ptr : PTR { !!r2 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Get_Ptr:        Ld      !r2,#.HIBYTE. Sparetable
                Ld      !r3,#.LOWBYTE. SpareTable
                
                Push    !r0 ;save structure ptr
                Ld      !r1,!r0
                Clr     !r0
                Add     !r1,!r1 ; !!r0 := 4 * !r1
                Add     !r1,!r1
                Adc     !r0,#0
                Add     !r3,!r1         ;add offset into table
                Adc     !r2,!r0
                Pop     !r0 ;get original structure ptr back
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Get_Spr_Code
;>
;>      This function returns the SpareCode portion of BlkStat
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Get_Spr_Code: 2 BITS { !r0/Bits 1:0 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Get_Spr_Code:
                Ld      !r0,BlkStat
                And     !r0,#03 ;mask off all but SpareCode portion
                Ret
                
                .LSTOFF
                
