* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DISKETTE MAINTENANCE UTILITY * * TO FORMAT, VERIFY AND COPY AMPRO DISKETTES * * COPYRIGHT (C) 1983, 1984, 1985 AMPRO COMPUTERS, INC. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; assemble with asm.com or equivalent. there is no z80 code. VER EQU 33 ; REVISION HISTORY: ; ; Version 3.3 12 Dec 85 Changed SETUP and READY routines to ; work better with microfloppies. ; Added interrupt disable/enable so ; can be used with future s/w rtc code. ; ; Version 3.2 24 Jun 85 Changed cmds to FDC to use proper step ; rate if 2.x+ bios. ; ; Version 3.1 21 Feb 85 Changed prompt & display routine to get ; real unit # (version 2.0+). Removed ; warning message of 12-dec-84. ; ; Version 3.0 12 Dec 84 Added warning message when used with ; hard disk bios. ; ; Version 2.6 10 May 84 Cleaned up one more response. ; ; Version 2.5 8 May 84 Cleaned up the responses so that only ; characters of interest are acted upon. ; ; Version 2.4 5/3/84 Added 10 ms delay after any line feed. ; Only ESC or CTLC will exit the program. ; ; Version 2.3 3/20/84 Increased restore timeout to 5 sec ; ; Version 2.2 Delayed step until after index pulse ; due to apparent 1770 problem resulting ; in improper stepping ; ; Version 2.1 Added motor on delay to restore command ; ; Version 2.0 Initial release YES EQU 1 NO EQU 0 RAW EQU NO ; wd1770 equates REST EQU 00 ; slow restore RDSEC EQU 88H ; read sector command WRSEC EQU 0A8H ; write sector command WRTRK EQU 0F8H ; write track command STEPI EQU 58H ; step in command RDID EQU 0C8H ; read address command MOT EQU 80H ; motor on status WPR EQU 40H ; write protected status SPU EQU 20H ; disk at speed status (type i) TYP EQU 20H ; record type status (types ii and iii) RNF EQU 10H ; record not found status CRC EQU 8 ; crc error status TK0 EQU 4 ; track zero status (type i) LDT EQU 4 ; lost data status (types ii and iii) IDX EQU 2 ; index status (type i) DRQ EQU 2 ; data request status (types ii and iii) BSY EQU 1 ; controller busy status ERRII EQU WPR+RNF+CRC+LDT ; type ii error status mask ERRIII EQU WPR+LDT ; type iii error status mask CMND EQU 0C0H ; fdc command register WTRK EQU CMND+1 ; write to track register WSEC EQU WTRK+1 ; write to sector register WDAT EQU WSEC+1 ; write to data register STAT EQU WDAT+1 ; fdc status register RTRK EQU STAT+1 ; read from track register RSEC EQU RTRK+1 ; read from sector register RDAT EQU RSEC+1 ; read from data register CONT EQU 0 ; system control port ROMOFF EQU 40H ; turn rom off SID0 EQU 0EFH ; mask side bit off SID1 EQU 10H ; side bit in control register SDEN EQU 20H ; single density bit in control register TRY EQU 3 ; tries TRYHARD EQU 10 ; we try harder MSEC EQU 167 ; constant for 1 ms delay CTLC EQU 3 ; control c CR EQU 13 ; carriage return LF EQU 10 ; line feed ESC EQU 27 ; escape key UPCASE EQU 5FH ; upper case mask ORG 100H start: lxi sp,stack call clrsc call get$bios$vers mvi a,16 jnz new$sys lhld 1 mvi l,5ch mov a,m jmp plugem new$sys: push psw mvi a,0 lxi h,jplug1 mov m,a inx h mov m,a inx h mov m,a lxi h,jplug2 mov m,a inx h mov m,a inx h mov m,a pop psw plugem: adi '@' sta plug1 sta plug2 inr a sta cplug1 sta cplug2 jmp doit ***** bdos equ 5 cr equ 13 lf equ 10 DISPLAY$FDEV: lda lb$vers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB CR,LF,'FLOPPY DISK ASSIGNMENTS',CR,LF DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB '------------------------',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB ' ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' ; end of DISPLAY$FDEV TO$UPPER: CPI 'z'+1 ; Convert to upper case JP UPPER$ALREADY ; . CPI 'a' ; . JM UPPER$ALREADY ; . ANI 5FH ; . UPPER$ALREADY: RET ; and return GET$BIOS$VERS: LHLD 1 ; Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage LXI B,LB$LEN ; . (length of bios area) DB 0edh,0b0h ; . (LDIR) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage LXI B,LB$XLEN ; . (length of extra table) DB 0edh,0b0h ; . (LDIR) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and return. ; Replicated BIOS to make direct calls easier . . . LB$BIOS$TBL: LB$WBOOT DS 3 ; Warm boot LB$CONST DS 3 ; Console status LB$CONIN DS 3 ; Console input LB$CONOUT DS 3 ; Console output LB$LISTOUT DS 3 ; List output LB$PUNCH DS 3 ; Punch output LB$READER DS 3 ; Reader input LB$HOMDSK DS 3 ; Home disk (move to track 00) LB$SELDSK DS 3 ; Select disk drive LB$SETTRK DS 3 ; Select track number LB$SETSEC DS 3 ; Select sector number LB$SETDMA DS 3 ; Set DMA address LB$DSKREAD DS 3 ; Disk read LB$DSKWRITE DS 3 ; Disk write LB$LISTST DS 3 ; List status LB$SECTRN DS 3 ; Sector translate routine ; AMPRO-specific BIOS calls LB$GETNXT DS 3 ; Get bios ver & next tbl address LB$GETEDSK DS 3 ; Get pointer to E-disk storage LB$IOINIT DS 3 ; Set new I/O parameters LB$SCSIDRV DS 3 ; SCSI direct driver LB$LEN EQU $-LB$WBOOT ; Length of bios table LB$XTBL: ; 'Extra' table definitions ... LB$SWAP$DRV DS 3 ; Swap two logical drives LB$GET$WDP DS 3 ; Set/get win drive parameters LB$PHYTAB DS 3 ; Set/get phytab access LB$GET$LDTE DS 3 ; Get logical device table entry LB$RESERVED DS 3 ; Reserved entry LB$XLEN EQU $-LB$XTBL ; Length of extra table LB$VERS DB 0 ; Bios version number doit: CALL ILPRT ; print following text DB CR,LF,' AMPRO Copy/Format/Verify Utility' DB CR,LF,' Copyright (C) 1984 AMPRO Computers, Inc.' DB CR,LF,' Version ',VER/10+'0','.' DB VER MOD 10+'0','$' ASK1: CALL ILPRT ; print following string DB CR,LF,LF,'COPY, FORMAT or VERIFY? (C, F or V)' DB CR,LF,'Press or ^C to quit. $' ASK1A: CALL CONIN ; get response CPI ESC JZ EXIT ; exit to operation system CPI 3 JZ EXIT ; ctl c ANI UPCASE ; force upper case CPI 'V' JZ SETV ; if verify CPI 'C' JZ SETC ; if copy CPI 'F' JNZ ASK1A ; otherwise, do this again ; set function code and do it SETF: MVI A,1 STA FUNC JMP FORMAT SETV: MVI A,2 STA FUNC JMP VERIFY SETC: MVI A,3 STA FUNC JMP COPY FORMAT: CALL CLRSC CALL ILPRT DB 8,32,CR,LF,LF ; overwrite response and make new line DB 'FORMAT prepares a fresh diskette for data or program storage.',cr,lf,'$' call display$fdev CALL ASK5 ; ask destination JC ASK1 ; restart if bad selection CALL ASK2 JC ASK1 CALL ASK3 FORM0: CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ; restart at end of format VERIFY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'VERIFY checks the reliability of data on a disk.',cr,lf,'$' call display$fdev CALL ASK5 ; ask for destination disk JC ASK1 CALL EXEC ; do it JMP ASK1 COPY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'COPY creates a duplicate of a disk.',cr,lf,'$' call display$fdev CALL ASK4 ; ask for source JC ASK1 CALL ASK5 JC ASK1 CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ASK2: CALL ILPRT ; print following string DB CR,LF,LF,'Formats Available:' db cr,lf,' 1. Single side 48 tpi' db cr,lf,' 2. Double side 48 tpi' db cr,lf,' 3. Single side 96 tpi' db cr,lf,' 4. Double side 96 tpi' db cr,lf,lf,'Choose one (1, 2, 3 or 4). $' ASK2E: CALL CONIN ; get the answer CPI ESC JZ EXIT CPI CTLC JZ EXIT CPI '1' ; less than 1? JC ASK2E ; error return CPI '5' ; more than 4? JNC ASK2E push psw call conout pop psw ANI 0FH ; mask hi order DCR A ; 1 side = 0, two sides = 1 JZ SS48 DCR A JZ DS48 DCR A JZ SS96 DS96: STA TWOSID STA TPI96 MVI A,16 STA SBIAS ORA A RET SS48: STA TWOSID STA TPI96 STA SBIAS ORA A RET DS48: STA TPI96 INR A STA TWOSID MVI A,16 STA SBIAS ORA A RET SS96: STA SBIAS STA TWOSID INR A STA TPI96 ORA A ; reset error flag RET ASK3: LDA TPI96 ORA A MVI A,79 JNZ ASK3X MVI A,39 ASK3X: STA MAXTRK ORA A RET ASK4: CALL ILPRT DB CR,LF,LF,'Source drive? (A - ' plug1: DB 'x) $' ask4e: call conin cpi esc jz exit cpi ctlc jz exit ani upcase cpi 'A' jc ask4E cplug1: equ $+1 cpi 'E' JNC ASK4E STA ASK40 push psw call conout pop psw sui 'A' jplug1: jmp ask40s call lb$get$ldte mov a,m cpi 01h jnz ask4 inx h mov a,m ani 03h ask40s STA SDRIV ; source ask40E: CALL ILPRT DB CR,LF,LF,'Place source disk on drive ' ASK40: DB 'a',CR,LF,'Press to continue, to quit.$' ask40h CALL CONIN CPI CR RZ CPI ESC JZ EXIT CPI CTLC JZ EXIT JMP ASK40h ASK5: CALL ILPRT DB CR,LF,LF,'Destination drive? (A - ' plug2: DB 'x) $' ASK5E: CALL CONIN ; get the answer CPI ESC JZ EXIT CPI CTLC JZ EXIT ANI UPCASE ; force upper case CPI 'A' ; first valid drive JC ASK5e cplug2: equ $+1 CPI 'E' ; first invalid drive JNC ASK5e sta ask60 push psw call conout pop psw sui 'A' jplug2: jmp ask50s call lb$get$ldte mov a,m cpi 1 jnz ask5 inx h mov a,m ani 3 ask50s: STA DDRIV ; save drive designator CALL SETSEL ; disk select bits ORA A RET ASK6: CALL ILPRT ; print the following string DB CR,LF,LF,'Place destination disk on drive ' ask60 db 'x' DB CR,LF,'Press to write, ' DB ' to quit. $' ASK6E: CALL CONIN ; get answer CPI CR RZ CPI ESC JZ EXIT JMP ASK6E EXEC: CALL ILPRT DB CR,LF,LF,'$' LDA FUNC ; function 1=fmt, 2=vfy, 3=cpy CPI 1 JZ FMT CPI 2 JZ VFY ; else fall through to cpy CPY: MVI A,0 STA HEAD MVI A,39 STA MAXTRK LDA DDRIV ; destination CALL SETSEL CALL SETUP LDA SDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES CP0: CALL READID JZ CP1 LXI H,TRIES DCR M JNZ CP0 CALL ILPRT DB CR,LF,LF,'COPY failed. Cannot read source disk.',CR,LF,'$' RET CP1: LDA IDSV+2 ; sector # CPI 17 ; two-sided if no carry MVI A,0 JC CP2 INR A CP2: STA TWOSID ORA A ; reset carry RAL RAL RAL RAL STA SBIAS XRA A ; get a zero STA TRACK CALL SETDSK CPYLP: CALL KEY LDA HEAD ORA A PUSH PSW LDA SDRIV CALL SETSEL POP PSW LDA SELBYT JZ CPL0 ORI SID1 CPL0: OUT CONT ; select destination STA SELBYT LXI H,RDMSG CALL PRINT CALL TMRPRT cp14: MVI A,TRYHARD STA TRIES CP3: CALL READTRK JZ CP4 LXI H,TRIES DCR M JNZ CP3 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Unrecoverable read error on source disk.',CR,LF,'$' call report call ilprt db cr,lf,'Try again? (Y or N) $' cf002z: call conin ani upcase cpi 'N' rz cpi 'Y' jnz cf002z call ilprt db cr,lf,lf,'$' jmp cp14 CP4: LDA HEAD ORA A PUSH PSW LDA DDRIV CALL SETSEL POP PSW LDA SELBYT JZ CPL1 ORI SID1 CPL1: OUT CONT STA SELBYT LXI H,WRMSG CALL PRINT CALL TMRPRT CALL MAKETRK ; format destination MVI A,TRY STA TRIES CP5: CALL WRITRK JZ CP6 LXI H,TRIES DCR M JNZ CP5 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Cannot write destination disk.',CR,LF,'$' JMP REPORT CP6: MVI A,TRY STA TRIES CP7: CALL WRITETRK JZ CP8 LXI H,TRIES DCR M JNZ CP7 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Unrecoverable write error on destination disk.',CR,LF,'$' JMP REPORT CP8: IF RAW LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES CP9: CALL READTRK JZ CP10 LXI H,TRIES DCR M JNZ CP9 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Unrecoverable read error on destination disk.',CR,LF,'$' JMP REPORT CP10: ENDIF ; RAW LDA TWOSID ORA A LDA TRACK JZ CP11 LDA HEAD ORA A LDA TRACK JZ CP12 CP11: LXI H,MAXTRK CMP M JNZ CP12 CALL ILPRT DB CR,' ' DB CR,LF,'COPY complete.',CR,LF,LF,'$' IF RAW RET ENDIF JMP VFY CP12: INR A STA TRACK CALL STEPIN LDA TWOSID ORA A JZ CP13 LDA HEAD CMA ANI 1 STA HEAD JNZ CP13 LXI H,TRACK INR M CP13: LDA SDRIV CALL SETSEL CALL STEPIN LDA TRACK OUT WTRK JMP CPYLP FMT: LDA DDRIV CALL SETSEL CALL SETUP XRA A STA TRACK STA HEAD NEXTRK: CALL KEY LXI H,FRMSG CALL PRINT CALL TMRPRT CALL MAKETRK MVI A,TRY STA TRIES NT3: CALL WRITRK JZ NT2 LXI H,TRIES DCR M JNZ NT3 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT failed.',CR,LF,'$' CALL REPORT RET NT2: IF RAW LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES NT4: CALL READTRK JZ NT5 LXI H,TRIES DCR M JNZ NT4 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT failed. Bad destination disk.',CR,LF,'$' CALL REPORT RET NT5: ENDIF ; RAW LDA TWOSID ORA A LDA TRACK JZ NT0 LDA HEAD ORA A LDA TRACK JZ NT1 NT0: LXI H,MAXTRK CMP M JNZ NT1 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT complete.',CR,LF,LF,'$' IF RAW RET ; finished ENDIF JMP VFY NT1: INR A STA TRACK CALL STEPIN JMP NEXTRK VFY: MVI A,0 STA HEAD LDA DDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES V1: CALL READID JZ V0 LXI H,TRIES DCR M JNZ V1 CALL ILPRT DB CR,LF,'VERIFY failed. Cannot read source disk.',cr,lf,'$' RET V0: LDA IDSV+2 CPI 17 MVI A,0 JC VF0 INR A VF0: STA TWOSID ORA A RAL RAL RAL RAL STA SBIAS XRA A STA TRACK ; start with track 0 CALL SETDSK VLOOP: CALL KEY LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES VL1: CALL READTRK JZ VL0 LXI H,TRIES DCR M JNZ VL1 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY failed. Unrecoverable read error.',CR,LF,'$' CALL REPORT RET VL0: LDA TWOSID ORA A LDA TRACK JZ VF1 LDA HEAD ORA A LDA TRACK JZ VF2 VF1: LXI H,MAXTRK CMP M JNZ VF2 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY complete.',CR,LF,'$' RET VF2: INR A STA TRACK CALL STEPIN JMP VLOOP SETDSK: LDA IDSV+3 CPI 3 JZ SDSK MVI A,39 STA MAXTRK XRA A STA SKEW RET SDSK: MVI A,79 STA MAXTRK MVI A,1 STA SKEW RET STEPIN: LDA TWOSID ORA A JZ STI ; single sided LDA HEAD ORA A MVI A,1 JZ STI0 MVI A,0 STI0: STA HEAD JZ STI1 STI: LDA SELBYT ANI SID0 ; mask side bit off OUT CONT ; select side 0 STA SELBYT CALL WAIT MVI A,STEPI CALL OUTCMD STILP: IN STAT RAR JC STILP RET STI1: LDA SELBYT ORI SID1 OUT CONT ; select side 1 STA SELBYT LXI H,TRACK DCR M JMP WAIT WRITRK: IN STAT RAR JC WRITRK LXI H,TKBUF MVI A,WRTRK ; write track command CALL OUTCMD CALL WR MOV A,B STA STATUS ANI ERRIII RET WR: IN STAT ; get fdc status MOV B,A ; save status RAR ; check busy RNC ; end of command, return to caller RAR ; check for drq JNC WR ; if not MOV A,M ; get a byte from buffer OUT WDAT ; to fdc INX H ; bump hl JMP WR ; again MAKETRK: LXI H,TKBUF ; create track image in memory MVI B,60 MVI A,4EH MTLP: MOV M,A ; write gap4a INX H DCR B JNZ MTLP SHLD DMAADR ; sector 1 starts here LDA HEAD STA SIDE LDA TPI96 ORA A LXI H,128*256+2 JZ MTL1 LXI H,3 MTL1: CALL CHGFMT CALL GETSKW ; point hl to skew table LOOP: MOV C,M INX H INR C JZ ENDTRK ; if c was 0ffh DCR C LDA SBIAS ADD C STA SECTOR PUSH H ; save skew pointer on stack CALL MAKTRK POP H JMP LOOP ENDTRK: LHLD DMAADR LXI B,1000 ETLP: MVI M,4EH INX H DCX B MOV A,B ORA C JNZ ETLP SHLD DMAADR RET CHGFMT: MOV A,L STA SIZE MOV A,H MVI B,4 LXI H,DAT0 LXI D,2 CHG0: MOV M,A DAD D DCR B JNZ CHG0 RET MAKTRK: LHLD DMAADR ; track image PUSH H ; save it LXI H,TABLE ; track format table MAKT1: MOV D,M ; get count INX H ; bump pointer MOV E,M ; get data INX H ; bump pointer MOV A,E ; check for end of table (0ffh) INR A ; 0ffh + 1 = 0 JZ MAKT2 ; if end of table XTHL ; point to track buffer CALL LOAD ; fill track buffer XTHL ; point to format table JMP MAKT1 ; again MAKT2: POP H ; get track buffer address from stack SHLD DMAADR ; save pointer to track buffer RET ; to caller WRITETRK: ; write current track from read buffer LXI H,RDBUF SHLD DMAADR CALL GETSKW ; point hl to skew table WTLOOP: MOV C,M INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C OUT WSEC ; to fdc PUSH H ; save skew pointer CALL WRITESEC POP H JMP WTLOOP WRITESEC: ; write a sector from dma buffer IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR MVI A,WRSEC ; write sector command CALL OUTCMD ; to fdc CALL WR ; write the data SHLD DMAADR ; save pointer MOV A,B ; get status STA STATUS ANI ERRII RZ ; return to this caller POP H ; adjust stack from writetrk POP H RET ; return to previous caller READTRK: ; read current track into read buffer LXI H,RDBUF SHLD DMAADR CALL GETSKW ; piont hl to skew table RTLOOP: MOV C,M ; get sector number from table INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C STA SECTOR OUT WSEC ; to fdc PUSH H ; save skew pointer CALL READSEC ; read the sector RT0: POP H JMP RTLOOP READSEC: IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR ; pointer to read buffer MVI A,RDSEC ; read sector command CALL OUTCMD ; to fdc CALL RD ; read the data SHLD DMAADR ; save pointer MOV A,B STA STATUS ANI ERRII RZ POP H ; adjust stack from readtrk POP H RET ; to previous caller RD: IN STAT ; get fdc status byte MOV B,A ; save status RAR ; rotate busy bit to carry RNC ; end of command, return to caller RAR ; rotate data request to carry JNC RD ; wait for data request RD0: IN RDAT ; get data from fdc MOV M,A ; put it into buffer INX H ; bump hl JMP RD ; again READID: IN STAT IN RDAT LXI H,IDSV MVI A,RDID CALL OUTCMD CALL RD MOV A,B ; get status STA STATUS ANI ERRIII RET WAIT: LXI B,50 * MSEC WT0: DCX B MOV A,B ORA C JNZ WT0 RET WAIT10: LXI B,10 * MSEC ; wait 10 ms JMP WT0 ; wt0 returns to caller LOAD: MOV M,E ; (e) to track buffer INX H ; increment pointer DCR D ; decrement count JNZ LOAD ; again RET CLRSC: MVI D,24 ; print 24 line feed chars to clear screen CLS: MVI A,LF CALL CONOUT ; out to console CALL WAIT10 ; wait 10 ms after line feed DCR D ; decrement count JNZ CLS ; again RET PRINT: MOV A,M ; hl points to text string INX H ; bump hl CPI '$' ; check for terminator RZ ; return to caller PUSH PSW ; save for test CALL CONOUT ; send byte to console POP PSW ; get the character CPI LF ; if line feed.. CZ WAIT10 JMP PRINT ; again ILPRT: XTHL ; return address to hl, point to text CALL PRINT XTHL ; return address follows text RET CONOUT: PUSH B ; save PUSH D ; the PUSH H ; registers MOV E,A ; text to be printed mvi c,6 call bdos POP H ; restore POP D ; the POP B ; registers RET BIOS: LHLD 1 MOV L,A PCHL CONIN: CONINB: PUSH B PUSH D ; save PUSH H ; registers mvi e,0ffh MVI C,6 ; console input function CALL 5 ; bdos POP H ; restore POP D ; registers POP B RET ; The current setup routine does a restore with the 1772 ; motor on flag enabled. It exits as soon as the BUSY ; status bit goes away, or after a 4 second timeout. SETUP: LDA SELBYT ; get selected drive OUT CONT ; select the drive MVI A,REST ; restore command CALL OUTCMD ; output the command LXI H,4000 ; 4000 ms timeout setup DEL0: MVI C,0 DEL1: DCR C JNZ DEL1 IN STAT RAR JNC READY ; go on if 1772 done DCX H MOV A,H ORA L JNZ DEL1 MVI A,0D0H ; timed out -- force interrupt, CALL OUTCMD ; then report failure JMP FAILED ; The current ready function checks to see if a diskette ; is inserted in a drive. A read address command with ; the motor on flag enabled is used. If the command ; hangs up, the 1772 is not receiving index pulses, ; indicating the lack of a spinning diskette. READY: MVI A,0C0H ; read address command CALL OUTCMD LXI H,4000 ; 4000 mS timeout setup MVI C,0 RDY1: DCR C JNZ RDY1 IN STAT RAR RNC ; finished, if 1772 done DCX H MOV A,H ORA L JNZ RDY1 ; loop till timeout MVI A,0D0H ; timeout -- force interrupt, CALL OUTCMD ; then report failure FAILED: LDA SELBYT ANI 0FH MVI C,0 FLD1: INR C RAR JNC FLD1 MOV A,C adi 30H ; add ascii bias STA DRI CALL ILPRT ; print following string DB CR,LF,'Drive ' DRI: DB 'A Not Ready, Insert disk, close door, and try again.',CR,LF,'$' POP B ; adjust stack RET GETSKW: ; point hl to skew table MVI H,0 LDA SKEW ; skew factor -1 MOV L,A ; hl holds skew factor -1 DAD H ; *2 XCHG LXI H,SK1 ; first skew table address DAD D ; hl points to correct table pointer MOV E,M ; get lo order INX H MOV D,M ; get hi order XCHG ; hl points to skew table RET OUTCMD: OUT CMND MVI A,10 OC0: DCR A JNZ OC0 ; wait 35 us. for fdc to set-up RET KEY: push b push d MVI C,6 mvi e,0ffh CALL 5 pop d pop b ORA A RZ CPI CTLC JZ EXIT PUSH PSW CALL ILPRT DB CR,' ',CR,'$' ; clear the line POP PSW CPI ESC RNZ POP H RET EXIT: JMP 0 ; warm boot TMRPRT: LDA TRACK LXI D,TKMSG0 CALL BINASC LDA HEAD LXI D,SDMSG0 CALL BINASC LXI H,TKMSG JMP PRINT ; print returns to caller REPORT: LXI D,DR ; point to error message LDA SELBYT ANI 0FH ; mask upper nybble MVI C,0 ; clear counter R1: INR C ; bump it RAR ; rotate selbit into carry JNC R1 ; again? MOV A,C ADI 30H ; add ascii bias STAX D ; store it in message STA WPRMSG0 LDA STATUS ANI WPR ; is disk protected? JZ R2 LXI H,WPRMSG ; write protected message CALL PRINT POP H ; adjust the stack R1A: CALL CONIN ; get response CPI CTLC JZ EXIT CPI CR ; yes? JZ EXEC ; if so CPI ESC JNZ R1A RET ; get out of here R2: LXI D,TK ; in error message LDA TRACK CALL BINASC LXI D,HD LDA SIDE ORA A ; set flags JZ RPRT1 MVI A,1 RPRT1: CALL BINASC LXI D,SC LDA SECTOR CALL BINASC LXI D,ST LDA STATUS ANI RNF JNZ SRNF LXI H,CRCER CALL MOV3 JMP RPRT2 SDNR: LXI H,DNRER CALL MOV3 JMP RPRT2 SRNF: LXI H,RNFER CALL MOV3 RPRT2: LXI H,ERRMSG RPRT3: JMP PRINT ; print returns to caller MOV3: MVI B,3 MOVL: MOV A,M STAX D INX H INX D DCR B JNZ MOVL RET BINASC: PUSH PSW ; save value PUSH D ; save string ptr MVI A,'0' ; ascii zero STAX D LXI B,2 ; b=0, c=2 XRA A ; a=0 B0: INX D ; bump ptr STAX D ; zero to str DCR C JNZ B0 ; again please POP D ; restore de LXI H,TBL ; conversion table B1: MVI C,0 ; clear count MOV A,M ; table value INR A JZ BEND ; end of table, conv done POP PSW ; restore value B3: SUB M ; begin division JC B2 INR C ; keep count JMP B3 B2: ADD M ; restore acc PUSH PSW ; save it MOV A,C ; count CPI 0 JNZ STSTR ; set ascii value in string MOV A,B CPI 0 ; 1st time? JNZ STSTR B4: INX H ; bump tbl ptr JMP B1 ; next STSTR: MVI B,1 ; flag 1st time MOV A,C ; count to c ADI 30H ; ascii bias STAX D ; write it into string INX D ; bump str ptr JMP B4 BEND: POP PSW ; adjust stack RET ; return to caller TBL: DB 100 DB 10 DB 1 DB 255 ; end of table SETSEL: inr a MOV C,A XRA A STC STSL: RAL DCR C JNZ STSL ORI ROMOFF STA SELBYT RET ERRMSG: DB CR,LF,' Error: Drive ' DR: DB 0,': Track ' TK: DB 0,0,0,' Head ' HD: DB 0,0,0,' Sector ' SC: DB 0,0,0,' Status ' ST: DB 0,0,0,CR,LF,'$' TKMSG: DB 'Track ' TKMSG0: DB 0,0,0,' Side ' SDMSG0: DB 0,0,0,CR,'$' WRMSG: DB 'Writing $' VFMSG: DB 'Verify $' RDMSG: DB 'Reading $' FRMSG: DB 'Format $' CPMSG: DB 'Copy $' WPRMSG: DB CR,' ' DB CR,LF,'Remove write protect tab from destination diskette.' DB CR,LF,'Place diskette in drive ' WPRMSG0:DB 'A, then press to write or to quit. $' DNRER: DB 'DNR' RNFER: DB 'RNF' CRCER: DB 'CRC' TABLE: DB 12,0 ; defines sector format (#bytes,data) DB 3,0F5H ; write 0a1h DB 1,0FEH ; id address mark DB 1 TRACK: DB 0 DB 1 SIDE: DB 0 DB 1 SECTOR: DB 1 DB 1 SIZE: DB 2 ; always 512 bytes DB 1,0F7H ; write crc (2 bytes) GAP2: DB 22,4EH ; gap 2 length, data DB 12,0 ; preamble DB 3,0F5H ; write 0a1h DB 1,0FBH ; data address mark DAT0: DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 1,0F7H ; write crc (2 bytes) GAP3: DB 24,4EH ; gap 3 length, data DW -1 ; end of table (0ffffh) SK1: DW SKW1 ; point to skw1 SK2: DW SKW2 ; 2 SKW1: DB 1,6,2,7,3,8,4,9,5,10,255 ; skew factor 2 SKW2: DB 1,4,2,5,3,255 ; skew 2 (Osborne) FUNC: DS 1 ; function 1=format, 2=verify, 3=copy MAXTRK: DS 1 ; maximum track TWOSID: DS 1 HEAD: DB 0 SDRIV: DS 1 ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96: SKEW: DB 0 ; default skew factor 2 DMAADR: DS 2 STATUS: DS 1 TRIES: DS 1 DS 64 ; space for 32 level stack STACK: DS 2 ; space for ccp stack pointer IDSV: DS 6 ; id save area RDBUF: DS 10 * 512 ; read buffer TKBUF: END START ; end of program