                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Programs
;>
;>      This module contains those routines that are 'high-level'
;>      programs.
;>
;>      PROCEDURE Scan
;>      PROCEDURE Strt_FreeProcess
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .Page
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Scan
;>
;>      This procedure reads each logical block on the disk and
;>      spares them if they are bad.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       FOR i := 0 TO MaxLogicalBlocks DO
;>        Seek_Type := Access_Offset
;>        Data_Type := User
;>        DiskStat.Wr_Op := False
;>        IF NOT( Srch_Cach( i ) ) OR ( Srch_Cach.SeekNeeded )
;>         THEN 
;>              Seek( CnvrtLogical )
;>              Load_Cache
;>         ELSE
;>              IF ( Srch_Cach.HdChg )
;>               THEN  
;>                      SelectHead( Complement( Head ) )
;>                      Load_Cache
;>               ELSE
;>                      Sector := Srch_Cach.Sector
;>        IF NOT( Read_Common )
;>         THEN Data_Ex_Handler( Read_Common.ErrorCode )
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

D_Scan:
                Call    Scan_Clr
                
                 Ld     Wrk_Io+$A,#D_Scan_Response
                Call    Ack_Read
                
Scan:           Tm      SlfTst_Result,#No_SprTbl
                Jr      Z,Scan_1
                
                Call    Abort
                
Scan_1:         Ld      !r0,#0
                Ld      !r1,#7
                Ld      !r2,#Wrk_Sys+$09 ;init PBlock and Track-Head-Sector
Scn_Init1:      Ld      @!r2,!r0
                Inc     !r2
                Djnz    !r1,Scn_Init1
                Call    St_PBlock
                 
Scan_Lp:         Ld     Seek_Type,#Access
                Call    Seek

Scan_Read:       Ld     !r2,#.HIBYTE. Read_Common
                 Ld     !r3,#.LOWBYTE. Read_Common
                Call    Bank_Call
                Jr      Nz,Scan_More
                
Scan_Except:     Push   !r0 ;save error code
                Call    Ext_Push
                
Scan_Cnvrt:     Ld      !r1,#0 ;convert to logical interleave
                Ld      !r2,#.HIBYTE. Map_Table
                Ld      !r3,#.LOWBYTE. Map_Table
                Ld      !r4,#NbrSctrs
Scan_Map_Lp:    Lde     !r0,@!!r2
                Cp      !r0,Sector
                Jr      Z,Scan_Map_End
                Incw    !!r2
                Inc     !r1
                Djnz    !r4,Scan_Map_Lp
                
                Call    Abort
                
Scan_Map_End:   Call    Gt_PBlock
                Add     !rB,!r1 ;add in the sector offset
                Adc     !rA,#0
                Adc     !r9,#0
                
                Ld      !r0,#0
                Or      !r0,!rB
                Or      !r0,!rA
                Or      !r0,!r9
                Jr      Z,Scan_Ld_L     ;block zero can not be a spare
; Convert the Physical block number to a Logical number
                
                .DO     W_10MB
                Or      !rB,!rB ;check for spareblock
                Jr      Z,Scn_Spare
                Sub     !rB,!rA
                Sbc     !rA,#0
                Sbc     !r9,#0
                .FIN
                
                .DO     W_20MB
                Ld      !r0,!rA ;check for spare block
                And     !r0,#$01
                Or      !r0,!rB
                Jr      Z,Scn_Spare
                Ld      !r1,!r9
                Ld      !r2,!rA
                Rcf
                Rrc     !r1
                Rrc     !r2
                Sub     !rB,!r2
                Sbc     !rA,!r1
                Sbc     !r9,#0
                .FIN
                
                .DO     W_40MB
                Ld      !r0,!rA ;check for spare block
                And     !r0,#$01
                Or      !r0,!rB
                Jr      Z,Scn_Spare
                Ld      !r1,!r9
                Ld      !r2,!rA
                Ld      !r0,#2
P_To_L:         Rcf
                Rrc     !r1
                Rrc     !r2
                Djnz    !r0,P_To_L
                Sub     !rB,!r2
                Sbc     !rA,!r1
                Sbc     !r9,#0
                .FIN
                
Scan_Ld_L:      Call    Scan_LdLB
                Or      !r0,#1  ;set non-zero flag if not spare
                
Scn_Spare:      Jr      Z,Scan_M_Pop
                 
                 Ld     Data_Type,#User_Type
                Call    Load_Cache
                Call    Load_Logical
                
                 Ld     !r2,#.HIBYTE. SC_Vector
                 Ld     !r3,#.LOWBYTE. SC_Vector
                Call    Bank_Call
                
                Pop     !r0 ;retrieve error code
                Tm      BlkStat,#S_Block ;check for Spare block
                Jr      Nz,Scan_M_Pop
                
Scan_Rd_Err:     Ld     !r2,#.HIBYTE. Data_Ex_Handler
                 Ld     !r3,#.LOWBYTE. Data_Ex_Handler
                Call    Bank_Call
                
                Call    Zero_Header
                
Scan_M_Pop:     Call    Ext_Pop

Scan_More:      Inc     Sector     ;read next sector
                Cp      Sector,#NbrSctrs ;check for over flow
                Jr      Lt,Scan_Read
                
                Call    Gt_PBlock
                Add     !rB,#NbrSctrs ;go to next set of blocks
                Adc     !rA,#0
                Adc     !r9,#0
                Call    St_PBlock
                
                Ld      Sector,#0 ;otherwise start at sector 0
                Inc     Head    ;and go to next head
                Cp      Head,#NbrHds
                Jr      Ge,Scan_IncTrks
                
                 Ld     !rE,Head
                Call    SelectHead
                Jp      Scan_Read
                
Scan_IncTrks:   Ld      !rE,#0 ;otherwise seek to next track
                Ld      !rF,#0
                Ld      !rD,Cylinder+1
                Ld      !rC,Cylinder
                Add     !rD,#1
                Adc     !rC,#0
                Ld      !r0,#.HIBYTE. ( NbrTracks-1 ) ;check for last track
                Ld      !r1,#.LOWBYTE. ( NbrTracks-1 )
                Xor     !r1,!rD
                Xor     !r0,!rC
                Or      !r0,!r1
                Jp      Nz,Scan_Lp

Scan_End:       Ld      !r4,#0 ;start searching for bad blocks
Scn_BadLp:      Ld      !r2,#.HIBYTE. SegPtrArray
                Ld      !r3,#.LOWBYTE. SegPtrArray
                Add     !r3,!r4 ;get index to HeadPtr
Scn_Bd3:        Adc     !r2,#0
                Lde     !r0,@!!r2 ;get HeadPtr
                Tm      !r0,#Nil  ;check for any elements here
                Jr      Nz,Scn_BdNext
                
Scn_Bd1:        And     !r0,#$7F ;mask off NIL bit
                 Ld     !r2,#.HIBYTE. Get_Ptr
                 Ld     !r3,#.LOWBYTE. Get_Ptr
                Call    Bank_Call
                Lde     !r0,@!!r2 ;get status of element
                
                Tm      !r0,#User_Type ;check only user data
                Jr      Z,Scn_Bd2
                Tm      !r0,#Spare ;look at only badblocks
                Jr      Nz,Scn_Bd2
                
                Call    Ext_Push ;get logical block
                
                Ld      !r9,#0
                Rl      !r4
                Rlc     !r4
                Rlc     !r9
                Incw    !!r2
                Lde     !rA,@!!r2
                Or      !rA,!r4
                Incw    !!r2
                Lde     !rB,@!!r2
                Call    Scan_LdLB
                 
                Call    Load_Logical
                 Ld     !r2,#.HIBYTE. CnvrtLogical
                 Ld     !r3,#.LOWBYTE. CnvrtLogical
                Call    Bank_Call
                Call    Seek
                
                 Ld     !r0,#Error+Ex_BadBlock
                 Ld     Data_Type,#User_Type
                 Ld     BlkStat,#B_Block
                 Ld     !r2,#.HIBYTE. Data_Ex_Handler
                 Ld     !r3,#.LOWBYTE. Data_Ex_Handler
                Call    Bank_Call
                
                Call    Ext_Pop
                
Scn_Bd2:        Tm      !r0,#Nil ;check for end of chain
                Jr      Nz,Scn_BdNext
                Add     !r3,#3 ;get ptr to next
                Jr      Scn_Bd3

Scn_BdNext:     Inc     !r4 ;go to next HeadPtr
                
                .DO     W_10MB
                Cp      !r4,#$20 ;only 32 HeadPtrs for 10MB
                .FIN
                .DO     W_20MB
                Cp      !r4,#$40 ;64 HeadPtrs for 20MB
                .FIN
                .DO     W_40MB
                Cp      !r4,#$80 ;128 HeadPtrs for 40MB
                .FIN
                
                Jr      Nz,Scn_BadLp
                
                Call    Park_Heads
                Call    Scan_Clr
                Jp      Bank_Ret
                
                .Page
;****************************

Scan_Clr:        Ld     !r2,#.HIBYTE. ClrNormStat
                 Ld     !r3,#.LOWBYTE. ClrNormStat
                Call    Bank_Call
                Ret
                
Scan_LdLB:      Ld      !r2,#.HIBYTE. LogicalBlock
                Ld      !r3,#.LOWBYTE. LogicalBlock
                Ld      !r1,#4
                Ld      !r0,#Wrk_Sys+$09
Scan_LB_Lp:     Ldei    @!!r2,@!r0
                Djnz    !r1,Scan_LB_Lp
                Ret
                
St_PBlock:      Ld      !r2,#.HIBYTE. PBlk
                Ld      !r3,#.LOWBYTE. PBlk
                Ld      !r0,#Wrk_Sys+$09
                Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ldei    @!!r2,@!r0
                Ret
                
Gt_PBlock:      Ld      !r2,#.HIBYTE. PBlk
                Ld      !r3,#.LOWBYTE. PBlk
                Ld      !r0,#Wrk_Sys+$09
                Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Ldei    @!r0,@!!r2
                Ret
                
                .LSTOFF

                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Strt_FreeProcess
;>
;>      BANK 1 PROCEDURE
;>
;>      This procedure is used by the controller to start any process
;>      ( along the lines of internal bookkeeping ) that it chooses.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       IF ( SeekCount >= 2048 )
;>        THEN ArmSweep
;>       Free_SlfTst := 0
;>       WHILE NOT( CMD ) DO
;>              Bsy_Wait for 3 seconds
;>              IF NOT( Parked ) THEN Park_Heads
;>              CASE Free_SlfTst OF
;>               0 : Test Eprom
;>               1 : Test Sector Count
;>               2 : Test Motor Speed
;>               3 : Test Read/Write; Free_SlfTst := 0
;>
;>       Take care of Host
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Strt_FreeProcess:
                Di
                Srp     #Wrk_Sys ;get into a reasonable state
                Clr     Sph
                Ld      Spl,#Stack_Top
                
                And     Port2,#$FF-Bsy ;clear BSY
                
                Tm      SeekCount,#$F8 ;do arm sweep every 2k seeks or so
                Jr      Z,Chk_Park
                
                Clr     SeekCount
                Clr     SeekCount+1
                
                 Ld     !rC,#Init_HiCyl ;seek to data recal loaction
                 Ld     !rD,#Init_LoCyl
                 Ld     !rE,#0 ;head zero
                 Ld     !rF,#0 ;sector zero
                Call    New_Seek
                
                 Ld     !rC,#0
                 Ld     !rD,#64
                 Ld     !rE,#0
                 Ld     !rF,#0
                Call    New_Seek
                
                And     DiskStat,#$FF-On_Track
                Call    Set_SeekNeeded
                
Chk_Park:       Clr     Free_SlfTst ;get ready to do some self tests!
                 Ld     !r2,#.HIBYTE. 200 ;wait for two seconds
                 Ld     !r3,#.LOWBYTE. 200
                 Jr     Chk_Pk_Int

Chk_Pk_Jp:       Ld     !r2,#.HIBYTE. 800 ;wait for two seconds
                 Ld     !r3,#.LOWBYTE. 800
Chk_Pk_Int:     Call    Chk_Park1

Chk_Park3:      Tm      DiskStat,#Parked
                Jr      Nz,FreeP_NoPark
                
                Call    Park_Heads
                Jr      Chk_Pk_Jp
                
FreeP_NoPark:   Tm      Free_SlfTst,#$01 ;check for even value
                Jr      Z,FreeP_SlfTst   ;to do tests only every other time
                Inc     Free_SlfTst ;otherwise make even for next time
                Jr      Chk_Pk_Jp
                
FreeP_SlfTst:   Ld      !r2,#.HIBYTE. SlfTst_Table
                Ld      !r3,#.LOWBYTE. SlfTst_Table
                Add     !r3,Free_SlfTst
                Adc     !r2,#0
                Inc     Free_SlfTst ;make value odd
                Ldc     !rE,@!!r2
                Incw    !!r2
                Ldc     !rF,@!!r2
                Jp      @!rE
                
SlfTst_Table:   .DW     Free_Ram
                .DW     Chk_Pk_Jp       ;"
                .DW     Free_Eprom
                .DW     Chk_Pk_Jp       ;"
                .DW     Free_MtrSpd
                .DW     Chk_Pk_Jp       ;"
                .DW     Free_SctrCnt
                .DW     Chk_Pk_Jp       ;"
                .DW     Free_Rw
                
Free_Ram:        Ld     !r2,#.HIBYTE. Chk_SprChk
                 Ld     !r3,#.LOWBYTE. Chk_SprChk
                Call    Bank_Call
                Jr      Nz,Chk_Pk_Jp
                
                Or      SlfTst_Result,#Ram_Fail
                Jr      Nz,Chk_Pk_Jp
                
Free_Eprom:      Ld     !r0,#Eprom2
                Call    EpromTest
                Jr      Z,Chk_Pk_Jp
                
                Or      SlfTst_Result,#Eprom_Fail
                Jr      Chk_Pk_Jp
                
Free_SctrCnt:    Ld     !r2,#.HIBYTE. SctrCount
                 Ld     !r3,#.LOWBYTE. SctrCount
                Call    Bank_Call
                Jr      Z,Chk_Pk_Jp
                
                Or      SlfTst_Result,#Sector_Cnt
                Jr      Chk_Pk_Jp
                
Free_MtrSpd:     Ld     !r2,#.HIBYTE. MtrSpd
                 Ld     !r3,#.LOWBYTE. MtrSpd
                Call    Bank_Call
                Jr      Z,Chk_Pk_Jp
                
                Or      SlfTst_Result,#Disk_Speed
                Jp      Chk_Pk_Jp
                
Free_Rw:        Or      SlfTst_Result,#Rw_Fail ;assume failure
                 Ld     !r2,#.HIBYTE. RwTest1
                 Ld     !r3,#.LOWBYTE. RwTest1
                Call    Bank_Call
                Jp      Z,Chk_Pk_Jp
                
                And     SlfTst_Result,#$FF-Rw_Fail
                 
                Clr     Free_SlfTst
                Jp      Strt_FreeProcess ;check for arm sweep
                
                .LSTOFF
                
