.PAGE 96 .TITLE 'FFC - FAST DISK DUPLICATION PROGRAM' .SBTTL 'EQUATES' .PREL .PHEX ; W EARNEST MOD 4/03/82 ; 5/14/82 ADD FORMAT CODE ; 9/1/82 CHANGE STEP AND SKEW FOR NEW DRIVES ; 1/16/83 FIX REFORM FLAG BUG ; 2/11/83 FIX STOP TEST BUG ; 7/29/83 MOD DRIVE RDY TEST ; FOR BIGBOARD SYSTEM DATA ONLY COPY VER = 1 REV = 5 .PROGID FFC,VER,REV ; ; BIOS ENTRY POINT OFFSETS ; CONSTA = 06H ;CONSOLE STATUS (A=0, NO DATA) CONIN = 09H ;CONSOLE INPUT (INTO A) CONOUT = 0CH ;CONSOLE OUTPUT (FROM C) SELDSK = 1BH ;SELECT DISK (FROM C, 0..1) SETTRK = 1EH ;SET TRACK (FROM C, 0..76) SETSEC = 21H ;SET SECTOR (FROM C, 1..26) SETDMA = 24H ;SET DMA ADDRESS (FROM BC) READ = 27H ;READ SECTOR INTO DMA BUFFER WRITE = 2AH ;WRITE SECTOR FROM DMA BUFFER ; DISK = 10H ;DISK BASE ADDR DCOM = DISK ;DISK COMMAND PORT STATP = DISK ;DISK STATUS PORT TRACK = DISK+1 ;DISK TRACK COMMAND SECTP = DISK+2 ;DISK SECTOR PORT DDATA = DISK+3 ;DISK DATA PORT ROMSEL = 0F01BH ;FERGUSON SELECT SUBR. NMIVEC = 066H ;NMI ADDRESS STEP = 1 ;STEPPING RATE 2=10 MSEC,1=6 MSEC LF = 0AH ;LINE FEED CR = 0DH ;CARRIAGE RETURN BELL = 07H ;BELL ; FCB = 5CH BOOT = 0000H BDOS = 5 NBPT = 128*26 SKEW = 7 DRVI = 0 ;DRIVE A INPUT DRVO = 1 ;DRIVE B OUTPUT ; .SBTTL 'MAIN COPY ROUTINE' START: LXI SP,STACK+64 XRA A STA RFORM ; ; PRINT HEADING ; NEXTC: LXI H,STR1 CALL WASC CALL CRCK REDO: MVI A,2 ;START TRACK STA TRKI STA TRKO STA TRKV MVI A,77 STA STPTRK ;DEFAULT FULL DISK MVI A,5 ;NR OF PASSES STA PASCNT ; ; BEGIN MAIN LOOP ; CALL CRLF MVI A,10 ;RETRYS ALLOWED STA ERCNT COPY1: MVI C,DRVI MVI E,SELDSK CALL BIOSC CALL DRDYTS JRNZ COPY1 MVI A,'R' STA RWCHR CALL INIPAS COPY2: LHLD PTR ;READ NEXT N TRACKS LDA TRKI CALL WSTS CALL RDTRK CALL CKEMT JRNZ ..A ;THIS TRACK HAS DATA LDA TRKI STA STPTRK ;MARK IT AS TOO FAR JMPR COPY2A ..A: CALL INCSEC LDA TRKI INR A STA TRKI LDA TRKCNT DCR A STA TRKCNT JRNZ COPY2 ; COPY2A: MVI C,DRVO MVI E,SELDSK CALL BIOSC CALL DRDYTS JRNZ COPY2A MVI A,'W' STA RWCHR CALL INIPAS COPY3: LHLD PTR ;WRITE NEXT N TRACKS LDA TRKO CALL WSTS CALL WRTRK CALL INCSEC LDA TRKO INR A STA TRKO MOV L,A ;HOLD NEXT TRACK LDA STPTRK SUB L ;THERE YET? JRZ COPY4 ;TIME TO STOP, FOUND EMPTY JM COPY4 ;IN CASE OVERSHOOT LDA TRKCNT DCR A STA TRKCNT JRNZ COPY3 ; LDA PASCNT DCR A STA PASCNT JNZ COPY1 ;LOOP UNTIL ALL PASSES DONE ; COPY4: LXI H,STR5 ;PRINT 'COPY COMPLETE' CALL WASC JMP START ;RESTART IT, CLEAN FLAGS ; INIPAS: LXI H,TRKBUF SHLD PTR MVI A,15 ;TRKCNT = NUMBER OF TRACKS PER PASS STA TRKCNT MVI A,1 STA STSECT RET ; INCSEC: LHLD PTR LXI D,NBPT DAD D SHLD PTR LDA STSECT ADI SKEW CPI 27 JRC ..A SUI 26 ..A: STA STSECT RET .SBTTL 'READ/WRITE ROUTINES' ; ; RDTRK - READ ABSOLUTE TRACK INTO MEMORY ; ; ENTRY CONDITIONS ; HL........FWA OF AREA TO READ TRACK INTO ; A.........TRACK NUMBER (0 TO 76) ; RDTRK: PUSH D PUSH H CALL INIRW RTRK0: MVI B,26 ;SECTOR COUNTER LDA STSECT ;INITIAL SECTOR # MOV C,A ;SECTOR NR IN C RDTRK1: PUSH B CALL INISEC MVI E,READ CALL BIOSC ;READ A SECTOR ORA A ;OK? JNZ RERR ;NO GOOD CALL INCPTR POP B CALL SECINC NOWRP3: DJNZ RDTRK1 POP H POP D RET ; RERR: POP B ;CLEAN STACK LXI H,RERCT DCR M JZ HERR ;HARD ERROR LHLD HLDDMA SHLD DMAPTR ;RESET IT JMP RTRK0 ; INIRW: SHLD DMAPTR SHLD HLDDMA MOV C,A MVI E,SETTRK CALL BIOSC MVI A,5 STA RERCT RET ; INISEC: MVI E,SETSEC CALL BIOSC LBCD DMAPTR MVI E,SETDMA JMP BIOSC ; INCPTR: LHLD DMAPTR LXI D,80H DAD D SHLD DMAPTR ;UPDATE POINTER RET ; SECINC: INR C MOV A,C CPI 27 RC SUI 26 MOV C,A RET ; ; WRTRK - WRITE ABSOLUTE TRACK FROM MEMORY ; ; ENTRY CONDITIONS ; HL........FWA OF AREA TO WRITE TRACK FROM ; A.........TRACK NUMBER (0 TO 76) ; WRTRK: PUSH D PUSH H CALL INIRW RWRTRK: LDA STSECT ;INITIAL SECTOR # MOV C,A MVI B,26 ;SECTOR COUNT WRTRK1: PUSH B CALL INISEC MVI E,WRITE CALL BIOSC ORA A JNZ WERR CALL INCPTR POP B CALL SECINC NOWRP4: DJNZ WRTRK1 ; LXI H,VBUF SHLD DMAPTR LDA STSECT MOV C,A MVI B,26 VTRK1: PUSH B CALL INISEC MVI E,READ CALL BIOSC ORA A JNZ VERR CALL INCPTR POP B CALL SECINC NOWRP5: DJNZ VTRK1 POP H POP D RET ; VERR: POP B ;CLEAN UP STACK LXI H,ERCNT DCR M LXI H,STR7 ;DEST ERR, SOFT? JZ XERR POP H ;RECOV BUFFER ADDR AT START PUSH H SHLD DMAPTR JMP RWRTRK ; WERR: POP B LXI H,RERCT DCR M LXI H,STR4 JRZ XERR ;WRITE ERROR, MAYBE SOFT LHLD HLDDMA SHLD DMAPTR JMP RWRTRK ;TRY WRITE AGAIN ; HERR: LXI H,STR3 ;HARD SOURCE ERROR MESSAGE JMP ERRC ; XERR: CALL WASC ;REPORT DEST ERR LDA RFORM ;HISTORY ORA A JNZ ERR ;HARD ERROR POP B DCR A STA RFORM ;NARK FORMAT NOW LXI H,STR6 CALL WASC CALL FORMT ;REFORMAT THE DEST JMP REDO ; ERR: LXI H,STR2 ;HARD DEST ERROR ERRC: CALL WASC JMP START ; ; WASC - WRITE ASCII STRING TO CONSOLE ; WASC: MOV A,M ORA A RZ CALL WACC INX H JMPR WASC ; ; CRLF - WRITE END OF LINE TO CONSOLE ; CRLF: MVI A,CR CALL WACC MVI A,LF ; ; WACC - WRITE ASCII CHARACTER TO CONSOLE ; WACC: PUSH H PUSH D PUSH B MOV C,A MVI E,CONOUT CALL BIOSC POP B POP D POP H RET ; ; RACC - READ ASCII CHARACTER FROM CONSOLE ; RACC: PUSH H PUSH D PUSH B KBLP: CALL CONSTT ORA A JRZ KBLP ;WAIT FOR SOMETHING MVI E,CONIN CALL BIOSC ANI 7FH POP B POP D POP H RET ; CONSTT: MVI A,30 ;HALF MIN STA 0FF6CH ;KEEP DISK MOTORS ON MVI E,CONSTA CALL BIOSC RET ; ; CRCK - TEST FOR CR INPUT ; CRCK: CALL RACC CPI 0DH RZ CPI 3 JZ BOOT CPI 60H JRC ..A ANI 5FH ..A: CPI 'F' JRNZ CRCK CALL FORMT JMP START ; WSTS: PUSH PSW MVI A,0DH ;CR CALL WACC LDA RWCHR CALL WACC MVI A,' ' CALL WACC POP PSW PUSH PSW CALL HXBYT POP PSW RET ; HXBYT: PUSH PSW RAR RAR RAR RAR CALL HOUT POP PSW HOUT: ANI 0FH ADI 90H DAA ACI 40H DAA JMP WACC ; BIOSC: MVI D,0 ;FORCE LOW LXI H,0EA00H ;BIOS START ADDR DAD D ;CALC ADDR PCHL ;DO CALL ; DRDYTS: IN DISK BIT 7,A RZ ;DRIVE IS READY DRDYLP: IN DISK CMA BIT 7,A RNZ ;DRIVE IS READY CALL CONSTT ORA A JRZ DRDYLP ;WAIT FOR SOMETHING MVI E,CONIN CALL BIOSC ANI 7FH CPI 'C'-40H JZ START ;ABORT IT JMP DRDYLP ;TEST AGAIN ; CKEMT: PUSH H PUSH B LHLD HLDDMA ;DATA START LXI B,26*128 ;AMOUNT OF DATA EMTLP: MOV A,M CPI 0E5H ;NULL PATTERN JRNZ ..A ;NOT EMPTY INX H DCX B MOV A,B ORA C JRNZ EMTLP ..A: POP B POP H RET ; FORMT: DI ;NO INTERRUPTS BUT NMI (NO CLOCK) LXI H,26 SHLD FSECT ;DEFINE # SECTORS & FIRST TRK MVI C,1 CALL ROMSEL CALL HOME CALL DOFORM ENDFIL: CALL HOME MVI C,0 CALL ROMSEL EI ;INTERRUPTS OK NOW JMP CRLF ;BACK TO MENU ; ; DISK FORMATTING ROUTINES. ; DOFORM: LXI H,TRKBUF ;POINT TO TRACK BUFFER MVI A,'F' STA RWCHR XRA A CALL WSTS CALL INDX DOF1: CALL ADDR CALL DATA LDA FSECT DCR A ;DECR SECTOR COUNT STA FSECT JNZ DOF1 CALL FILBUF ;FILL END OF BUFFER WITH FF'S LXI D,TRKBUF ORA A DSBC D ;CALC SIZE OF BUFFER BUILT INR H ;ADJUST FOR FIRST DCR SHLD CNTSAV ;NEED MORE THAN ONCE LXI H,NMWCOD LXI B,NMWEND-NMWCOD LXI D,NMIVEC LDIR ; DOF4: LXI H,TRKBUF ;POINT TO FORMAT BUFFER CALL FILADR ;PLACE TRACK AND SECTOR NRS IN BUFF LXI H,TRKBUF ;POINT TO TRACK BUFFER LXI B,DDATA ;DATA PORT FOR OUTI,CLEAR B LDED CNTSAV ;REALLY JUST D REG IN STATP ;CLEAR ANY LEFTOVER FLAGS MVI A,0F4H ;TRACK WRITE COMMAND CALL CMDOUT ;START & KILL SOME TIME ; DOF7: HLT ;WAIT FOR INTERRUPT JMP DOF7 ;LOOP TILL ALL DONE ; TRKDUN: CALL BUSY ;MAKE SURE SHUT DOWN ANI 0FFH ;TEST IT JNZ ERRMSG ;ERROR HERE, DIDNT WORK LDA TRK ;TRACK NO INR A ;INCREMENT IT STA TRK CPI 77 ;PAST LAST TRK? RZ ;IF DONE ALL TRACKS CALL WSTS MVI A,58H+STEP ;STEP COMMAND,NO VERIF CALL WTCMD ;ISSUE IT JMP DOF4 ; WTCMD: CALL CMDOUT ;EXECUTE & FALL THRU ; BUSY: IN STATP ;TEST 1771 BUSY BIT 0,A JNZ BUSY ;LOOP TILL FINISHED RET ; CMDOUT: OUT DCOM ;ISSUE COMMAND PAUSE: XTHL XTHL RET ; ; INDX - INDEX BLOCK FOR IBM FORMATS (NOT REQUIRED FOR 1771) ; 73 IN MEM, 73 ON DSK ; INDX: LXI B,40<8+0FFH ;40 COUNT,ONES BYTE CALL MOVEIT ;STORE THE BLOCK LXI B,6<8+0 ;COUNT 6, ZERO DATA CALL MOVEIT ;STORE THE BLOCK MVI M,0FCH ;INDEX MARK INX H ;INCR POINTER LXI B,26<8+0FFH ;NOW 26 MORE FF'S JMP MOVEIT ;STORE THE BLOCK ; ; ADDR - ADDRESS BLOCK 12 IN MEM, 13 ON DSK ; ADDR: LXI B,6<8+0 ;WRITE 6 ZEROS CALL MOVEIT MVI M,0FEH ;ID ADDRESS MARK INX H MVI B,4 ;TRACK AND SECTOR ZERO INITIALLY CALL MOVEIT MVI M,0F7H ;WRITE 2 CRC'S INX H RET ; ; DATA - WRITE DATA BLOCK FILLED WITH E5'S ; 180 IN MEM, 181 ON DSK DATA: LXI B,11<8+0FFH ;WRITE 11 FF'S CALL MOVEIT LXI B,6<8+0 ;NOW 6 ZEROS CALL MOVEIT MVI M,0FBH ;DATA ADDRESS MARK INX H LXI B,128<8+0E5H ;DATA FILL CHARACTER CALL MOVEIT MVI M,0F7H ;WRITE 2 CRC'S INX H LXI B,33<8+0FFH ;INTERRECORD GAP, FALL THRU ; ; MOVEIT ROUTINE HL --> MEMORY, DE = COUNT, B CONTAINS BYTE ; MOVEIT: MOV M,C ;STORE BYTE INX H DJNZ MOVEIT RET ; ; FILADR - FILL IN TRACK AND SECTOR NUMBERS ; FILADR: LXI B,26*256+1 LXI D,190 ;FILL ADDR OFFSET (180+12)-2 LXI H,TRKBUF+80 ;LOCATION OF FIRST TRACK NUMBER FIL01: LDA TRK ;TRACK NO MOV M,A ;TO BUFFER INX H INX H ;POINT TO SECTOR MOV M,C ;SECTOR NUMBER TO BUFFER DAD D ;INCR BUFFER POINTER INR C ;INCR SECTOR MAP NUMBER DJNZ FIL01 RET ; ; FILBUF - FILL END OF TRACK WITH FF'S ; FILBUF: LXI D,1024 ;END OF TRACK FILL MVI C,0FFH ;FILL CHAR ET1: MOV M,C INX H DCX D ;DECR COUNT MOV A,D ORA E JNZ ET1 RET ; ; ERROR ROUTINE ; ERRMSG: JMP ENDFIL ; ; HOME SELECTED DRIVE ; HOME: IN STATP ;CHECK IF BUSY RRC JC HOME MVI A,0+STEP ;HOME COMMAND CALL WTCMD ;ISSUE COMMAND, WAIT TILL NOT BUSY IN STATP ;READ DISK STATUS ANI 4 ;CHECK TRACK ZERO FLAG RNZ ; HOMERR: JMP ENDFIL ;EXIT ; NMWCOD: OUTI RNZ DCR D RNZ POP D JMP TRKDUN NMWEND = . ; ; STRING DATA ; STR1: .ASCII 'Fast Disk Duplicator Utility' .ASCII ' V '[VER+'0']'.'[REV+'0']' ' .DATE .BYTE CR,LF .ASCII 'Source in Drive 0(A), Blank in Drive 1(B)'[CR][LF] .ASCII 'Press RETURN to copy, "F" to format,'[CR][LF] .ASCIZ 'Ctrl-C to Exit.'[CR][LF] STR2: .ASCIZ ' error, Disk Unsalvagable, Aborting'[BELL][CR][LF] STR3: .ASCIZ [CR][LF][BELL]'HARD Error on Source disk, Aborting'[CR][LF] STR4: .ASCIZ [CR][LF]'Write' STR5: .ASCIZ [CR][LF]'COPY COMPLETE'[BELL][CR][LF][LF] STR6: .ASCIZ [BELL]' error, Attempting reformat'[CR][LF] STR7: .ASCII [CR][LF]'Verification' ; .LOC .DATA. ; TRKNO: .BLKB 1 ;TRACK NUMBER DMAPTR: .BLKW 1 ;DMA POINTER HLDDMA: .BLKW 1 ;DMA HOLD FOR RETRY CNTSAV: .BLKW 1 ;D REG SAVE OF BUFFER SIZE CNT FSECT: .BLKB 1 ;SECTOR COUNT USED IN FORMATTING TRK: .BLKB 1 ;TRACK NUMBER USED IN FORMATTING DISK ; PTR: .BLKW 1 VPTR: .BLKW 1 TRKI: .BLKB 1 ;INPUT TRACK NUMBER TRKO: .BLKB 1 ;OUTPUT TRACK NUMBER TRKV: .BLKB 1 ;VERIFY TRACK NUMBER STPTRK: .BLKB 1 RFORM: .BLKB 1 RWCHR: .BLKB 1 ;R OR W FOR STATUS ERCNT: .BLKB 1 ;ERROR COUNTER RERCT: .BLKB 1 ;RETRY COUNTER PASCNT: .BLKB 1 ;PASS COUNT TRKCNT: .BLKB 1 ;TRACK COUNT STSECT: .BLKB 1 ;STARTING SECTOR STACK: .BLKW 32 VBUF: .BLKB 26*128 TRKBUF = . ; .END START