        EXT RDY0,IO,ABORT,MSG,EXIT
        EXT PBLK0,UNIT0
        EXT SEC,TK,DRV,HEAD,BUFF,SRW
        EXT PASCT
        EXT ERRCT
        ENTRY HDNSEC,DRNBN,VBUF,BUFSW,NEXSC
        ENTRY UNIT,DBUFF
;
;
;
; EQUATES FOR HARD DISK COMMAND OPCODES
;
RSTCOD: EQU  0140       OPCODE FOR "READ STATUS"
WBCOD:  EQU  0100       OPCODE FOR "WRITE BUFFER"
WSCOD:  EQU  040        OPCODE FOR "WRITE SECTOR"
RSCOD:  EQU  060        OPCODE FOR "READ SECTOR"
RBCOD:  EQU  0120       OPCODE FOR "READ BUFFER"
;
; OTHER EQUATES
;
MAXSEC: EQU  23         MAXIMUM SECTOR NUMBER
MAXTK:  EQU  405        MAXIMUM TRACK NUMBER
;
;************************************************************
;
;       ENTRY POINT FROM THE MAIN CONTROL ROUTINE
;
;***********************************************************
;
;       START OF THE  UNIT PROCESSING SUBROUTINE
;
; SETUP AND CHECK ERROR COUNT AGAINST ERROR LIMIT
; ENTER WITH [HL] POINTING TO UNIT PARAMETER BLOCK
;
UNIT:   INX  H
.C      INX  H
        MOV  A,M        GET ERROR LIMIT
        INX  H
        CMP  M          COMPARE TO ERROR COUNT
        RC               COUNT > LIMIT, RETURN (SHOULD NEVER HAP

        JNZ  +D          COUNT < LIMIT, CONTINUE
        DCX  H           COUNT = LIMIT, GET READY TO LOG OUT
        DCX  H            BACK UP
        DCX  H             TO UNIT NUMBER
        MOV  A,M
        ORI  128           OR-IN "LOGGED OUT" BIT
        MOV  M,A           SAVE MODIFIED UNIT NUMBER
        CALL MSG
        DW   ERLMSG
        JMP  EXIT
;
; COMPARE PASS COUNT TO PASS LIMIT
;
.D      INX  H
        MOV  A,M        GET PASS COUNT
        INX  H
        CMP  M          COMPARE COUNT TO LIMIT
        LXI  H,UNIT0
        MOV  A,M        GET UNIT NUMBER
        JC   +E
        ORI  128        PASS COUNT=LIMIT,
        MOV  M,A        SAVE UNIT NUMBER AS "LOGGED-OUT"
        CALL MSG
        DW   PSLMSG
        JMP  EXIT
.E      PUSH H          SAVE PBLK POINTER
        JMP  RDY0
;
;
;
; SWITCH CONTROLLER BUFFERS SO NEXT OP USES A NEW ONE
; CALLED AFTER EACH "WRITE SECTOR" COMMAND
;
BUFSW:  LXI  H,BUFF     POINT TO BUFFER NUMBER
        MOV  A,M        GET BUFFER NUMBER
        INR  A          INCREMENT IT
        ANI  3          SAVE ONLY 2 LSB (CAN'T GO PAST 3)
        MOV  M,A        SAVE NEW BUFFER NUMBER
;
; SET SRW SO NEXT OP WILL BE "SEEK AWAY"
;
        LXI  H,SRW
        INR  M          INCREMENT SRW
        RET             << TO MAIN >>
;
; VERIFY THE DATA JUST READ FROM THE BUFFER
;
VBUF:   POP  B          POINT [BC] TO VERIFY BUFFER
        LXI  H,TK
        LDAX B
        CMP  M          IS TK(LOW) CORRECT ?
        JZ   +B           YES - SKIP ERROR STUFF
        CALL MSG
        DW   TKLMSG
        CALL INCERR     UP ERROR COUNT
.B      INX  H          POINT TO TK(HIGH)
        INX  B
        LDAX B
        CMP  M          IS TK(HIGH) CORRECT ?
        JZ   +C           YES - SKIP ERROR STUFF
        CALL MSG
        DW   TKHMSG
        CALL INCERR     UP ERROR COUNT
.C      LXI  H,SEC
        INX  B
        LDAX B
        CMP  M          IS SECTOR NUMBER CORRECT ?
        JZ   +D           YES - SKIP ERROR STUFF
        CALL MSG
        DW   SNMSG
        CALL INCERR     UP ERROR COUNT
.D      LXI  D,253      [D] = 0 (FIRST PATTERN), [E] = 253 (LAST N)
.V      INX  B
        LDAX B          GET A BYTE FROM THE VERIFY BUFFER
        CMP  D          IS IT WHAT WE EXPECT ?
        JZ   +E           YES - SKIP ERROR STUFF
        CALL MSG
        DW   RDMSG
        CALL INCERR     UP ERROR COUNT
.E      INR  D            YES - SET UP NEXT EXPECTED PATTERN
        MOV  A,D
        CMP  E          ARE WE DONE ?
        JNZ  -V           NO - CHECK ALL BYTES
;
; TRY TO INCREMENT TO NEXT SECTOR.
; IF SECTOR = 24, GO TO NEXT TRACK.
;
NEXSC:  LXI  H,SEC
        MOV  A,M
        INR  A          INCREMENT IT
        MOV  M,A        SAVE NEW SECTOR NUMBER
        CPI  MAXSEC+1   PAST END OF TRACK ?
        JC   +O          NO- STAY ON SAME TRACK
        XRA  A
        MOV  M,A         YES- RESET TO SECTOR 0
        DCX  H
        DCX  H
        DCX  H          POINT TO TK(HIGH)
        MOV  D,M        SAVE IT
        DCX  H
        MOV  E,M        GET TK(LOW)
        PUSH H          SAVE PBLK POINTER
        LXI  H,MAXTK-1  GET TRACK COMPARE VALUE
        MOV  A,H        IS
        SUB  D           THIS
        JNZ  +S           THE
        MOV  A,L           LAST
        SUB  E              TRACK ?
.S      JC   +W                 YES - RESET TO TRACK ZERO
;
; INCREMENT TRACK NUMBER.
;
.T      POP  H          GET PBLK POINTER BACK
        INX  D          INCREMENT TRACK NUMBER
        MOV  M,E        SAVE NEW TK(LOW)
        INX  H
        MOV  M,D        SAVE NEW TK(HIGH)
;
; SET SRW TO ZERO SO NEW SEEK IS NEXT OP
;
.O      LXI  H,SRW
        XRA  A
        MOV  M,A        SRW = 0 (NEW SEEK NEXT)
        RET             << TO MAIN >>
;
;
;
;************************************************************
;
;
;       END OF A COMPLETE PASS
;
;
;*************************************************************
;
;
; TRACK ROLLOVER - RESET TRACK NUMBER TO 0
;
.W      POP  H
        XRA  A
        LXI  H,SRW
        MOV  M,A        SRW = 0
        INX  H
        MOV  M,A        TK(LOW) = 0
        INX  H
        MOV  M,A        TK(HIGH) = 0
;
; LOG END OF PASS
;
        CALL MSG
        DW   ENDPAS
;
; INCREMENT HEAD NUMBER.
; IF NEW HEAD NUMBER IS EVEN, SWITCH LOGICAL DRIVE
;
        LXI  H,HEAD
        MOV  A,M
        INR  A          INCREMENT HEAD NUMBER
        ANI  3          SAVE ONLY 2 LSB <<<<<<< CHANGE TO "ANI 7
PLATTER DRIVES
        MOV  M,A        STORE NEW HEAD NUMBER
        ANI  1          TEST: EVEN/ODD
        JNZ  PASINC       ODD - STAY ON THIS LOGICAL DRIVE
;
; SWITCH LOGICAL DRIVE
;
        LXI  H,DRV       EVEN - SWITCH LOGICAL DRIVE
        MOV  A,M
        INR  A          INCREMENT DRIVE NUMBER
        ANI  1          SAVE ONLY LSB <<<<<<< CHANGE TO "ANI 3"
LATTER DRIVES
        MOV  M,A        STORE NEW LOGICAL DRIVE NUMBER
;
; INCREMENT PASS COUNT
;
PASINC: LXI  H,PASCT
        INR  M          NEW PASS COUNT
;
; RETURN TO MAIN CONTROL ROUTINE
;
        RET
;
;
;
; INCREMENT ERROR COUNT AND CHECK AGAINST ERROR LIMIT
;
INCERR: PUSH H
        LXI  H,ERRCT    POINT TO ERROR COUNT
        INR  M          INCREMENT IT
        MOV  A,M        GET A COPY
        DCX  H          POINT TO ERROR LIMIT
        CMP  M          COMPARE COUNT TO LIMIT
        POP  H
        RC              RETURN IF COUNT < LIMIT
        POP  H          ELSE KILL RETURN ADDRESS
        CALL MSG        PRINT "ERROR LIMIT REACHED"
        DW   ERLMSG
        JMP  EXIT               END THE PROGRAM
;
;
;
; COMBINE SECTOR AND HEAD NUMBERS IN LOW COMMAND BYTE T.
; CALLED WITH [HL] POINTING TO SECTOR NUMBER BYTE IN PBLKn.
; EXITS WITH [HL] POINTING TO HEAD NUMBER IN PBLKn.
;
HDNSEC: MOV  E,M        SAVE SECTOR NUMBER
        INX  H
        MOV  A,M        GET HEAD NUMBER
        RLC             SHIFT
        RLC              HEAD NUMBER
        RLC               LEFT
        RLC                FIVE
        RLC                 TIMES
        ORA  E          OR-IN SECTOR NUMBER
        RET
;
;
; COMBINE DRIVE AND BUFFER NUMBERS IN HIGH COMMAND BYTE T.
; CALLED WITH [HL] POINTING TO DRIVE NUMBER BYTE IN PBLKn.
; EXITS WITH [HL] POINTING TO BUFFER NUMBER BYTE IN PBLKn.
;
DRNBN:  MOV  A,M        GET DRIVE NUMBER
        RLC             SHIFT LEFT
        RLC             ...TWICE
        INX  H          POINT TO BUFFER NUMBER
        ORA  M          OR-IN BUFFER NUMBER
        RET
;
;
;
;
;
; COMMON DATA
;
DBUFF:  DS   256        VERIFY BUFFER
;
;
; ERROR MESSAGES
;
ERLMSG: DB 015,012," ERROR LIMIT REACHED ",015,0212
PSLMSG: DB 015,012," PASS LIMIT REACHED ",015,0212
TKLMSG: DB 015,012," LOW BYTE OF TRACK NUMBER INCORRECT "
        DB 015,0212
TKHMSG: DB 015,012," HIGH BYTE OF TRACK NUMBER INCORRECT "
        DB 015,0212
SNMSG:  DB 015,012," SECTOR NUMBER INCORRECT ",015,0212
RDMSG:  DB 015,012," BAD DATA PATTERN BYTE ",015,0212
ENDPAS: DB 007,007,015,012," END OF PASS "
        DB 007,007,015,0212
;
;
        END

