|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 15360 (0x3c00) Types: TextFile Names: »FCOPY.ASM«
└─⟦1f6b46325⟧ Bits:30004393 CP/M-80 rel. 1 Utilities source disk └─ ⟦this⟧ »FCOPY.ASM«
TITLE 'MINI FLOPPY DISKETTE COPY UTILITY' PAGE 43 ;****************************************************************************** ; CHRISTIAN ROVSING A/S MINI FLOPPY DISKETTE COPY PROGRAM ;****************************************************************************** ; ; ; MINI FLOPPY DISKETTE COPY PROGRAM FOR DUPLICATING A CHRISTIAN ; ROVSING A/S FORMATTED MINI FLOPPY DISKETTE USING 96 TPI ; 5 1/4 INCH MINIFLOPPY DISK DRIVES. THIS COPY PROGRAM WILL ; ACCESS TWO SEPERATE DRIVES TO PERFORM THE COPY OPERATION. ; ; THIS PROGRAM CONFIGURATION WILL SUPPORT TWO MINI FLOPPY DRIVES. ; MINI FLOPPY FORMAT IS AS FOLLOWS: ; ; 77 TRACKS ; 16 RECORDS PER TRACK ; TWO HEADS/SIDES ; 256 BYTE RECORDS ; CP/M MAPS LOGICAL DRIVE E: TO THE MINI FLOPPY WITH ; ODD TRACKS ON HEAD 0 AND EVEN TRACKS ON HEAD 1 ; PHYSICAL SECTORS SKEWED FOR LOGICAL ACCESS WITH ORDER ; OF: 1,2,5,6,9,10,13,14,3,4,7,8,11,12,15,16 ; PAGE ;*************************************************************************** ; ; ;GENERAL EQUATES ; CR EQU 0DH ;CARRIAGE RETURN CODE LF EQU 0AH ;LINE FEED CODE BS EQU 08H ;BACK SPACE CODE BEL EQU 07H ;BELL RING CODE ESC EQU 01BH ;ESCAPE CODE TRUE EQU 0FFFFH ;TRUE CODE FALSE EQU NOT TRUE ;FALSE CODE ; ; ; ;DEFINE MEMORY BASED I/O MODULE ENTRY POINTS ; MODBASE EQU 0F800H ;SET JUMP TABLE EQUIVALENT ADDRESSES ; INITSER EQU MODBASE+00 ;INITIALIZE SERIAL I/O PORTS ; ;(NO PARAMETERS) SETCBAUD EQU MODBASE+03 ;SET CONSOLE I/O BAUD RATE FACTOR ; ;(HL) = COUNTER TIMER PARAMETER VALUE SETLBAUD EQU MODBASE+06 ;SET LINE PRINTER I/O BAUD RATE FACTOR ; ;(HL) = COUNTER TIMER VALUE SETLRMSK EQU MODBASE+09 ;SET LINE PRINTER SIO RECEIVER MASK VALUE ;(A) = LINE PRINTER SIO MASK BYTE SETLRVAL EQU MODBASE+012 ;SET LINE PRINTER SIO RECEIVER POLL VALUE ; ;(A) = LINE PRINTER POLL VALUE SETLTMSK EQU MODBASE+015 ;SET LINE PRINTER SIO TRANSMITTER MASK VALUE ; ;(A) = LINE PRINTER SIO MASK BYTE SETLTVAL EQU MODBASE+018 ;SET LINE PRINTER SIO TRANSMITTER POLL VALUE ; ;(A) = LINE PRINTER SIO POLL VALUE BYTE CONSTAT EQU MODBASE+021 ;GET CONSOLE STATUS ; ;RETURN (A)=00 FOR NOT READY INPUT ; ; (A)=FF FOR READY INPUT CONIN EQU MODBASE+024 ;GO GET CONSOLE INPUT CHARACTER ; ;(A)=INPUT CONSOLE CHARACTER CONOUT EQU MODBASE+027 ;PUT OUT CONSOLE CHAR ; ;(C)=CHARACTER TO OUTPUT LPTSTAT EQU MODBASE+030 ;GET LINE PRINTER STATUS ; ;RETURN (A)=00 FOR NOT NEXT OUTPUT ; ; (A)=FF FOR READY OUTPUT LPTIN EQU MODBASE+033 ;GO GET LINE PRINTER INPUT CHARACTER ; ;(A)=INPUT LPT SERIAL PORT CHARACTER LPTOUT EQU MODBASE+036 ;PUT OUT LINE PRINTER CHARACTER ; ;(C)=LPT SERIAL OUTPUT CHARACTER HUNIT EQU MODBASE+039 ;SELECT HARD DISK UNIT NUMBER ; ;(C)=UNIT NUMBER ON MSC 9205 CONTROLLER HPLAT EQU MODBASE+042 ;SELECT HARD DISK PLATTER (HEAD) NUMBER ; ;(C)=HEAD SELECT NUMBER HSURF EQU MODBASE+045 ;SELECT HARD DISK SURFACE(HEAD 2^2) NUMBER ; ;(C)=MSB OF HEAD NUMBER HCYL EQU MODBASE+048 ;SELECT HARD DISK CYLINDER NUMBER ; ;(BC)=CYLINDER NUMBER HREC EQU MODBASE+051 ;SELECT HARD DISK RECORD NUMBER ; ;(C)=RECORD NUMBER HCNT EQU MODBASE+054 ;SELECT HARD DISK SECTOR COUNT ; ;(C)=RECORD COUNT HBADDR EQU MODBASE+057 ;SET 9205 CONTROLLER DMA ADDRESS ; ;(BC)=16 BIT DATA BUFFER ADDRESS HREST EQU MODBASE+060 ;RESTORE SELECTED HARD DISK UNIT ; ;(A) RETURNS ERROR CODE HREAD EQU MODBASE+063 ;READ SELECTED SECTOR(S) ; ;(A) RETURNS ERROR CODE HVERF EQU MODBASE+066 ;VERIFY SELECTED SECTOR(S) ; ;(A) RETURNS ERROR CODE HWRIT EQU MODBASE+069 ;WRITE SELECTED SECTOR(S); ; ;(A) RETURNS ERROR CODE HEXEC EQU MODBASE+072 ;EXECUTE SPECIAL COMMAND OF MSC 9205 ; ;(C) ENTRY WITH MSC 9205 COMMAND ; ;(A) RETURNS ERROR CODE HRESET EQU MODBASE+075 ;RESET HARD DISK CONTROLLER MSC 9205 ; ;NO PARAMETERS MUNIT EQU MODBASE+078 ;SELECT MINI FLOPPY UNIT NUMBER ; ;(C)=FLOPPY PHYSICAL UNIT NUMBER MSURF EQU MODBASE+081 ;SELECT MINI FLOPPY SURFACE(HEAD) NUMBER ; ;(C)=FLOPPY SIDE NUMBER MCYL EQU MODBASE+084 ;SELECT MINI FLOPPY CYLINDER(TRACK) NUMBER ; ;(C)=FLOPPY TRACK NUMBER MREC EQU MODBASE+087 ;SELECT MINI FLOPPY RECORD NUMBER ; ;(C)=FLOPPY SECTOR NUMBER MCNT EQU MODBASE+090 ;SELECT MINI FLOPPY PHYSICAL SECTOR COUNT ; ;(C)=MINI FLOPPY SECTOR COUNT MSIZE EQU MODBASE+093 ;SELECT FLOPPY SECTOR SIZE (00)=256 BYTES ; ;(C)=MINI FLOPPY TRACK NUMBER MBADDR EQU MODBASE+096 ;SET FLOPPY DISK DATA BUFFER ADDRESS ; ;(BC)=FLOPPY BUFFER ADDRESS MREST EQU MODBASE+099 ;RESTORE SELECTED MINI FLOPPY UNIT ; ;(A)=RETURNS ERROR STATUS MVERF EQU MODBASE+102 ;VERIFY (READ) SELECTED SECTOR ; ;(A)=RETURNS STATUS MWRIT EQU MODBASE+105 ;WRITE SELECTED SECTOR ; ;(A)=RETURNED STATUS MREAD EQU MODBASE+108 ;READ SELECTED SECTOR ; ;(A)=RETURNED STATUS MWTRK EQU MODBASE+111 ;WRITE SELECTED FLOPPY TRACK ; ;(A)=RETURNED STATUS MMODE EQU MODBASE+114 ;SET FLOPPY OPERATION MODE ; ;(C)=STANDARD MODE DEFINITION MINST EQU MODBASE+117 ;FETCH CURRENT INSTRUCTION CODE ; ;(A)=RETURNED INSTRUCTION PATTERN MMOFF EQU MODBASE+120 ;CHECK MINI FLOPPY MOTOR ON COUNT ; ;OUT TIMER PAGE ; ; UNIT/MODE REGISTER FOR DISK DRIVES SELECT ; ; BIT 7 - COMPENSATION "1" ENABLES FLOPPY WRITE PRECOMPENSATION ; BIT 6 - DRIVE TYPE "1" SELECTS CLOCKING FOR A 5 1/4 DRIVE ; "0" SELECTS FOR AN 8 INCH UNIT ; BIT 5 - DENSITY "1" SETS FOR MFM DOUBLE DENSITY ; "0" SELECTS FM SINGLE DENSITY COMPEN EQU 080H ;WRITE COMPENSATION ENABLE MINIEN EQU 040H ;MINI DRIVE ENABLE DENSEL EQU 020H ;BIT MASK FOR DENSITY SELECT ; FSPT EQU 016 ;NUMBER OF MINI FLOPPY 256 BYTE ;SECTORS PER TRACK FSECSIZ EQU 256 ;NUMBER OF BYTES IN A MINI FLOPPY SECTOR FTPS EQU 77 ;NUMBER OF FLOPPY TRACKS PER SIDE ; ;****************************************************************************** ; ;SET START OF PROGRAM CP/M TRANSIENT PROGRAM AREA ; ORG 0100H ; DI ;DON'T ALLOW INTERRUPTS HERE JMP START ; ; ; ;COMPARE DOUBLE REGISTER PAIRS (DE) TO (HL) AND RETURN ;FLAGS SIMILAR TO STANDARD CMP B INSTRUCTION. IE (A) CORRESPONDS ;TO (DE) AND (B) CORRESPONDS TO (HL). ; CDEHL: MOV A,D ;CHECK HIGH BYTES FIRST CMP H RNZ ;RETURN IF HIGH BYTES SET FLAGS MOV A,E CMP L ;CHECK LOW BYTES RET ; PAGE ;****************************************************************************** ; START: ;BEGINNING OF PROGRAM LXI SP,STCKK ;MAKE OURSELVES A STACK ; SIGNON: ;SEND HELLO TO CRT CALL CRLF CALL CRLF LXI D,STRMSG CALL CRTMS JMP MONITOR ;GO TO MONITOR ROUTINE ; ; ;FORMAT PROGRAM MESSAGES ; STRMSG: DB ESC,'Æ7;2m' DB 'CHRISTIAN ROVSING A/S - CR8 DISKETTE COPY PROGRAM',CR,LF DB 'FOR TANDON TM-100 96 TPI 5 1/4 MINI FLOPPY DRIVES',CR,LF DB ESC,'Æ',6DH DB CR,LF,CR,LF DB ' INSERT SOURCE DISKETTE IN DRIVE A:',CR,LF DB ' DESTINATION DISKETTE IN DRIVE B:',CR,LF DB CR,LF DB ' TYPE "Y" WHEN READY TO COPY (Y) ','#' ; PAGE ;****************************************************************************** ; ; MONITOR: CALL CECHO ;GET OPERATOR ENTRY CHARACTER ANI 05FH ;CONVERT TO UPPER CASE CPI 'Y' ;CHECK IF HE WANTS TO START JNZ ENDCHK ; ; ;HERE IF TO COPY A DISKETTE IN A: TO A DISKETTE IN B: ; LXI D,GOMS3 ;PRINT READY MESSAGE FOR FLOPPY CALL CRTMS CALL CECHO ;GET OPERATOR RESPONSE ANI 05FH ;UPPER CASE CPI 'Y' JNZ ENDCHK ;END PROCESS IF NOT READY ; CALL CRLF CALL FLOPCPY ;GO COPY THE TWO DISKETTES ; CPYDONE: LXI D,COPDMS ;PRINT FORMAT COMPLETE MESSAGE CALL CRTMS JMP ENDCHK ; ; GOMS3: DB CR,LF,'READY TO COPY DISKETTE IN A: TO DISKETTE IN B: ' DB '(Y/N) ','#' COPDMS: DB CR,LF,'DISKETTE COPY COMPLETE',CR,LF,'#' ; PAGE ;****************************************************************************** ; ; OPERATION DONE OR ERROR EXIT POINT ; ; ENDCHK: LXI D,DONMSG ;PRINT DONE MESSAGE CALL CRTMS CALL CECHO ;GET OPERATOR ANSWER ANI 05FH ;CONVERT RESPONSE TO UPPER CASE CPI 'Y' ;SEE IF HE WANTS TO GO AGAIN JZ SIGNON ;GO START ALL OVER AGAIN ; CALL CRLF JMP 0000H ;GO GO TO WARM BOOT ; ; DONMSG: DB CR,LF,'DO YOU WANT TO COPY ANOTHER DISK? (Y/N) ','#' ; PAGE ;****************************************************************************** ; ; GENERAL PURPOSE I/O SUBROUTINES ; ; CRLF: ;ROUTINE TO DO CONSOL CR AND LF MVI C,CR CALL CONOUT MVI C,LF CALL CONOUT RET ; ; ; CECHO: ;ROUTINE TO GET AND ECHO A CHARACTER CALL CONIN MOV C,A PUSH PSW CALL CONOUT POP PSW ANI 07FH ;GET RID OF PARITY RET ; ; ; NBL: ;ROUTINE TO CONVERT A BYTE TO A HEX NIBBLE SUI '0' RC ADI 0E9H RC ADI 06H JP NIO ADI 07H RC NIO: ADI 10 ORA A RET ; PAGE ; BYTEC: ;ROUTINE TO GET A HEX BYTE IN A CALL CECHO ;GET CHARACTER BYTC1: CALL NBL ;CONVERT TO HEX JC ERRR ;TO ERROR ROUTINE RLC RLC RLC RLC PUSH PSW ;SAVE 1ST ENTRY CALL CECHO ;GET 2ND CHARACTER CALL NBL ;CONVERT IT TO HEX JC ERRR POP B ;RECOVER 1ST RESULT ORA B ;COMBINE WITH 2ND RET ; ; ; CONI: ;ROUTINE TO GET A 1 BYTE PARAMETER PUSH B CALL BYTEC POP B RET ; PAGE ; PARAM: ;ROUTINE TO INPUT 4 HEX CHARACTERS LXI H,0 PARM1: CALL CECHO ;GET INPUT CPI 0DH ;LOOK FOR RETURN RZ DAD H DAD H DAD H DAD H JC ERRR CALL NBL ;CONVERT ENTRY TO HEX JC ERRR ORA L MOV L,A JMP PARM1 ;GO FOR NEXT CHARACTER ; ; ; HLCO1: ;ROUTINE TO PRINT CONTENTS OF (HL) MOV A,H CALL BYTEO MOV A,L CALL BYTEO RET ; PAGE ; BYTEO: ;ROUTINE TO OUTPUT A HEX BYTE TO THE CONSOLE PUSH PSW CALL BYTO1 MOV C,A CALL CONOUT POP PSW CALL BYTO2 MOV C,A CALL CONOUT RET ; BYTO1: RRC RRC RRC RRC BYTO2: ANI 0FH CPI 0AH JM BYTO3 ADI 07H BYTO3: ADI 030H RET ; ; ;ERROR ON ENTRY OF OPERATOR PARAMETERS ; ERRR: MVI C,'?' ;OUTPUT UNKNOWN PARAMETER CALL CONOUT CALL CRLF JMP ENDCHK ;GO TO OPERATOR END CHECK SEQUENCE ; PAGE ;****************************************************************************** ; ; ;CRTMS - ROUTINE TO DISPLAY A MESSAGE ON THE CRT. REGISTERS D AND E ; CONTAIN THE MESSAGE POINTER. END OF MESSAGE IS INDICATED BY ; A "#" CHARACTER. ; ; CRTMS: ;ROUTINE PRINTS MESSAGE ON CRT LDAX D CPI '#' ;END MESSAGE MARKER RZ ;YES - RETURN MOV C,A CALL CONOUT INX D JMP CRTMS ; PAGE ;****************************************************************************** ; ; ROUTINE TO COPY ALL TRACKS OF THE MINI FLOPPY DISKETTE ; IN DRIVE UNIT 0 (A:) TO THE CORRESPONDING TRACKS ON THE ; DISKETTE IN DRIVE UNIT 1 (B:). TRACKS ARE READ TWO AT A ; TIME INTO A LARGE BUFFER AT THE END OF THIS PROGRAM. ; THE SAME TRACKS ARE THEN WRITTEN FROM THE BUFFER. ONCE ; A TRACK IS WRITTEN IT A REREAD AS A MEANS OF VERIFYING ; THE COPY. THE DATA IS NOT FULLY COMPARED. ONLY A CRC ; CHECK. CRC'S ARE REALLY GOOD ANYWAY. ; FLOPCPY: MVI C,00H ;RESTORE UNIT 0 MOV A,C STA FUNIT ;SAVE FOR ERROR REPORTING CALL MUNIT CALL MREST ORA A JNZ REPERR ;ERROR REPORT MAY BE NECESSARY ; MVI C,01H ;RESTORE UNIT 1 MOV A,C STA FUNIT ;SAVE FOR ERROR REPORTING CALL MUNIT CALL MREST ORA A JNZ REPERR ; ; ;HERE IS WHERE THE COPY WILL REALLY START ; XRA A ;START LOOP COUNT AT 0 STA LOOPCNT ; PAGE ; COPYLOOP: LXI D,TRKMSG ;PRINT TRACK NUMBER REPORT CALL CRTMS LDA LOOPCNT ORA A RAL PUSH PSW ;SAVE TRACK # CALL BYTEO ;PRINT FIRST TRACK NUMBER LXI D,ANDMSG ;PRINT AND CALL CRTMS POP PSW INR A CALL BYTEO ;PRINT SECOND TRACK NUMBER ; ; ;READ IN TWO TRACKS TO THE BUFFER FROM DRIVE A: ; MVI C,00H ;READ UNIT 0 MOV A,C STA FUNIT ;SAVE FOR ERROR REPORTING CALL MUNIT LDA LOOPCNT ;SET TRACK NUMBER MOV C,A CALL MCYL MVI C,01H ;SET START SECTOR NUMBER CALL MREC MVI C,00H ;SET SECTOR SIZE CODE CALL MSIZE MVI C,FSPT ;SET FLOPPY NUMBER OF SECTORS TO DO CALL MCNT LXI B,DATBF1 ;POINT TO FIRST TRACK BUFFER CALL MBADDR MVI C,00H ;READ SIDE ZERO FIRST CALL MSURF CALL MREAD ;GO READ TRACK INTO BUFFER ORA A JNZ REPERR ;GO REPORT ERROR IF SO LXI B,DATBF2 ;POINT TO SECOND TRACK BUFFER CALL MBADDR MVI C,01H ;READ SIDE ONE NEXT CALL MSURF CALL MREAD ;GO READ SECOND TRACK IN ORA A JNZ REPERR ;GO REPORT ERROR IF ONE ; ; ;WRITE THE BUFFERS TO THE TWO TRACKS OF DRIVE B: ; MVI C,01H ;WRITE UNIT 1 MOV A,C STA FUNIT ;SAVE FOR ERROR REPORTING CALL MUNIT LDA LOOPCNT ;SET TRACK NUMBER MOV C,A CALL MCYL MVI C,01H ;SET START SECTOR NUMBER CALL MREC MVI C,00H ;SET SECTOR SIZE CODE CALL MSIZE MVI C,FSPT ;SET FLOPPY NUMBER OF SECTORS TO DO CALL MCNT LXI B,DATBF1 ;POINT TO FIRST TRACK BUFFER CALL MBADDR MVI C,00H ;WRITE SIDE ZERO FIRST CALL MSURF CALL MWRIT ;GO READ TRACK INTO BUFFER ORA A JNZ REPERR ;GO REPORT ERROR IF SO LXI B,DATBF2 ;POINT TO SECOND TRACK BUFFER CALL MBADDR MVI C,01H ;WRITE SIDE ONE NEXT CALL MSURF CALL MWRIT ;GO READ SECOND TRACK IN ORA A JNZ REPERR ;GO REPORT ERROR IF ONE ; PAGE ; ;NOW READ DATA JUST WRITTEN TO VERIFY THE CRC'S ;OBVIOUSLY THIS WILL BE ON UNIT 01 (B:) ; MVI C,01H ;READ UNIT 1 MOV A,C STA FUNIT ;SAVE FOR ERROR REPORTING CALL MUNIT LDA LOOPCNT ;SET TRACK NUMBER MOV C,A CALL MCYL MVI C,01H ;SET START SECTOR NUMBER CALL MREC MVI C,00H ;SET SECTOR SIZE CODE CALL MSIZE MVI C,FSPT ;SET FLOPPY NUMBER OF SECTORS TO DO CALL MCNT LXI B,DATBF1 ;POINT TO FIRST TRACK BUFFER CALL MBADDR MVI C,00H ;READ SIDE ZERO FIRST CALL MSURF CALL MREAD ;GO READ TRACK INTO BUFFER ORA A JNZ REPERR ;GO REPORT ERROR IF SO LXI B,DATBF2 ;POINT TO SECOND TRACK BUFFER CALL MBADDR MVI C,01H ;READ SIDE ONE NEXT CALL MSURF CALL MREAD ;GO READ SECOND TRACK IN ORA A JNZ REPERR ;GO REPORT ERROR IF ONE ; LDA LOOPCNT ;CHECK IF DONE WITH LOOP YET INR A STA LOOPCNT CPI FTPS ;DONE WITH ALL TRACKS? JNZ COPYLOOP ;..NOTE FIRST TRACK WAS #0 RET ; PAGE ; ;MINI FLOPPY COPY TRACK REPORT MESSAGE ; TRKMSG: DB CR,'TRACK ','#' ANDMSG: DB ' AND ','#' ; ; ;**************************************************************************** ; ; ;MINI FLOPPY ERROR REPORTING SUBROUTINE ; REPERR: PUSH PSW ;SAVE THE ERROR CODE LXI D,ERRMSG ;PRINT ERROR MESSAGE CALL CRTMS POP PSW CALL BYTEO ;OUTPUT ERROR CODE LXI D,ERRMS1 ;PRINT REST OF MESSAGE CALL CRTMS LDA FUNIT ;PRINT DRIVE NUMBER WITH PROBLEM ADI 'A' MOV C,A CALL CONOUT LXI D,ERRMS2 ;FINISH THE COMPLETE PRINTING CALL CRTMS JMP ENDCHK ; ; ERRMSG: DB CR,LF,LF,BEL,BEL,' *** MINI FLOPPY DISK I/O ERROR - CODE(','#' ; ERRMS1: DB ') DRIVE ','#' ERRMS2: DB ': ***',CR,LF,'#' ; PAGE ; ;**************************************************************************** ; ; MINI FLOPPY COPY DATA STORAGE AREA FOR PARAMETERS ; ; ; FUNIT: DS 1 ;STORAGE FOR SELECTED MINI UNIT NUMBER ; LOOPCNT: DS 1 ;PLACE TO KEEP TRACK OF HOW MANY TRKS ARE DONE ; ; DS 80 ;SETUP STORAGE FOR 40 LEVEL STACK STCKK EQU $ ; DATBF1: DS FSECSIZ*FSPT ;DATA BUFFER FOR SIDE 0 TRACK ; DATBF2: DS FSECSIZ*FSPT ;DATA BUFFER FOR SIDE 1 TRACK ; END ; ;+++...END OF FILE «eof»