.TITLE 'FFC - FAST DISK DUPLICATION PROGRAM' ; 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 ; 1/12/85 MODIFIED BY R.PARSONS FOR 4MHZ XEROX ; 820/1 AND ZILOG MNEMONICS .ORG 100H ; ; BIOS ENTRY POINT OFFSETS ; CONSTA .EQU 06H ;CONSOLE STATUS (A=0, NO DATA) CONIN .EQU 09H ;CONSOLE INPUT (INTO A) CONOUT .EQU 0CH ;CONSOLE OUTPUT (FROM C) SELDSK .EQU 1BH ;SELECT DISK (FROM C, 0..1) SETTRK .EQU 1EH ;SET TRACK (FROM C, 0..76) SETSEC .EQU 21H ;SET SECTOR (FROM C, 1..26) SETDMA .EQU 24H ;SET DMA ADDRESS (FROM BC) READ .EQU 27H ;READ SECTOR INTO DMA BUFFER WRITE .EQU 2AH ;WRITE SECTOR FROM DMA BUFFER ; DISK .EQU 10H ;DISK BASE ADDR DCOM .EQU DISK ;DISK COMMAND PORT STATP .EQU DISK ;DISK STATUS PORT TRACK .EQU DISK+1 ;DISK TRACK COMMAND SECTP .EQU DISK+2 ;DISK SECTOR PORT DDATA .EQU DISK+3 ;DISK DATA PORT ROMSEL .EQU 0F01BH ;FERGUSON SELECT SUBR. NMIVEC .EQU 066H ;NMI ADDRESS STEP .EQU 2 ;STEPPING RATE 2=10 MSEC,1=6 MSEC LF .EQU 0AH ;LINE FEED CR .EQU 0DH ;CARRIAGE RETURN BELL .EQU 07H ;BELL NL .EQU 0 ; FCB .EQU 5CH BOOT .EQU 0000H BDOS .EQU 5 BIOS .EQU 0EA00H NBPT .EQU 128*26 SKEW .EQU 6 DRVI .EQU 0 ;DRIVE A INPUT DRVO .EQU 1 ;DRIVE B OUTPUT MOTOR .EQU 0FF69H ;MOTOR TIMER ; 'MAIN COPY ROUTINE' START: LD SP,STACK+64 XOR A LD (RFORM),A ; ; PRINT HEADING ; NEXTC: LD HL,STR1 CALL WASC CALL CRCK REDO: LD A,2 ;START TRACK LD (TRKI),A LD (TRKO),A LD (TRKV),A LD A,77 LD (STPTRK),A;DEFAULT FULL DISK LD A,5 ;NR OF PASSES LD (PASCNT),A ; ; BEGIN MAIN LOOP ; CALL CRLF LD A,10 ;RETRYS ALLOWED LD (ERCNT),A COPY1: LD C,DRVI LD E,SELDSK CALL BIOSC CALL DRDYTS JR NZ,COPY1 LD A,'R' LD (RWCHR),A CALL INIPAS COPY2: LD HL,(PTR);READ NEXT N TRACKS LD A,(TRKI) CALL WSTS CALL RDTRK CALL CKEMT JR NZ,AAA ;THIS TRACK HAS DATA LD A,(TRKI) LD (STPTRK),A;MARK IT AS TOO FAR JR COPY2A AAA: CALL INCSEC LD A,(TRKI) INC A LD (TRKI),A LD A,(TRKCNT) DEC A LD (TRKCNT),A JR NZ,COPY2 ; COPY2A: LD C,DRVO LD E,SELDSK CALL BIOSC CALL DRDYTS JR NZ,COPY2A LD A,'W' LD (RWCHR),A CALL INIPAS COPY3: LD HL,(PTR);WRITE NEXT N TRACKS LD A,(TRKO) CALL WSTS CALL WRTRK CALL INCSEC LD A,(TRKO) INC A LD (TRKO),A LD L,A ;HOLD NEXT TRACK LD A,(STPTRK) SUB L ;THERE YET? JR Z,COPY4 ;TIME TO STOP, FOUND EMPTY JP M,COPY4 ;IN CASE OVERSHOOT LD A,(TRKCNT) DEC A LD (TRKCNT),A JR NZ,COPY3 ; LD A,(PASCNT) DEC A LD (PASCNT),A JP NZ,COPY1 ;LOOP UNTIL ALL PASSES DONE ; COPY4: LD HL,STR5 ;PRINT 'COPY COMPLETE' CALL WASC JP START ;RESTART IT, CLEAN FLAGS ; INIPAS: LD HL,TRKBUF LD (PTR),HL LD A,15 ;TRKCNT = NUMBER OF TRACKS PER PASS LD (TRKCNT),A LD A,1 LD (STSECT),A RET ; INCSEC: LD HL,(PTR) LD DE,NBPT ADD HL,DE LD (PTR),HL LD A,(STSECT) ADD A,SKEW CP 27 JR C,AAB SUB 26 AAB: LD (STSECT),A RET ; '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 DE PUSH HL CALL INIRW RTRK0: LD B,26 ;SECTOR COUNTER LD A,(STSECT);INITIAL SECTOR # LD C,A ;SECTOR NR IN C RDTRK1: PUSH BC CALL INISEC LD E,READ CALL BIOSC ;READ A SECTOR OR A ;OK? JP NZ,RERR ;NO GOOD CALL INCPTR POP BC CALL SECINC NOWRP3: DJNZ RDTRK1 POP HL POP DE RET ; RERR: POP BC ;CLEAN STACK LD HL,RERCT DEC (HL) JP Z,HERR ;HARD ERROR LD HL,(HLDDMA) LD (DMAPTR),HL;RESET IT JP RTRK0 ; INIRW: LD (DMAPTR),HL LD (HLDDMA),HL LD C,A LD E,SETTRK CALL BIOSC LD A,5 LD (RERCT),A RET ; INISEC: LD E,SETSEC CALL BIOSC LD BC,(DMAPTR) LD E,SETDMA JP BIOSC ; INCPTR: LD HL,(DMAPTR) LD DE,80H ADD HL,DE LD (DMAPTR),HL;UPDATE POINTER RET ; SECINC: INC C LD A,C CP 27 RET C SUB 26 LD 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 DE PUSH HL CALL INIRW RWRTRK: LD A,(STSECT);INITIAL SECTOR # LD C,A LD B,26 ;SECTOR COUNT WRTRK1: PUSH BC CALL INISEC LD E,WRITE CALL BIOSC OR A JP NZ,WERR CALL INCPTR POP BC CALL SECINC NOWRP4: DJNZ WRTRK1 ; LD HL,VBUF LD (DMAPTR),HL LD A,(STSECT) LD C,A LD B,26 VTRK1: PUSH BC CALL INISEC LD E,READ CALL BIOSC OR A JP NZ,VERR CALL INCPTR POP BC CALL SECINC NOWRP5: DJNZ VTRK1 POP HL POP DE RET ; VERR: POP BC ;CLEAN UP STACK LD HL,ERCNT DEC (HL) LD HL,STR7 ;DEST ERR, SOFT? JP Z,XERR POP HL ;RECOV BUFFER ADDR AT START PUSH HL LD (DMAPTR),HL JP RWRTRK ; WERR: POP BC LD HL,RERCT DEC (HL) LD HL,STR4 JR Z,XERR ;WRITE ERROR, MAYBE SOFT LD HL,(HLDDMA) LD (DMAPTR),HL JP RWRTRK ;TRY WRITE AGAIN ; HERR: LD HL,STR3 ;HARD SOURCE ERROR MESSAGE JP ERRC ; XERR: CALL WASC ;REPORT DEST ERR LD A,(RFORM);HISTORY OR A JP NZ,ERR ;HARD ERROR POP BC DEC A LD (RFORM),A;NARK FORMAT NOW LD HL,STR6 CALL WASC CALL FORMT ;REFORMAT THE DEST JP REDO ; ERR: LD HL,STR2 ;HARD DEST ERROR ERRC: CALL WASC JP START ; ; WASC - WRITE ASCII STRING TO CONSOLE ; WASC: LD A,(HL) OR A RET Z CALL WACC INC HL JR WASC ; ; CRLF - WRITE END OF LINE TO CONSOLE ; CRLF: LD A,CR CALL WACC LD A,LF ; ; WACC - WRITE ASCII CHARACTER TO CONSOLE ; WACC: PUSH HL PUSH DE PUSH BC LD C,A LD E,CONOUT CALL BIOSC POP BC POP DE POP HL RET ; ; RACC - READ ASCII CHARACTER FROM CONSOLE ; RACC: PUSH HL PUSH DE PUSH BC KBLP: CALL CONSTT OR A JR Z,KBLP ;WAIT FOR SOMETHING LD E,CONIN CALL BIOSC AND 7FH POP BC POP DE POP HL RET ; CONSTT: LD A,30 ;HALF MIN LD (MOTOR),A;KEEP DISK MOTORS ON LD E,CONSTA CALL BIOSC RET ; ; CRCK - TEST FOR CR INPUT ; CRCK: CALL RACC CP 0DH RET Z CP 3 JP Z,BOOT CP 60H JR C,AAC AND 5FH AAC: CP 'F' JR NZ,CRCK CALL FORMT JP START ; WSTS: PUSH AF LD A,0DH ;CR CALL WACC LD A,(RWCHR) CALL WACC LD A,' ' CALL WACC POP AF PUSH AF CALL HXBYT POP AF RET ; HXBYT: PUSH AF RRA RRA RRA RRA CALL HOUT POP AF HOUT: AND 0FH ADD A,90H DAA ADC A,40H DAA JP WACC ; BIOSC: LD D,0 ;FORCE LOW LD HL,BIOS ;BIOS START ADDR ADD HL,DE ;CALC ADDR JP (HL) ;DO CALL ; DRDYTS: IN A,(DISK) BIT 7,A RET Z ;DRIVE IS READY DRDYLP: IN A,(DISK) CPL BIT 7,A RET NZ ;DRIVE IS READY CALL CONSTT OR A JR Z,DRDYLP ;WAIT FOR SOMETHING LD E,CONIN CALL BIOSC AND 7FH CP 'C'-40H JP Z,START ;ABORT IT JP DRDYLP ;TEST AGAIN ; CKEMT: PUSH HL PUSH BC LD HL,(HLDDMA);DATA START LD BC,26*128 ;AMOUNT OF DATA EMTLP: LD A,(HL) CP 0E5H ;NULL PATTERN JR NZ,AAD ;NOT EMPTY INC HL DEC BC LD A,B OR C JR NZ,EMTLP AAD: POP BC POP HL RET ; FORMT: DI ;NO INTERRUPTS BUT NMI (NO CLOCK) LD HL,26 LD (FSECT),HL ;DEFINE # SECTORS & FIRST TRK LD C,1 CALL ROMSEL CALL HOME CALL DOFORM ENDFIL: CALL HOME LD C,0 CALL ROMSEL EI ;INTERRUPTS OK NOW JP CRLF ;BACK TO MENU ; ; DISK FORMATTING ROUTINES. ; DOFORM: LD HL,TRKBUF ;POINT TO TRACK BUFFER LD A,'F' LD (RWCHR),A XOR A CALL WSTS CALL INDX DOF1: CALL ADDR CALL DATA LD A,(FSECT) DEC A ;DECR SECTOR COUNT LD (FSECT),A JP NZ,DOF1 CALL FILBUF ;FILL END OF BUFFER WITH FF'S LD DE,TRKBUF OR A SBC HL,DE ;CALC SIZE OF BUFFER BUILT INC H ;ADJUST FOR FIRST DCR LD (CNTSAV),HL ;NEED MORE THAN ONCE LD HL,NMWCOD LD BC,NMWEND-NMWCOD LD DE,NMIVEC LDIR ; DOF4: LD HL,TRKBUF ;POINT TO FORMAT BUFFER CALL FILADR ;PLACE TRACK AND SECTOR NRS IN BUFF LD HL,TRKBUF ;POINT TO TRACK BUFFER LD BC,DDATA ;DATA PORT FOR OUTI,CLEAR B LD DE,(CNTSAV) ;REALLY JUST D REG IN A,(STATP) ;CLEAR ANY LEFTOVER FLAGS LD A,0F4H ;TRACK WRITE COMMAND CALL CMDOUT ;START & KILL SOME TIME ; DOF7: HALT ;WAIT FOR INTERRUPT JP DOF7 ;LOOP TILL ALL DONE ; TRKDUN: CALL BUSY ;MAKE SURE SHUT DOWN AND 24H ;TEST IT JP NZ,ERRMSG ;ERROR HERE, DIDNT WORK LD A,(TRK) ;TRACK NO INC A ;INCREMENT IT LD (TRK),A CP 77 ;PAST LAST TRK? RET Z ;IF DONE ALL TRACKS CALL WSTS LD C,1 ;RESET MOTOR TIMER CALL ROMSEL LD A,58H+STEP ;STEP COMMAND,NO VERIF CALL WTCMD ;ISSUE IT JP DOF4 ; WTCMD: CALL CMDOUT ;EXECUTE & FALL THRU ; BUSY: IN A,(STATP) ;TEST 1771 BUSY BIT 0,A JP NZ,BUSY ;LOOP TILL FINISHED RET ; CMDOUT: OUT (DCOM),A ;ISSUE COMMAND CALL PAUSE PAUSE: EX (SP),HL EX (SP),HL RET ; ; INDX - INDEX BLOCK FOR IBM FORMATS ; 73 IN MEM, 73 ON DSK ; INDX: LD BC,40*256+0FFH ;40 COUNT,ONES BYTE CALL MOVEIT ;STORE THE BLOCK LD BC,6*256+0 ;COUNT 6, ZERO DATA CALL MOVEIT ;STORE THE BLOCK LD (HL),0FCH ;INDEX MARK INC HL ;INCR POINTER LD BC,26*256+0FFH ;NOW 26 MORE FF'S JP MOVEIT ;STORE THE BLOCK ; ; ADDR - ADDRESS BLOCK 12 IN MEM, 13 ON DSK ; ADDR: LD BC,6*256+0 ;WRITE 6 ZEROS CALL MOVEIT LD (HL),0FEH ;ID ADDRESS MARK INC HL LD B,4 ;TRACK AND SECTOR ZERO INITIALLY CALL MOVEIT LD (HL),0F7H ;WRITE 2 CRC'S INC HL RET ; ; DATA - WRITE DATA BLOCK FILLED WITH E5'S ; 174 IN MEM, 175 ON DSK DATA: LD BC,11*256+0FFH ;WRITE 11 FF'S CALL MOVEIT LD BC,6*256+0 ;NOW 6 ZEROS CALL MOVEIT LD (HL),0FBH ;DATA ADDRESS MARK INC HL LD BC,128*256+0E5H ;DATA FILL CHARACTER CALL MOVEIT LD (HL),0F7H ;WRITE 2 CRC'S INC HL LD BC,27*256+0FFH ;INTERRECORD GAP, FALL THRU ; ; MOVEIT ROUTINE HL --> MEMORY, DE = COUNT, B CONTAINS BYTE ; MOVEIT: LD (HL),C ;STORE BYTE INC HL DJNZ MOVEIT RET ; ; FILADR - FILL IN TRACK AND SECTOR NUMBERS ; FILADR: LD BC,26*256+1 LD DE,184 ;FILL ADDR OFFSET (174+12)-2 LD HL,TRKBUF+80 ;LOCATION OF FIRST TRACK NUMBER FIL01: LD A,(TRK) ;TRACK NO LD (HL),A ;TO BUFFER INC HL INC HL ;POINT TO SECTOR LD (HL),C ;SECTOR NUMBER TO BUFFER ADD HL,DE ;INCR BUFFER POINTER INC C ;INCR SECTOR MAP NUMBER DJNZ FIL01 RET ; ; FILBUF - FILL END OF TRACK WITH FF'S ; FILBUF: LD DE,1024 ;END OF TRACK FILL LD C,0FFH ;FILL CHAR ET1: LD (HL),C INC HL DEC DE ;DECR COUNT LD A,D OR E JP NZ,ET1 RET ; ; ERROR ROUTINE ; ERRMSG: LD HL,STR8 JP ERRC ; ; HOME SELECTED DRIVE ; HOME: IN A,(STATP) ;CHECK IF BUSY RRCA JP C,HOME LD A,0+STEP ;HOME COMMAND CALL WTCMD ;ISSUE COMMAND, WAIT TILL NOT BUSY IN A,(STATP) ;READ DISK STATUS AND 4 ;CHECK TRACK ZERO FLAG RET NZ ; HOMERR: JP ERRMSG ;ABORT ; NMWCOD: OUTI RET NZ DEC D RET NZ POP DE JP TRKDUN NMWEND .EQU $ ; ; STRING DATA ; STR1: .BYTE 'Fast Disk Duplicator Utility V 1.6',CR,LF .BYTE 'Source in Drive 0(A), Blank in Drive 1(B)',CR,LF .BYTE 'Press RETURN to copy, "F" to format,',CR,LF .BYTE 'Ctrl-C to Exit.',CR,LF,NL STR2: .BYTE ' error, Disk Unsalvageable, Aborting',CR,LF,NL STR3: .BYTE CR,LF,'HARD Error on Source disk, Aborting',CR,LF,NL STR4: .BYTE CR,LF,'Write',NL STR5: .BYTE CR,LF,'COPY COMPLETE',CR,LF,NL STR6: .BYTE CR,LF,' error, Attempting reformat',CR,LF,NL STR7: .BYTE CR,LF,'Verification',NL STR8: .BYTE CR,LF,'Error, Aborting',CR,LF,NL ; ; 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 .EQU $ ; .END START