                .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:
                 Ld     !r2,#.HIBYTE. ClrNormStat
                 Ld     !r3,#.LOWBYTE. ClrNormStat
                Call    Bank_Call
                
                 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
Scan_Init:      Ld      @!r2,!r0
                Inc     !r2
                Djnz    !r1,Scan_Init

Scan_Lp:         Ld     Seek_Type,#Access
                Call    New_Seek

Scan_Read:       Ld     Sector,!rF
                 Ld     Wrk_Sys2+$09,!r9 ;save some regs
                 Ld     Wrk_Sys2+$0A,!rA ;save some regs
                 Ld     Wrk_Sys2+$0B,!rB ;save some regs
                 Ld     !r2,#.HIBYTE. Read_Common
                 Ld     !r3,#.LOWBYTE. Read_Common
                Call    Bank_Call
                 Ld     !r9,Wrk_Sys2+$09 ;save some regs
                 Ld     !rA,Wrk_Sys2+$0A ;save some regs
                 Ld     !rB,Wrk_Sys2+$0B ;save some regs
                Jr      Nz,Scan_More
                
                And     !r0,#$FF-RdError ;check for non-fatal error
                Jr      Z,Scan_More
                
                 Push   !r0 ;save error code
                Call    Ext_Push
                
                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,!rF
                Jr      Z,Scan_Map_End
                Incw    !!r2
                Inc     !r1
                Djnz    !r4,Scan_Map_Lp
                
                Call    Abort
                
Scan_Map_End:   Add     !rB,!r1 ;add in the sector offset
                Adc     !rA,#0
                Adc     !r9,#0
                
                Ld      !r0,!r9 ;check for logical block zero
                Or      !r0,!rA
                Or      !r0,!rB
                Jr      Z,Scan_L_Err
                
; Convert the Physical block number to a Logical number
                
                .DO     W_10MB
                Or      !rB,!rB ;check for spareblock
                Jr      Z,Scan_M_Pop
                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,Scan_M_Pop
                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,Scan_M_Pop
                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_L_Err:     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
                
                 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,#B_Block+S_Block ;check for bad 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     !rF     ;read next sector
                Cp      !rF,#NbrSctrs ;check for over flow
                Jp      Lt,Scan_Read
                
                Add     !rB,#NbrSctrs ;go to next set of blocks
                Adc     !rA,#0
                Adc     !r9,#0
                
                Ld      !rF,#0 ;otherwise start at sector 0
                Inc     !rE    ;and go to next head
                Cp      !rE,#NbrHds
                Jr      Ge,Scan_IncTrks
                
                Call    SelectHead
                Jp      Scan_Read
                
Scan_IncTrks:   Ld      !rE,#0 ;otherwise seek to next track
                Add     !rD,#1
                Adc     !rC,#0
                Ld      !r0,!rC ;check for last track
                Ld      !r1,!rD
                Xor     !r1,#.LOWBYTE. ( NbrTracks-1 )
                Xor     !r0,#.HIBYTE. ( NbrTracks-1 )
                Or      !r0,!r1
                Jp      Nz,Scan_Lp

                Call    Park_Heads
                 Ld     !r2,#.HIBYTE. ClrNormStat
                 Ld     !r3,#.LOWBYTE. ClrNormStat
                Call    Bank_Call
                
                Jp      Bank_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,#$FC ;do arm sweep every 1k 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,#$69
                 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!
Chk_Pk_Jp:       Ld     !r2,#.HIBYTE. 200 ;wait for two seconds
                 Ld     !r3,#.LOWBYTE. 200
                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       ;nop
                .DW     Free_MtrSpd
                .DW     Chk_Pk_Jp       ;"
                .DW     Free_SctrCnt
                .DW     Chk_Pk_Jp       ;"
                .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
                
