;
; TOGGLE ACTIVE BUFFER # IN BUFNUM
;
DBLBUF LDX LINDX
 LDA BUF0,X ;TOGGLE ACTIVE FLAG
 EOR #$80
 STA BUF0,X
DBL1 LDA BUF1,X ;TOGGLE ACTIVE FLAG
 EOR #$80
 STA BUF1,X
DBL2 JSR GETACT ;GET ACTIVE BUF#
 TAX
 JMP WATJOB ; AND WAIT FOR BUFFER READY
;
PIBYTE
 LDX #IWSA
 STX SA
PBYTE
 JSR FNDWCH
 LDA SA
 CMP #15
 BEQ L42
 BNE L40
;
; MAIN ROUTINE TO WRITE TO CHANL
;
PUT LDA ORGSA ;IS CHANL CMD OR DATA
 AND #$8F
 CMP #15 ;<15 
 BCS L42
L40 JSR TYPFIL ;DATA BYTE TO STORE
 BCS L41 ;BRANCH IF RND
 LDA DATA ;SEQ FILE
 JMP WRTBYT ;WRITE BYTE TO CHANL
L41
 BNE L46
 JMP WRTREL
L46 LDA DATA ;RND FILE WRITE
 JSR PUTBYT ;WRITE TO CHANL
 LDY LINDX ; PREPARE NXT BYTE
 JMP RNGET2 
L42 LDA #CMDCHN ;WRITE TO CMD CHANL
 STA LINDX
 JSR GETPNT ;TEST IF COMM AND BUFFER FULL
 CMP #CMDLEN
 BEQ L50 ;IT IS FULL
 LDA DATA ;NOT FULL YET
 JSR PUTBYT ;STORE THE BYTE 
L50 LDA EOIFLG ;TST IF LST BYTE OF MSG
 BEQ L45 ;IT IS
 RTS ;NOT YET , RETURN
 L45
 INC CMDPND ;SET CMD PENDING FLAG <HD>
 RTS
OKK6 ;<HD>
 DEC ERRCNT,X ;REDO UNTIL ERRCNT=0
 BPL AGAIN
 BMI RECOV
;
;
;
;
;TEST IF JOB(.X) IS DONE YET
;IF NOT DONE RETURN
;IF OK THEN RETURN ELSE REDO IT
;
TSTJOB LDA JOBS,X
 BMI NOTYET
 CMP #2
 BCC OKK4 ;BR IF NO ERROR
 JSR CSER ;GO COUNT SOFT ERRORS
 PHP ;SAVE PROCESSOR STATUS  (RR)
 LDA LSTJOB,X ;GET CURRENT DRIVE (RR)
 AND #1 ;*                   (RR)
 BEQ OKK4A                   (RR)
 PLP ;RESTORE PROCESSOR STATUS (RR)
 BEQ RECOV ;BR IF TIME OUT ERROR
 BCS OKK6 ;BR IF ERROR
RECOV
 TYA ;SAVE .Y
 PHA
 BIT REVCNT
 BMI REC4 ;NO RECOVERY
;
 LDA LSTJOB,X ;RESTORE HEAD TO TRACK 1
 AND #1
 ORA #BUMP
 STA JOBS,X
 JSR HDSTRT ;<HD>
REC1
 JSR HDCHK ;<HD>
 LDA JOBS,X
 BMI REC1
;
 LDA REVCNT ;RECOVERY COUNT
 AND #$3F
 TAY
REC2
 LDA LSTJOB,X ;SET LAST JOB
 STA JOBS,X
 JSR HDSTRT ;<HD>
REC3
 JSR HDCHK ;<HD>
 LDA JOBS,X ;WAIT
 BMI REC3
;
 CMP #2
 BCC REC5
 JSR CSER ;COUNT SOFT ERRORS
 BEQ REC4 ;BR IF TIME OUT
 DEY ;TRY IT A # OF TIMES
 BPL REC2
REC4
 PHA ;SAVE ERROR #
 LDA LSTJOB,X ;GET THE DRIVE #
 AND #1
 BEQ REC4A ;BR IF DRIVE 0
 INC HERCNT+1 ;BUMP DRIVE 1 COUNT
 JMP REC4B
REC4A
 INC HERCNT ;BUMP DRIVE 0 COUNT
REC4B
 PLA
 BIT JOBRTN ;RETURN TO CALLER?
 BMI REC5 ;BR IF YES
 JMP ERROR ;GIVE UP!!
;
REC5 ;IT WORKED!
 PLA ;RESTORE .Y
 TAY
OKK4
 LDA JOBS,X ;RESTORE ORIG RET CODE
OK CLC ;C=0 DONE OK
 RTS
AGAIN LDA LSTJOB,X
 STA JOBS,X
 JSR HDSTRT ;<HD>
NOTYET
 JSR HDCHK ;CHECK ENTRY <HD>
 SEC ;C=1 NOT YET
 RTS
OKK4A ;                  (RR)
 PLP ;CLEAN STACK        (RR)
 LDA JOBS,X ;GET ERROR   (RR)
 CMP #6 ;RECOV DATA ERROR (RR)
 BEQ OKK4 ;BRIF IT IS    (RR)
 PHA ;PUSH A BYTE        (RR)
 BNE REC4A ;EXIT         (RR)
;
;
;
;
; WAIT UNTIL JOB(.X) IS DONE
; RETURN WHEN DONE
;
WATJOB JSR TSTJOB
 BCS WATJOB
 PHA ;CLR JOBRTN FLAG
 LDA #0
 STA JOBRTN
 PLA
 RTS
;
; SET HEADER OF ACTIVE BUFFER OF THE 
; CURRENT LINDX TO TRACK,SECTOR,ID
;
SETHDR JSR GETACT
SETH
 ASL A ;<HD>
 TAY
 LDA TRACK
 STA HDRS,Y ;SET TRACK
 LDA SECTOR
 STA HDRS+1,Y ;SET SECTOR
 LDA DRVNUM ;GET THE DISK ID
 ASL A ;TIMES 2
 TAX ;*
 LDA DSKID,X ;FIRST BYTE
 STA JOBID,Y ;INTO CONTROLLER LIST
 LDA DSKID+1,X ;SECOND BYTE
 STA JOBID+1,Y ;INTO CONTR LIST
 RTS 
;
; PUT .A INTO ACTIVE BUFFER OF LINDX
;
PUTBYT PHA ; SAVE .A
 JSR GETACT ;GET ACTIVE BUF#
 BPL PUTB1 ;BRACH IF THERE IS ONE
 PLA ;NO BUFFER ERROR
 LDA #FILNOP
 JMP CMDERR ; JMP TO ERROR ROUTINE
PUTB1 ASL A ;SAVE THE BYTE IN BUFFER
 TAX
 PLA
 STA (BUFTAB,X)
 INC BUFTAB,X ; INC THE BUFFER POINTER
 RTS ;Z=1 IF LAST CHAR SLOT IN BUFFER
 .PAG 'INIT CMD'
;
; FIND THE ACTIVE BUFFER # (LINDX)
;
;
;INITIALIZE DRIVES (COMMAND)
INTDRV JSR SIMPRS
 JSR INITDR
 LDA IMAGE ;USED AS FLAG FOR BOTH DRIVES
 BPL ID20
 JSR TOGDRV
 JSR INITDR
 JSR TOGDRV
ID20 JMP ENDCMD
 .PAG 'START DOUBLE'
;
;
; START DOUBLE BUFFERING
; USE TRACK,SECTOR AS STARTING BLOACK
; 
STRDBL
 JSR SETHDR
 JSR RDBUF
 JSR WATJOB
 JSR GETBYT
 STA SECTOR ;<HD>
 JSR GETBYT
 STA TRACK ;<HD>
 LDA SECTOR ;<HD>
 CMP #255 ;LAST SECTOR ? <HD>
 BNE STR1
 RTS
STR1 JSR DBLBUF
 JSR SETHDR
 JSR RDBUF
 JMP DBLBUF
;
; START A READ JOB ON TRACK,SECTOR
;
RDBUF LDA #READ
 BNE STRTIT
;
; START A WRITE JOB ON TRACK,SECTOR
;
WRTBUF LDA #WRITE
STRTIT STA CMD
 JSR GETACT
 TAX
 JSR SETLJB
 TXA
 PHA
 ASL A
 TAX
 LDA #0
 STA BUFTAB,X
 JSR TYPFIL
 CMP #4
 BCS WRTC1 ;NOT SEQUENTIAL TYPE
;
 INC NBKL,X
 BNE WRTC1
 INC NBKH,X
WRTC1 PLA
 TAX
 RTS
;
;
;****************************
;*
;*   FNDRCH
;******************************
;*
;*
FNDRCH LDA SA
 CMP #MAXSA+1
 BCC FNDC20
 AND #$F
FNDC20
 CMP #CMDSA
 BNE FNDC25
 LDA #ERRSA
FNDC25
 TAX
 SEC
 LDA LINTAB,X
 BMI FNDC30
 AND #$F
 STA LINDX
TAX
 CLC
FNDC30 RTS
;
;
;*
;*
;*****************************
;*
;*   FNDWCH
;*
;*****************************
;*
; LINTAB TWO HIGH BITS
;   00 - READ CHNL
;   10 - WRITE CHNL
;   01 - READ/WRITE CHNL (NA)
;   11 - ILLEGAL
;
FNDWCH LDA SA
 CMP #MAXSA+1
 BCC FNDW13
 AND #$F
FNDW13 TAX
 LDA LINTAB,X
 TAY
 ASL A
 BCC FNDW15
 BMI FNDW20
FNDW10 TYA
 AND #$0F
 STA LINDX
TAX
 CLC
 RTS
FNDW15 BMI FNDW10
FNDW20 SEC
 RTS
;
TYPFIL ;GET FILE TYPE
 LDX LINDX
 LDA FILTYP,X
 LSR A
 AND #7
 CMP #RELTYP
 RTS
;
GETPRE JSR GETACT
 ASL A
 TAX
 LDY LINDX
 RTS
 .SKIP
; READ BYTE FROM ACTIVE BUFFER
; AND SET FLAG IF LAST DATA BYTE
; IF LAST THEN Z=1 ELSE Z=0 ;
GETBYT JSR GETPRE
 LDA LSTCHR,Y
 BEQ GETB1
 LDA (BUFTAB,X)
 PHA 
 LDA BUFTAB,X
 CMP LSTCHR,Y
 BNE GETB2
 LDA #$FF
 STA BUFTAB,X
GETB2 PLA
 INC BUFTAB,X
 RTS
GETB1 LDA (BUFTAB,X)
 INC BUFTAB,X
 RTS
;
;
; READ A CHAR FROM FILE AND READ NEXT
; BLOCK OF FILE IF NEEDED.
; SET CHNRDY=EOI IF END OF FILE
;
RDBYT JSR GETBYT
 BNE RD3
 STA DATA
 .SKIP
RD0 LDA LSTCHR,Y
 BEQ RD1
 LDA #EOIOUT
RD01 STA CHNRDY,Y
 LDA DATA
 RTS
RD1 JSR DBLBUF
 LDA #0
 JSR SETPNT
 JSR GETBYT
 CMP #255 ;LAST SECTOR <HD>
 BEQ RD4
 STA SECTOR ;<HD>
 JSR GETBYT
 STA TRACK ;<HD>
 JSR DBLBUF
 JSR SETDRN
 JSR SETHDR
 JSR RDBUF
 JSR DBLBUF
 LDA DATA
RD3 RTS
RD4 JSR GETBYT
 LDY LINDX
 STA LSTCHR,Y
 LDA DATA
 RTS
 .SKIP 2
 .SKIP
; WRITE A CHAR TO CHANL AND WRITE 
; BUFFER OUT TO DISK IF ITS FULL
;
WRTBYT JSR PUTBYT
 BEQ WRT0
 RTS
 .SKIP
WRT0 JSR SETDRN
 JSR GETHDR ;*
 JSR NXTTS
 LDA #0
 JSR SETPNT
 LDA SECTOR ;<HD>
 JSR PUTBYT
 LDA TRACK ;<HD>
 JSR PUTBYT
 JSR WRTBUF
 JSR DBLBUF
 JSR SETHDR
 LDA #2
 JMP SETPNT
;
; INC POINTER OF ACTIVE BUFFER
; BY .A
;
;
INCPTR ; SCOTT PATCH 
INCPNT STA TEMP
 JSR GETPNT
 CLC
 ADC TEMP
 STA BUFTAB,X
 STA DIRBUF
 RTS
; SET DRVNUM TO DRIVE INDICATED BY
; LSTJOB OF ACTIVE BUFFER
;
SETDRN JSR GETACT
 TAX
 LDA LSTJOB,X
 AND #1
 STA DRVNUM
 RTS
;
;  COUNT SOFT ERRORS
; X=JOB #
;
CSER
 TXA ;SAVE JOB #
 PHA ;*
 LDA JOBS,X ;GET ERROR CODE
 CMP #2 ;TIMEOUT
 BEQ CSER1 ;BR IF T.O.
 CMP #5 ;LRC
 BEQ CSER2 ;BR IF LRC ERROR
 CMP #6 ;GCR
 BEQ CSER3 ;BR IF GCR ERROR
 CMP #7 ;VERIFY ERROR
 BEQ CSER5 ;BR IF SO
CSERA
 PLA ;RESTORE JOB #
 TAX
 LDA JOBS,X
 CMP #2
 RTS
CSER1 ;T.O.
 LDA #0
 .BYTE $2C ;THREE BYTE OP-CODE
CSER2 ;LRC
 LDA #2
 .BYTE $2C ;THREE BYTE OP-CODE
CSER3 ;GCR
 LDA #4
 .BYTE $2C ;THREE BYTE OP-CODE
CSER5
 LDA #6
 PHA ;SAVE INDEX
 LDA LSTJOB,X ;GET DRIVE #
 AND #1 ;*
 ROR A ;SET CARRY WITH BIT 0
 PLA ;INDEX IN A
 ADC #0 ;IF DRIVE 1 THEN ADD 1
 TAX ;USE TO INDEX
 LDA SERCNT,X ;CHK IF CTR IS AT MAX
 CMP #$FF ;*
 BEQ CSER4 ;BR IF AT MAX ALREADY
 INC SERCNT,X ;BUMP THE COUNTER
CSER4
 PLA ;RESTORE JOB #
 TAX ;*
 LDA JOBS,X ;RESTORE A
 CMP #2 ;REISSUE CMP
 RTS ;EXIT TO CALLER
.END
