IMD 1.17: 29/05/2011 18:18:01 disk drivers disk     DREQUATELIBSQHD4020RELSQHDC MAC^SQHDS506RELSQHDT502REL003H ;I/O CONFIGURATION BYTE CURDRV EQU 0004H ;CURRENT DEFAULT DRIVE OPSYS EQU 0005H ;OPERATING SYSTEM ENTRYPOINT TFCB EQUFORMATT MAClPQRSTUVWXYZ[\]FORMATT REL^_LDRBDOS MACj`abcdefghijklmLODRBIOSMACnopqrstuvwxyz{|} ;LF AVT EQU 0BH ;VT AFF EQU 0CH ;FF ACR EQU 0DH ;CR ASO EQU 0EH ;SO ASI EQU 0FH ;SI ADLE EQU 10H ;DLE ADC1 EQU 11HDST58F MACN DST58F RELEQUATE ASM(EQUATE LIB)SQHDT503RELTK0BOOT COMTRK02010LDRTRK02020LDR 005CH ;DEFAULT FILE CONTROL BLOCK TBUF EQU 0080H ;DEFAULT DISK BUFFER ADDRESS TPA EQU 0100H ;TRANSIENT PROGRAM AREA BASE LODRBIOSMAC~LODRBIOSMAC/SBCBOOT MACSBCHBOOTMAC ;DC1 ADC2 EQU 12H ;DC2 ADC3 EQU 13H ;DC3 ADC4 EQU 14H ;DC4 ANAK EQU 15H ;NAK ASYN EQU 16H ;SYN AETB EQU 17H ;ETB FMTHDC MAC,FMTHDC REL !FMTI5F ASM="#$%&'()FMTI5F REL*TRK02040LDRTRK04020LDRTRK0DSDDLDRTRK0S506LDR; ; DISK COMMAND PACKET OFFSETS ; PDRDP EQU 0 ;PD REQUEST DESCRIPTOR PACKET PDRFCN EQU 0 ;PD REQUEST FUNCTION NUMBER PDRDS6DSK MACS6DSK MACS6DSK REL S6FOR5 GENACAN EQU 18H ;CAN AEM EQU 19H ;EM ASUB EQU 1AH ;SUB AESC EQU 1BH ;ESC AFS EQU 1CH ;FS AGS EQU 1DH ;GS ARS EQU 1EH ;FMTI8F ASM3+,-./01FMTI8F REL2FMTWD ASMF3456789:;FMTWD REL< .XLIST .XCREF ; ; ASCII EQUIVALENCES ; ANUL EQU 00H ;NULL ASOH EQU 01H ;SOH ASTX EQU 02H ;STX AETX EQU 03H ;ETX ATRK0SSDDLDRTRK0SSSDLDRTRK0T502LDRTRK0T503LDRRV EQU 1 ;PD REQUEST DRIVE NUMBER PDRTRK EQU 2 ;PD REQUEST TRACK NUMBER PDRSEC EQU 4 ;PD REQUEST SECTOR NUMBER PDRSC EQU 6S6FOR8 GENSQHD2010RELSQHD2020RELSQHD2040RELRS AUS EQU 1FH ;US ASP EQU 20H ;SPACE ARUB EQU 7FH ;RUBOUT (DEL) ; WBOOT EQU 0000H ;WARM START ENTRYPOINT IOBYTE EQU 0FORHDC COM=>?FORHDC GEN@FORMAT ASMgABCDEFGHIJKLMFORMAT RELNOEOT EQU 04H ;EOT AENQ EQU 05H ;ENQ AACK EQU 06H ;ACK ABEL EQU 07H ;BELL ABS EQU 08H ;BS AHT EQU 09H ;HT ALF EQU 0AH   ;PD REQUEST SECTOR COUNT PDRTC EQU 8 ;PD REQUEST TRANSFER COUNT PDRDMA EQU 10 ;PD REQUEST DMA ADDRESS PDRDST EQU 12 ;PD 1 shl 4);number of blocks endif db 4 ;number of directory blocks db 3 ;physical sector size (2^n*128) dw 16 ;physic ; on double density disks ; tsd equ 2 ;two-sided disk bit (type code) ddd equ 3 ;double density disk bit (type code)  ; 1024 byte sector, double-density, two-sided (mini) ; dw $+dstl ;disk spec table link pointer db 4 ;block size if cr size (2^n*128) dw 8 ;physical sectors per track dw 77 ;physical tracks per disk dw 1 ;number of reserved tracks elsREQUEST DRIVE SPEC TABLE ADDR PDRLEN EQU 14 ;PD REQUEST DESCRIPTOR PACKET LENGTH ; DSKNFO EQU 14 ;DISK TYPE INFORMATION BLal sectors per track dw 77 ;physical tracks per disk if cpm dw 1 ;number of reserved tracks else dw 0 ;number of  mini equ 4 ;mini-floppy disk bit (type code) tpi96 equ 5 ;96-tpi disk bit (type code) ; public xltbl,dtco,typcod,gaplen pm dw (39*(8*(1 shl 3)))/(1 shl 4);number of blocks db 2 ;number of directory blocks db 3 ;physical sector size (2^n*128 title turbodos operating system drive specification tables subttl copyright 1983, software 2000, inc. .z80 ; ; copyright e dw (80*(10*(1 shl 3)))/(1 shl 4);number of blocks db 4 ;number of directory blocks db 3 ;physical sector size (2^n*128KSIZ EQU 14 ;BLOCK SIZE NMBLKS EQU 15 ;NUMBER OF BLOCKS NMBDIR EQU 17 ;NUMBER OF DIRECTORY BLOCKS SECSIZ EQU 18 ;PHYSICALreserved tracks endif dw 0 ;translation table address db 1 shl ddd or 1 shl tsd or 3 ;disk type code db 35h ;gap len; cseg ;locate in program area ; ; 1024 byte sector, double-density, two-sided ; dstbls:: dw $+dstl ;disk spec table l) dw 8 ;physical sectors per track dw 40 ;physical tracks per disk dw 1 ;number of reserved tracks else dw (40*(10*1983, software 2000, inc. ; ; version: 02/03/83 ; name ('dskfmt') ;module id ; include DREQUATE.LIB ;driver symbolic eq) dw 10 ;physical sectors per track dw 80 ;physical tracks per disk dw 0 ;number of reserved tracks endif dw 0 ; SECTOR SIZE (2^N*128) SECTRK EQU 19 ;PHYSICAL SECTORS PER TRACK TRKDSK EQU 21 ;PHYSICAL TRACKS PER DISK RESTRK EQU 23 ;NUgth ; ; 1024 byte sector, double-density, two-sided, 96-tpi (mini) ; dw $+dstl ;disk spec table link pointer db 4 ;blocink pointer db 4 ;block size if cpm dw (76*(16*(1 shl 3)))/(1 shl 4);number of blocks else dw (77*(16*(1 shl 3)))/((1 shl 3)))/(1 shl 4);number of blocks db 2 ;number of directory blocks db 3 ;physical sector size (2^n*128) dw 10 ;phyuivalences ; false equ 0 ;logical equates true equ not false ; ; cpm equ true ;set to false for TURBODOS 0 track offsetstranslation table address db 1 shl tpi96 or 1 shl mini or 1 shl ddd or 1 shl tsd or 3;disk type code db 35h ;gap length ; MBER OF RESERVED TRACKS DNFOL EQU 11 ;DISK INFO LENGTH ; ; .CREF .LIST k size if cpm dw (76*(8*(1 shl 3)))/(1 shl 4);number of blocks db 2 ;number of directory blocks db 3 ;physical secto sical sectors per track dw 40 ;physical tracks per disk dw 0 ;number of reserved tracks endif dw 0 ;translation tabhl 3)))/(1 shl 3);number of blocks db 1 ;number of directory blocks db 3 ;physical sector size (2^n*128) dw 4 ;physical else dw (80*(5*(1 shl 3)))/(1 shl 4);number of blocks db 2 ;number of directory blocks db 3 ;physical sector size (2^ 4) ;number of blocks ; db 3 ;number of directory blocks ; db 2 ;physical sector size (2^n*128) ; dw 15 ;physical sectors perved tracks else dw 0 ;reserved tracks endif dw 0 ;translation table address db 1 shl ddd or 3 ;disk type code  pointer ; db 4 ;block size ; dw (77*(30*(1 shl 2)))/(1 shl 4) ;number of blocks ; db 4 ;number of directory blocks ; db 2 le address db 1 shl mini or 1 shl ddd or 1 shl tsd or 3;disk type code db 35h ;gap length ; ; 1024 byte sector, double-de sectors per track dw 40 ;physical tracks per disk dw 1 ;reserved tracks else dw (40*(5*(1 shl 3)))/(1 shl 3);number on*128) dw 5 ;physical sectors per track dw 80 ;physical tracks per disk dw 0 ;reserved tracks endif dw 0 ;translr track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracks ; dw 0 ;translation table address ; db 1 shl ddd or 2 ;didb 35h ;gap length ; ; 1024 byte sector, double-density, one-sided, 96-tpi (mini) ; dw $+dstl ;disk spec table link point;physical sector size (2^n*128) ; dw 30 ;physical sectors per track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracksnsity, one-sided ; dw $+dstl ;disk spec table link pointer db 4 ;block size if cpm dw (76*(8*(1 shl 3)))/(1 shl 4);f blocks db 2 ;number of directory blocks db 3 ;physical sector size (2^n*128) dw 5 ;physical sectors per track dw 40ation table address db 1 shl tpi96 or 1 shl mini or 1 shl ddd or 3;disk type code db 35h ;gap length ; ; 1024 byte sectorsk type code ; db 1bh ;gap length ; ; 512 byte sector, single-density, two-sided ; dw $+dstl ;disk spec table link pointeer db 4 ;block size if cpm dw (76*(4*(1 shl 3)))/(1 shl 4);number of blocks db 1 ;number of directory blocks db 3  ; dw 0 ;translation table address ; db 1 shl ddd or 1 shl tsd or 2 ;disk type code ; db 1bh ;gap length ; ; 512 byte sectnumber of blocks else dw (77*(8*(1 shl 3)))/(1 shl 4);number of blocks endif db 3 ;number of directory blocks db 3  ;physical tracks per disk dw 0 ;reserved tracks endif dw 0 ;translation table address db 1 shl mini or 1 shl ddd o, double-density, one-sided (mini) ; dw $+dstl ;disk spec table link pointer db 3 ;block size if cpm dw (39*(4*(1 sr db 4 ;block size dw (77*(16*(1 shl 2)))/(1 shl 4);number of blocks db 3 ;number of directory blocks db 2 ;physical  ;physical sector size (2^n*128) dw 4 ;physical sectors per track dw 77 ;physical tracks per disk dw 1 ;reserved tracksor, double-density, one-sided ; ; dw $+dstl ;disk spec table link pointer ; db 4 ;block size ; dw (77*(15*(1 shl 2)))/(1 shl ;physical sector size (2^n*128) dw 8 ;physical sectors per track dw 77 ;physical tracks per disk if cpm dw 1 ;reser 3 ;disk type code db 35h ;gap length ; ; 512 byte sector, double-density, two-sided ; ; dw $+dstl ;disk spec table link sector size (2^n*128) dw 16 ;physical sectors per track dw 77 ;physical tracks per disk dw 0 ;reserved tracks dw 0 ; shl 4) ;number of blocks ; db 3 ;number of directory blocks ; db 1 ;physical sector size (2^n*128) ; dw 30 ;physical sectorsk spec table link pointer ; db 4 ;block size ; dw (77*(26*(1 shl 1)))/(1 shl 4) ;number of blocks ; db 2 ;number of directoh ; ; 128 byte sector, single-density, two-sided ; ; dw $+dstl ;disk spec table link pointer ; db 4 ;block size ; dw (77*(6 byte sector, double-density, two-sided ; ; dw $+dstl ;disk spec table link pointer ; db 4 ;block shzet ; dw (77*(52*(1 shldw 0 ;translation table address ; db 1 ;disk type code ; db 0eh ;gap length ; ; 128 byte sector, single-density, two-sided (translation table address db 1 shl tsd or 2 ;disk type code db 1bh ;gap length ; ; 512 byte sector, single-density, one-s per track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracks ; dw 0 ;translation table address ; db 1 shl tsd or 1 ry blocks ; db 1 ;physical sector size (2^n*128) ; dw 26 ;physical sectors per track ; dw 77 ;physical tracks per disk ; dw 52*(1 shl 0)))/(1 shl 4) ;number of blocks ; db 2 ;number of directory blocks ; db 0 ;physical sector size (2^n*128) ; dw 52 1)))/(1 shl 4) ;number of blocks ; db 4 ;number of directory blocks ; db 1 ;physical sector size (2^n*128) ; dw 52 ;physicaold) ; ; dw $+dstl ;disk spec table link pointer ; db 4 ;block size ; dw (76*(52*(1 shl 0)))/(1 shl 4) ;number of blocks ;sided ; dw $+dstl ;disk spec table link pointer db 4 ;block size dw (77*(8*(1 shl 2)))/(1 shl 4);number of blocks db ;disk type code ; db 0eh ;gap length ; ; 256 byte sector, single-density, one-sided ; ; dw $+dstl ;disk spec table link poi0 ;reserved tracks ; dw 0 ;translation table address ; db 1 shl ddd or 1 ;disk type code ; db 0eh ;gap length ; ; 256 byte  ;physical sectors per track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracks ; dw 0 ;translation table address ; dl sectors per track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracks ; dw 0 ;translation table address ; db 1 shl d db 2 ;number of directory blocks ; db 0 ;physical sector size (2^n*128) ; dw 52 ;physical sectors per track ; dw 77 ;physica2 ;number of directory blocks db 2 ;physical sector size (2^n*128) dw 8 ;physical sectors per track dw 77 ;physical trnter ; db 4 ;block size ; dw (77*(15*(1 shl 1)))/(1 shl 4) ;number of blocks ; db 2 ;number of directory blocks ; db 1 ;physector, single-density, two-sided ; ; dw $+dstl ;disk spec table link pointer ; db 4 ;block size ; dw (77*(30*(1 shl 1)))/(1b 1 shl tsd ;disk type code ; db 7 ;gap length ; ; 128 byte sector, single-density, one-sided ; dsta: dw 0 ;disk spec tabldd or 1 shl tsd or 1 ;disk type code ; db 0eh ;gap length ; ; 256 byte sector, double-density, one-sided ; ; dw $+dstl ;dil tracks per disk ; dw 1 ;reserved tracks ; dw 0 ;translation table address ; db 1 shl tsd ;disk type code ; db 7 ;gap lengtacks per disk dw 0 ;reserved tracks dw 0 ;translation table address db 2 ;disk type code db 1bh ;gap length ; ; 25sical sector size (2^n*128) ; dw 15 ;physical sectors per track ; dw 77 ;physical tracks per disk ; dw 0 ;reserved tracks ;  e link pointer dstb: db 3 ;block size dw (75*(26*(1 shl 0)))/(1 shl 3);number of blocks db 2 ;number of directory blocks R NUMBER M10SEC: .BYTE 0 ;ACTUAL M10 SECTOR NUMBER M10DMA: .WORD 0 ;CURRENT DMA ADDRESS SECKEY: .BYTE 0 ;SECTOR KEY RDYMSK: @@;`pƵ4A4`݈&  M6`4&@ 2` @pP PXD.±  ;I/O CONFIGURATION BYTE CURDRV == 0004H ;CURRENT DEFAULT DRIVE OPSYS == 0005H ;OPERATING SYSTEM ENTRYPOINT TFCB == 005CH ;DEable ; trtbl: db 0,6,12,18,24,4,10,16,22 db 2,8,14,20,1,7,13,19,25 db 5,11,17,23,3,9,15,21 ; end BH ;VT AFF == 0CH ;FF ACR == 0DH ;CR ASO == 0EH ;SO ASI == 0FH ;SI ADLE == 10H ;DLE ADC1 == 11H ;DC1 ADC2 == 12H  db 0 ;physical sector size (2^n*128) dw 26 ;physical sectors per track dw 77 ;physical tracks per disk dw 2 ;reserve.BYTE 0 ;READY MASK ; .XSYM .END SECTOR NUMBER M10DMA: .WORD 0 ;CURRENT DMA ADDRESS SECKEY: .BYTE 0 ;SECTOR KEY RDYMSK: i  ʋ*i 8ZD@@ ƴ`D 0 M@,kUFAULT FILE CONTROL BLOCK TBUF == 0080H ;DEFAULT DISK BUFFER ADDRESS TPA == 0100H ;TRANSIENT PROGRAM AREA BASE ; WSFCN == 0 AL SECTORS PER TRACK .WORD 244 ;PHYSICAL TRACKS PER DISK .WORD 122 ;NUMBER OF RESERVED TRACKS ;] .IFN EIGHT , [ .BYTE 5;DC2 ADC3 == 13H ;DC3 ADC4 == 14H ;DC4 ANAK == 15H ;NAK ASYN == 16H ;SYN AETB == 17H ;ETB ACAN == 18H ;CAN AEM == 1d tracks ; xltbl equ $-dstb ;translation table address offset ; dw trtbl ;translation table address ; dtco equ $-dsta ;RESS RWERR: .BYTE 0 ;READ/WRITE ERROR TRYCNT: .BYTE 0 ;TRY COUNT REQDSK: .BYTE 0 ;REQUESTED DISK NUMBER CURDSK: .BYTE 0 ;CUR;FUNCTION 0 (WARM START) CIFCN == 1 ;FUNCTION 1 (CONSOLE INPUT) COFCN == 2 ;FUNCTION 2 (CONSOLE OUTPUT) RCIFCN == 3 ;FUNCT ;BLOCK SIZE .WORD (243*84*(1<2))/(1<5) ;NUMBER OF BLOCKS .BYTE 16 ;NUMBER OF DIRECTORY BLOCKS .BYTE 2 ;PHYSICAL SECTOR SI9H ;EM ASUB == 1AH ;SUB AESC == 1BH ;ESC AFS == 1CH ;FS AGS == 1DH ;GS ARS == 1EH ;RS AUS == 1FH ;US ASP == 20H ;disk type code offset typcod equ $-dstb ;disk type code offset ; db 0 ;disk type code ; gaplen equ $-dstb ;gap length o.SLIST .XLIST ; ; ASCII EQUIVALENCES ; ANUL == 00H ;NULL ASOH == 01H ;SOH ASTX == 02H ;STX AETX == 03H ;ETX AEOT == RENT DRIVE NUMBER PRVTRK: .BYTE 0 ;PREVIOUS TRACK NUMBER CURTRK: .BYTE 0 ;CURRENT TRACK NUMBER CURSEC: .WORD 0 ;CURRENT SECTOION 3 (RAW CONSOLE INPUT) RCOFCN == 4 ;FUNCTION 4 (RAW CONSOLE OUTPUT) LOFCN == 5 ;FUNCTION 5 (LIST OUTPUT) DCFCN == 6 ;FUѓU UD$Q >TYPCODTSdE5D$9@ZD@@ ƴ`D 0 M@,kUSPACE ARUB == 7FH ;RUBOUT (DEL) ; ; OPERATING SYSTEM EQUIVALENCES ; WBOOT == 0000H ;WARM START ENTRYPOINT IOBYTE == 0003Hffset ; db 7 ;gap length ; dstl equ $-dsta ;disk spec table length ; ; single-density/single-sided sector translation t04H ;EOT AENQ == 05H ;ENQ AACK == 06H ;ACK ABEL == 07H ;BELL ABS == 08H ;BS AHT == 09H ;HT ALF == 0AH ;LF AVT == 0 NCTION 6 (DIRECT CONSOLE I/O) RIBFCN == 7 ;FUNCTION 7 (RETURN I/O BYTE) SIBFCN == 8 ;FUNCTION 8 (SET I/O BYTE) PBFCN == 9 ALV INFO) RDPFCN == 75 ;FUNCTION 75 (RETURN DISK PARMS) SRPFCN == 76 ;FUNCTION 76 (SET/RET PRINT MODE) EOPFCN == 77 ;FUNCT(SET/RETURN USER) RRFFCN == 33 ;FUNCTION 33 (READ RANDOM FILE) WRFFCN == 34 ;FUNCTION 34 (WRITE RANDOM FILE) CFSFCN == 35 TION 104 (SET DATE/TIME) DT2FCN == 105 ;FUNCTION 105 (RETURN DATE/TIME) ; RSNFCN == 107 ;FUNCTION 107 (RETURN S/N) SCLFCN EAD SEQUENTIAL FILE) WSFFCN == 21 ;FUNCTION 21 (WRITE SEQ FILE) MFFCN == 22 ;FUNCTION 22 (MAKE FILE) RFFCN == 23 ;FUNCTION CCOFCN == 89 ;FUNCTION 89 (COMM CHANNEL OUTPUT) SCBFCN == 90 ;FUNCTION 90 (SET COMM BAUD RATE) RCBFCN == 91 ;FUNCTION 91 (;FUNCTION 9 (PRINT BUFFER) CIBFCN == 10 ;FUNCTION 10 (CONSOLE IN BUFFERED) CSFCN == 11 ;FUNCTION 11 (CONSOLE STATUS) RVNFCNION 77 (SIGNAL END OF PRINT) SRDFCN == 78 ;FUNCTION 78 (SET/RET DE-SPOOL) QPFFCN == 79 ;FUNCTION 79 (QUEUE PRINT FILE) NLOF;FUNCTION 35 (COMPUTE FILE SIZE) SRRFCN == 36 ;FUNCTION 36 (SET RANDOM RECORD) RDFCN == 37 ;FUNCTION 37 (RESET DRIVE) ; LK== 108 ;FUNCTION 108 (SEND COMMAND LINE) SESFCN == 109 ;FUNCTION 109 (SET ERROR SERVICE) SERFCN == 110 ;FUNCTION 110 (SET E 23 (RENAME FILE) RLIFCN == 24 ;FUNCTION 24 (RETURN LOGIN VECTOR) RCDFCN == 25 ;FUNCTION 25 (RETURN CURRENT DISK) SDFCN == RETURN COMM BAUD) SMCFCN == 92 ;FUNCTION 92 (SET COMM MODEM CTRL) RMCFCN == 93 ;FUNCTION 93 (RET COMM MODEM CTRL) ; EBPFCN == 12 ;FUNCTION 12 (RETURN VERSN NUMBER) RDSFCN == 13 ;FUNCTION 13 (RESET DISK SYSTEM) SELFCN == 14 ;FUNCTION 14 (SELECT DCN == 80 ;FUNCTION 80 (NETWORK LIST OUT) FLBFCN == 81 ;FUNCTION 81 (FLUSH LIST BUFFER) ; SDTFCN == 83 ;FUNCTION 83 (SET DARFCN == 42 ;FUNCTION 42 (LOCK RECORD) FRRFCN == 43 ;FUNCTION 43 (FREE RECORD) ; DFSFCN == 46 ;FUNCTION 46 (DISK FREE SPACERROR RETURN) LOGFCN == 111 ;FUNCTION 111 (LOG ON/OFF) LFDFCN == 112 ;FUNCTION 112 (LOCKOUT/FREE DRIVE) LFFCN == 113 ;FUNCT26 ;FUNCTION 26 (SET DMA) ; WPDFCN == 28 ;FUNCTION 28 (WRITE PROTECT DISK) RROFCN == 29 ;FUNCTION 29 (RETURN R/O VECTOR)  == 95 ;FUNCTION 95 (ENABLE BOOT PROM) SBPFCN == 96 ;FUNCTION 96 (SET BUFFER PARMS) RBPFCN == 97 ;FUNCTION 97 (RETURN BUFFEISK) OFFCN == 15 ;FUNCTION 15 (OPEN FILE) CFFCN == 16 ;FUNCTION 16 (CLOSE FILE) SFFFCN == 17 ;FUNCTION 17 (SEARCH FOR 1ST TE/TIME) RDTFCN == 84 ;FUNCTION 84 (RETURN DATE/TIME) SRSFCN == 85 ;FUNCTION 85 (SET/RET DISK STATUS) PDAFCN == 86 ;FUNCTI) CHNFCN == 47 ;FUNCTION 47 (CHAIN TO PROGRAM) ; ROSFCN == 73 ;FUNCTION 73 (RESET O/S) RAVFCN == 74 ;FUNCTION 74 (RETURN ION 113 (LOAD FILE) RDMFCN == 114 ;FUNCTION 114 (REBUILD DISK MAP) FFBFCN == 115 ;FUNCTION 115 (FLUSH/FREE BUFFERS) ; RCFCSFAFCN == 30 ;FUNCTION 30 (SET FILE ATTRIBUTES) DPBFCN == 31 ;FUNCTION 31 (DISK PARAMETER BLOCK) SRUFCN == 32 ;FUNCTION 32 R PARMS) ADFFCN == 98 ;FUNCTION 98 (ACTIVATE DO FILE) ALDFCN == 99 ;FUNCTION 99 (AUTO LOAD DISABLE) ; DT1FCN == 104 ;FUNCFILE) SNFFCN == 18 ;FUNCTION 18 (SEARCH FOR NEXT FILE) DFFCN == 19 ;FUNCTION 19 (DELETE FILE) RSFFCN == 20 ;FUNCTION 20 (RON 86 (PHYSICAL DISK ACCESS) CCSFCN == 87 ;FUNCTION 87 (COMM CHANNEL STATUS) CCIFCN == 88 ;FUNCTION 88 (COMM CHANNEL INPUT)  N == 118 ;FUNCTION 118 (REMOTE CONSOLE) ROUFCN == 119 ;FUNCTION 119 (RETURN ORIGIN/UNIT) SCFFCN == 120 ;FUNCTION 120 (SET CU 2 ;FUNCTION 2 (CONSOLE OUTPUT) RCIFCN EQU 3 ;FUNCTION 3 (RAW CONSOLE INPUT) RCOFCN EQU 4 ;FUNCTION 4 (RAW CONSOLE OUTPUT)RS AUS EQU 1FH ;US ASP EQU 20H ;SPACE ARUB EQU 7FH ;RUBOUT (DEL) ; ; OPERATING SYSTEM EQUIVALENCES ; WBOOT EQU 0000H CTION 28 (WRITE PROTECT DISK) RROFCN EQU 29 ;FUNCTION 29 (RETURN R/O VECTOR) SFAFCN EQU 30 ;FUNCTION 30 (SET FILE ATTRIBUTESEOT EQU 04H ;EOT AENQ EQU 05H ;ENQ AACK EQU 06H ;ACK ABEL EQU 07H ;BELL ABS EQU 08H ;BS AHT EQU 09H ;HT ALF EQU 0AH UNCTION 16 (CLOSE FILE) SFFFCN EQU 17 ;FUNCTION 17 (SEARCH FOR 1ST FILE) SNFFCN EQU 18 ;FUNCTION 18 (SEARCH FOR NEXT FILE) OMPATABILITY) AMFCN == 121 ;FUNCTION 121 (ALLOCATE MEMORY) DMFCN == 122 ;FUNCTION 122 (DE-ALLOCATE MEMORY) SMFCN == 123 ;F LOFCN EQU 5 ;FUNCTION 5 (LIST OUTPUT) DCFCN EQU 6 ;FUNCTION 6 (DIRECT CONSOLE I/O) RIBFCN EQU 7 ;FUNCTION 7 (RETURN I/O B;WARM START ENTRYPOINT IOBYTE EQU 0003H ;I/O CONFIGURATION BYTE CURDRV EQU 0004H ;CURRENT DEFAULT DRIVE OPSYS EQU 0005H ;O) DPBFCN EQU 31 ;FUNCTION 31 (DISK PARAMETER BLOCK) SRUFCN EQU 32 ;FUNCTION 32 (SET/RETURN USER) RRFFCN EQU 33 ;FUNCTION 3 ;LF AVT EQU 0BH ;VT AFF EQU 0CH ;FF ACR EQU 0DH ;CR ASO EQU 0EH ;SO ASI EQU 0FH ;SI ADLE EQU 10H ;DLE ADC1 EQU 11HDFFCN EQU 19 ;FUNCTION 19 (DELETE FILE) RSFFCN EQU 20 ;FUNCTION 20 (READ SEQUENTIAL FILE) WSFFCN EQU 21 ;FUNCTION 21 (WRITEUNCTION 123 (SEND MESSAGE) RMFCN == 124 ;FUNCTION 124 (RECEIVE MESSAGE) DPFCN == 125 ;FUNCTION 125 (DISPATCH PROCESS) CTPFCYTE) SIBFCN EQU 8 ;FUNCTION 8 (SET I/O BYTE) PBFCN EQU 9 ;FUNCTION 9 (PRINT BUFFER) CIBFCN EQU 10 ;FUNCTION 10 (CONSOLE INPERATING SYSTEM ENTRYPOINT TFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK TBUF EQU 0080H ;DEFAULT DISK BUFFER ADDRESS TPA EQU 03 (READ RANDOM FILE) WRFFCN EQU 34 ;FUNCTION 34 (WRITE RANDOM FILE) CFSFCN EQU 35 ;FUNCTION 35 (COMPUTE FILE SIZE) SRRFCN E ;DC1 ADC2 EQU 12H ;DC2 ADC3 EQU 13H ;DC3 ADC4 EQU 14H ;DC4 ANAK EQU 15H ;NAK ASYN EQU 16H ;SYN AETB EQU 17H ;ETB  SEQ FILE) MFFCN EQU 22 ;FUNCTION 22 (MAKE FILE) RFFCN EQU 23 ;FUNCTION 23 (RENAME FILE) RLIFCN EQU 24 ;FUNCTION 24 (RETURN == 126 ;FUNCTION 126 (CREATE/TERM PROCESS) USRFCN == 127 ;FUNCTION 127 (USER DEFINED) .RLIST  BUFFERED) CSFCN EQU 11 ;FUNCTION 11 (CONSOLE STATUS) RVNFCN EQU 12 ;FUNCTION 12 (RETURN VERSN NUMBER) RDSFCN EQU 13 ;FUNC100H ;TRANSIENT PROGRAM AREA BASE ; WSFCN EQU 0 ;FUNCTION 0 (WARM START) CIFCN EQU 1 ;FUNCTION 1 (CONSOLE INPUT) COFCN EQQU 36 ;FUNCTION 36 (SET RANDOM RECORD) RDFCN EQU 37 ;FUNCTION 37 (RESET DRIVE) ; LKRFCN EQU 42 ;FUNCTION 42 (LOCK RECORD) ACAN EQU 18H ;CAN AEM EQU 19H ;EM ASUB EQU 1AH ;SUB AESC EQU 1BH ;ESC AFS EQU 1CH ;FS AGS EQU 1DH ;GS ARS EQU 1EH ;N LOGIN VECTOR) RCDFCN EQU 25 ;FUNCTION 25 (RETURN CURRENT DISK) SDFCN EQU 26 ;FUNCTION 26 (SET DMA) ; WPDFCN EQU 28 ;FUN .XLIST .XCREF ; ; ASCII EQUIVALENCES ; ANUL EQU 00H ;NULL ASOH EQU 01H ;SOH ASTX EQU 02H ;STX AETX EQU 03H ;ETX ATION 13 (RESET DISK SYSTEM) SELFCN EQU 14 ;FUNCTION 14 (SELECT DISK) OFFCN EQU 15 ;FUNCTION 15 (OPEN FILE) CFFCN EQU 16 ;F   FRRFCN EQU 43 ;FUNCTION 43 (FREE RECORD) ; DFSFCN EQU 46 ;FUNCTION 46 (DISK FREE SPACE) CHNFCN EQU 47 ;FUNCTION 47 (CHAINRROR RETURN) LOGFCN EQU 111 ;FUNCTION 111 (LOG ON/OFF) LFDFCN EQU 112 ;FUNCTION 112 (LOCKOUT/FREE DRIVE) LFFCN EQU 113 ;FUUNCTION 95 (ENABLE BOOT PROM) SBPFCN EQU 96 ;FUNCTION 96 (SET BUFFER PARMS) RBPFCN EQU 97 ;FUNCTION 97 (RETURN BUFFER PARMS)IRECTORY BLOCKS .BYTE 2 ;PHYSICAL SECTOR SIZE (2^N*128) .WORD 168 ;PHYSICAL SECTORS PER TRACK .WORD 244 ;PHYSICAL TRACKS P84 ;FUNCTION 84 (RETURN DATE/TIME) SRSFCN EQU 85 ;FUNCTION 85 (SET/RET DISK STATUS) PDAFCN EQU 86 ;FUNCTION 86 (PHYSICAL DIOCESS) CTPFCN EQU 126 ;FUNCTION 126 (CREATE/TERM PROCESS) USRFCN EQU 127 ;FUNCTION 127 (USER DEFINED) .CREF .LIST  TO PROGRAM) ; RAVFCN EQU 74 ;FUNCTION 74 (RETURN ALV INFO) RDPFCN EQU 75 ;FUNCTION 75 (RETURN DISK PARMS) SRPFCN EQU 76 NCTION 113 (LOAD FILE) RDMFCN EQU 114 ;FUNCTION 114 (REBUILD DISK MAP) FFBFCN EQU 115 ;FUNCTION 115 (FLUSH/FREE BUFFERS) ;  ADFFCN EQU 98 ;FUNCTION 98 (ACTIVATE DO FILE) ALDFCN EQU 99 ;FUNCTION 99 (AUTO LOAD DISABLE) ; DT1FCN EQU 104 ;FUNCTION ER DISK .WORD 1 ;NUMBER OF RESERVED TRACKS ;] .IFE FASTIL , [ XLATBL: .BYTE 0,10,20,9,19,8,18,7,17,6,16,5,15,4,14 .BYTE SK ACCESS) CCSFCN EQU 87 ;FUNCTION 87 (COMM CHANNEL STATUS) CCIFCN EQU 88 ;FUNCTION 88 (COMM CHANNEL INPUT) CCOFCN EQU 89  RESERVED TRACKS ; .BYTE 4 ;BLOCK SIZE .WORD (10*168*(1<2))/(1<4) ;NUMBER OF BLOCKS .BYTE 4 ;NUMBER OF DIRECTORY BLOCKS ;FUNCTION 76 (SET/RET PRINT MODE) EOPFCN EQU 77 ;FUNCTION 77 (SIGNAL END OF PRINT) SRDFCN EQU 78 ;FUNCTION 78 (SET/RET DE-SP RCFCN EQU 118 ;FUNCTION 118 (REMOTE CONSOLE) ROUFCN EQU 119 ;FUNCTION 119 (RETURN ORIGIN/UNIT) SCFFCN EQU 120 ;FUNCTION 12104 (SET DATE/TIME) DT2FCN EQU 105 ;FUNCTION 105 (RETURN DATE/TIME) ; RSNFCN EQU 107 ;FUNCTION 107 (RETURN S/N) SCLFCN EQU3,13,2,12,1,11 ;] .LOC .DATA.# ;LOCATE IN DATA AREA ; FLAGS: .BYTE 0 ;GENERAL PURPOSE FLAGS RETSP: .WORD 0 ;RETURN STACK P;FUNCTION 89 (COMM CHANNEL OUTPUT) SCBFCN EQU 90 ;FUNCTION 90 (SET COMM BAUD RATE) RCBFCN EQU 91 ;FUNCTION 91 (RETURN COMM B .BYTE 2 ;PHYSICAL SECTOR SIZE .WORD 168 ;PHYSICAL SECTORS PER TRACK .WORD 244 ;PHYSICAL TRACKS PER DISK .WORD 234 ;NUMBEROOL) QPFFCN EQU 79 ;FUNCTION 79 (QUEUE PRINT FILE) NLOFCN EQU 80 ;FUNCTION 80 (NETWORK LIST OUT) FLBFCN EQU 81 ;FUNCTION 80 (SET COMPATABILITY) AMFCN EQU 121 ;FUNCTION 121 (ALLOCATE MEMORY) DMFCN EQU 122 ;FUNCTION 122 (DE-ALLOCATE MEMORY) SMFCN  108 ;FUNCTION 108 (SEND COMMAND LINE) SESFCN EQU 109 ;FUNCTION 109 (SET ERROR SERVICE) SERFCN EQU 110 ;FUNCTION 110 (SET EOINTER DSTADR: .WORD 0 ;DRIVE SPEC. TABLE ADDRESS RWERR: .BYTE 0 ;READ/WRITE ERROR TRYCNT: .BYTE 0 ;TRY COUNT REQDSK: .BYTE AUD) SMCFCN EQU 92 ;FUNCTION 92 (SET COMM MODEM CTRL) RMCFCN EQU 93 ;FUNCTION 93 (RET COMM MODEM CTRL) ; EBPFCN EQU 95 ;F OF RESERVED TRACKS ;] .IFN SIXTN , [ .BYTE 5 ;BLOCK SIZE .WORD (243*168)/(1<3) ;NUMBER OF BLOCKS .BYTE 16 ;NUMBER OF D1 (FLUSH LIST BUFFER) DLOFCN EQU 82 ;FUNCTION 82 (DE-SPOOL LIST OUT) SDTFCN EQU 83 ;FUNCTION 83 (SET DATE/TIME) RDTFCN EQU EQU 123 ;FUNCTION 123 (SEND MESSAGE) RMFCN EQU 124 ;FUNCTION 124 (RECEIVE MESSAGE) DPFCN EQU 125 ;FUNCTION 125 (DISPATCH PR   TITLE TURBODOS OPERATING SYSTEM HDC1001 HARD DISK FORMATTER .z80 ; NAME ('FMTHDC') ; INCLUDE EQUATE.LIB ; DSEG ; iormat area ex DE,HL ;save ld HL,(opsys+1) ;got enuf room sbc HL,DE ld A,0ffh ;set error return ret c ;return if2 ADD HL,HL ;*4 ADD HL,BC ;*5 ADD HL,HL ;*10 ADD A,L ;add in new value LD L,A JP NZ,DIGNC INC H DIGNC: poThis place taken? AND A JP M,GOTIT ; If not, we can use it INC DE ; Else, check next one JP CHECK GOTIT: LD A,B ;;How many chars returned cp 0 jr z,bad ;no chars cp 3 ;to many chars jr C,good ;if not skip bad: ld DE,inval ldL LD (LIMIT),HL ;Now, negative sector count LD A,B ; Get sectors per track (SECTRK) CPL ; And twos complement LD Lnbuf: db 6 ; Line input buffer numchr: db 4 ; Number of characters returned SECTRK:: ds 1 ; Number of sectors NMBTRK: not enuf ;Calculate interleave table ;But first clear the table to all FF's LD B,32 ; Make table 32 long LD HL,?END?##p AF dec A ;done yet JP NZ,DECLP ;if not go back for more add HL,HL ;now make ref into table of drive parameters ad Store sector number LD (DE),A LD HL,(INTER) ; Increment pointer by ADD HL,DE ; interleave INC B ; Increment sector C,pbfcn call opsys ld DE,menu ;ask again ld C,pbfcn call opsys jr strt1 good: LD DE,inbuf+2 ;set up registers L,A LD H,-1 INC HL LD (NSECS),HL ;Calculate interleave table LD B,0 ; Clear sector number LD DE,?END?## ; Index int: DW 0 ; Format number of tracks NMBHDS:: DB 0 ; Format number of heads INTER: DW 8 ; Current interleave limit: ds  ; Index interleave table SETLP: LD (HL),-1 INC HL DEC B JP NZ,SETLP ;Next, calculate interleave table upper limit LDd HL,HL ;*4 ld DE,dskprms add HL,DE ld DE,SECTRK ;now move parms to use locs ld BC,4 ldir ret ; ; track initial count LD A,(SECTRK) ; Have we done enough? CP B JP NZ,XCHECK ; ; housekeeping ; ld HL,?end?## ;address for format D HL,0 DECLP: PUSH AF ;Save char count LD A,(DE) ;get char INC DE CP '0' JP C,BAD ;Char less than a '0' CP '9'+erleave table CHECK: LD HL,(LIMIT) ; Make sure limits not exceeded ADD HL,DE JP NC,WITHIN ; We are within limits LD HL,2 ; Upper memory limit of table nsecs: ds 2 ; 16 bit negitive sectors ; ; cseg ; FMTNIT:: ld DE,signon ;send signo A,(SECTRK) ; Get number of sectors LD B,A ; Save for later LD E,A ; Offset off base of int table LD D,0 LD HL,?ENDization ; TRKNIT:: ld DE,512 ;length of format data ld HL,?end?## ;begining of format area add HL,DE ;find end of fdata ld (pdrdma##),HL ; init dma address ld A,(SECTRK) ld (pdrsc##),A ;init sector count ld A,(headno##) ;send head n1 JP NC,BAD ;Char greater than a '9' SUB '0' ;make = 0-9 LD B,H ;mult present value * 10 LD C,L ADD HL,HL ;*(NSECS) ; Otherwise subtract SECTRK ADD HL,DE XCHECK: EX DE,HL JP CHECK ; And check limits again WITHIN: LD A,(DE) ; n message ld C,pbfcn call opsys strt1: ld DE,inbuf ;Get response to disk type ld C,cibfcn call opsys LD A,(NUMCHR) ?## ADD HL,DE LD A,L ; Negate (2s complement) CPL LD L,A LD A,H CPL LD H,A ; This is our upper limit INC H  o. in sector l (pdrsec##),A xor a ;clear sector cnt & high sec byte ld (pdrsc##+1),A ld (pdrsec##+1),A ld HL,512  '4 = TM603S',ACR,ALF db '5 = TM603SE',ACR,ALF db '6 = TM501 ; Tandon Magnetics TM501',ACR,ALF db '7 = TM502',ACR, dw 512 ;cylinders db 6 ;heads q2040: db 16 ;sectors dw 512 ;cylinders db 8 ;heads m2010: db 16 ;sectors dw 480 ;cyliUe4T5E$95 QI.NMBHDSUU eE$I@`x\K . K@4 f@3@G p0p%j8 w 306 ;cylinders db 4 ;heads tm503: db 16 ;sectors dw 306 ;cylinders db 6 ;heads sa602: db 16 ;sectors dw 160 ;cylinde OUT HDCMND CALL FCNCOM ;DO COMMON FUNCTION SETUP ORI 0CH ;FORCE STEP PULSE/DIRECTION HIGH OUT HDFUNC CALL CALCHD ;CALCld (pdrtc##),HL ; init transfer count ret ; ; Disk parameters ; dskprms: st503: db 16 ;sectors dw 153 ;cylinders db ALF db '8 = TM503',ACR,ALF db '9 = SA602 ; Shugart Associates SA602',ACR,ALF db '10 = SA604',ACR,ALF db '11 = SA60nders db 2 ;heads m2020: db 16 ;sectors dw 480 ;cylinders db 4 ;heads ; ; Messages ; signon: db 'Select disk type froPM0mQF!4R)PN< P`95 QI.3Pc;`AIM3P<AIQ<P@QI-FORMAT DENSITY FMTHDS: .BYTE 0 ;FORMAT NUMBER OF HEADS FMTTRK: .BYTE 0 ;FORMAT NUMBER OF TRACKS FMTTYP: .BYTE 0 ;FORMAT TYPE  T FORMAT NUMBER OF HEADS ORA A ;FORMAT NUMBER OF HEADS=0? JRNZ ..ISC ;IF NOT, CONTINUE LXI H,FLAGS ;ELSE, GET FLAGS SET IS "Enter format type (TurboDOS/Cpm): " CALL INPLN ;INPUT LINE JRZ ..ITE ;IF NULL INPUT, CONTINUE CALL UPRCAS ;FORCE UPPERCC: MVI C,35 ;GET 35 TRACKS CPI "3" ;NUMBER OF TRACKS=3? JRZ ..ICCC ;IF SO, CONTINUE MVI C,40 ;ELSE, GET 40 TRACKS CPI "GAP LENGTH TABLE DAD D JRZ ..SD4 ;IF FORMAT DENSITY FLAG=0, CONTINUE DCX H ;ELSE, DECREMENT TABLE POINTER ..SD4: MOV A,M =0? JRNZ ..ICC ;IF NOT, CONTINUE LXI H,FLAGS ;ELSE, GET FLAGS SET CRLF,M ;SET CR/LF REQUIRED FLAG ..INPC: CALL DMS ;DISPLH,MSNTBL ;GET MAX SECTOR NUMBER TABLE LDA SECSIZ ;GET FORMAT SECTOR SIZE MOV E,A ;FORMAT SECTOR SIZE TO DE-REG MVI D,0 ;DCRLF,M ;SET CR/LF REQUIRED FLAG ..INPS: CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter number of sides (1/2): " CASE CPI "T" ;RESPONSE=T? JRZ ..ITC ;IF SO, CONTINUE CPI "C" ;RESPONSE=C? JRZ ..ITC ;IF SO, CONTINUE ..ITE: CALL DMS ;4" ;NUMBER OF TRACKS=40? JRZ ..ICCC ;IF SO, CONTINUE MVI C,80 ;ELSE, GET 80 TRACKS ..ICCC: MOV A,C ;GET NUMBER OF TRACKS ;GET GAP LENGTH STA GAPLEN ;SET FORMAT GAP LENGTH LDA FLAGS ;GET FLAGS BIT CRLF,A ;CR/LF REQUIRED FLAG SET? RZ ;IF NOT,AY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter number of tracks (3=35, 4=40, 8=80): " CALL INPLN ;INPUT LINE JRZ ..ICE ;IF OUBLE LENGTH DAD D ;INDEX INTO MAX SECTOR NUMBER TABLE LDA DENSTY ;GET FORMAT DENSITY FLAG ORA A ;FORMAT DENSITY FLAG=0?  CALL INPLN ;INPUT LINE JRZ ..ISE ;IF NULL INPUT, CONTINUE CPI "1" ;RESPONSE=1? JRZ ..ISC ;IF SO, CONTINUE CPI "2" ;REELSE, SOUND BELL .ASCIS [ABEL] JMPR ..INPT ;CONTINUE ..ITC: LXI H,SECSIZ ;GET SECTOR SIZE MVI M,0 ;SET SECTOR SIZE=0 CSTA NMBTRK ;SET FORMAT NUMBER OF TRACKS LDA FMTTYP ;GET FORMAT TYPE ORA A ;FORMAT TYPE=0? JRNZ ..ITC ;IF NOT, CONTINUE L DONE CALL DMS ;ELSE, DISPLAY MESSAGE .ASCIS [ACR] [ALF] RET ;DONE ; GETOPT: LXI D,TBUF ;GET DEFAULT BUFFER LDAX D ;GNULL INPUT, CONTINUE CPI "3" ;RESPONSE=3? JRZ ..ICC ;IF SO, CONTINUE CPI "4" ;RESPONSE=4? JRZ ..ICC ;IF SO, CONTINUE C JRZ ..SD3 ;IF SO, CONTINUE DCX H ;ELSE, DECREMENT TABLE POINTER ..SD3: MOV A,M ;GET NUMBER OF SECTORS/TRACK STA SECTRK ;SESPONSE=2? JRZ ..ISC ;IF SO, CONTINUE ..ISE: CALL DMS ;ELSE, SOUND BELL .ASCIS [ABEL] JMPR ..INPS ;CONTINUE ..ISC: SUI "0PI "C" ;FORMAT TYPE=C? JRZ ..CPM ;IF SO, CONTINUE INR M ;ELSE, INCREMENT SECTOR SIZE BY 2 INR M ..CPM: LDA DENSTY ;GET FOXI H,FLAGS ;ELSE, GET FLAGS SET CRLF,M ;SET CR/LF REQUIRED FLAG ..INPT: CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCET BUFFER COUNT ORA A ;BUFFER COUNT=0? RZ ;IF SO, DONE MOV B,A ;ELSE, BUFFER COUNT TO B-REG ..SSL: INX D ;INCREMENT BUFFPI "8" ;RESPONSE=8? JRZ ..ICC ;IF SO, CONTINUE ..ICE: CALL DMS ;ELSE, SOUND BELL .ASCIS [ABEL] JMPR ..INPC ;CONTINUE ..IT FORMAT NUMBER OF SECTORS/TRACK LXI H,GAPTBL ;GET GAP LENGTH TABLE LDA SECSIZ ;GET FORMAT SECTOR SIZE DAD D ;INDEX INTO " ;STRIP ASCII BIAS STA NMBHDS ;SET NUMBER OF HEADS LDA FMTTRK ;GET FORMAT NUMBER OF TRACKS ORA A ;FORMAT NUMBER OF TRACKSRMAT DENSITY FLAG ORA A ;FORMAT DENSITY FLAG=0? JRZ ..SD2 ;IF SO, CONTINUE INR M ;ELSE, INCREMENT SECTOR SIZE ..SD2: LXI  ER POINTER LDAX D ;GET CHARACTER FROM BUFFER CPI ";" ;CHARACTER=SEMICOLON? JRZ ..OSL ;IF SO, CONTINUE DJNZ ..SSL ;ELSE, CONSOLE INPUT LENGTH=0? RZ ;IF SO, DONE LDA INBUF+2 ;ELSE, GET CONSOLE INPUT CHARACTER RET ;DONE ; DMS: XTHL ;GET MES, CONTINUE JMPR ..FTC ;ELSE, CONTINUE ..NTBO: CPI "C" ;CHARACTER=C? JRNZ ..OSL ;IF NOT, CONTINUE ..FTC: STA FMTTYP ;ELSE, E CURRENT TRACK NUMBER SDED CSEC ;STORE CURRENT SECTOR NUMBER SHLD CDMA ;STORE CURRENT DMA ADDRESS MVI A,RETRYS ;GET NUMB ..N1S: CPI "2" ;CHARACTER=2? JRNZ ..N2S ;IF NOT, CONTINUE ..NHC: STA FMTHDS ;ELSE, SET FORMAT NUMBER OF HEADS JMPR ..OSL ;HARACTER TO CONSOLE POP PSW ;RESTORE REGISTERS POP H POP D POP B RET ;DONE ; UPRCAS: CPI "a" ;LOWER CASE ALPHA? RCONTINUE RET ;DONE ..OSL: DCR B ;DECREMENT COMMAND BUFFER COUNT RZ ;IF COMMAND BUFFER COUNT=0, DONE INX D ;INCREMENT BUSAGE ADDRESS CALL MSGHL ;DISPLAY MESSAGE XTHL ;SET UP RETURN ADDRESS RET ;DONE ; MSGHL: PUSH PSW ;SAVE AF ..L: MOV A,SET FORMAT TYPE JMPR ..OSL ;CONTINUE ; MSNTBL: .BYTE 16 ;N=0,1 16 SECTORS .BYTE 9 ;N=1,2 9 SECTORS .BYTE 5 ;N=2,3 5 SER OF RETRIES STA TRYCNT ;SET TRY COUNT ORA A ;MAKE STATUS NON-ZERO ..AGN: CZ RECAL ;FORCE RACALIBRATE ON ERROR CALL SETUCONTINUE ..N2S: CPI "3" ;CHARACTER=3? JRNZ ..N35T ;IF NOT, CONTINUE JMPR ..NTC ;ELSE, CONTINUE ..N35T: CPI "4" ;CHARACTER=C ;IF NOT, DONE CPI "z"+1 ;LOWER CASE ALPHA? RNC ;IF NOT, DONE SUI 20H ;ELSE, FORCE UPPER CASE RET ;DONE ; .XSYM .FFER POINTER LDAX D ;GET CHARACTER FROM BUFFER CALL UPRCAS ;FORCE UPPER CASE CPI "S" ;CHARACTER=S? JRNZ ..NSD ;IF NOT, CM ;GET MESSAGE BYTE INX H ;INCREMENT POINTER CALL CONOUT ;DISPLAY CHARACTER ORA A ;LAST CHARACTER? JP ..L ;IF NOT, CONTIECTORS ; GAPTBL: .BYTE 1BH,36H ;N=0,1 .BYTE 2AH,54H ;N=1,2 .BYTE 3AH,74H ;N=2,3 ; INPLN: LXI D,INBUF ;GET INPUT BUFFER UMQ`RDENSTYd$E8SECSIZe4T5E$ GAPLENd%E$FMTNIT+XeX$eX,eGX 4? JRNZ ..N40T ;IF NOT, CONTINUE JMPR ..NTC ;ELSE, CONTINUE ..N40T: CPI "8" ;CHARACTER=8? JRNZ ..N80T ;IF NOT, CONTINUE END ONTINUE JMPR ..FDC ;ELSE, CONTINUE ..NSD: CPI "D" ;CHARACTER=D? JRNZ ..NDD ;IF NOT, CONTINUE ..FDC: STA FMTDEN ;ELSE, SET NUE POP PSW ;ELSE, RESTORE AF RET ;DONE ; CONOUT: PUSH B ;SAVE REGISTERS PUSH D PUSH H PUSH PSW ANI 7FH ;STRIP SI MVI C,CIBFCN ;C=CONSOLE IN BUFFERED FUNCTION CALL OPSYS ;GET CONSOLE INPUT LDA INBUF+1 ;GET CONSOLE INPUT LENGTH ORA A ;n p8-͠@Qt2C)i:Dg6ECyl2GJmٴ SA@A3(p: qClfm㡔 7M#)@o3f!..NTC: STA FMTTRK ;ELSE, SET FORMAT NUMBER OF TRACKS JMPR ..OSL ;CONTINUE ..N80T: CPI "T" ;CHARACTER=T? JRNZ ..NTBO ;IF NOTH STA STEPR% RET ;DONE ; READ%:: DI ;ENSURE INTERRUPTS ARE DISABLED SSPD RETSP ;SAVE STACK POINTER SBCD CTRACK ;STORFORMAT DENSITY JMPR ..OSL ;CONTINUE ..NDD: CPI "1" ;CHARACTER=1? JRNZ ..N1S ;IF NOT, CONTINUE JMPR ..NHC ;ELSE, CONTINUE GN BIT FROM CHARACTER MOV E,A ;OUTPUT CHARACTER TO E-REG MVI C,RCOFCN ;C=RAW CONSOLE OUTPUT FUNCTION CALL OPSYS ;OUTPUT C   E!H@;"Cb(?B36! e@X(n &p8-͠@Qt2㩴e9 aa1b@z3A`,tf`@13A@)8 A FMTDEN ;CLEAR FORMAT DENSITY STA FMTHDS ;CLEAR FORMAT NUMBER OF HEADS STA FMTTYP ;CLEAR FORMAT TYPE CALL GETOPT ;GET COMSITY FLAG NMBHDS::.BYTE 0 ;FORMAT NUMBER OF HEADS SECSIZ::.BYTE 0 ;FORMAT SECTOR SIZE SECTRK::.BYTE 0 ;FORMAT SECTORS/TRACK ULL INPUT, CONTINUE CPI "1" ;RESPONSE=1? JRZ ..ISC ;IF SO, CONTINUE CPI "2" ;RESPONSE=2? JRZ ..ISC ;IF SO, CONTINUE ..IH ;SET INITIAL HEAD LOAD FLAG ;(READ+HEAD LOAD) MVI C,DCTL1 ;SET INTRQ STATUS I/O PORT LDED CDMA ;SET CURRENT DMA ADDRESASCIS [ABEL] JMPR ..INPD ;CONTINUE ..IDC: CPI "S" ;FORMAT DENSITY=S? JRZ ..SD1 ;IF SO, CONTINUE LXI H,DENSTY ;ELSE, GET \oᘠ?8y`P [Bc3h84E7 !r6Ne SD'3R:P3oͥ@O⠠! 08l!uC{@GMAND LINE OPTION LDA FMTDEN ;GET FORMAT DENSITY ORA A ;FORMAT DENSITY=0? JRNZ ..IDC ;IF NOT, CONTINUE LXI H,FLAGS ;ELSE,GAPLEN::.BYTE 0 ;FORMAT GAP LENGTH NMBTRK::.WORD 77 ;FORMAT NUMBER OF TRACKS ; FLAGS: .BYTE 0 ;FORMAT FLAGS FMTDEN: .BYTE 0 SE: CALL DMS ;ELSE, SOUND BELL .ASCIS [ABEL] JMPR ..INPS ;CONTINUE ..ISC: SUI "0" ;STRIP ASCII BIAS STA NMBHDS ;SET NUMBE.PAGE 85 .TITLE "TURBODOS OPERATING SYSTEM FORMATTER INITIALIZATION (8 INCH FLOPPY)" .SBTTL "COPYRIGHT 1983, SOFTWARE 2000, INFORMAT DENSITY FLAG MVI M,0FFH ;SET FORMAT DENSITY FLAG=0FFH ..SD1: LDA FMTHDS ;GET FORMAT NUMBER OF HEADS ORA A ;FORMAT NUXGXn(,!# "8,fp j)@KvA&0dLT)A# @aA#d HaASh  GET FLAGS SET CRLF,M ;SET CR/LF REQUIRED FLAG ..INPD: CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter density;FORMAT DENSITY FMTHDS: .BYTE 0 ;FORMAT NUMBER OF HEADS FMTTRK: .BYTE 0 ;FORMAT NUMBER OF TRACKS FMTTYP: .BYTE 0 ;FORMAT TYPER OF HEADS LDA FMTTYP ;GET FORMAT TYPE ORA A ;FORMAT TYPE=0? JRNZ ..ITC ;IF NOT, CONTINUE LXI H,FLAGS ;ELSE, GET FLAGS C." ; ; COPYRIGHT 1983, SOFTWARE 2000, INC. ; ; VERSION: 03/02/83 ; .IDENT FMTI8F ;MODULE ID ; .INSERT EQUATE ;SYMBOLIMBER OF HEADS=0? JRNZ ..ISC ;IF NOT, CONTINUE LXI H,FLAGS ;ELSE, GET FLAGS SET CRLF,M ;SET CR/LF REQUIRED FLAG ..INPS: CA 2@3 x2`@ EA#h: v@2\ldO6m[pŒj^c|f@ E[A d (Single/Double): " CALL INPLN ;INPUT LINE JRZ ..IDE ;IF NULL INPUT, CONTINUE CALL UPRCAS ;FORCE UPPER CASE CPI "S" ;RES INBUF: .BYTE 1,0,0 ;INPUT BUFFER ; .LOC .PROG.# ;LOCATE IN PROGRAM AREA ; FMTNIT::XRA A STA FLAGS ;CLEAR ALL FLAGS ST SET CRLF,M ;SET CR/LF REQUIRED FLAG ..INPT: CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter format type (TurboDC EQUIVALENCES ; CRLF = 0 ;CR/LF REQUIRED FLAG (FLAGS) ; .LOC .DATA.# ;LOCATE IN DATA AREA ; DENSTY::.BYTE 0 ;FORMAT DENLL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter number of sides (1/2): " CALL INPLN ;INPUT LINE JRZ ..ISE ;IF NEEK ;ELSE, SEEK TO REQUESTED TRACK ; LDED CSEC ;SET DE TO FIRST SECTOR NUMBER EXX ;SWAP TO ALTERNATE REGISTERS MVI B,084PONSE=S? JRZ ..IDC ;IF SO, CONTINUE CPI "D" ;RESPONSE=D? JRZ ..IDC ;IF SO, CONTINUE ..IDE: CALL DMS ;ELSE, SOUND BELL . OS/Cpm): " CALL INPLN ;INPUT LINE JRZ ..ITE ;IF NULL INPUT, CONTINUE CALL UPRCAS ;FORCE UPPER CASE CPI "T" ;RESPONSE=T? ACTER FROM BUFFER CPI ";" ;CHARACTER=SEMICOLON? JRZ ..OSL ;IF SO, CONTINUE DJNZ ..SSL ;ELSE, CONTINUE RET ;DONE ..OSL:Z ..SD4 ;IF FORMAT DENSITY FLAG=0, CONTINUE DCX H ;ELSE, DECREMENT TABLE POINTER ..SD4: MOV A,M ;GET GAP LENGTH STA GAPLEN N: LXI D,INBUF ;GET INPUT BUFFER MVI C,CIBFCN ;C=CONSOLE IN BUFFERED FUNCTION CALL OPSYS ;GET CONSOLE INPUT LDA INBUF+1 ;BER TABLE LDA SECSIZ ;GET FORMAT SECTOR SIZE MOV E,A ;FORMAT SECTOR SIZE TO DE-REG MVI D,0 ;DOUBLE LENGTH DAD D ;INDEX I JRNZ ..N2S ;IF NOT, CONTINUE ..NHC: STA FMTHDS ;ELSE, SET FORMAT NUMBER OF HEADS JMPR ..OSL ;CONTINUE ..N2S: CPI "T" ;CHA JRZ ..ITC ;IF SO, CONTINUE CPI "C" ;RESPONSE=C? JRZ ..ITC ;IF SO, CONTINUE ..ITE: CALL DMS ;ELSE, SOUND BELL .ASCIS [AB DCR B ;DECREMENT COMMAND BUFFER COUNT RZ ;IF COMMAND BUFFER COUNT=0, DONE INX D ;INCREMENT BUFFER POINTER LDAX D ;GET CH;SET FORMAT GAP LENGTH LDA FLAGS ;GET FLAGS BIT CRLF,A ;CR/LF REQUIRED FLAG SET? RZ ;IF NOT, DONE CALL DMS ;ELSE, DISPLGET CONSOLE INPUT LENGTH ORA A ;CONSOLE INPUT LENGTH=0? RZ ;IF SO, DONE LDA INBUF+2 ;ELSE, GET CONSOLE INPUT CHARACTER NTO MAX SECTOR NUMBER TABLE LDA DENSTY ;GET FORMAT DENSITY FLAG ORA A ;FORMAT DENSITY FLAG=0? JRZ ..SD3 ;IF SO, CONTINUE RACTER=T? JRNZ ..NTBO ;IF NOT, CONTINUE JMPR ..FTC ;ELSE, CONTINUE ..NTBO: CPI "C" ;CHARACTER=C? JRNZ ..OSL ;IF NOT, CONTEL] JMPR ..INPT ;CONTINUE ..ITC: LXI H,SECSIZ ;GET SECTOR SIZE MVI M,0 ;SET SECTOR SIZE=0 CPI "C" ;FORMAT TYPE=C? JRZ ARACTER FROM BUFFER CALL UPRCAS ;FORCE UPPER CASE CPI "S" ;CHARACTER=S? JRNZ ..NSD ;IF NOT, CONTINUE JMPR ..FDC ;ELSE, CAY MESSAGE .ASCIS [ACR] [ALF] RET ;DONE ; GETOPT: LXI D,TBUF ;GET DEFAULT BUFFER LDAX D ;GET BUFFER COUNT ORA A ;BUFFRET ;DONE ; DMS: XTHL ;GET MESSAGE ADDRESS CALL MSGHL ;DISPLAY MESSAGE XTHL ;SET UP RETURN ADDRESS RET ;DONE ; MSG DCX H ;ELSE, DECREMENT TABLE POINTER ..SD3: MOV A,M ;GET NUMBER OF SECTORS/TRACK STA SECTRK ;SET FORMAT NUMBER OF SECTORS/TRINUE ..FTC: STA FMTTYP ;ELSE, SET FORMAT TYPE JMPR ..OSL ;CONTINUE ; MSNTBL: .BYTE 26 ;N=0,1, 26 SECTORS .BYTE 15 ;N=1,2,..CPM ;IF SO, CONTINUE INR M ;ELSE, INCREMENT SECTOR SIZE BY 2 INR M ..CPM: LDA DENSTY ;GET FORMAT DENSITY FLAG ORA A ;FOONTINUE ..NSD: CPI "D" ;CHARACTER=D? JRNZ ..NDD ;IF NOT, CONTINUE ..FDC: STA FMTDEN ;ELSE, SET FORMAT DENSITY JMPR ..OSL ;ER COUNT=0? RZ ;IF SO, DONE MOV B,A ;ELSE, BUFFER COUNT TO B-REG ..SSL: INX D ;INCREMENT BUFFER POINTER LDAX D ;GET CHARHL: PUSH PSW ;SAVE AF ..L: MOV A,M ;GET MESSAGE BYTE INX H ;INCREMENT POINTER CALL CONOUT ;DISPLAY CHARACTER ORA A ;LAST ACK LXI H,GAPTBL ;GET GAP LENGTH TABLE LDA SECSIZ ;GET FORMAT SECTOR SIZE DAD D ;INDEX INTO GAP LENGTH TABLE DAD D JR 15 SECTORS .BYTE 8 ;N=2,3, 8 SECTORS ; GAPTBL: .BYTE 1BH,36H ;N=0,1 .BYTE 2AH,54H ;N=1,2 .BYTE 3AH,74H ;N=2,3 ; INPLRMAT DENSITY FLAG=0? JRZ ..SD2 ;IF SO, CONTINUE INR M ;ELSE, INCREMENT SECTOR SIZE ..SD2: LXI H,MSNTBL ;GET MAX SECTOR NUMCONTINUE ..NDD: CPI "1" ;CHARACTER=1? JRNZ ..N1S ;IF NOT, CONTINUE JMPR ..NHC ;ELSE, CONTINUE ..N1S: CPI "2" ;CHARACTER=2? CHARACTER? JP ..L ;IF NOT, CONTINUE POP PSW ;ELSE, RESTORE AF RET ;DONE ; CONOUT: PUSH B ;SAVE REGISTERS PUSH D PUS`4/["kC"2#,dPݐG ñ@ dY06b`",u?"`,m`TOR, SINGLE-DENSITY, ONE SIDED ; ; .WORD .+DSTL ;DISK SPEC TABLE LINK POINTER ; .BYTE 4 ;BLOCK SIZE ; .WORD (77*(4*(1<3)))/(TY FLAG LXI B,5500 ;GET MAX SGL DENSITY TRACK LENGTH ORA A ;FORMAT DENSITY FLAG=0? JRZ ..SD1 ;IF SO, CONTINUE LXI B,1100 .WORD 0 ;TRANSLATION TABLE ADDRESS .BYTE 3!12 K( FORMAU((   FORMAT ABORTE! 4! 5 :G 2 2 * #" * +"'S .KLIT 12,0 ;12 ZEROES .KLIT 3,0F5H ;3 F5'S .KLIT 1,0FEH ;ID ADDRESS MARK (FE) .WORD KTRK ;TRACK NUMBER .WORD KSID ;l`DD`  X _dN@ld@,@X` z @-@9l`[r ^NGTH .KLIT 1,0F7H ;CRC GENERATION (F7) .KLIT 22,04EH ;22 4E'S (ADDR/DATA GAP) .KLIT 12,0 ;12 ZEROES .KLIT 3,0F5H ;3 F5'SXp`8D5D:ҐUP LYo+7Rr\@k 44 VP*`X  @t@AGN: CZ RECAL ;IF SO, RE-CALIBRATE DRIVE ..RTK: IN TRACK ;WHAT TRACK ARE WE ON? CPI 2 ;IS IT AT LEAST TRACK 2? JRNC ..RAD ; |  SUCCESSFUL FORMAT STARTING VERIFY PASi INSERT DISK TO BE VERIFIED IN DRIVE: A, ENTER TO BEGIN SIDE NUMBER .WORD KSEC ;SECTOR NUMBER .KLIT 1,3 ;RECORD LENGTH .KLIT 1,0F7H ;CRC GENERATION (F7) .KLIT 22,04EH ;22 4E'S N@ ȇ 4Jhq JIq` H1P Jhq 8 .KLIT 1,0FBH ;DATA ADDRESS MARK (FB) .KLIT 128,0E5H ;512 E5'S .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 1@,`[{ X C@,d@,@ -` }  @@,`YES,OK TO DO IT HERE. LDA STEPR% ;FORM STEP COMMAND ORI 058H OUT DCOM ;STEP IN ONE TRACK CALL WTSEEK ;WAIT FOR COMPLETVERIFYING  (  ! " >2 K!" !: =E)" N S *Rڝ* " 2 !" * "!" K((ADDR/DATA GAP) .KLIT 12,0 ;12 ZEROES .KLIT 3,0F5H ;3 F5'S .KLIT 1,0FBH ;DATA ADDRESS MARK (FB) .KLIT 128,0E5H ;1,024 E>COPYRIGHT (C) 1982, SOFTWARE 2000, INC. (VERSION 09/29/82) 1B wx:\=2 : O³: 60F INSERT DISK TO,0F7H ;CRC GENERATION (F7) .KLIT 34,04EH ;34 4E'S .WORD KNXT ;JMP KLP ; ; 1,024 BYTE SECTOR, DOUBLE DENSITY ; KLSTD3: .KOX ȀYp :` +{ [@-@9l`[{ X :@0`o[Y .g@,`/{QU&RINTLVeE$Ip>V*X v 1u@@؜ vX: VERIFU((   VERIFY ABORTE* #" *+"| * #" * +" |  SUCCESSFUL VERIF NON-PRIVI5'S .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KLIT 128,0E5H .KL BE FORMATTED IN DRIVE: A, ENTER TO BEGIN FORMATTING  ( >2 KW STARTING FORMAT PASS *ELIT 80,04EH ;80 4E'S .KLIT 12,0 ;12 ZEROES .KLIT 3,0F6H ;3 F6'S .KLIT 1,0FCH ;INDEX MARK (FC) KLPD3: .KLIT 50,04EH ;50 4E'X `޶@-@9l`D`  X _dN@ld@,@X` z @-@9 LEGED USER NO FORMAT DRIVE SPECIFIED UNABLE TO LOCKOUT FORMAT DRIVE FORMAT DRIVE NOT READY j INS ANI 1 ;1791 BUSY? JRNZ FDPR ;IF SO, LOOP ; GETSTS: MVI A,0D0H ;FORCE STATUS UPDATE OUT DCOM XTHL ;WAIT FOR 1791 TO SE = TM502 8 = TM503 9 = SA602 ; Shugart Associates SA602 10 = SA604 11 = SA606 12 = SA1002 ; Shugart Associates SA1CLADDR ;SAVE ADDRESS OF CURRENT LATCH BYTE ; CALL GETSTS ;GET DRIVE STATUS ANI 80H ;CHECK NOT-READY BIT JRZ ..RDY ;IS REA:a0DM)) )o”$=y))-D !N *R> !N 6#½:D G_!N }/o|/g#"J x/o&#"L N *J *L xFORMATT ;SUPER QUAD FORMATTER COMMON ROUTINE FMTHDC ;HDC1001 FORMATTING SPECIFICS UFFICIENT MEMORY TO FORMATU INSUFFICIENT MEMORY TO VERIFY: O +. VERIFY DRIVE NOT READY : Ojó! ˆ : TTLE XTHL XTHL XTHL IN DSTAT ;GET STATUS STA CSTAT ;SAVE CURRENT STATUS RET ; SELDSK: LDA CDSK ;GET REQ DRIVE CP002 13 = SA1004 14 = Q2010 ; Quantum Q2010 15 = Q2020 16 = Q2030 17 = Q2040 18 = M4010 ; MiniScribe 4010 19 = M40DY, JUMP CALL GETSTS ;NOT READY, GIVE IT ANOTHER CHANCE ANI 80H JRNZ ..NRDY ;IF NOT-READY, RETURN ERROR ; ..RDY: LXI D,D*H :D !N " :D 2 : 2 2 2 !" 222SelWAIT FOR COMPLETION POP B ;RESTORE NEW DRIVE NUMBER ..TST: MOV L,B ;COMPUTE LATCH STORAGE LOCATION MVI H,0 LXI D,LATBL GOjóG;(! =R V _pѷs V ERROR, DRIVE:: A,, TRACK:* I 4 ;COMPARE WITH MAX DRIVE NUMBER JNC ..NRDY ;IF INVALID, RETURN NOT READY MOV B,A ;SAVE DRIVE NUMBER LDA FDCDRV ;GET LAS20 ? $ Invalid input try again. $RTBL ;GET DRIVE TRACK TABLE LDA FDCDRV ;GET LAST REFERENCED DRIVE INR A ;UNDEFINED? JRZ ..UND ;YES, CONTINUE DCR A MOVect disk type from following menu *** Hard Disk selection choices *** 0 = ST503 ; Seagate Technology ST503 1 = ST50DAD D MOV A,M ;GET OLD LATCH VALUE CPI 0FFH ;IS IT UNDEFINED? JRNZ ..OLD ;NO, USE OLD VALUE MOV A,B ;GET NEW DRIVE NUMBE (RETRY, IGNORE, ABORT)( =A7( R(I   'd  R0x  0,T DRIVE USED CMP B ;ARE THEY THE SAME? JRZ ..TST ;YES, NO NEED TO UNLOAD HEAD. CALL GETSTS ;GET CURRENT DRIVE STATUS ANI L,A ;MAKE DOUBLE LENGTH MVI H,0 DAD D ;CALCULATE TRACK TABLE ADDRESS IN TRACK ;GET 1791 TRACK REGISTER MOV M,A ;SAVE IN6 2 = TM601S ; Tandon Magnetics TM601S 3 = TM602S 4 = TM603S 5 = TM603SE 6 = TM501 ; Tandon Magnetics TM501 7 R ADD A ;SHIFT TO BITS 4&5 ADD A ADD A ADD A ..OLD: OUT DCONT ;SELECT DRIVE MOV M,A ;SAVE CURRENT LATCH VALUE SHLD  ~#,  _A[ } B  :C (8   D !0a 0A0H ;READY AND HEAD LOADED? CPI 020H JRNZ ..TST ;NO, NO NEED TO UNLOAD. IN TRACK ;UNLOAD WITH A SEEK TO PRESENT TRACK  .PAGE 85 .TITLE "TURBODOS OPERATING SYSTEM FORMAT A DISK UTILITY PROGRAM" .SBTTL "COPYRIGHT (C) 1982, SOFTWARE 2000, INC." ;  ;ELSE, SOUND BELL .ASCIS [ABEL] JMPR ..CRL1 ;CONTINUE ..CR1: MVI A,3 ;GET RETURN READY FUNCTION NUMBER STA PDRFCN ;SET P CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Insert disk to be formatted in drive " LDA PDRDRV ;GET PD REQUEST IF NOT, CONTINUE CALL CONIN ;ELSE, GET CONSOLE INPUT CHARACTER CPI AETX ;CHARACTER=CONTROL C? JRNZ ..FMTC ;IF NOT, CONTINU? JZ ..NPU ;IF NOT, CONTINUE LDA TFCB ;ELSE, GET DEFAULT FCB DRIVE ORA A ;FORMAT DRIVE SPECIFIED? JZ ..NFDS ;IF NOT, CONRKNIT# ;INITIALIZE TRACK BUFFER ORA A ;TRACK BUFFER INITIALIZED OK? JNZ ..IFME ;IF NOT, CONTINUE MVI A,4 ;GET FORMAT TRACK ; COPYRIGHT (C) 1982, SOFTWARE 2000, INC. ; ; VERSION: 09/29/82 ; .IDENT FORMAT ;MODULE ID ; .INSERT EQUATE ;SYMBOLIC ED REQUEST PACKET FUNCTION CALL XECPDA ;RETURN FORMAT DRIVE READY STATUS JZ ..FDNR ;IF DRIVE NOT READY, CONTINUE CALL DMS ;DRIVE ADI "A" ;ADD ASCII BIAS CALL CONOUT ;DISPLAY PD REQUEST DRIVE LETTER CALL FLSHCI ;FLUSH CONSOLE INPUT CALL DMS ;DIE CALL DMS ;ELSE, DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Format aborted" JMP ..X ;CONTINUE ..NCA1: LXI H,HEADNO ;GTINUE DCR A ;ELSE, DECREMENT FORMAT DRIVE STA PDRDRV ;SET PD REQUEST DRIVE CALL GETOPT ;ELSE, GET OPTIONS LDA OPTFLG ;GE FUNCTION NUMBER STA PDRFCN ;SET PD REQUEST PACKET FUNCTION ..FTL: CALL XECPDA ;FORMAT TRACK JRZ ..FMTC ;IF NO ERRORS, CONTQUIVALENCES ; REP = 0 ;REPEAT FLAG (OPTFLG) VFY = 1 ;VERIFY ONLY FLAG (OPTFLG) ; .LOC .PROG.# ;LOCATE IN PROGRAM AREA ;ELSE, DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCII "Starting format pass" .ASCIS [ACR] [ALF] LHLD NMBTRK# ;GET NUMBER OF TRSPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Enter to begin formatting " ..CRL1: CALL CONIN ;GET CONSOLE INPUT CPI ACR ;ET HEAD NUMBER INR M ;INCREMENT HEAD NUMBER LXI H,HEADCT ;GET HEAD COUNT DCR M ;DECREMENT HEAD COUNT JRNZ ..FHL ;CONTINT OPTION FLAGS BIT VFY,A ;VERIFY ONLY FLAG SET? JNZ ..VFYO ;IF SO, CONTINUE LDA PDRDRV ;ELSE, GET FORMAT DRIVE CALL LOKDINUE CALL DMS .ASCII [ACR] [ALF] .ASCIS "Format" CALL ERRCOM ;PROCESS FORMAT ERROR JC ..X ;IF CONTROL C, CONTINUE JR .ASCII "COPYRIGHT (C) 1982, SOFTWARE 2000, INC." .ASCII " (VERSION 09/29/82) " ;VERSION DATE ; START: LXI SP,STACK ;SETACKS SHLD TRKCNT ;SET TRACK COUNT LXI H,0 SHLD PDRTRK ;SET PD REQUEST TRACK NUMBER=0 ..FCL: CALL DMS ;DISPLAY MESSAGE .CHARACTER=CARRIAGE RETURN? JRZ ..CR1 ;IF SO, CONTINUE CPI AETX ;CHARACTER=CONTROL C? JZ ..ERRX ;IF SO, CONTINUE CALL DMSUE FOR ALL HEADS LHLD PDRTRK ;GET PD REQUEST TRACK NUMBER INX H ;INCREMENT PD REQUEST TRACK NUMBER SHLD PDRTRK ;UPDATE PD RV ;LOCKOUT FORMAT DRIVE JNZ ..LFDE ;IF FORMAT DRIVE IN USE, CONTINUE ..FMT: CALL FMTNIT# ;ELSE, INITIALIZE FORMAT PARAMETERSZ ..FTL ;IF CARRIAGE RETURN, CONTINUE ..FMTC: CALL CONST ;ELSE, GET CONSOLE STATUS ORA A ;CHARACTER AVAILABLE? JRZ ..NCA1 ; UP STACK POINTER MVI C,ROUFCN ;C=RETURN ORIGIN/UNIT FUNCTION CALL OPSYS ;GET ORIGIN/UNIT NUMBER BIT 7,B ;PRIVILEGED USERASCIS "." LDA NMBHDS# ;GET NUMBER OF HEADS STA HEADCT ;SET HEAD COUNT XRA A STA HEADNO ;SET HEAD NUMBER=0 ..FHL: CALL T REQUEST TRACK NUMBER LHLD TRKCNT ;GET TRACK COUNT DCX H ;DECREMENT HEAD COUNT SHLD TRKCNT ;UPDATE TRACK COUNT MOV A,H  PD REQUEST PACKET DMA ADDRESS DAD D ;CALC END OF DMA ADDRESS XCHG ;END OF DMA ADDRESS TO DE-REG LHLD OPSYS+1 ;GET TOP OFL XECPDA ;SELECT VERIFY DRIVE JZ ..VDNR ;IF DRIVE NOT READY, CONTINUE LHLD SECTRK ;GET NUMBER OF SECTORS/TRACK SHLD PDRSC ;GET PD REQUEST TRACK NUMBER INX H ;INCREMENT PD REQUEST TRACK NUMBER SHLD PDRTRK ;UPDATE PD REQUEST TRACK NUMBER LHLD TRKASCIS "Enter to begin verifying " ..CRL2: CALL CONIN ;GET CONSOLE INPUT CPI ACR ;CHARACTER=CARRIAGE RETURN? JRZ ..CR2 CONTINUE CALL DMS .ASCII [ACR] [ALF] .ASCIS "Verify" CALL ERRCOM ;PROCESS VERIFY ERROR JC ..X ;IF CONTROL C, CONTINUE ORA L ;TRACK COUNT=0? JRNZ ..FCL ;IF NOT, CONTINUE CALL DMS ;ELSE, DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCII "Successful TRANSIENT PROGRAM AREA ORA A ;CLEAR CARRY FLAG DSBC D ;SUFFICIENT MEMORY FOR TRACK READ? JC ..IVME ;IF NOT, CONTINUE LH;SET PD REQUEST SECTOR COUNT DAD H ;SHIFT HL-REG LEFT 7 (*128) DAD H DAD H DAD H DAD H DAD H DAD H LDA SECSIZ ;GCNT ;GET TRACK COUNT DCX H ;DECREMENT HEAD COUNT SHLD TRKCNT ;UPDATE TRACK COUNT MOV A,H ORA L ;TRACK COUNT=0? JRNZ ..;IF SO, CONTINUE CPI AETX ;CHARACTER=CONTROL C? JZ ..ERRX ;IF SO, CONTINUE CALL DMS ;ELSE, SOUND BELL .ASCIS [ABEL] JM JRZ ..VTL ;IF CARRIAGE RETURN, CONTINUE ..VFYC: CALL CONST ;ELSE, GET CONSOLE STATUS ORA A ;CHARACTER AVAILABLE? JRZ ..NC format" .ASCII [ACR] [ALF] .ASCIS "Starting verify pass" JMPR ..CR2 ;CONTINUE ..VFYO: CALL DMS ;DISPLAY MESSAGE .ASCIILD TRKDSK ;ELSE, GET NUMBER OF TRACKS/DISK SHLD TRKCNT ;SET TRACK COUNT XRA A ;ELSE, GET READ FUNCTION STA PDRFCN ;SET PD ET SECTOR SIZE ..SL: DCR A ;DECREMENT SECTOR SIZE JM ..SLX ;IF UNDERFLOW, CONTINUE DAD H ;ELSE, SHIFT BYTE COUNT LEFT JMPVCL ;IF NOT, CONTINUE CALL DMS ;ELSE, DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Successful verify" JMP ..X ;CONTINUE .PR ..CRL2 ;CONTINUE ..CR2: CALL DMS ;DISPLAY MESSAGE .ASCIS [ACR] [ALF] LXI H,VFYDST ;GET VERIFY DST ADDRESS SHLD PDRDMAA2 ;IF NOT, CONTINUE CALL CONIN ;ELSE, GET CONSOLE INPUT CHARACTER CPI AETX ;CHARACTER=CONTROL C? JRNZ ..VFYC ;IF NOT, CON [ACR] [ALF] .ASCIS "Insert disk to be verified in drive " LDA PDRDRV ;GET PD REQUEST DRIVE ADI "A" ;ADD ASCII BIAS CALLREQUEST PACKET FUNCTION LXI H,0 ;GET TRACK 0 SHLD PDRTRK ;SET PD REQUEST PACKET TRACK=0 SHLD PDRSEC ;SET PD REQUEST PACKETR ..SL ;CONTINUE ..SLX: SHLD PDRTC ;SET PD REQUEST TRANSFER COUNT LXI D,.END.# ;GET VERIFY BUFFER ADDRESS SDED PDRDMA ;SET.NPU: CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Non-privileged user" [ABEL] JMP ..ERRX ;DONE ..NFDS: CALL DMS  ;SET PD REQUEST PACKET DMA ADDRESS MVI A,2 ;GET RETURN DST FUNCTION NUMBER STA PDRFCN ;SET PD REQUEST PACKET FUNCTION CALTINUE CALL DMS ;ELSE, DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Verify aborted" JMP ..X ;CONTINUE ..NCA2: LHLD PDRTRK  CONOUT ;DISPLAY PD REQUEST DRIVE LETTER CALL FLSHCI ;FLUSH CONSOLE INPUT CALL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] . SECTOR=0 ..VCL: CALL DMS ;DISPLAY MESSAGE .ASCIS "." ..VTL: CALL XECPDA ;READ PD REQUEST TRACK JRZ ..VFYC ;IF NO ERRORS,  ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "No format drive specified" [ABEL] JMP ..ERRX ;CONTINUE ..LFDE: CALL DMS ;DISPMENT COMMAND BUFFER COUNT RZ ;IF COMMAND BUFFER COUNT=0, DONE INX D ;INCREMENT BUFFER POINTER LDAX D ;GET CHARACTER FROM SET? JZ WBOOT ;IF NOT, DONE BIT VFY,A ;VERIFY ONLY BIT SET? JZ ..FMT ;IF NOT, CONTINUE JMP ..VFYO ;ELSE, CONTINUE ; GECALL DMS ;DISPLAY MESSAGE .ASCIS ", Track: " LHLD PDRTRK ;GET PD REQUEST TRACK NUMBER CALL DECOUT ;DISPLAY SORCE TRACK NUMT VFY,A ;VERIFY ONLY FLAG SET? JRNZ ..ERRX ;IF SO, CONTINUE JMPR ..X ;ELSE, CONTINUE ..VDNR: CALL DMS ;DISPLAY MESSAGE .ANOT, DONE MVI D,80H ;D=FREE BUFFER FLAG MVI C,FFBFCN ;C=FLUSH/FREE BUFFERS FUNCTION CALL OPSYS ;FLUSH FREE DRIVE BUFFERS LAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Unable to lockout format drive" [ABEL] JMP ..ERRX ;CONTINUE ..FDNR: CALL DMS ;DISPBUFFER CALL UPRCAS ;FORCE UPPER CASE CPI "R" ;CHARACTER=R? JRNZ ..NREP ;IF NOT, CONTINUE SET REP,M ;ELSE, SET REPEAT FLATOPT: LXI D,TBUF ;GET DEFAULT BUFFER LDAX D ;GET BUFFER COUNT ORA A ;BUFFER COUNT=0? RZ ;IF SO, DONE MOV B,A ;ELSE, BUFBER CALL DMS ;DISPLAY MESSAGE .ASCIS " (Retry, Ignore, Abort) " ..CIL: CALL DMS ;SOUND BELL .ASCIS [ABEL] CALL FLSHCI ;SCII [ACR] [ALF] .ASCII "Verify drive not ready" [ABEL] .ASCIS [ACR] [ALF] LDA OPTFLG ;GET OPTION FLAGS BIT VFY,A ;VERIF XRA A ;SET ZERO FLAG RET ;DONE ; XECPDA: LXI D,PDRDP ;GET PD REQUEST PACKET ADDRESS MVI C,PDAFCN ;C=PHYSICAL DISK ACCELAY MESSAGE .ASCII [ACR] [ALF] .ASCII "Format drive not ready" [ABEL] .ASCIS [ACR] [ALF] JMP ..FMT ;CONTINUE ..IFME: CAG JMPR ..OSL ;CONTINUE ..NREP: CPI "V" ;CHARACTER=V? JRNZ ..OSL ;IF NOT, CONTINUE SET VFY,M ;ELSE, SET VERIFY ONLY FLAG FER COUNT TO B-REG ..SSL: INX D ;INCREMENT BUFFER POINTER LDAX D ;GET CHARACTER FROM BUFFER CPI ";" ;CHARACTER=SEMICOLON? FLUSH CONSOLE INPUT ..CSL: CALL CONST ;GET CONSOLE STATUS ORA A ;CHARACTER AVAILABLE? JRZ ..CSL ;IF NOT, CONTINUE CALL COY ONLY FLAG SET? JZ ..FMT ;IF NOT, CONTINUE JMP ..VFYO ;ELSE, CONTINUE ..ERRX: LXI H,OPTFLG ;GET OPTION FLAGS RES REP,M SS FUNCTION CALL OPSYS ;PERFORM PHYSICAL DISK ACCESS ORA A ;RETURN CODE=0? RET ;DONE ; ERRCOM: CALL DMS ;DISPLAY MESSAGLL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Insufficient memory to format" [ABEL] JMPR ..ERRX ;CONTINUE ..IVME: CA JMPR ..OSL ;CONTINUE ; LOKDRV: MOV E,A ;FORMAT DRIVE TO E-REG PUSH D ;SAVE DRIVE MVI D,0FFH ;D=LOCK DRIVE FLAG MVI C,LF JRZ ..OS ;IF SO, CONTINUE DJNZ ..SSL ;ELSE, CONTINUE RET ;DONE ..OS: LXI H,OPTFLG ;GET OPTION FLAGS ..OSL: DCR B ;DECRENIN ;ELSE, GET CONSOLE INPUT CALL UPRCAS ;FORCE UPPER CASE CPI "A" ;CHARACTER=ABORT? STC ;SET CARRY FLAG JRZ ..X ;IF CH;RESET REPEAT FLAG ..X: CALL DMS ;DISPLAY MESSAGE .ASCIS [ACR] [ALF] LDA OPTFLG ;GET OPTION FLAGS BIT REP,A ;REPEAT FLAG E .ASCIS " error, Drive: " LDA PDRDRV ;GET PD REQUEST DRIVE ADI "A" ;ADD ASCII BIAS CALL CONOUT ;DISPLAY DRIVE LETTER LL DMS ;DISPLAY MESSAGE .ASCII [ACR] [ALF] .ASCIS "Insufficient memory to verify" [ABEL] LDA OPTFLG ;GET OPTION FLAGS BIDFCN ;C=LOCKOUT/FREE DRIVE FUNCTION CALL OPSYS ;LOCKOUT DRIVE POP D ;RESTORE DRIVE ORA A ;LOCKOUT SUCCESSFUL? RNZ ;IF  ARACTER=CONTROL C, CONTINUE CPI "R" ;CHARACTER=RETRY? JRZ ..X ;IF SO, CONTINUE CPI "I" ;CHARACTER=IGNORE? JRNZ ..CIL ;IFSAVE REGISTERS PUSH D PUSH H MVI C,RCIFCN ;C=RAW CONSOLE INPUT FUNCTION CALL OPSYS ;GET CONSOLE INPUT POP H ;RESTORE  ;GET MESSAGE ADDRESS CALL MSGHL ;DISPLAY MESSAGE XTHL ;SET UP RETURN ADDRESS RET ;DONE ; MSGHL: PUSH PSW ;SAVE AF .CATION BLOCKS NMBDIR: .BYTE 0 ;NUMBER OF DIRECTORY BLOCKS SECSIZ: .BYTE 0 ;SECTOR SIZE SECTRK: .WORD 0 ;SECTORS/TRACK TRKDSK ..DO INR C ;INCREMENT LEADING ZERO FLAG LXI D,1 ;DISPLAY UNITS DIGIT ..DO: MVI B,-1 ;PRESET QUOTENT ORA A ;CLEAR CARRY F;LOCATE IN DATA AREA ; HEADNO::.BYTE 0 ;HEAD NUMBER ; PDRDP:: ;PD REQUEST PACKET PDRFCN::.BYTE 0 ;PD REQUEST FUNCTION PD NOT, CONTINUE ORA A ;ELSE, CLEAR ZERO FLAG ..X: CALL DMS ;DISPLAY MESSAGE .ASCIS [ACR] [ALF] RET ;DONE ; FLSHCI: CALLREGISTERS POP D POP B RET ;DONE ; CONOUT: PUSH B ;SAVE REGISTERS PUSH D PUSH H PUSH PSW ANI 7FH ;STRIP SIGN BIT.L: MOV A,M ;GET MESSAGE BYTE INX H ;INCREMENT POINTER CALL CONOUT ;DISPLAY CHARACTER ORA A ;LAST CHARACTER? JP ..L ;IF : .WORD 0 ;TRACKS/DISK RESTRK: .WORD 0 ;RESERVED TRACKS ; OPTFLG: .BYTE 0 ;OPTION FLAGS TRKCNT: .WORD 0 ;TRACK COUNT HEADCTLAG ..DL: INR B ;INCREMENT QUOTENT DSBC D ;SUBTRACT DIVISOR JRNC ..DL ;UNTIL UNDERFLOW DAD D ;RESTORE UNDERFLOW MOV A,BRDRV::.BYTE 0 ;PD REQUEST DRIVE NUMBER PDRTRK::.WORD 0 ;PD REQUEST TRACK NUMBER PDRSEC::.WORD 0 ;PD REQUEST SECTOR NUMBER PDR CONST ;GET CONSOLE STATUS ORA A ;CHARACTER AVAILABLE? RZ ;IF NOT, DONE CALL CONIN ;ELSE ,GET CONSOLE INPUT CHARACTER J FROM CHARACTER MOV E,A ;OUTPUT CHARACTER TO E-REG MVI C,RCOFCN ;C=RAW CONSOLE OUTPUT FUNCTION CALL OPSYS ;OUTPUT CHARACTNOT, CONTINUE POP PSW ;ELSE, RESTORE AF RET ;DONE ; CONST: PUSH B ;SAVE REGISTERS PUSH D PUSH H MVI C,CSFCN ;C=CONS: .BYTE 0 ;HEAD COUNT ; .BLKW 64 ;STACK AREA STACK = . ;TOP OF STACK AREA ; .XSYM .END START  ;GET QUOTENT ORA A ;QUOTENT=0? JRNZ ..DD ;IF NOT, DISPLAY DIGIT INR C DCR C ;LEADING ZERO FLAG SET? RZ ;IF NOT, DONESC:: .WORD 0 ;PD REQUEST SECTOR COUNT PDRTC:: .WORD 0 ;PD REQUEST TRANSFER COUNT PDRDMA::.WORD 0 ;PD REQUEST DMA ADDRESS PDRDMPR FLSHCI ;CONTINUE ; DECOUT: MVI C,0 ;CLEAR LEADING ZERO FLAG LXI D,10000 ;DISPLAY TEN THOUSANDS DIGIT CALL ..DO LXI DER TO CONSOLE POP PSW ;RESTORE REGISTERS POP H POP D POP B RET ;DONE ; UPRCAS: CPI "a" ;LOWER CASE ALPHA? RC ;IFOLE STATUS FUNCTION CALL OPSYS ;GET CONSOLE STATUS POP H ;RESTORE REGISTERS POP D POP B RET ;DONE ; CONIN: PUSH B ;R LDA FDCDRV ;GET LAST DRIVE USED CMP B ;ARE THEY THE SAME? JRZ ..SEL ;YES, NO NEED TO UNLOAD HEAD. CALL GETSTS ;GET CUR ..DD: ADI "0" ;ADD ASCII BIAS CALL CONOUT ;DISPLAT CHARACTER INR C ;INCREMENT LEADING ZERO FLAG RET ;DONE ; DMS: XTHLST::.WORD 0 ;PD REQUEST DST ADDRESS ; VFYDST: ;VERIFY DST AREA BLKSIZ: .BYTE 0 ;BLOCK SIZE NMBLKS: .WORD 0 ;NUMBER OF ALLO,1000 ;DISPLAY THOUSANDS DIGIT CALL ..DO LXI D,100 ;DISPLAY HUNDREDS DIGIT CALL ..DO LXI D,10 ;DISPLAY TENS DIGIT CALL NOT, DONE CPI "z"+1 ;LOWER CASE ALPHA? RNC ;IF NOT, DONE SUI 20H ;ELSE, FORCE UPPER CASE RET ;DONE ; .LOC .DATA.#  ԓPU&@HEADNOUE$EPDRFCNeE$E%hPDRTRKeE%4T88PDRSCUE%D8XPDRDMAeE$E5Ih P,$rAP@(!DjB"dX*)%$FP*r!#IaY<@+ x +NF1@d9NQt! E,ʬ ;L!@ 36QC4#Y=Yv"8L4a$CiFA_!INUE DEC A ;ELSE, DECREMENT FORMAT DRIVE LD (PDRDRV),A ;SET PD REQUEST DRIVE CALL GETOPT ;ELSE, GET OPTIONS LD A,(OPTF͡>ͻQt2H| :#)n#Ii7 o*n"0f@j(CX,|`m'eZP1V`pHR)E#&=}S!Ha"  EQUIVALENCES ; REP DEFL 0 ;REPEAT FLAG (OPTFLG) VFY DEFL 1 ;VERIFY ONLY FLAG (OPTFLG) ; CSEG ;LOCATE IN PROGRAM AREA d,b\R"CX $bE)$p`9"R qݚ2 :.=` maY=iGXDT0 3n 4I7̧#i9CxeYSICAL SECTOR SIZE (2^N*128) ; .WORD 8 ;PHYSICAL SECTORS PER TRACK ; .WORD 2*77 ;PHYSICAL TRACKS PER DISK ; .WORD 0 ;RESERVED <_a :KPpf@ ,٠P 4 [Yx@e9!`r41, ͻPa1JVfڐFm FS,Ly,LFLG) ;GET OPTION FLAGS BIT VFY,A ;VERIFY ONLY FLAG SET? JP NZ,..VFYO ;IF SO, CONTINUE LD A,(PDRDRV) ;ELSE, GET FORMAT DRIVS`X [JM*,6`"`, ͻm'ٷx +NF3LAWL PfE:ͿͻQXr4" r:\;*`1aX  ; DB "COPYRIGHT (C) 1982, SOFTWARE 2000, INC." DB " (VERSION 09/29/82) " ;VERSION DATE ; START: LD SP,STACK ;SET UP STACK#it2pr4cY gx "SxC)Cxe3M1m0q@Ϳhp6! e@Lٷx ) '#g#i TRACKS ; .WORD 0 ;TRANSLATION TABLE ADDRESS ; .BYTE 2!1 TO BEGIN VERIFYING"," "+80H ..CRL2: CALL CONIN ;GET CONSOLE INPUT CP ACRADY, CONTINUE CALL DMS ;ELSE, DISPLAY MESSAGE DB ACR,ALF DB "STARTING FORMAT PASS" DB ACR,ALF+80H LD HL,(NMBTRK##) ;GAD COUNT LD (TRKCNT),HL ;UPDATE TRACK COUNT LD A,H OR L ;TRACK COUNT=0? JR NZ,..FCL ;IF NOT, CONTINUE CALL DMS ;ELSE INPUT CALL DMS ;DISPLAY MESSAGE DB ACR,ALF DB "ENTER TO BEGIN FORMATTING"," "+80H ..CRL1: CALL CONIN ;GET CONSOLE80H JP ..X ;CONTINUE ..NCA1: LD HL,HEADNO ;GET HEAD NUMBER INC (HL) ;INCREMENT HEAD NUMBER LD HL,HEADCT ;GET HEAD COUNT TRACK JR Z,..FMTC ;IF NO ERRORS, CONTINUE CALL DMS DB ACR,ALF+80H DB "FORMA","T"+80H CALL ERRCOM ;PROCESS FORMAT ERR ;CHARACTER=CARRIAGE RETURN? JR Z,..CR2 ;IF SO, CONTINUE CP AETX ;CHARACTER=CONTROL C? JP Z,..ERRX ;IF SO, CONTINUE CET NUMBER OF TRACKS LD (TRKCNT),HL ;SET TRACK COUNT LD HL,0 LD (PDRTRK),HL ;SET PD REQUEST TRACK NUMBER=0 LD A,(NMBHDS##, DISPLAY MESSAGE DB ACR,ALF DB "SUCCESSFUL FORMAT" DB ACR,ALF DB "STARTING VERIFY PAS","S"+80H JR ..CR2 ;CONTINUE . INPUT CP ACR ;CHARACTER=CARRIAGE RETURN? JR Z,..CR1 ;IF SO, CONTINUE CP AETX ;CHARACTER=CONTROL C? JP Z,..ERRX ;IF S DEC (HL) ;DECREMENT HEAD COUNT JR NZ,..FCL ;CONTINUE FOR ALL HEADS LD A,(NMBHDS##) ;GET NUMBER OF HEADS LD (HEADCT),A OR JP C,..X ;IF CONTROL C, CONTINUE JR Z,..FTL ;IF CARRIAGE RETURN, CONTINUE ..FMTC: CALL CONST ;ELSE, GET CONSOLE STATUALL DMS ;ELSE, SOUND BELL DB ABEL+80H JR ..CRL2 ;CONTINUE ..CR2: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF+80H LD HL,VFYD) ;GET NUMBER OF HEADS LD (HEADCT),A ;SET HEAD COUNT XOR A LD (HEADNO),A ;SET HEAD NUMBER=0 ..FCL: CALL DMS ;DISPLAY MES.VFYO: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF DB "INSERT DISK TO BE VERIFIED IN DRIVE"," "+80H LD A,(PDRDRV) ;GET PD REQUESO, CONTINUE CALL DMS ;ELSE, SOUND BELL DB ABEL+80H JR ..CRL1 ;CONTINUE ..CR1: LD A,3 ;GET RETURN READY FUNCTION NUMBER;SET HEAD COUNT XOR A LD (HEADNO),A ;SET HEAD NUMBER=0 LD HL,(PDRTRK) ;GET PD REQUEST TRACK NUMBER INC HL ;INCREMENT PDS OR A ;CHARACTER AVAILABLE? JR Z,..NCA1 ;IF NOT, CONTINUE CALL CONIN ;ELSE, GET CONSOLE INPUT CHARACTER CP AETX ;CHAST ;GET VERIFY DST ADDRESS LD (PDRDMA),HL ;SET PD REQUEST PACKET DMA ADDRESS LD A,2 ;GET RETURN DST FUNCTION NUMBER LD (PSAGE DB "."+80H ..FHL: CALL TRKNIT## ;INITIALIZE TRACK BUFFER OR A ;TRACK BUFFER INITIALIZED OK? JP NZ,..IFME ;IF NOT, CT DRIVE ADD A,"A" ;ADD ASCII BIAS CALL CONOUT ;DISPLAY PD REQUEST DRIVE LETTER CALL FLSHCI ;FLUSH CONSOLE INPUT CALL  LD (PDRFCN),A ;SET PD REQUEST PACKET FUNCTION CALL XECPDA ;RETURN FORMAT DRIVE READY STATUS JP Z,..FDNR ;IF DRIVE NOT RE REQUEST TRACK NUMBER LD (PDRTRK),HL ;UPDATE PD REQUEST TRACK NUMBER LD HL,(TRKCNT) ;GET TRACK COUNT DEC HL ;DECREMENT HE DRFCN),A ;SET PD REQUEST PACKET FUNCTION CALL XECPDA ;SELECT VERIFY DRIVE JP Z,..VDNR ;IF DRIVE NOT READY, CONTINUE LD HL"VERIFY ABORTE","D"+80H JP ..X ;CONTINUE ..NCA2: LD HL,(PDRSEC) ;GET PD REQUEST SECTOR NUMBER INC HL ;INCREMENT PD REQUESALL XECPDA ;READ PD REQUEST TRACK JR Z,..VFYC ;IF NO ERRORS, CONTINUE CALL DMS DB ACR,ALF DB "VERIF","Y"+80H CALL ERR DB ACR,ALF DB "FORMAT DRIVE NOT READY",ABEL DB ACR,ALF+80H JP ..FMT ;CONTINUE ..IFME: CALL DMS ;DISPLAY MESSAGE DB A OR A ;CLEAR CARRY FLAG SBC HL,DE ;SUFFICIENT MEMORY FOR TRACK READ? JP C,..IVME ;IF NOT, CONTINUE LD HL,(TRKDSK) ;ELSE0? JR NZ,..VCL ;IF NOT, CONTINUE CALL DMS ;ELSE, DISPLAY MESSAGE DB ACR,ALF+80H DB "SUCCESSFUL VERIF","Y"+80H JP ..X ,1 LD (PDRSC),HL ;SET PD REQUEST SECTOR COUNT LD HL,128 LD A,(SECSIZ) ;GET SECTOR SIZE ..SL: DEC A ;DECREMENT SECTOR SIZT SECTOR NUMBER LD (PDRSEC),HL ;UPDATE PD REQUEST SECTOR NUMBER LD HL,(SECCNT) ;GET SECTOR COUNT DEC HL ;DECREMENT SECTORCOM ;PROCESS VERIFY ERROR JP C,..X ;IF CONTROL C, CONTINUE JR Z,..VTL ;IF CARRIAGE RETURN, CONTINUE ..VFYC: CALL CONST CR,ALF DB "INSUFFICIENT MEMORY TO FORMAT",ABEL+80H JR ..ERRX ;CONTINUE ..IVME: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF D, GET NUMBER OF TRACKS/DISK LD (TRKCNT),HL ;SET TRACK COUNT XOR A ;ELSE, GET READ FUNCTION LD (PDRFCN),A ;SET PD REQUEST  ;CONTINUE ..NPU: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF DB "NON-PRIVILEGED USER",ABEL+80H JP ..ERRX ;DONE ..NFDS: CALL E JP M,..SLX ;IF UNDERFLOW, CONTINUE ADD HL,HL ;ELSE, SHIFT BYTE COUNT LEFT JR ..SL ;CONTINUE ..SLX: LD (PDRTC),HL ;SE COUNT LD (SECCNT),HL ;UPDATE SECTOR COUNT LD A,H OR L ;SECTOR COUNT=0? JR NZ,..VTL ;IF NOT, CONTINUE LD HL,(PDRTRK) ;ELSE, GET CONSOLE STATUS OR A ;CHARACTER AVAILABLE? JR Z,..NCA2 ;IF NOT, CONTINUE CALL CONIN ;ELSE, GET CONSOLE INPUT CB "INSUFFICIENT MEMORY TO VERIFY",ABEL+80H LD A,(OPTFLG) ;GET OPTION FLAGS BIT VFY,A ;VERIFY ONLY FLAG SET? JR NZ,..ERRX PACKET FUNCTION LD HL,0 ;GET TRACK 0 LD (PDRTRK),HL ;SET PD REQUEST PACKET TRACK=0 ..VCL LD HL,(SECTRK) LD (SECCNT),HL DMS ;DISPLAY MESSAGE DB ACR,ALF DB "NO FORMAT DRIVE SPECIFIED",ABEL+80H JP ..ERRX ;CONTINUE ..LFDE: CALL DMS ;DISPLAY T PD REQUEST TRANSFER COUNT LD DE,?END?## ;GET VERIFY BUFFER ADDRESS LD (PDRDMA),DE ;SET PD REQUEST PACKET DMA ADDRESS ADD;GET PD REQUEST TRACK NUMBER INC HL ;INCREMENT PD REQUEST TRACK NUMBER LD (PDRTRK),HL ;UPDATE PD REQUEST TRACK NUMBER LD HARACTER CP AETX ;CHARACTER=CONTROL C? JR NZ,..VFYC ;IF NOT, CONTINUE CALL DMS ;ELSE, DISPLAY MESSAGE DB ACR,ALF DB ;IF SO, CONTINUE JR ..X ;ELSE, CONTINUE ..VDNR: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF DB "VERIFY DRIVE NOT READY",ABEL ;SET SECTOR COUNT L HL, LD (PDRSEC),HL ;SET PD REQUEST PACKET SECTOR=0 CALL DMS ;DISPLAY MESSAGE DB "."+80H ..VTL: CMESSAGE DB ACR,ALF DB "UNABLE TO LOCKOUT FORMAT DRIVE",ABEL+80H JP ..ERRX ;CONTINUE ..FDNR: CALL DMS ;DISPLAY MESSAGE  HL,DE ;CALC END OF DMA ADDRESS EX DE,HL ;END OF DMA ADDRESS TO DE-REG LD HL,(OPSYS+1) ;GET TOP OF TRANSIENT PROGRAM AREA HL,(TRKCNT) ;GET TRACK COUNT DEC HL ;DECREMENT HEAD COUNT LD (TRKCNT),HL ;UPDATE TRACK COUNT LD A,H OR L ;TRACK COUNT=  DB ACR,ALF+80H LD A,(OPTFLG) ;GET OPTION FLAGS BIT VFY,A ;VERIFY ONLY FLAG SET? JP Z,..FMT ;IF NOT, CONTINUE JP ..VFY ;SET ZERO FLAG RET ;DONE ; XECPDA: LD DE,PDRDP ;GET PD REQUEST PACKET ADDRESS LD C,PDAFCN ;C=PHYSICAL DISK ACCESS FUNC;CONTINUE ..NREP: CP "V" ;CHARACTER=V? JR NZ,..OSL ;IF NOT, CONTINUE SET VFY,(HL) ;ELSE, SET VERIFY ONLY FLAG JR ..OSL  RET ;DONE ; FLSHCI: CALL CONST ;GET CONSOLE STATUS OR A ;CHARACTER AVAILABLE? RET Z ;IF NOT, DONE CALL CONIN ;ELCREMENT BUFFER POINTER LD A,(DE) ;GET CHARACTER FROM BUFFER CP ";" ;CHARACTER=SEMICOLON? JR Z,..OS ;IF SO, CONTINUE DH CALL FLSHCI ;FLUSH CONSOLE INPUT ..CSL: CALL CONST ;GET CONSOLE STATUS OR A ;CHARACTER AVAILABLE? JR Z,..CSL ;IF NOO ;ELSE, CONTINUE ..ERRX: LD HL,OPTFLG ;GET OPTION FLAGS RES REP,(HL) ;RESET REPEAT FLAG ..X: CALL DMS ;DISPLAY MESSAGE TION CALL OPSYS ;PERFORM PHYSICAL DISK ACCESS OR A ;RETURN CODE=0? RET ;DONE ; ERRCOM: CALL DMS ;DISPLAY MESSAGE ;CONTINUE ; LOKDRV: LD E,A ;FORMAT DRIVE TO E-REG PUSH DE ;SAVE DRIVE LD D,0FFH ;D=LOCK DRIVE FLAG LD C,LFDFCN ;C=LOCSE ,GET CONSOLE INPUT CHARACTER JR FLSHCI ;CONTINUE ; DECOUT: LD C,0 ;CLEAR LEADING ZERO FLAG LD DE,10000 ;DISPLAY TEN TJNZ ..SSL ;ELSE, CONTINUE RET ;DONE ..OS: LD HL,OPTFLG ;GET OPTION FLAGS ..OSL: DEC B ;DECREMENT COMMAND BUFFER COUNT T, CONTINUE CALL CONIN ;ELSE, GET CONSOLE INPUT CALL UPRCAS ;FORCE UPPER CASE CP "A" ;CHARACTER=ABORT? SCF ;SET CARDB ACR,ALF+80H LD A,(OPTFLG) ;GET OPTION FLAGS BIT REP,A ;REPEAT FLAG SET? JP Z,WBOOT ;IF NOT, DONE BIT VFY,A ;VERIFYDB " ERROR, DRIVE:"," "+80H LD A,(PDRDRV) ;GET PD REQUEST DRIVE ADD A,"A" ;ADD ASCII BIAS CALL CONOUT ;DISPLAY DRIVE LETKOUT/FREE DRIVE FUNCTION CALL OPSYS ;LOCKOUT DRIVE POP DE ;RESTORE DRIVE OR A ;LOCKOUT SUCCESSFUL? RET NZ ;IF NOT, DHOUSANDS DIGIT CALL ..DO LD DE,1000 ;DISPLAY THOUSANDS DIGIT CALL ..DO LD DE,100 ;DISPLAY HUNDREDS DIGIT CALL ..DO RET Z ;IF COMMAND BUFFER COUNT=0, DONE INC DE ;INCREMENT BUFFER POINTER LD A,(DE) ;GET CHARACTER FROM BUFFER CALL UPRCARY FLAG JR Z,..X1 ;IF CHARACTER=CONTROL C, CONTINUE CP "R" ;CHARACTER=RETRY? JR Z,..X1 ;IF SO, CONTINUE CP "I" ;CHAR ONLY BIT SET? JP Z,..FMT ;IF NOT, CONTINUE JP ..VFYO ;ELSE, CONTINUE ; GETOPT: LD DE,TBUF ;GET DEFAULT BUFFER LD A,(TER CALL DMS ;DISPLAY MESSAGE DB ", TRACK:"," "+80H LD HL,(PDRTRK) ;GET PD REQUEST TRACK NUMBER CALL DECOUT ;DISPLAY SONE LD D,80H ;D=FREE BUFFER FLAG LD C,FFBFCN ;C=FLUSH/FREE BUFFERS FUNCTION CALL OPSYS ;FLUSH FREE DRIVE BUFFERS XOR A LD DE,10 ;DISPLAY TENS DIGIT CALL ..DO INC C ;INCREMENT LEADING ZERO FLAG LD DE,1 ;DISPLAY UNITS DIGIT ..DO: LD B,-1 S ;FORCE UPPER CASE CP "R" ;CHARACTER=R? JR NZ,..NREP ;IF NOT, CONTINUE SET REP,(HL) ;ELSE, SET REPEAT FLAG JR ..OSL ACTER=IGNORE? JR NZ,..CIL ;IF NOT, CONTINUE OR A ;ELSE, CLEAR ZERO FLAG ..X1: CALL DMS ;DISPLAY MESSAGE DB ACR,ALF+80H DE) ;GET BUFFER COUNT OR A ;BUFFER COUNT=0? RET Z ;IF SO, DONE LD B,A ;ELSE, BUFFER COUNT TO B-REG ..SSL: INC DE ;INORCE TRACK NUMBER CALL DMS ;DISPLAY MESSAGE DB " (RETRY, IGNORE, ABORT)"," "+80H ..CIL: CALL DMS ;SOUND BELL DB ABEL+80  ;PRESET QUOTENT OR A ;CLEAR CARRY FLAG ..DL: INC B ;INCREMENT QUOTENT SBC HL,DE ;SUBTRACT DIVISOR JR NC,..DL ;UNTIL A AREA ; HEADNO:: DB 0 ;HEAD NUMBER ; PDRDP:: ;PD REQUEST PACKET PDRFCN:: DB 0 ;PD REQUEST FUNCTION PDRDRV:: DB 0 C RET ;DONE ; CONOUT: PUSH BC ;SAVE REGISTERS PUSH DE PUSH HL PUSH AF AND 7FH ;STRIP SIGN BIT FROM CHARACTER LH RET ;DONE ; RECAL: IN HDSTAT ;GET DRIVE STATUS ANI TKZERO ;ON TRACK ZERO? JRZ ..HOME ;IF SO, CONTINUE MVI A,1 ;ELSENT POINTER CALL CONOUT ;DISPLAY CHARACTER OR A ;LAST CHARACTER? JP P,..L ;IF NOT, CONTINUE POP AF ;ELSE, RESTORE AF TRK: DW 0 ;RESERVED TRACKS ; OPTFLG: DB 0 ;OPTION FLAGS TRKCNT: DW 0 ;TRACK COUNT SECCNT: DW 0 ;SECTOR COUNT HEADCT: DBUNDERFLOW ADD HL,DE ;RESTORE UNDERFLOW LD A,B ;GET QUOTENT OR A ;QUOTENT=0? JR NZ,..DD ;IF NOT, DISPLAY DIGIT INC ;PD REQUEST DRIVE NUMBER PDRTRK:: DW 0 ;PD REQUEST TRACK NUMBER PDRSEC:: DW 0 ;PD REQUEST SECTOR NUMBER PDRSC:: DW 0 ;PD E,A ;OUTPUT CHARACTER TO E-REG LD C,RCOFCN ;C=RAW CONSOLE OUTPUT FUNCTION CALL OPSYS ;OUTPUT CHARACTER TO CONSOLE POP , SET COUNT=1 STC ;SET DIRECTION=OUT CALL STEPDR ;STEP DRIVE ONE TRACK OUT JMPR RECAL ;CONTINUE ..HOME: XRA A STA CURT RET ;DONE ; CONST: PUSH BC ;SAVE REGISTERS PUSH DE PUSH HL LD C,CSFCN ;C=CONSOLE STATUS FUNCTION CALL OPSYS ;GE 0 ;HEAD COUNT ; DS 128 ;STACK AREA STACK DEFL $ ;TOP OF STACK AREA ; END START C DEC C ;LEADING ZERO FLAG SET? RET Z ;IF NOT, DONE ..DD: ADD A,"0" ;ADD ASCII BIAS CALL CONOUT ;DISPLAT CHARACTER D REQUEST SECTOR COUNT PDRTC:: DW 0 ;PD REQUEST TRANSFER COUNT PDRDMA:: DW 0 ;PD REQUEST DMA ADDRESS PDRDST:: DW 0 ;PD AF ;RESTORE REGISTERS POP HL POP DE POP BC RET ;DONE ; UPRCAS: CP "A" ;LOWER CASE ALPHA? RET C ;IF NOT, DONE ԓPU eE$E%hAI :PDRTRKPQeE$DAIMPDRTCPUE$EAIMRQ<5CHG$@1BLF*%"(d0 I8T CONSOLE STATUS POP HL ;RESTORE REGISTERS POP DE POP BC RET ;DONE ; CONIN: PUSH BC ;SAVE REGISTERS PUSH DE PU RET ;DONE ; RETDST: CALL RETRDY ;GET READY STATUS ORA A ;DRIVE READY? JRZ ..N ;IF DRIVE NOT READY, ABORT LHLD DSTADR ;INC C ;INCREMENT LEADING ZERO FLAG RET ;DONE ; DMS: EX (SP),HL ;GET MESSAGE ADDRESS CALL MSGHL ;DISPLAY MESSAGE EX REQUEST DST ADDRESS ; VFYDST: ;VERIFY DST AREA BLKSIZ: DB 0 ;BLOCK SIZE NMBLKS: DW 0 ;NUMBER OF ALLOCATION BLOCKS NMBDCP "Z"+1 ;LOWER CASE ALPHA? RET NC ;IF NOT, DONE SUB 20H ;ELSE, FORCE UPPER CASE RET ;DONE ; DSEG ;LOCATE IN DAT. RLO'xr/ "٠P,ʽCnʡ`cіfАAeVuK@٠6ADqLR*,@T'DQR&JB)@I'"IX`SH HL LD C,RCIFCN ;C=RAW CONSOLE INPUT FUNCTION CALL OPSYS ;GET CONSOLE INPUT POP HL ;RESTORE REGISTERS POP DE POP BLOAD DST ADDRESS JMPR ..Y ;DRIVE IS READY - RETURN ..N: LXI H,0 ;PRESET RETURN=READY ..Y: MOV PDRDST(X),L MOV PDRDST+1(X),(SP),HL ;SET UP RETURN ADDRESS RET ;DONE ; MSGHL: PUSH AF ;SAVE AF ..L: LD A,(HL) ;GET MESSAGE BYTE INC HL ;INCREMEIR: DB 0 ;NUMBER OF DIRECTORY BLOCKS SECSIZ: DB 0 ;SECTOR SIZE SECTRK: DW 0 ;SECTORS/TRACK TRKDSK: DW 0 ;TRACKS/DISK RES  1JAY)8E)2@T'DR9$ #D PI' : o*o"0XRUP PR*IqR&JS@ @INVALID, RETURN NOT READY STA CURDSK ;SAVE THE DRIVE NUMBER LXI H,HDDST ;GET THE DRIVE SPEC. TABLE ADDRESS SHLD DSTADR ;SA98R"tN_) Hf@j)͢ vC6D 'fހ@ͽ z 6 ;JCdC`for turbodos loader iff devlp nmbcpm defl 1 ;if not devlopment loader force cpm number to 1 endif choice macro num EXlV"`Ũ"ͿQLC!Je21T +JD3e}ٷ 'ҁHV$r)@U)JHvf@h(O"i "%b(P"$bIa6m l come up. ; ; For a standard loader to load either CP/M or TURBO DOS ; set DEVLP equal to false and TURBO to false for CP/M ,:`mW3@ ,ͩ6QDbyHAj3j#j " Yt<ٷ#D P@A!EB+}8h!àQuBFXt^2#`; ; Program to investigate CP/M directory structures on the disk ; ; Warning! assumes first sector number is 0!!!! ; Will oͥ KAA\lFͥ wxXW(8- %rl(`XW+/(hY/ a[h5 p0?Ech&num: db num+'0',' = ' endm ; ; The following MACROS define the .SYS file name choices ; for selecable booting. Put in E a I' R$Y$mE {ٷw3o 5!,> 620`p :`B",<uڳ@ equ 2000h ;address to read loaded file to monit equ 0f033h ;address to return to monitor for error memory equ 16h ;portRKNITlFͥ wxXW(8- %rl(`XW+/(hY/ a[h5 p0?Eavailable total ; and how many of them are CP/M versions. ; slct0 macro db 'CPM548 ',0DH,0AH endm slct1 macro db + &fӠWH@eX@eT,PEn 6hdp8mJE"yHX "%b(@:@ b 6o @T)HdҀU(R,t to load nmbch equ 5 ;number of choices to choose from nmbcpm defl 5 ;number of cp/m choices turbo equ FALSE ;true if b,"` ,*€ B(6+ Pf@h(E)H͖mRm_@1CDAV6b6AEb)HF,$"yHEb0XT @j Y to enable monitor PROM bdossecs equ 44 ;sectors to read on warm boot ; ; The following equates govern how the loader wil  'CPMFT501',0DH,0AH endm slct2 macro db 'CPMFT502',0DH,0AH endm slct3 macro db 'CPMFT503',0DH,0AH endm slct4 m ;HL=DPH address ld C,(HL) ;XLT table, low order byte inc HL ld B,(HL) ld A,B or C ;A=0 if no sector translation E,namlng ;get length of name entry floop: dec a ;add in length jp m,fdone ;skip out if no more to add in add HL,DE ;e system file resides has been selected ; and the head has been stepped to the first directory track ; Note that the directo HL,signon ;say were here call pstrng if devlp ques: ld HL,quesms ;send which boot mess. call pstrng xor a call cHL ld A,(HL) ld (BLM),A ;block mask inc A ld (blksec),A ;sectors per block inc HL inc HL inc HL ld A,(HL) ;acro db 'CPMFS506',0DH,0AH endm ;slct5 macro ; db 'CPMF506 ',0DH,0AH ; endm ;slct1 macro ; db 'OSLOAD ',0DH,0AH ; ld (trans),A ld (XLT),BC ld DE,7 add HL,DE ;(HL)=DIRBUF address - might as well use it ;for our workspace ld Celse add in lingth of entry jr floop ; and go back for more fdone: ;HL points to beg. of name to load ld DE,filefcbry will always start at sector 1 of ; the first non-system track, and will occupy consecutive ; sectors through the end of onin ;get response push psw ;save input ld C,A ;display it xor a call conout ld C,0dh ;goto newline xor a A=msb of DSM or total block count of drive ld (blkmsb),A inc HL ld E,(HL) inc HL ld D,(HL) inc DE ;make = max dirs endm ;slct4 macro ; db 'OSLOAD5 ',0DH,0AH ; endm select macro num slct&num endm ; ; loader bios access addres,(HL) inc HL ld B,(HL) ld (dirbuf),BC push HL call setdma ;use the dirbuf for operations pop HL inc HL ;(HL)=D+1 ;destination to move to ld BC,8 ;amount to move ldir ;now move file to load endif ;devlp ld C,0 ld E,0 ;the directory. The total number ; of sectors occupied is (maxdir)/4, but they may be on more ; than one track. ; nextsec:call conout ld C,0ah xor a call conout pop psw ;get input back sub '0' ;make number cp nmbch ;make sure valid . not -1 ld (maxdir),DE ld DE,5 add HL,DE ;(HL)=track offset ld C,(HL) inc HL ld B,(HL) ld (trkoff),BC ld (curses ; bios equ 500h conin equ bios+09h conout equ bios+0ch seldsk equ bios+1bh settrk equ bios+1eh setsec equ bios+21h PB address ld E,(HL) inc HL ld D,(HL) page ex DE,HL ;HL=DPB address ld E,(HL) inc HL ld D,(HL) ;(HL)=sectors make seldsk know this is the first call call seldsk ld A,H or L ld DE,badsel jp z,error ;bad select-HL=0000  ;read next directory sector into the DIRBUF ld HL,(SPT) ld BC,(cursec) sbc HL,BC jr nc,trksame ;haven't gone to nex jr nc,ques ;if not ask again ld (typeld),A ;save type of load ld HL,filetbl ;get address of start of file names ld Dtrk),BC call settrk ;directory starts at first non-system track page ; Current status of program: ; The disk on which th setdma equ bios+24h read equ bios+27h sectran equ bios+30h page start: ld SP,100h ;use default buffer for stack ldper track ld (SPT),DE ;highest sector number before next track inc HL ld A,(HL) ;Block shift factor ld (BSH),A inc ! t track yet ld BC,(curtrk) inc BC ld (curtrk),BC call settrk ;step disk ld BC,0 ;first sector, new track trksame:or, dw last sector found: ld DE,15d add HL,DE ;(HL)=records in this extent ld DE,filefcb+15d ;DE=block allocation arematches. ; match: ex DE,HL ;use DE to point to directory ld HL,Filefcb ;first character in filename to search ld BC,0c0L ;last sector of this block ld (IX+5),H xor A ld (IX+3),A ;start sector zero ld (IX+2),A ld C,(IX-6) ld B,(IX-5) ;match directory entry with FCB pop BC pop DE pop HL jr z,found ;file found add HL,DE djnz nextdir ; ; we've sea jr nz,newtrk ;block overflows to next track skp: add HL,DE ;add sectors per track back in ld (IX+4),L ;save last sector  push BC ;logical sector ld A,(trans) or A jr z,notran ;do we need to do sector translation? ld DE,(XLT) ;translate a in filefcb ld BC,17d ldir ;move to file fcb ld IY,filefcb+16 ;pointer to next block ld IX,boottbl ;pointer to cdh ;11 characters to match nextch: ld A,(DE) ;next character in directory entry inc DE and 7fh ;mask file attribute bi ;last track inc BC ld (IX),C ld (IX+1),B jr nxtblk page moreblks: push DE ;save new block # ld L,(IX+4) ;last rch this sector-no match. Was it the last? ; ld HL,(absec) inc HL ld (absec),HL dec HL ;HL=sectors read so far add ld (IX+5),H nxtblk: call getblk ;get next block # pop HL ;last block scf ccf sbc HL,DE inc HL ;HL=0 if new bltable call sectran push HL pop BC notran: call setsec call read or A ld DE,permerr jp nz,error ;physical error urrent table entry call getblk ;returns block # in DE newtbl: push DE call mktrk ;returns track in BC, 1st sector in ts cpi ret nz ;no match, return djnz nextch ret page ; ; Now we have the correct directory entry, with HL pointing sector so far ld H,(IX+5) jr mrebks1 ;go do rest of overflow check ; getblk returns the block # (IY) in DE and moves IY HL,HL add HL,HL ;sectors x 4 = directory entries ld DE,(maxdir) sbc HL,DE ld DE,nofile jp z,error jr nextsec ock adjacent to last ld A,H or L jr z,moreblks ld BC,6 add IX,BC ;set pointer to next track item jr newtbl newt pop HL ;sector just read inc HL ld (cursec),HL ; ; The next sector of the directory (4 entries) is now in the DIRBUF HL ld (IX),C ld (IX+1),B ;store track ld (IX+2),L ;first sector ld (IX+3),H dec HL ;set up for add mrebks1: ld to ; the the start of the FCB ; Next we expand the block allocation data into a table of items: ; ; dw track, dw first sect to the next ; also, exits loop if block # = 0 getblk: ld E,(IY) ld A,(blkmsb) or A jr z,onebyte inc IY ld A,(IY) page ; ; Match: match takes as a parameter HL pointing to a directory ; entry. Match returns the zero flag set if the file rk: ld (IX+4),E ;spt-1 last sector on track ld (IX+5),D ld BC,6 add IX,BC ;pointer to next track dec HL ld (IX+4),; Now see if we can find the file ; ld HL,(dirbuf) ld DE,32d ld B,4 nextdir: push HL push DE push BC call match DE,(blksec) add HL,DE ;HL=last sector of block ld DE,(spt) dec DE ;sectors numbered 0-(spt-1) sbc HL,DE jr c,skp "  onebyte: ld D,A inc IY or E ;block # = 0? ret nz pop DE ;lose return in loop jr tbldone ; mktrk gets block # iot cp/m leave ; ; we must go through it and remove all the BIOS sectors ; to make it a table of CCP and BDOS sectors only forsector ld H,(IY+5) sbc HL,BC ;any more on this track pop HL ;fix stack jr c,nxttrk ;done with last sector ld (nexoottbl ld DE,buffer+1637h ;boottbl in buffer-after jump table ldir ;move table ;boottbl filled in, now move imag to boot table nxttrk: push HL ;current DMA ;read sectors of next track ld DE,6 ;update track pointer add IY,DE the item we must cut down ;B=first sector, C=last sector, E=C-B+1 ;A=bdossecs, L=sectors through end of track n DE, returns track in BC, 1st sector in HL mktrk: ex DE,HL ld A,(bsh) ld B,A shftblk: add HL,HL djnz shftblk ;H wboot ; ld IX,boottbl-6 ld HL,0 ;count of sectors in table so far nxtitem: push HL ;save count of sectors so far tsc),BC ;save next sector ld DE,128 add HL,DE ;update DMA push HL ld DE,(xlt) call sectran ld C,L ld B,H calle to execution ;area ld HL,buffer ld DE,(buffer+1633h) ;ccp start ld C,0 ld A,(filefcb+15) ;128 byte records allo ld C,(IY) ld B,(IY+1) ;BC=track ld A,B or C jr z,bootdone ;last track done call settrk ld C,(IY+2) ;get next sld D,A ld A,L sub D ;A=sectors to remove ld E,A ld D,0 ld L,(IX+4) ld H,(IX+5) sbc HL,DE ld (IX+4),L ;must cL=absolute sector number ld DE,(spt) scf ccf ld BC,(trkoff) dec BC mortrk: sbc HL,DE inc BC jr nc,mortrk adld DE,6 add IX,DE ld C,(IX+2) ;get first sector this track ld B,(IX+3) ld L,(IX+4) ;get last sector this track ld H, setsec call read or A ld DE,permerr jr nz,error ;physical read error jr nxtsec page ; ; the .SYS file is now icated rrca rr C ;carry=> odd number of records and 7fh ld B,A ldir ;transfer jp buffer+1600h ;coldboot jump ector to read ld B,(IY+3) dec BC ;pre decrement it ld (nextsc),BC ;save it nxtsec: pop BC ;DMA push BC call seontain at least one sector in track ld (IX+5),H page ; ; table has now been modified for CP/M wboot use ; IX+5 is end of ld HL,DE ;restore sector relative in track ret page ; ; table now contains the track/sector map for all the blocks in ; t(IX+5) sbc HL,BC inc HL ;sectors in this track pop DE add HL,DE ;total sectors so far ld A,bdossecs ;number of sen memory starting at (buffer) ; bootdone: ld A,(typeld) ;load of cp/m or something else cp nmbcpm jp nc,trboot ;if npage ; ; turbodos loader stuff ; trboot: ld HL,80h ;first need to clear default buffer ld DE,81h xor A ld (HL),A ltdma scf ;clear carry flag ccf ld BC,(nextsc) ;get next sector to read inc BC ;update it ld L,(IY+4) ;get last ast table entry movtbl: push IX pop HL ld DE,boottbl-6 sbc HL,DE ;HL=length to move ld B,H ld C,L ld HL,bhe directory. Now read the table into memory. ; tbldone: ld HL,buffer ;start of CCP-starting DMA ld IY,boottbl-6 ;pointctors for wboot cp L jr z,movtbl ;this track ends exactly at the BIOS jr nc,nxtitem ;keep reading table ;this is# d BC,30h ldir ; jp buffer ;now go to loader page ;-------------------------------------------- ; ; error message r ch1-ch0 ;length of name entry in above table endif ;devlp badsel: db 8,0dh,0ah,'Select' permerr: db 6,0dh,0ah,'Read'ack count maxdir: ds 2 ;number of directory entries on disk trkoff: ds 2 ;track offset curtrk: ds 2 ;current track cur TITLE ADVANCED DIGITAL LOADER BIOS FOR SUPER QUAD Apr 04 1983 08:30 ;******************************************************' ;file name filled in at beg. of code for devlp loader else db 'OSLOAD ' endif db 'SYS' ;extension ds 20 ;dum ;GET PD REQ DISK NUMBER ; .IFE SIXTN , [ CPI 16 ;COMPARE WITH MAX DRIVE NUMBER JRNC ..X ;IF INVALID, RETURN NOT READY outine ; error: ex DE,HL ;put message address in HL call pstrng ;send message ld HL,errmsg ;send error message call nofile: db 16,0dh,0ah,'File not found' errmsg: db 14,' error: file ' signon: db boottbl-$,0dh,0ah,0ah,'Advanced Digital Corsec: ds 2 absec: ds 2 ;absolute sector typeld: ds 1 ;load type 0=cp/m, 1=turbodos nextsc: ds 2 ;temp storage for next s*********** ;** ** ;** ADVANCED DIGITAL SUPER QUAD Z80 SBC ** ;** ** ;** LOADER BIOS ** ;** my rest of dir entry BSH: ds 1 ;block shift factor = log2(records/block) BLM: ds 1 ;block mask = records/block-1 blkmsbPUSH PSW ;GET LOGICAL DRIVE NUMBER ANI 03H LXI H,HDDST ;COMPUTE TABLE ADDRESS JRZ ..NOA MOV B,A LXI D,11 ..ADL: DAD D pstrng ld B,11d ;send file name ld HL,filefcb call pstr2 ld A,4fh ;turn prom back on out (memory),A jp monit p. system loader',0dh,0ah,0ah boottbl: ds 60 lastadd: end ector to read ; ;messages ; if devlp quesms: db badsel-$ db 0dh,0ah,'Which .SYS file to load',0dh,0ah filetbl equ $+4** ;** This bios contains drivers for: ** ;** ** ;** Floppy disk or ** ;** Hard disk ** ;** Serial inp: ds 1 ;non-zero is >255 blocks on drive ;=msb of DSM in DPB blksec: ds 2 ;sectors per block (BLM+1) dirbuf: ds 2  DJNZ ..ADL ..NOA: SHLD DSTADR ;SAVE FOR FUTURE USE POP PSW ;GET REAL DRIVE NUMBER SRLR A SRLR A STA CURDSK ;SAVE IT ;go back to monitor pstrng: ld B,(HL) pstr2: inc HL ;HL=first character, B=count push HL ld C,(HL) push BC xor A YMSK ;SAVE READY MASK LXI D,RDYPOL ;GET READY POLL ROUTINE ADDR CALL LNKPOL# ;CREATE POLL ROUTINE CALL RDYPR ;EXECUTE POL ;beginning of file name table x defl 0 rept nmbch choice %x select %x x defl x + 1 endm db '? ' namlng equut & output ** ;** ** ;** Written by: ** ;** ** ;** Scott Carter ** ;** Greg Lindberg ** ;;address of DIRBUF trans: ds 1 ;0 if no sector translation XLT: ds 2 ;translate table address SPT: ds 2 ;sector per tr ;] .IFN SIXTN , [ CPI 4 ;COMPARE WITH MAX. DRIVE NUMBER JRNC ..X ;IF INVALID, RETURN NOT READY STA CURDSK ;SAVE THE DRI call conout pop BC pop HL djnz pstr2 ret ; ;storage ; filefcb: db 0 ;user number iff turbo db 'CPM L ROUTINE LXI H,DWRSPH ;GET WAIT INTERRUPT SEMAPHORE JMP WAIT# ;DISPATCH IF NECESSARY ; RETRDY: SELDSK: MOV A,PDRDRV(X) $ ** ** ;***************************************************************** SUBTTL Customization Equates page 60 .ister data equ cmd+3 ;data register wait equ 14h ;INTRQ and DRQ synch port (see manual) memry equ 16h ;memory control po Q2020 EQU 16 Q2030 EQU 17 Q2040 EQU 18 M4010 EQU 19 ; MiniScribe 4010 M4020 EQU 20 A3020 EQU 21 ; Atasi 3020 A3033 EQU must be power of 2 outbfsz equ 64 ;size of output buffer for interrupt output must be power of 2 SUBTTL Hard disk equate times double for minifloppies ;*** Hard Disk selection choices *** ST503 EQU 1 ; Seagate Technology ST503 ST506 EQU 2THIS IS OFFSET INTO TABLE, VALUE IN TABLE CAN BE ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these times double for minifz80 true equ 0ffffh false equ 0 mini equ false ;true for minifloppy BIOS special equ false ;true for 8"-5" special boardrt ; ; sector deblocking equates ; hstcnt equ 8 ;number of sectors in buffer hstshft equ 3 ;shift factor for # of sectors22 A3046 EQU 23 ;*** HDC1001 Physical drives *** hd0 equ false ; Set to type of drive or false if not used ;*** HDs page ;*** HDC1001 Disk equates *** HOFF EQU 1 ; Number of reserved tracks for loader TST MACRO DN ;physical h TM601S EQU 3 ; Tandon Magnetics TM601S TM602S EQU 4 TM603S EQU 5 TM603SE EQU 6 TM501 EQU 7 ; Tandon Magnetics TM501 TM5loppies pspt equ 2 ;physical sectors per track (one side) drvtrk equ 3 ;track a floppy is at parmlen equ 4 ;length of the  m48tpi equ false ;true for 48tpi mini drives m96tpi equ false ;true for 96tpi mini drives nmbfpy equ 2 ;number of floppy  in buffer if mini ddpspt equ 4 ;double density physical sectors per track if m48tpi tracks equ 39 ;minifloppies elC1001 ECC selection *** eccbit equ 80h ;ecc command bit ecc equ false ;set true to enable ecc SUBTTL SYMBOLIC EQUATES ard disk defined IF HD&DN x defl 1 else x defl 0 endif endm hddsks defl 0 ;number of physical hard disk drives h02 EQU 8 TM503 EQU 9 CM5206 EQU 7 ; Computer Memories Inc CM5206 CM5412 EQU 8 CM5619 EQU 9 SA602 EQU 10 ; Shugart Associaparameter block ; ; miscellaneous equates ; iobyte equ 3 ;used to select various consoles and printers cdisk equ 4 ;defaudisk drives ;------------------------------------------------------------------------ ; This is the seek rate constant!! sese tracks equ 76 ;96tpi drives endif else ddpspt equ 8 ;eight inch tracks equ 76 endif dpblen equ 15 ;length of a page ; board hardware equates cmd equ 0ch ;fdc command register trk equ cmd+1 ;track register sec equ cmd+2 ;sector regdldrvs defl 0 ;number of logical hard disk drives hdtst macro tst %hddsks ;test for physical drives iff x exitm etes SA602 SA604 EQU 11 SA606 EQU 12 SA1002 EQU 13 ; Shugart Associates SA1002 SA1004 EQU 14 Q2010 EQU 15 ; Quantum Q2010 lt disk user number retries equ 10 ;retry count for disk operations inbfsz equ 32 ;size of input buffer for interrupt input ekrt, below, is an offset! seekrate equ 1 ;6ms for 8", 12ms for 5" ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these DPB ; ; floppy disk hardware parameter offsets ; density equ 0 ;0=single, 1=single side double D, 2= 2S2D seekrt equ 1 ;% ndif .lall hddsks defl hddsks+1 .xall endm ;end hdtst hdtst ;calculate number of physical hard disks if hddskhd,stprt .lall hdesc&dn: db hdcbase ;base i/o port address db dn ;physical unit no. db inter ;hardware interleave096 ;cp/m block size cpmspt equ hdstcnt*secs ;cp/m sectors per track per head cpmscbk equ blksiz/128 ;cp/m sectors per cp/m bon vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdsc %dn,152,3,3 endm ND EQU HDCBASE+7 ; Command register STATUS EQU COMND ; Status register ;*** Command equates for HDC1001 *** CREST EQU h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdscs ;set flag for hard disks hard equ true else hard equ false endif .sfcond if hard ;put this stuff in only if ne db secs ;sectors per track dw mxcl ;last cylinder db mxhd ;last head db hstsiz/128 ;sector size/128 db stprt lock ; dpbg macro dn,secs,bls,blm,ext,dks,dir,al0,al1,cks,off,phys .lall dpb&dn: dw secs ;sec per track db bls ;blockhddr&dn defl 1 endif if typ eq TM603S hpb&dn macro no dw -1,hdesc&dn als&no defl 00E4h ;size of allocation vector 10H ; Restore command CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command CWRITE EQU 30H ; Write command CFg %dn,152,3,3 endm hddr&dn defl 1 endif if typ eq TM601S hpb&dn macro no dw -1,hdesc&dn als&no defl 004Ch ;sizeeded .lfcond ;*** Port equates for HDC1001 *** HDCBASE EQU 0E0H ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port  ;step rate .xall endm dsktyp macro dn,typ .lall .sfcond if typ eq ST503 hpb&dn macro no dw -1,hdesc&dn als&n shift db blm ;block mask db ext ;extnt mask dw dks ;disk size-1 dw dir ;directory max db al0 ;alloc0 db acss&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1823,1023,255,0,0,1,%dn hdscg %dn,152,5,3 endm hddr&dn dORM EQU 50H ; Format track inter equ 8 ;hard disk sector interleave factor secs equ 16 ;Physical sectors per track per he of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,%dn hdsc %dn,152,1WPC EQU HDCBASE+1 ; Write precomp port HDCERR EQU WPC ; Error port SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; o defl 004Ch ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,l1 ;alloc1 dw cks ;check size dw off ;offset db phys ;physical disk drive .xall endm hdscg macro dn,mxcl,mxefl 1 endif if typ eq TM603SE hdpb603E0&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector cssad hstsiz equ 512 ;size of a hard disk physical sector hdstcnt equ hstsiz/128 ;cp/m sectors per physical sector blksiz equ 4,3 endm hddr&dn defl 1 endif if typ eq TM602S hpb&dn macro no dw -1,hdesc&dn als&no defl 0098h ;size of allocatiSector number CYLLO EQU HDCBASE+4 ; Cylinder low CYLHI EQU HDCBASE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COM%dn hdscg %dn,152,1,3 endm hddr&dn defl 1 endif if typ eq ST506 hpb&dn macro no dw -1,hdesc&dn als&no defl 0098& &no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,229,5,3 endm hdpb603E1& defl 2 endif if typ eq SA602 hpb&dn macro no dw -1,hdesc&dn als&no defl 0050h ;size of allocation vector css&no del 2 endif if typ eq TM503 hdpb5030&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no d256,5,31,1,2039,1023,255,0,0,1,%dn hdscg %dn,255,3,0 endm hddr&dn defl 1 endif if typ eq Q2010 hpb&d macr no dw 1 endif if typ eq TM502 hdpb5020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no def elements dpbg %no,384,5,31,1,1907,1023,255,0,0,1,%dn hdscg %dn,159,5,3 endm hddr&dn defl 1 endif if typ eq SA1002 dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,fl 0 ;number of checksum elements dpbg %no,128,5,31,1,635,511,240,0,0,1,%dn hdscg %dn,159,1,3 endm hddr&dn defl 1 endefl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,5,3 endm hdpb5031&dn mac-1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,l 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,3,3 endm hdpb5021&dn macro hpb&dn macro no dw -1,hdesc&dn als&no defl 0080h ;size of allocation vector css&no defl 0 ;number of checksum elements 699,511,240,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb603E0&dn %x x defl x+1 hdpb603E1&dn %x endm hif if typ eq SA604 hpb&dn macro no dw -1,hdesc&dn als&no defl 009Fh ;size of allocation vector css&no defl 0 ;numbero no als&no defl 00CAH ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1611,12043,1023,255,0,0,1,%dn hdscg %dn,511,1,0 endm hddr&dn defl 1 endif if typ eq Q2020 hdpb20&dn macro no dw -1,hdesc no als&no defl 0031H ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,391,511, dpbg %no,128,5,31,1,1019,511,240,0,0,1,%dn hdscg %dn,255,1,0 endm hddr&dn defl 1 endif if typ eq SA1004 hpb&dn macddr&dn defl 2 endif if typ eq TM501 hpb&dn macro no dw -1,hdesc&dn als&no defl 0099h ;size of allocation vector cssr of checksum elements dpbg %no,256,5,31,1,1271,511,240,0,0,1,%dn hdsc %dn,159,3,3 endm hddr&dn defl 1 endif if typ023,255,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb5030&dn %x x defl x+1 hdpb5031&dn %x endm hddr&dn&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,102240,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb5020&dn %x x defl x+1 hdpb5021&dn %x endm hddr&dn defro no dw -1,hdesc&dn als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1219,511,240,0,0,1,%dn hdscg %dn,305,1,3 endm hddr&dn defl  eq SA606 hpb&dn macro no dw -1,hdesc&dn als&no defl 00EFh ;size of allocation vector css&no defl 0 ;number of checksum' 3,255,0,0,1,%dn hdscg %dn,511,3,0 endm hdpb21&dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ctor css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2031,1023,255,0,0,385,%dn endm hdpb4021&dn macro n ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,7,0 endm hdpb41&dn macro no fl x+1 hdpb4021&dn %x endm hddr&dn defl 2 endif if typ eq A3020 hdpb320&dn macro no dw -1,hdesc&dn als&no defl 01umber of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,172,%dn endm hdpb32&dn macro no als&no defl 00FEh ;si hdscg %dn,479,1,0 endm hddr&dn defl 1 endif if typ eq M4020 hdpb4020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;number of checksum elements dpbg %no,256,5,31,1,2039,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no o als&no defl 00DFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1783,1023,als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,25500h ;;size of allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,192,5,31,1,2047,1023,255,0,0,1,%dn ze of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2031,1023,255,0,0,343,%dn endm  ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdschdpb20&dn %x x defl x+1 hdpb21&dn %x endm hddr&dn defl 2 endif if typ eq Q2030 hdpb30&dn macro no dw -1,hdesc&dn 255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb40&dn %x x defl x+1 hdpb41&dn %x x defl x+1 hdpb42&dn,0,0,129,%dn endm hdpb42&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum e hdscg %dn,634,2,0 endm hdpb321&dn macro no als&no defl 00DCh ;;size of allocation vector css&no defl 0 ;;number of chpb&dn macro no local x x defl no hdpb30&dn %x x defl x+1 hdpb31&dn %x x defl x+1 hdpb32&dn %x endm hddr&dn defl 3g %dn,480,3,0 endm hdpb4021&dn macro no als&no defl 00DFh ;size of allocation vector css&no defl 0 ;number of checksu als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,25 %x x defl x+1 hdpb43&dn %x endm hddr&dn defl 4 endif if typ eq M4010 hpb&dn macro no dw -1,hdesc&dn als&no defllements dpbg %no,512,5,31,1,2047,1023,255,0,0,257,%dn endm hdpb43&dn macro no als&no defl 00FEh ;size of allocation vehecksum elements dpbg %no,192,5,31,1,1755,1023,255,0,0,343,%dn endm hpb&dn macro no local x x defl no hdpb320&dn %x  endif if typ eq Q2040 hdpb40&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0m elements dpbg %no,256,5,31,1,1783,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb4020&dn %x x de5,0,0,1,%dn hdscg %dn,511,5,0 endm hdpb31&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;n 00F0h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1915,1023,255,0,0,1,%dn (  x defl x+1 hdpb321&dn %x endm hddr&dn defl 2 endif if typ eq A3033 hdpb330&dn macro no dw -1,hdesc&dn als&no defements dpbg %no,448,5,31,1,2047,1023,255,0,0,442,%dn endm hdpb344&dn macro no als&no defl 0100h ;;size of allocation v,2047,1023,255,0,0,1,%dn hdscg %dn,634,6,0 endm hdpb341&dn macro no als&no defl 0100h ;;size of allocation vector cssdpbs macro times ;define hard disk parameter blocks local x,y x defl 0 y defl nmbfpy rept times hdpbs %x,%y ;define b333&dn macro no als&no defl 0018h ;;size of allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,320,ist .lall hdph&dn: dw 0000h,0000h ;translate table dw 0000h,0000h ;scratch area dw dirbuf,dpb&dn ;dir buff,parm blocl 0100h ;;size of allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,320,5,31,1,2047,1023,255,0,0,1,%ector css&no defl 0 ;;number of checksum elements dpbg %no,448,5,31,1,653,511,240,0,0,589,%dn endm hpb&dn macro no l&no defl 0 ;;number of checksum elements dpbg %no,448,5,31,1,2047,1023,255,0,0,148,%dn endm hdpb342&dn macro no als&nodpb's for this hd drive endm x defl x+1 ;bump counters y defl y+lgdrvs endm ; ddb macro data,comm ; define a db state5,31,1,191,511,240,0,0,616,%dn endm hpb&dn macro no local x x defl no hdpb330&dn %x x defl x+1 hdpb331&dn %x x defk dw 0000h,0000h ;check, alloc vectors .xall endm ; hddisks macro nd ; define nd disks ndisks defl nd ;for later redn hdscg %dn,634,4,3 endm hdpb331&dn macro no als&no defl 0100h ;;size of allocation vector css&no defl 0 ;;number ocal x x defl no hdpb340&dn %x x defl x+1 hdpb341&dn %x x defl x+1 hdpb342&dn %x x defl x+1 hdpb343&dn %x x defl x+ defl 0100h ;;size of allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,448,5,31,1,2047,1023,255,0,0ment db data comm endm ; ddw macro data,comm ; define a dw statement dw data comm endm ; defds macro lab,space l x+1 hdpb332&dn %x x defl x+1 hdpb333&dn %x endm hddr&dn defl 4 endif if typ eq A3046 hdpb340&dn macro no dw -ference dpbase equ $ ;base of disk parameter blocks ; generate the nd elements dsknxt defl nmbfpy rept nd dskhdr %dsknxof checksum elements dpbg %no,320,5,31,1,2047,1023,255,0,0,206,%dn endm hdpb332&dn macro no als&no defl 0100h ;;size o1 hdpb344&dn %x endm hddr&dn defl 5 endif hdldrvs defl hdldrvs+hddr&dn .lfcond .xall endm x defl 0 rept hdd,295,%dn endm hdpb343&dn macro no als&no defl 0100h ;;size of allocation vector css&no defl 0 ;;number of checksum el lab: ds space endm ; lds macro lb,dn,val size defl val&dn defds lb&dn,%size endm ; ; logdsk defl nmbfpy endif 1,hdesc&dn als&no defl 0100h ;;size of allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,448,5,31,1t dsknxt defl dsknxt+1 endm endm ; lgdrvs defl 0 ; hdpbs macro dn,lgno hpb&dn lgno lgdrvs defl hddr&dn endm ; hdf allocation vector css&no defl 0 ;;number of checksum elements dpbg %no,320,5,31,1,2047,1023,255,0,0,411,%dn endm hdpsks dsktyp %x,hd%x ;define hard disk parameters x defl x+1 endm ; ; dskhdr macro dn ; define a single disk header l) ;hard disk definitions .lfcond fdskhdr macro dn .lall fdph&dn: dw trans,0,0,0 dw dirbuf,fdpbase dw 0000h,0000h .ort ld C,A in A,(C) and 1 ret z ;no character waiting ld A,0ffh ret serin:: ld B,A call pserin ld A,B jw 0 jp pserin jp serin jp serout ret ;no list dw 0 ret ;no punch dw 0 ret ;no reader dw 0 jp home oppy disk drive driver module ; .sfcond iff hard ;if not hard disk .lfcond dskparm:: ;disk hardware parameter block lse ;fpyfrst dw hdc rept hdldrvs-1 dwdsk hdc,%x x defl x+1 endm ;rept y defl 0 rept nmbfpy dwdsk fpy,%x  pop AF hex1:: and 0fh add A,90h daa adc A,40h daa ld C,A xor A jp serout ; ; setdma:: ld (iodma),BC ;sharxall endm fdisks macro x defl 0 rept nmbfpy fdskhdr %x x defl x+1 endm endm dwdsk macro drvr,lgdsk dw drvr+lgdr z,serin ;loop until character received add A,A ld C,A in A,(C) and 7fh ;mask high order bit ret serout:: ld jp seldsk jp settrk jp setsec jp setdma jp read ret ;no write dw 0 ret ;no list status dw 0 jp sectran  ;one block for each drive rept nmbfpy if (mini and not special) db 1 ;single sided double density else db 0 ;dens iff y ;if first time thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 eed among all drivers ret ; ; Sectran input:: Logical sector in BC, translate table in DE ; no translation if DE=0 ; sk endm DSKTBL MACRO ;DEFINES DISK ASSIGNMENT TABLE x defl 0 .lall drvtbl equ $+1 .xall if fpyfrst dw fpy B,C ;character to output add A,A inc A ld C,A serst:: in A,(C) and 4 jr z,serst dec C out (C),B ret ; misce SUBTTL Console drivers page ; ; Console drivers ; All have entry A=driver number, other parameters per CP/M ; A=0 seriity - 0=single D; 1=1 side, Double D; 2= 2S 2D endif db seekrate ;seek rate - 0=3ms, 1=6ms, 2=10ms, 3=15ms if (mini anndif endm ;rept endif ddb %x,<;last logical drive> rept 16-nmbfpy-hdldrvs dw 0 endm ;rept endm ;dsktbl ; Returns physical sector in HL ; Note:: only used in single density sectran:: ld A,D or E ld L,C ld H,B ret  rept nmbfpy-1 dwdsk fpy,%x x defl x+1 endm ;rept y defl 0 rept hdldrvs dwdsk hdc,%x iff y ;if first timllaneous character i/o routines pmsg:: ;equivalent to BDOS function 9 (print) ld A,(DE) cp '$' ret z ld C,A inc Dal port 0; A=1 serial port 1 pserin:: ;poll serial in-return A=0ff if char ready, else 0 add A,A inc A ;A=command pd not special) db ddpspt else db 26 ;physical sectors per track - 26 in SD, ddpspt in DD endif db 0 ;track drive curSUBTTL BIOS ENTRY AND PUBLIC TABLES page ; ; BIOS jump table start:: ret ;no cold boot dw 0 ret ;no warm boot dz ;no sector translation ex DE,HL add HL,BC ld L,(HL) ld H,0 ret SUBTTL Floppy disk driver module page ; ; Fle thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 endif endm ;rept eE push DE xor A call serout pop DE jr pmsg phex:: ;print A in hex push AF rra rra rra rra call hex1* rently set at endm page ; ; CP/M disk tables fDPHbase:: fdisks ; defind disk parameter headers for floppys page ;physcial floppy ld E,C ;save logical disk call getden ;will set density byte if successful or A jr nz,fbadsel ;coulw 127 db 0c0h else dw 255 db 0f0h endif db 0 dw 32 dw 1 page trans:: ;single density translate table db 1 bit ld B,A ld A,(head) rlca rlca ;move head bit to bit 2 or B setdens:: ld B,A out (wait),A ld A,(IX+drvtrk) ;directories dw 2 ;track offset (system tracks) page ssdddpb:: ;single sided double density dw 8*ddpspt ;128 byte sectorE,9 ;offset of DPB in DPH add HL,DE ld (HL),C inc HL ld (HL),B dec HL dec HL sbc HL,DE ;restore DPH (carry res ; DPB's for the three formats of disk:: ; ; 8" Single sided, single density ; 5" Single sided, double density ; 5" Double dn't get density ;all physical operations OK here ld (hwptr),IX ;store for later use ld A,(IX+density) inc A ;m,7,13,19,25,5,11,17,23,3,9,15,21 ;sectors 1-13 db 2,8,14,20,26,6,12,18,24,4,10,16,22 ;secotrs 14-16 home:: ld C,0 settget track from parameter table ;this may be first physical i/o out (trk),A ret page ; ; Seek attempts to step the R/s per track db 4 db 0fh db 0 dw (tracks*ddpspt/2)-1 ;each of 76 tracks has ddpspt/2 2K blocks if mini dw 63 det by or A) ret fbadsel::ld HL,0 ret ;return error page ; ; Seldrv selects the drive , head from (head) ; (bit 0 sided, double density ; fdpbase:: sssddpb:: ;single density (1K block) dw 26 ;sectors per track db 3 ;block shift (loake 1-3 ld B,A ld HL,fdpbase-dpblen ld DE,dpblen fgetdpb:: add HL,DE djnz fgetdpb ;HL=DPB address ld C,L ld Brk:: ld A,C ld (iotrk),A ret setsec:: ld A,C ld (iosec),A ret page ; ; Fseldsk selects the physical floppy in W head to the track in (iotrk) ; seek:: ld A,retries ld (retryc),A seek2:: ld A,(iotrk) ld C,A ;track stays in C in b 80h else dw 127 db 0c0h endif db 0 dw 32 dw 1 dsdddpb:: ;double sided double density dw 16*ddpspt ;one trset for head1), and density from (IX+density) ; it assembles the correct byte and outputs to wait ; and updates the track regig2[block size/128]) db 7 ;block mask ([block size/128]-1) db 0 ;extent mask dw 242 ;highest block on disk (numbered fr,H ld HL,fdphbase ld A,(IX+density) or A jr z,setran ;single density,set translate vector xor A ld (HL),A inc HL A (0-3) ; B=0 if last disk selected was a different floppy ; C=logical disk the floppy corresponds to seldsk:: ld D,0 ;A,(trk) sub C ret z ;already there ld A,C out (data),A ld A,(IX+seekrt) ;seek rate mask or 1ch ;seek with verifyack consists of both sides db 4 db 0fh db 0 dw (tracks*ddpspt)-1 ;each of 76 tracks has ddpspt 2K blocks if mini dster with the most recent information seldrv:: ld A,(IX+density) or A jr z,setdens ld A,00001000b ;set double densityom 0) dw 63 ;directory entries-1 db 0c0h ;alloc0 -first two bits for two blocks for Dir db 0 ;alloc1 dw 16 ;checked  ld (HL),A jr putdpb setran:: ld DE,trans ;single density translate table ld (HL),E inc HL ld (HL),D putdpb:: ld D+  di out (cmd),A in A,(wait) ei rla jr c,seekerr ;no INTRQ from FDC in A,(cmd) and 10011001b ;seek error, CRC e from here to end of transfer in A,(cmd) and 20h ;bit 5=head loaded rrca rrca rrca ;move bit 5 to bit 2 cpl awrites the necessary sector ; it assumes that the head has already settled on the correct track ; (and that the head has been tion has been set by poking INI or OUTI instruction rdwrite:: ld B,128 ;bytes in one CP/M sector loop:: in A,(wait) ort of sector in buffer ldir ret ;transfer done rddbl:: call sidesec call readprep or A ret nz jr movrd rl sector ld A,E out (cmd),A ;start read/write operation call rdwrite ;do the actual i/o in A,(cmd) ei ;now ok to irror, or incomplete jr nz,seekerr ;seek successful ld (IX+drvtrk),C ret seekerr:: ld E,1ch ;seek command callnd B ; the purpose of these manipulations has been ; to set bit 2 of the FDC command if the head ; isn't settled.selected on the correct side!) ; and that the bytes in rdwrite for R/W and sector size have been filled diskio:: ld A,retr A ret p ;no more DRQ iotran:: ini ;start with read ;the second byte of this instruction is patched to ;be eithedsngl:: ld A,(iosec) ld (psec),A ;physical sector same as CP/M sector ;in single density readprep:: ld A,0A2h ;snterrupt-status is saved ld E,A ;save status or B ;B returned from rdwrite is lost bytes count ret z ;if status OK and  diskerror jr seek2 page ; ; Read reads the sector from the selected disk ; In double density, the sector may already be i Bit 2 will give a 15 ms delay ld E,A ld A,(IX+density) or A ld D,1 ;one sector i/o transfer for single denisty jr zies ld (retryc),A iotry:: ld A,0d0h ;force interrupt no conditions out (cmd),A ld A,(oper) ld B,A ld C,data ;pr INI or OUTI depending on need jr nz,loop dec D jr nz,rdwrite jr loop ;sector done, wait for INTRQ from fdc page ;econd byte of INI instruction ld (iotran+1),A ;patch rdwrite routine ld A,08ch ;sector read command ld (oper),A page no lost bytes call diskerror call seek or A jr z,iotry ;if nonzero then hopeless seek error ret ; ; rdwrite doesn the host buffer ; read:: ld IX,(hwptr) ;restore parameter pointer ld A,(IX+density) ;density byte or A jr z,rdsngl,dmasingl ;use the CP/M DMA buffer in single density ld HL,hstbuf ;use host buffer for double density operations ld D,hstcntrepare for indirect I/O instruction ex (SP),HL ;waste some time ex (SP),HL ex (SP),HL ex (SP),HL di ;no interrupts ; disk error will eventually have all kinds of nice messages ; diskerror:: ld A,(retryc) dec A jr nz,restore ;more restrtsel:: call seldrv ;physically select drive and head call seek ;step to correct track ; ; diskio actually reads or  the actual transfer to/from the FDC ; HL set to DMA address on entry, D=number of 128 byte units to transfer ; transfer direc ;singl density call inbuf jr c,rddbl ;sector not in buffer ; sector is in buffer movrd:: call mkbufad ;HL=star ;number of 128 byte units to transfer jr strtio dmasingl:: ld HL,(iodma) strtio:: ld A,(psec) out (sec),A ;set physica, tries to attempt ld A,E cp 1ch ;was it a seek error? jr z,pseekerr cp 0ach ;writing? jr z,pwriterr ld DE,rderr ctor is in buffer, returns offset (0 - hstcnt-1) in A ; inbuf:: ld A,(iosec) ld D,A ld A,(bufvalid) ;0 if contains valid (iosec) and not(hstcnt-1) ;computer first CP/M sector in block ld (blksec),A sideflsh:: ;called to set up for a flushD=0 getparm:: ld B,A inc B ld IX,dskparm-parmlen ;hardware parameter block ld DE,parmlen shft1:: add IX,DE djnz shrecord was found but ;read/written with error resto1:: ;restore to track 0 and seek again ld A,(IX+seekrt) ;get ser, DE=DMA address, BC=128, A=0 mkbufad:: ld (blkptr),IX ld HL,(iodrvtrk) ld (blkdrvtrk),HL ld A,(iosec) ld B,A and  jr perrtyp pwriterr:: ld DE,wrterr jr perrtyp pseekerr:: ld DE,skerr perrtyp:: call pmsg ld DE,trkerr call pmsg ld Adata, else 255 rra ret c inbuf2:: ld HL,(iodrvtrk) ;check for 2nd sector ;of unallocated block ld BC,(blkdrvtrk) rept hstshft rrca endm ;A=physical sector number, but it may ;be on the second side ld B,(IX+pspt) cp Bft1 ret page ; ; Getden attempts to find the density of the disk in drive (D) ; by trying to read the current track addek rate mask or 00001100b ;head load, restore, verify track 0 out (cmd),A tk0wait:: in A,(cmd) and 00000100b ;at tnot(hstcnt-1) ld (blksec),A ld A,B and hstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-128 ld D,(iotrk) call phex ld DE,secerr call pmsg ld A,(psec) call phex ld DE,siderr call pmsg ld A,(head) call phex  sbc HL,BC ;same drive and track jr z,rttrk scf ret ;not a match rttrk:: ld A,(blksec) ld B,A ld A,D sub B  ld C,0 jr c,side0 sub B inc C side0:: inc A ld (psec),A ;physical sector on one side ld A,C ld (head),A ;seress in both densities ; If the attempt is successful, Getden will update the ; dens, pspt, and drvtrk fields of the paramter rack 0 jr z,tk0wait xor A out (trk),A ;back at track 0 ld (IX+drvtrk),A ;update track table ret page ; ; sidesecE,128 shft2:: add HL,DE djnz shft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvalid),A ret pdrv:: ld DE,drverr call pmsg ld DE,crlf call pmsg ld A,255 ret page ; ; Restore is called from a disk operation  ret C ;sector lower # than buffer cp hstcnt ;carry set if in buffer ccf ret ; stores drive, track, sector of contt head control byte ret page ; ; inbuf returns carry flag set if sector not in buffer ; also returns (iosec) in D ; if setable ; If E (logical disk) is zero, then getden assumes the density hasn't ; changed (if it has, then we can't do a warm boot is the read/write preparation for double density ; sidesec computes the correct physical sector and side ; sidesec:: ld A, page ; ; returns IX=start of DHPB (disk hardware parameter block) for ; the drive in A (0-3) ; uses B,DE also, returns with A=retries left ; restore:: ld (retryc),A in A,(cmd) and 00010000b ;bit 4=record not found ret z ;try again if ents of buffer for use by flush ; also saves hardware pointer and sets buffer valid flag ; returns HL=start of sector in buffe- -table is wrong getden:: ld A,0d0h ;reset FDC out (cmd),A ld A,D and 7fh call getparm ld A,(7fh) ;code byte f ;send low order byte of track out (cyllo),a ld a,(hdiotrk+1) ;send high byte out (cylhi),a ld A,(hpsec) ;send physicseldsk:: ld HL,hdphbase ;add in base address ret ; and go ; ; Seldrv selects the drive from (curhdsk), head from (hheareturn if not ; page ; ; hard disk error message processor ; ; This routine gives the user a detailed error report ; hecan't change density else ;iff hard SUBTTL Hard disk drivers page .lfcond ; ; Hard disk drive driver module ; ; nd head call hseek ;step to correct track ; ; this actually reads the necessary sector ; it assumes that the head has aor disk type OR A jr z,codeok ;some SD disks have old loaders here sub 0e5h ;code for a normal single density disk cpal sector out (secno),A ld A,1 ;set sector count out (secnt),A ret page ; ; Read reads the sector from the selectedd) ; it assembles the correct byte and outputs it ; and updates the track register with the most recent information hseldrvrrors:: push AF ;save error indication ld DE,herrst CALL pmsg ; First the error code IN A,(HDCERR) CALL phex ld ; CP/M Hard disk tables ; hDPHbase:: hddisks hdldrvs ;set up disk parameter headers ; ; DPB's for HARD DISKS ; ; hdlready settled on the correct track ; (and that the proper head has been selected) ld HL,hstbuf ;point to buffer ld BC,h 3 jr c,codeok ld DE,badcode ;not our code byte call pmsg call pdrv ld A,255 ret codeok:: ld (IX+density),A or A disk ; it handles any necessary buffering ; read:: call hinbuf ;is it in the buffer jr c,hrd ;sector not in buffer :: ld A,(hhead) ;get head or 20h or (eccbit and ecc) ;set sector size to 512 bytes out (sdh),a ;send to controller reDE,errhd CALL pmsg ; then the head IN A,(SDH) push AF ;save drive no AND 7 CALL hex1 ; Print single digit ld Dpbase equ $+4 hddpbs hddsks ;set up disk parameter blocks page home:: ld BC,0 ;force track 0 settrk:: ld (hdiodcdata ;count and port di ;protect transfer ld A,cread ;send read command out (comnd),A hrdw:: in A,(status) ;done jr z,snglspt ld A,ddpspt ;physical sectors on one side of DD jr putpspt snglspt:: ld A,26d ;single density physical s; sector is in buffer hmvrd:: call hmkbfad ;HL=start of sector in buffer ldir ret ;transfer done hrd:: call hsit page ; ; Seek sets head to the track in (hdiotrk) ; and sector to (hpsec), sector count to one ; hseek:: ld a,(hdiotrk)E,errcyl CALL pmsg ; the cylinder IN A,(CYLHI) ; Report CYLHI first CALL phex IN A,(CYLLO) ; then CYLLO CALL phex trk),BC ;save track number ret setsec:: ld (hdiosec),BC ;save sector number ret ; ; Hseldsk selects the hard disk  yet and A jp m,hrdw ;if not wait inir ;256 bytes twice inir ei in A,(status) and 1 ;any errors ret z ;ectors putpspt:: ld (IX+pspt),A xor A ret ;no errors logdin::call getparm ld A,(IX+density) jr codeok ; drive dselc call hrdprep or A ret nz jr hmvrd ; ; read preperation ; hrdprep:: call hseldrv ;physically select drive a.  ld DE,errsec CALL pmsg ; and finally the sector IN A,(SECNO) CALL phex ld DE,errdr ;send drive mess call pmsg p cp H scf ;set failure flag ret nz ;exit if not equal ccf ;clear carry sbc HL,DE ret C ;sector lower # than in buffer, returns offset (0 - hdstcnt-1) in A ; hinbuf:: ld A,(bufvalid) ;0 if contains valid data, else 255 rra ret crk:: ds 2 ;drive and track for deblocking buffer iosec:: ds 1 ;current logical sector for DD, physical for SD blksec:: d;called to set up for a flush or a ;clear carry ld C,-1 ;set up head count ld DE,secs*4 ;set up number cpm sectors pe28 ld DE,128 hshft2:: add HL,DE djnz hshft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvaop AF rlca ;get drive rlca rlca and 3 call hex1 ld A,crest ;restore drive out (comnd),A herrlp:: in A,(stabuffer ld A,L cp hdstcnt ;carry set if in buffer ccf ret ; ; stores drive, track, sector of contents of buffer for u hinbuf2:: ld A,(hiodrvtrk) ;check for right drive ld B,A ld A,(hblkdrvtrk) sub B jr z,rthdd ;skip if right drivs 1 ;first logical sector in current host blk2sec:: ds 1 ;8th CP/M sector in an unallocated 2K block psec:: ds 1 ;currentr head sdsclp: inc C ;increment head count sbc HL,DE ;subtract out one heads worth of sectors jp p,sdsclp ;if not negilid),A ret endif SUBTTL Floppy disk storage page ; ; Floppy disk driver storage ; bufvalid:: db 0ffh ;buffer contus) rlca jr c,herrlp ;wait until done po AF RET page ; ; hsidselc is the read/write preparation for hard disk ;se by flush ; also sets buffer valid flag ; returns HL=start of sector in buffer, DE=DMA address, BC=128, A=0 ; hmkbfad:: e scf ret ;wrong drive return with carry set rthdd:: ld HL,(hiodrvtrk+1) ;check for right track ld BC,(hblkdrvtrk+1)  physical sector wrtpend:: db 0 ;write pending from buffer retryc:: db 0 ;number of retries left newfpy:: db 0 ;new tive do more add HL,DE ;restore sector number to HL ld A,L srl A ;find physical sector srl A ld (hpsec),A ld A,Ctains valid data for (blksec) ;0 = valid data iodma:: ds 2 ;dma storage .sfcond iff hard ;if not hard .lfcond  hsidselc computes the correct physical sector and side ; hsidselc:: ld HL,(hdiosec) ld E,L ;save L ld A,L and not(3ld A,(hiodrvtrk) ld (hblkdrvtrk),a ld HL,(hiodrvtrk+1) ld (hblkdrvtrk+1),HL ld HL,(hdiosec) ld B,L ld A,L and not( sbc HL,BC ;same drive and track scf ret nz ;not a match ld DE,(hblksec) ld HL,(hdiosec) ld A,D ;high bytes = floppy to be selected head:: db 0 ;head control = 0 or 1 oper:: db 0 ;operation (read/write) to be performed next hwptr:: d ld (hhead),A ;set head control byte ret page ; ; hinbuf returns carry flag set if sector not in buffer ; if sector is  iodrvtrk:: curfpy:: db 0 ;current selected physical floppy drive iotrk:: ds 1 ;current track for current disk blkdrvt1) ;compute first cp/m sector in buffer ld L,A ld (hblksec),HL ;save it ld L,E ;restore sector to HL hflsdsc:: hdstcnt-1) ld L,A ld (hblksec),HL ld A,B and hdstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-1/ w dskparm ;storage for pointer to current hw parameters blkptr:: dw dskparm ;pointer to paramters for block drive SUBTT) ; .WORD 16 ;PHYSICAL SECTORS PER TRACK ; .WORD 77 ;PHYSICAL TRACKS PER DISK ; .WORD 0 ;RESERVED TRACKS ; .WORD 0 ;TRANSLATrst:: DB 0dH,0ah,'HD1001 Error $' errhd:: DB ' on Head $' errcyl:: DB ', Cylinder $' errsec:: DB ', Sector $' errdr:: et sectors to load LD D,A LD HL,80H ;start loading at 80h LD E,1 ;start with sector 1 RBLK1: LD BC,DAL ; no sthysical sector hwrtpnd:: db 0 ;write pending from buffer hhead:: db 0 ;head control endif SUBTTL Error messages pagmonitor boot error entry point LOADER EQU 100H CMDSTATUS EQU 100H-4 SECTORS EQU 100H-2 ; CMD EQU 0CH ; fdc command & fdL Hard disk storage page ; ; Hard disk driver storage ; else .lfcond hiodrvtrk:: curhdsk:: db 0 ;current selected .z80 ; ; ;COLD BOOT LOADER FOR CP/M 2.2 ; FOR THE Z80 SBC ;LAST UPDATE 5/15/82 ; false equ 0 ;logical equates true db ', Drive $' endif SUBTTL Disk buffers and Cold Boot code page ; ; disk buffers ; These are not part of the floppy datus checks and data port into C LD A,E ; get sector OUT (SECMD),A ; set sector LD A,088H ; get operation OUT (CMD)e .sfcond iff hard .lfcond ; ; Floppy error messages ; badcode:: db 'Can''t recognize density of disk in$' rderr:: c status register TK EQU CMD+1 ; fdc track register SECMD EQU CMD+2 ; fdc sector register DAL EQU CMD+3 ; fdc data por physical hard disk drive hdiotrk:: ds 2 ;current track for current disk hblkdrvtrk:: ds 3 ;drive and track for deblocequ not false MINI EQU false ;set to true for mini trk0dd equ true ;true = track 00 double density dsd equ true ;trueriver module as such and ; should be shared by all disk modules as much as possible dirbuf:: hstbuf equ dirbuf+128 ;sector,A NOP READLOOP: IN A,(WAIT) ; wait for drq or intrq OR A ; was it intrq ? JP P,IODONE ; if so leave INI ;db 'Read$' wrterr:: db 'Write$' skerr:: db 'Seek$' trkerr:: db ' error on track $' secerr:: db ' sector $' siderr:: t WAIT EQU 014H ; hardware wait for fdc intrq + drq ; & drive select - restore latch ; ; BUFF EQU 80H ; default dking buffer hdiosec:: ds 2 ;current logical sector hblksec:: dw 0 ;first logical sector in host buffer hunalsec:: dw  = double sided for double density use ; RTYN EQU 10 ; disk io retries SEEKRT EQU 1 ; rate 0=3ms, 1=6ms, 2=10ms, 3=20ms  deblocking buffer ; ; lastadd equ $ SUBTTL SYMBOLS end  otherwise get data JR READLOOP ; and go do more IODONE: IN A,(CMD) ;get status LD C,A LD (CMDSTATUS),BC ;and db ' side $' drverr:: db ' drive $' crlf:: db 0dh,0ah,'$' page ; ; Hard disk error messages ; else .lfcond herma buffer ; ; BOOT: LD A,01101111B ;enable memory, turn prom and power on jump off OUT (16H),A LD A,(NSECTS) ;g0 ;first logical sector in current host unallocated block unalcv:: db 0 ;unallocated block vector hpsec:: ds 1 ;current pCDISK EQU 4 ; last disk selected by the ccp BELL EQU 07 ; ding MAXDSK EQU 1 ; largest disk number MONIT EQU 0F033H ; 0  save it AND 9CH ;any errors JR NZ,BOOTERROR ;leave if so DEC D ; one less block to get JP Z,LOADER ; if zero mu********************** ;** ** ;** ADVANCED DIGITAL SUPER QUAD Z80 SBC ** ;** ** ;** HARD DISK BOOT ** nd CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command ; ; loader program ; start: ld A,6fh ;get commanded flag else db 0e6h ;double density single sided flag endif else DB 0E5H ;density flag patched by sysgen endifor HDC1001 *** ; HDCBASE EQU 0E0H ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port WPC EQU HDCBASE+1 ; Write precompst be done INC E ; otherwise increment sector LD A,26+1 CP E ;past end of track JR NZ,RBLK1 ;if not go read more ;** ** ;** This is the cold boot code to load the loader ** ;** from track 0 on the hard disk into memory ** ;** atd to memory port out (memry),A ;turn off prom ; ld BC,hdcdata ;get port number and transfer length ld HL,80h ;startin END  port HDCERR EQU WPC ; Error port SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; Sector number CYLLO EQU HDCBA BOOTERROR: PUSH AF ;Save errors for monitor reporting LD (SECTORS),DE ;save error sector LD A,01001111B ;turn p 100h and run it. ** ;** ** ;** ** ;** Written by: ** ;** ** ;** Greg Lindberg ** ;** g address ld DE,10 ;number of sectors to transfer ; loop: ld A,D ;send sector to controller out (secno),A ld A,creadIVES ; .XSYM .END TER DRTBL: .BYTE [4]0FFH ;TRACK SAVE TABLE FOR 4 DRIVES LATBL: .BYTE [4]0FFH ;LATCH SAVE TABLE FOR 4 DRSE+4 ; Cylinder low CYLHI EQU HDCBASE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COMND EQU HDCBASE+7 ; Commandrom on OUT (16H),A JP MONIT ;and go back to monitor ORG 07EH NSECTS: IF trk0dd DB 4 ;if track o double densit ** ;***************************************************************** if2 .printx /pass 2/ endif SUBTTL SYMBO TITLE ADVANCED DIGITAL HARD DISK SECTOR 0 BOOT FOR SUPER QUAD Oct 26 1982 13:30 ;******************************************* ;send read command out (comnd),A swait: in A,(status) ;wait till done or A jp m,swait rra ;any errors jr c,her register STATUS EQU COMND ; Status register ; ;*** Command equates for HDC1001 *** ; CREST EQU 10H ; Restore commay get 4 1024b sectors ELSE DB 24 ; else get 24 ENDIF dens: if trk0dd if dsd db 0e7h ;double density double siLIC EQUATES page 60 .z80 ; ; Port equates for super quad ; memry equ 16h ;memory control port ; ;*** Port equates f1 ror ; inir ;get data inir ; inc D ;increment sector to read dec E ;decrement sector count jr nz,loop ;if mose ; banked equ false ;true for banked 1.3 system ; ; ctcch3 equ 0bh ;ctc channel 3 register ; fdccsr equ 0ch ;fdc  ;DISK DATA PORT FDWAIT = DISK+4 ;DISK WAIT PORT DCONT = DISK+4 ;DISK CONTROL PORT ; DDL = 3 ;DOUBLE DENSITY, BIT NUMBER (L drive: db 0ffh ;drive number sector: db 0 ;sector number seccnt: db 0 ;sector count trycnt: db 0 ;try counter dlybERSION ONLY *** ; .IDENT DSKTDD ;MODULE ID ; .INSERT DREQUATE ;O/S SYMBOLIC EQUIVALENCES ; TRUE = 0 ;DEFINE LOGICAL VALUcint equ 0d0h ;fdc interrupt command fdcfmt equ 0f0h ;fdc format track command ; hsdbit equ 2 ;head settle delay bit ;re go do it jp 100h ;else go execute loader ; herror: ld A,4fh ;turn prom back on out (memry),A jp 0f030h ;return command/status register fdctrk equ 0dh ;fdc track register fdcsec equ 0eh ;fdc sector register fdcdat equ 0fh ;fdc data TITLE TURBODOS OPERATING SYSTEM - SUPER SIX DISK DRIVER subttl copyright 1983, software 2000, inc. .Z80 ; ; copyright 198it: db 0 ;head settle delay bit intcst: db 0 ;interrupt completion status rwerrs: db 0 ;read/write error status dsrsav:ES FALSE = # TRUE ; DMAP = 0E0H ;DMA BASE ADDRESS DISK = 0F8H ;DISK BASE ADDRESS ; ADR0 = DMAP ;DMA ADDRESS REGISTER PO dmardc equ 01h ;dma read command dmawrc equ 05h ;dma write command ; tsd equ 2 ;two sided disk bit ddd equ 3 ;doubto monitor hard disk error return end  register ; dmactl equ 10h ;dma control register ; fdcdsr equ 14h ;fdc drive select register ; fdccal equ 08h ;fdc r3, software 2000, inc. ; converted to MICROSOFT M80 format by ; Advanced Digital Corp. ; ; version: 08/08/83 ; NAME ('S db 0 ;drive select register save ndxcnt: db 0 ;index pulse sequence count ndxtic: db 0 ;index pulse tick count retsp: RT WCT0 = DMAP+1 ;DMA WORD COUNT PORT CMND = DMAP+8 ;DMA COMMAND PORT DMACHK = DISK+5 ;DMA CHECK PORT ; DCOM = DISK ;DISK le density disk bit mini equ 4 ;mini-floppy disk bit tpi96 equ 5 ;96-tpi disk bit ; maxtry equ 10 ;max disk try count C. & MuSYS CORP." ; ; COPYRIGHT (C) 1981, SOFTWARE 2000, INC ; ; PORTIONS COPYRIGHT (C) 1981, 1982, MuSYS CORP. ; ; AUTHORe-calibrate command fdcskn equ 10h ;fdc seek command without head load fdcskh equ 18h ;fdc seek command with head load fd6DSK') ;module id ; INCLUDE DREQUATE.LIB ;driver symbolic equivalences ; false equ 0 ;logical equates true equ not faldw 0 ;error return stack pointer trktbl: db 0ffh,0ffh,0ffh,0ffh ;track save table ridbuf: ds 6 ;read id buffer ; dmxsph:COMMAND PORT DSTAT = DISK ;DISK STATUS PORT TRACK = DISK+1 ;DISK TRACK PORT SECTP = DISK+2 ;DISK SECTOR PORT DDATA = DISK+3 ; PUBLIC maxfpy ; DSEG ;locate in data area ; drvtbl:: db 0,0,1 shl mini,1 shl mini or 1 shl tpi96 ;drive table ;S: RONALD E. RAIKES ; MICHAEL D. BUSCH ; ; FOR MuSYS CORP.: WILLIAM A. SCHULTZ ; ; VERSION: 01/29/82 ; ; *** NON-DMA Vcrdc equ 82h ;fdc read sector command fdcwrc equ 0a2h ;fdc write sector command fdcrid equ 0c0h ;fdc read id command fd2  ;mutual exclusion semaphore dw 1 ;semaphore count ..dmxh: dw ..dmxh ;semaphore p/d head dw ..dmxh ; dwtsph:  ;function number=4? jr z,fmtdsk ;if so, continue ret ;else, done ; rddsk: ld a,maxtry ;get max try count ld (trycn ;save return code ld hl,dmxsph ;get mutual exclusion semaphore call signal## ;signal process as ready pop af ;restorast sector, continue ld a,(rwerrs) ;else, get read/write error status or a ;read/write error status=0? jr nz,..err1 ;iand db 0cfh ;write register 6 db 87h ;write register 6 ; dmapll equ $-dmapgm ;dma controller program list length ; ne ..err: call retry ;else, re-calibrate drive jr ..rd ;try again ; wrdsk: ld a,maxtry ;get max try count ld (trycnt;disk wait semaphore dw 0 ;semaphore count ..dwth: dw ..dwth ;semaphore p/d head dw ..dwth ; dmapgm: ;dma controlt),a ;set try counter ..rd: call setup ;do common setup jr nz,..err ;if seek error, continue ..rdl: call rwcom1 ;else,e return code ret ;done ; ..dd: ld (retsp),sp ;save error return stack pointer ld a,(ix+pdrfcn) ;get function number f not, continue call setup ;else, do common setup jr nz,..err1 ;if seek error, continue ..vfl: call rwcom1 ;else, do r common /?init?/ ;locate in initialization area ; dskin@:: call clrfdc ;clear fdc ld hl,dskisr ;get interrupt service ),a ;set try counter ..wr: call setup ;do common setup jr nz,..err1 ;if seek error, continue ..wrl: call rwcom1 ;else,ler program list db 0c3h ;write register 6 db 08bh ;write register 6 db 79h ;write register 0 dmaadr: dw 0 ;dma a do read/write common #1 ld de,fdcrdc shl 8 or 9dh ;get fdc read command/mask call rwcom2 ;do read/write common #2 ld a, or a ;function number=0? jr z,rddsk ;if so, continue dec a ;function number=1? jr z,wrdsk ;if so, continue decead/write common #1 ld d,fdcrdc ;get fdc read command call rwcom2 ;do read/write common #2 ld a,d ;get fdc read commaroutine ld (ctcvec##+6),hl ;set interrupt vector address ret ;done ; cseg ;locate in program area ; dskdr@:: l do read/write common #1 ld de,fdcwrc shl 8 or 0fdh ;get fdc read command/mask call rwcom2 ;do read/write common #2 ld address dmalen: dw 0 ;dma length db 14h ;write register 1 db 28h ;write register 2 db 85h ;write register 4 db fdmardc ;get dma read command call dmacom ;do dma common call rwcom3 ;do read/write common #3 jr nz,..rdl ;if not las a ;function number=2? jp z,retdst ;if so, continue dec a ;function number=3? jp z,retrdy ;if so, continue dec a nd call fdccmd ;output fdc read command and 99h ;extract relevant status bits call rwcom3 ;do read/write common #3 d hl,dmxsph ;get mutual exclusion semaphore call wait## ;dispatch if necessary call ..dd ;call disk driver push af ,dmawrc ;get dma write command call dmacom ;do dma common call rwcom3 ;do read/write common #3 jr nz,..wrl ;if not ldcdat ;fdc data port address db 8ah ;write register 5 db 0cfh ;write register 6 dmarwc: db 05h ;dma read/write commt sector, continue ld a,(rwerrs) ;else, get read/write error status or a ;read/write error status=0? ret z ;if so, do3  jr nz,..vfl ;if not last sector, continue ld a,(rwerrs) ;else, get read/write error status or a ;read/write error statudma) ;get requested dma address ld h,(ix+pdrdma+1) ld (dmaadr),hl ;set dma address ld b,(ix+secsiz) ;get sector size  h,(ix+pdrtc+1) dec hl ;decrement requested transfer count ld (dmalen),hl ;set dma length ld de,fdcfmt shl 8 or 0e1h ;g ld c,a ;sector number to c-reg ld a,(ix+pdrtrk) ;get track or a ;if it's zero jr z,..nstr ;don't translate sector e set 2,a ;else, set side one select bit ..s1nr: out (fdcdsr),a ;select drive/side/density ld (dsrsav),a ;save drive se saved drive select register bit ddd,a ;double density disk? jr nz,..ddd ;if so, continue res 3,(hl) ;else, reset dous=0? ret z ;if so, done ..err1: call retry ;else, re-calibrate drive jr ..wr ;try again ; fmtdsk: ld a,maxtry ;getinc b ;increment sector size ld hl,128/2 ;get sector size=0 (/2) ..sl: add hl,hl ;shift sector size left djnz ..sl ;et format command/mask ld a,dmawrc ;get dma write command call dmacom ;do dma common ret z ;if no errors, done ..err call getxlt ;get translation table address jr z,..nstr ;if no sector translation, continue ld b,0 ;make sector number lect register value ld a,(ix+pdrtrk) ;get requested track number or a ;requested track number=0? call z,recal ;if so,ble density bit ..ddd: bit tsd,a ;two sided disk? ld a,(sector) ;get sector number jr z,..ntsd ;if not two sided disk,  max try count ld (trycnt),a ;set try counter ..fmt: call seldsk ;select disk jp nz,fatal ;if drive not ready, continuesector size times dec hl ;decrement sector size ld (dmalen),hl ;set dma length xor a ld (rwerrs),a ;set read/write e2: call retry ;else, re-calibrate drive jr ..fmt ;try again ; setup: ld a,(ix+pdrsec) ;get requested sector number lddouble length add hl,bc ;index into translation table ld c,(hl) ;get translated sector number ..nstr: ld a,c ;get sec re-calibrate drive call seek ;seek to requested track jr nz,..err2 ;if seek error, continue ld l,(ix+pdrdma) ;get reqcontinue ld c,(ix+sectrk) ;get number of sectors/track srl c ;calc number of sectors/side cp c ;requested sector on s ld a,(dsrsav) ;get saved drive select register bit 7,(ix+pdrsec) ;double density requested? jr nz,..ddr ;if so, continrror status=0 call seldsk ;select disk jp nz,fatal ;if drive not ready, continue call seek ;else, seek to requested t (sector),a ;set sector number ld a,(ix+pdrsc) ;get requested sector count ld (seccnt),a ;set sector count ld l,(ix+pdrtor number inc a ;increment sector number to base 1 out (fdcsec),a ;set fdc sector register ld a,(dsrsav) ;get saved duested dma address ld h,(ix+pdrdma+1) ld (dmaadr),hl ;set dma address ld l,(ix+pdrtc) ;get requested transfer count ldide one? jr c,..ntsd ;if not, continue sub c ;else, adjust sector number set 2,(hl) ;set side one select bit ..ntsd:ue res 3,a ;else, reset double density bit ..ddr: bit 7,(ix+pdrsec+1) ;side one requested? jr z,..s1nr ;if not, continurack ret ;done ; rwcom1: call gettca ;get disk type code address ld a,(hl) ;get disk type code ld hl,dsrsav ;get4 rive select register out (fdcdsr),a ;select drive/side/density ret ;done ; rwcom2: ld a,(dsrsav) ;get saved drive sel retdst: call retrdy ;return ready status or a ;drive ready? ret z ;if not, done ld (ix+pdrtrk),1 ;and seek to trac# ;signal process as ready ld hl,0 ;set delay count=0 call delay## ;dispatch ld hl,dmxsph ;get mutual exclusion sema table value and 1 shl mini or 1 shl tpi96 ;extract relevant bits or c ;combine with disk type code ld c,a ;disk typeor number ld hl,seccnt ;get sector count dec (hl) ;decrement sector count ret ;done ; retry: ld c,abel ;get bellrfdc ;clear fdc and 80h ;drive ready? jr nz,..ntsd1 ;if not, continue push bc ;else, save disk type code call reaect register bit 2,a ;side one selected? ret z ;if not, done set 3,d ;else, set side one verify bit ret ;done k 1, will recal if first time call seek call readid ;read sector id jr nz,..nrdy ;if read unsuccessful, continue ld aphore call wait## ;dispatch if necessary pop hl ;restore error return stack pointer ld (retsp),hl ;set error return s code to c-reg ld de,dstbls## ;get dst table base ..dstl: ld hl,dtco## ;get offset to disk type code add hl,de ;calc di character call conout## ;output bell character to console ld a,(trycnt) ;get try counter and 01h ;even try? call nzdid ;read sector id pop bc ;restore disk type code jr nz,..ntsd1 ;if read unsuccessful, continue ld a,(dsrsav) ;get ; rwcom3: ld hl,rwerrs ;get read/write error status or (hl) ;combine with completion status ld (hl),a ;update read/wri,(ridbuf+3) ;else, get sector size ld c,a ;sector size to c-reg ld a,(dsrsav) ;get saved drive select register bit 3,atack pointer pop af ;restore try counter dec a ;decrement try counter ld (trycnt),a ;update try counter ret nz ;isk type code address ld a,c ;get disk type code cp (hl) ;dst type code match? ex de,hl ;dst address to hl-reg jr z,recal ;if not, re-calibrate drive ld a,(trycnt) ;get try counter push af ;save try counter ld hl,(retsp) ;get error saved drive select register xor c ;compare side one/two densities and 1 shl ddd jr nz,..ntsd1 ;if densities different, te error status ld hl,(dmaadr) ;get dma address ld de,(dmalen) ;get dma length inc de ;increment dma length add hl,d ;double density bit set? jr z,..nddd ;if not, continue set ddd,c ;else, set double density disk bit ..nddd: set 2,a f count not exhausted, done ; fatal: ld sp,(retsp) ;restore stack pointer ld a,0ffh ;return error code ret ;done ; ,..dstf ;if dst found, continue ld e,(hl) ;else, get next dst address inc hl ld d,(hl) ld a,d or e ;end of dst chreturn stack pointer push hl ;save error return stack pointer ld hl,dmxsph ;get mutual exclusion semaphore call signal#continue set tsd,c ;else, set two sided disk bit ..ntsd1: call getdta ;get drive table address ld a,(hl) ;get drivee ;calc next dma address ld (dmaadr),hl ;update dma address ld hl,sector ;get sector number inc (hl) ;increment sect ;set side one select bit out (fdcdsr),a ;select requested drive ld (dsrsav),a ;save drive select register value call cl5 ain? jr nz,..dstl ;if not, continue ..nrdy: xor a ;else, set return code=0 ret ;done ..dstf: inc hl ;advance past disk bit set? ret z ;if not, done ld a,2 ;get index pulse sequence count ld (ndxcnt),a ;set index pulse sequence counccmd ;output fdc re-calibrate command ret ;done ; retrdy: ld a,(ix+pdrdrv) ;get requested drive maxfpy equ $+1 ;poie ready? ret nz ;if not, done ld (dlybit),a ;else, set head settle delay bit=0 ld a,(drive) ;get drive number cp (ix) ;get requested track number out (fdcdat),a ;output requested track number call getdta ;get drive table address ld a,nt=0? cpl ;preset return code=0ffh ret z ;if sequence count=0, done xor a ;else, set return code=0 ret ;done link pointer inc hl ld (ix+pdrdst),l ;set dst address ld (ix+pdrdst+1),h ld a,0ffh ;set return code=0ffh ret ;dot=2 call enactc ;enable ctc interrupt controller ld a,fdcint or 1 shl 2 ;get fdc interrupt command out (fdccsr),a ;outpnt to max drive number for patching cp 4 ;test for valid drive number ld a,0 ;preset return code=0 ret nc ;if invali+pdrdrv) ;drive number=requested drive? ret z ;if so, done cp 0ffh ;drive number invalid? jr z,..dni ;if so, contin(hl) ;get drive table value and 3 ;extract step rate or fdcskh ;combine with fdc seek command call fdccmd ;output ; seldsk: ld a,(ix+pdrdrv) ;get requested drive set 3,a ;set double density bit call getdta ;get drive table address ne ; seek: in a,(fdctrk) ;get fdc track register inc a ;fdc track register=0ffh? call z,recal ;if so, re-calibrate drut fdc interrupt command ld hl,60 ;get one second delay count call delay## ;delay for one second ld a,03h ;get ctc d drive, return not ready call seldsk ;else, select requested drive ld a,0 ;preset return code=0 ret nz ;if drive noue call ..gtta ;else, get track save table address in a,(fdctrk) ;get fdc track register ld (hl),a ;save fdc track refdc seek command and 91h ;extract relevant status bits ret ;done ; recal: ld a,1 shl hsdbit ;get head settle delay b bit mini,(hl) ;mini-floppy disk? jr z,..nmfd ;if not, continue set 4,a ;else, set mini-floppy disk bit ..nmfd: out (fdive in a,(fdctrk) ;else, get fdc track register cp (ix+pdrtrk) ;fdc track=requested track? ret z ;if so, done ld a,1reset command out (ctcch3),a ;reset ctc channel 3 call clrfdc ;clear fdc ld hl,ndxcnt ;set index pulse sequence count t ready, done cpl ;else, set return code=0ffh ld hl,dsrsav ;get saved drive select register bit 4,(hl) ;mini-floppy gister ..dni: ld a,(ix+pdrdrv) ;get requested drive ld (drive),a ;set drive number call ..gtta ;get track save table adit ld (dlybit),a ;set head settle delay bit call clrfdc ;clear fdc ld a,fdccal ;get fdc re-calibrate command call fdcdsr),a ;select requested drive ld (dsrsav),a ;save drive select register value call clrfdc ;clear fdc and 80h ;driv shl hsdbit ;get head settle delay bit ld (dlybit),a ;set head settle delay bit call clrfdc ;clear fdc ld a,(ix+pdrtrk ld a,(hl) ;get index pulse sequence count ld (hl),0 ;set index pulse sequence count=0 or a ;index pulse sequence cou6 dress ld a,(hl) ;get fdc track register out (fdctrk),a ;set fdc track register out (fdcdat),a ;set fdc data register nd e ;extract relevant status bits push af ;save error status ld a,0c3h ;get dma reset command out (dmactl),a ;disaz,..ridl ;if not, continue ret ;else, done ; dmacom: ld (dmarwc),a ;set dma read/write command if banked call lokpt completion status ld a,(ndxcnt) ;get index pulse sequence count dec a ;index pulse sequence count=0? jp m,..isc0 ;iuble density bit ld a,(hl) ;get saved drive select register out (fdcdsr),a ;select drive/side/density ..ridl: ld de,fdcrclrfdc: ld a,fdcint ;get fdc interrupt command out (fdccsr),a ;output fdc interrupt command ex (sp),hl ;delay ex (sp), ld a,fdcskn ;get fdc seek command call fdccmd ;output fdc seek command xor a ;set return code=0 ret ;done ..gttable dma controller xor a ld (dlybit),a ;set head settle delay bit=0 if banked call frebnk## ;free mutual exclusion obnk## ;gain mutual exclusion on bank 1 endif call clrfdc ;clear fdc ld hl,dmapgm ;get dma program list ld bc,dmaplf so, continue jr nz,..fip ;if first index pulse, continue ld a,(ndxtic) ;else, get index pulse tick count ld c,a ;indid shl 8 or 9dh ;get read id command/mask ld a,dmardc ;get dma read command call dmacom ;read id ret z ;if read ok, dhl ex (sp),hl ex (sp),hl ex (sp),hl ex (sp),hl ex (sp),hl ex (sp),hl in a,(fdcdat) ;clear drq in a,(fdccsr) ;c: ld e,a ;drive number to de-reg ld d,0 ;double length ld hl,trktbl ;get track save table add hl,de ;index into tran bank 1 endif pop af ;restore error status ret ;done ; fdccmd: push af ;save fdc command call enactc ;enabl shl 8 or dmactl ;b=program length/c=port otir ;program dma controller ld a,(dlybit) ;get head settle delay bit or dex pulse tick count to c-reg ld a,(ticcnt##) ;get current tick count ld (ndxtic),a ;update index pulse tick count sub c one ld a,(dsrsav) ;get saved drive select register xor 1 shl 3 ;toggle single/double density bit out (fdcdsr),a ;outpulear intrq ret ;done ; dskisr:: ld (intsp##),SP ;save interrupt stack pointer ld sp,intstk## ;set up aux stack puck save table ret ;done ; readid: ld hl,ridbuf ;get read id buffer ld (dmaadr),hl ;set dma address ld hl,6-1 ;getle ctc interrupt controller pop af ;restore fdc command out (fdccsr),a ;output fdc command ld hl,dwtsph ;get disk wait ;combine with fdc command push de ;save error mask call fdccmd ;output fdc command pop de ;restore error mask a ;calc elapsed tick counts cp 14 ;index pulse timing within limits? jr nc,..isrx ;if not, continue xor a ld (ndxcnt)t drive select register value ld (dsrsav),a ;save drive select register value and 1 shl 3 ;double density selected? jr sh af ;save registers push bc push de push hl in a,(fdccsr) ;get fdc completion status ld (intcst),a ;save interru sector id length (-1) ld (dmalen),hl ;set dma length ld hl,dsrsav ;get saved drive select register set 3,(hl) ;set do semaphore call wait## ;wait for operation to complete ld a,(intcst) ;get interrupt completion status ret ;done ; 7 ,a ;set index pulse sequence count=0 jr ..iscx ;continue ..fip: ld (ndxcnt),a ;set index pulse sequence count=1 ld a,(tBYTE 0FFH ;DRIVE FOR 1791 TRACK REGISTER DRTBL: .BYTE [4]0FFH ;TRACK SAVE TABLE FOR 4 DRIVES LATBL: .BYTE [4]0FFH ;LATCH SAVE de add hl,de ;calc disk type code address ret ;done ; getdst: ld l,(ix+pdrdst) ;get dst address ld h,(ix+pdrdst+1)!f: &6ToQ W@Œf؀7L! 2: A qn7m`K @mX$u hn=7۴>kc Lfp0/γՒʹa2n05/B c.9 =9=UR6ՑP-`U1f<#M-all getdst ;get dst address ld de,xltbl## ;get offset to translation table add hl,de ;calc translation table address d7F 63nH: e&[eiX,J@E͹ L(u.`@hmp0X Wα@$#+b#N>[`26 > wait semaphore call signal## ;signal process as ready ..iscx: ld a,03h ;get ctc reset command out (ctcch3),a ;reset ct R!@b) 0ɖp4f  3@%s n(E1*YUz(6GfpaFB)6,ͫ@"h- oC,ͼ6add hl,de ;index into drive table ret ;done ; end I>S#@yM-%MJ3>1Q >3RS#'y%9QMQ.:PVc.yM%922Pӕ#4`yQeA =2FRU#2ua1Q 2p,`ld e,(hl) ;get translation table address inc hl ld d,(hl) ex de,hl ;translation table to hl-reg ld a,h or l ;tra @6O&=k`0ͣnd$|`m)` ?_AͯC^!` 3 |`m5`Ͳ`#Lͥ b~B?Ymme&[c channel 3 ..isrx: pop hl ;restore registers pop de pop bc pop af ld sp,(intsp##) ;restore stack pointer ei ;e_&mQY VD [ 3hYͪ 'ms&Yh@`!]C (e i@GX,&Z}&[]`fS&mSt b 0 ;CURRENT DMA ADDRESS CSTAT: .BYTE 0 ;CURRENT STATUS AFTER SELDSK: CLADDR: .WORD 0 ;ADDRESS OF CURRENT LATCH BYTE FDCDRV: .ٶt>z o6qo#!&<>x mld3ma7`( 7Mf" p)fe aٶ<n 27`hD egiOnslation table required? ret ;done ; gettca: call getdst ;get dst address ld de,typcod## ;get offset to disk type co`m)s ,: ۂۧ3n imWK`Y"(" (E8,?4|fP&@; 09K$e Cnable interrupts reti ;done ; enactc: ld a,0d7h ;get ctc channel 3 control word out (ctcch3),a ;initialize ctc chann3Eb,VpVmd3kaj?X~ 0t nb,R#R~X^2@ ´,"f32-<+('ce n(8  ;IxD[` 2ve* ũP 7$Cp,dpjʰc-rAvh:`%\@쪖>m4`9*՛f"STERN DIGITAL L PORT HLAB = 8 ;8 FOR HD LOAD AT BEG OF SEEK, 0 IF NOT RETRYS = 10 ;MAX RETRIES ; .LOC .PROG.# ;LOCATE IN PROGRAM AREA |8n7mq_P'ߋw4`9*՛f"TR@%9%PDSKIN@ dd$I@ ?INIT?+nF|pi2` ` pp<\ -h͢@QfKt[xx : Ls@8AqodOa8Y ̠`Abn&qd:i,4?AU€#-= 0F8H ;DISK BASE ADDRESS ; DCOM = DISK ;DISK COMMAND PORT DSTAT = DISK ;DISK STATUS PORT TRACK = DISK+1 ;DISK TRACK PORTFORMAT ;BASIC FORMAT MODULE FMTI8F ;INITIALIZATION FOR STANDARD 8 INCH FLOPPY FMTWD ;TRACK FORMATTING FOR WESTELENGTH ; DSKIN%::MVI A,0F2H ;CLEAR THE DRIVE SELECT LATCH OUT DCONT MVI A,0D0H ;SET UP 1771 BY FORCING INTERRUPT OUT DCO=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&FORMAT ;BASIC FORMAT MODULE FMTI5F ;INITIALIZATION FOR STANDARD 5.25 INCH FLOPPY FMTWD ;TRACK FORMATTING FOR WE SECTP = DISK+2 ;DISK SECTOR PORT DDATA = DISK+3 ;DISK DATA PORT FDWAIT = DISK+4 ;DISK WAIT PORT DCONT = DISK+4 ;DISK CONTRO9 M LDA STEPR% ;MASK STEP RATE TO PROPER BITS ANI 03H STA STEPR% LXI H,DSKIN% ;DEALLOCATE INITIALIZATION CODE JMP DEALO +6|lppF54 q7M&}i7+t nmvnaA{M4`9*՛f" +6|lppF54 q7M&}i7+t nmvnaA{M ȊihH I* li()`{)*Ͱ` q>4`9*՛f"TR@%9%PDSKIN@ dd$I@ ?INIT?+nF|pi2` ` pp<\ -h͢@QfKt[xx ..AGN ;CONTINUE ; FORMAT: MVI A,RETRYS ;GET NUMBER OF RETRIES STA TRYCNT ;SET TRY COUNT ORA A ;SET PSW NON-ZERO ..AGN: j 4fa@+ȊihH I* li()`{)*Ͱ` q>4`9*՛f"=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&TR@%9%PDSKIN@ dd$I@ ?INIT?+nF|pi2` ` pp<\ -h͢@QfKt[xx ;ENABLE INTERRUPTS AGAIN EXX ;SWAP BACK TO NORMAL REGISTERS ; ANI 0FDH ;MASK ERROR BITS CALL RWCOM2 ;DO READ/WRITE COM=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&CZ RECAL ;RECALIBRATE ON ERROR CALL SETUP ;DO COMMON READ/WRITE SETUP LDA CSTAT ;CHECK FOR WRITE PROTECTED ANI 040H JNZ ;MASK ERROR BITS CALL RWCOM2 ;DO READ/WRITE COMMON #2 JRNZ ..RDL ;IF NOT LAST SECTOR, CONTINUE LDA RWERR ;ELSE, GET READ/W}i7+7M" e02Yd` | iۮVmnm8X0 v! j i+,2Ͱ` q>4`9*՛f"=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&MON #2 JRNZ ..WRL ;IF NOT LAST SECTOR, CONTINUE LDA RWERR ;TEST FOR ERROR ORA A JRNZ ..ERR ;JUMP IF ERROR DETECTED ; }i7+7M" e02Yd` | iۮVmnm8X0 v! j i+,2Ͱ` q>4`9*՛f"FATAL ;WRITE PROTECTED - FATAL ERROR CALL RWCOM1 ;DO READ/WRITE COMMON #1 ; EXX ;SWAP TO ALTERNATE REGISTERS LXI H,..WL RITE ERROR ORA A ;ANY ERRORS? RZ ;IF NOT, DONE CALL TRYAGN ;ELSE, TRY AGAIN XRA A ;ZERO = FORCE RECALIBRATE JMPR ..AG +6|lppF54 q7M&}i7+t nmvnaA{M4`9*՛f"CALL SETUP ;DO COMMON SETUP FOR READ ..RDL: CALL RWCOM1 ;DO READ/WRITE COMMON #1 ; EXX ;SWAP TO ALTERNATE REGISTERS LXI H:  TITLE TURBODOS OPERATING SYSTEM - SUPER QUAD HARD DISK DRIVER .Z80 ; NAME ('SQHDC') ;MODULE ID ; INCLUDE DREQUATE.LIB  fixed&dn defl true ;fixed drive endif if typ eq ST506 strate&dn defl 3 ; 3 mS cyls&dn defl 153 heads&dn defl 4 fe to enable ecc TST MACRO DN ;physical hard disk defined IF HD&DN x defl 1 else x defl 0 endif endm hddsks defd drive endif if typ eq SA604 strate&dn defl 3 ; 3 mS cyls&dn defl 160 heads&dn defl 4 fixed&dn defl true ;fixed drQU 16 Q2030 EQU 17 Q2040 EQU 18 M4010 EQU 19 ; MiniScribe 4010 M4020 EQU 20 ; ;*** HDC1001 Disk equates *** ; HOFFdefl true ;fixed drive endif if typ eq TM501 strate&dn defl 3 ; 3 mS cyls&dn defl 306 heads&dn defl 2 fixed&dn defl ;O/S SYMBOLIC EQUATES ; FALSE EQU 0 ;DEFINE LOGICAL VALUES TRUE EQU NOT FALSE ; ; ;*** Hard Disk selection choices ixed&dn defl true ;fixed drive endif if typ eq TM601S strate&dn defl 3 ; 3 mS cyls&dn defl 153 heads&dn defl 2 fixl 0 ;number of physical hard disk drives hdtst macro rept 4 tst %hddsks ;test all four physical drives iff x exitive endif if typ eq SA606 strate&dn defl 3 ; 3 mS cyls&dn defl 160 heads&dn defl 6 fixed&dn defl true ;fixed drive  EQU 1 ; Number of reserved tracks for loader ; ;*** HDC1001 Physical drives *** ; hd0 equ TM502 ; Set to type of driv true ;fixed drive endif if typ eq TM502 strate&dn defl 3 ; 3 mS cyls&dn defl 306 heads&dn defl 4 fixed&dn defl tru*** ; ST503 EQU 1 ; Seagate Technology ST503 ST506 EQU 2 TM601S EQU 3 ; Tandon Magnetics TM601S TM602S EQU 4 TM603S EQed&dn defl true ;fixed drive endif if typ eq TM602S strate&dn defl 3 ; 3 mS cyls&dn defl 153 heads&dn defl 4 fixedm endif .lall hddsks defl hddsks+1 .xall endm ;end rept endm ;end hdtst hdtst ;calculate number of physical  endif if typ eq SA1002 strate&dn defl 0 ; 10 uS cyls&dn defl 256 heads&dn defl 2 fixed&dn defl true ;fixed drive e or false if not used hd1 equ false ; all drives must have same interface type hd2 equ false ; i.e. all SA1000 type ore ;fixed drive endif if typ eq TM503 strate&dn defl 3 ; 3 mS cyls&dn defl 306 heads&dn defl 6 fixed&dn defl true ;U 5 TM603SE EQU 6 TM501 EQU 7 ; Tandon Magnetics TM501 TM502 EQU 8 TM503 EQU 9 SA602 EQU 10 ; Shugart Associates SA602 &dn defl true ;fixed drive endif if typ eq TM603S strate&dn defl 3 ; 3 mS cyls&dn defl 153 heads&dn defl 6 fixed&dhard disks ; ; dsktyp macro dn,typ .sfcond if typ eq ST503 strate&dn defl 3 ; 3 mS cyls&dn defl 153 heads&dn defl 2endif if typ eq SA1004 strate&dn defl 0 ; 10 uS cyls&dn defl 256 heads&dn defl 4 fixed&dn defl true ;fixed drive en all ST506 type hd3 equ false ; ;*** HDC1001 ECC selection *** eccbit equ 80h ;ecc command bit ecc equ false ;set trufixed drive endif if typ eq SA602 strate&dn defl 3 ; 3 mS cyls&dn defl 160 heads&dn defl 2 fixed&dn defl true ;fixe SA604 EQU 11 SA606 EQU 12 SA1002 EQU 13 ; Shugart Associates SA1002 SA1004 EQU 14 Q2010 EQU 15 ; Quantum Q2010 Q2020 En defl true ;fixed drive endif if typ eq TM603SE strate&dn defl 3 ; 3 mS cyls&dn defl 230 heads&dn defl 6 fixed&dn ; dif if typ eq Q2010 strate&dn defl 0 ; 10 uS cyls&dn defl 512 heads&dn defl 2 fixed&dn defl true ;fixed drive endifSE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COMND EQU HDCBASE+7 ; Command register STATUS EQU COMND ; Statuctory blocks db 2 ; Sector size 512 bytes dw 16*heads&dn ; Sectors per track dw cyls&dn ; Total tracks on disk dw hds 1 ;temporary sector count storage ; ; CSEG ;CODE STUFF ; DSKDR@:: LD HL,DMXSPH ;GET MUTUAL EXCLUSION SEMAPHORE eq M4020 strate&dn defl 0 ; 10 uS cyls&dn defl 480 heads&dn defl 4 fixed&dn defl true ;fixed drive endif dks&dn deflALIZATION AREA ; DSKIN@:: xor A ;set track 0 out (cyllo),A out (cylhi),A ld A,cseek+2*strate0 ;seek and set steep ra if typ eq Q2020 strate&dn defl 0 ; 10 uS cyls&dn defl 512 heads&dn defl 4 fixed&dn defl true ;fixed drive endif s register ; ;*** Command equates for HDC1001 *** ; CREST EQU 10H ; Restore command CSEEK EQU 70H ; Seek command Coff ; Reserved tracks .xall dstlen defl $-dst&dn endm ; ; ;*** Port equates for HDC1001 *** ; HDCBASE EQU 0E0H CALL WAIT## ;DISPATCH IF NECESSARY CALL ..DD ;CALL DISK DRIVER PUSH AF ;SAVE RETURN CODE LD HL,DMXSPH ;GET MUTUAL heads&dn*(cyls&dn-hoff)*2 ;hard disk size in blocks ;dir&dn defl ((dks&dn / 128) + 1) ; DIR entries = blocks / 128 dir&dn dte out (comnd),A ret ; DSEG ;DATA STUFF ; DMXSPH: ;MUTUAL EXCLUSION SEMAPHORE DW 1 ;SEMAPHORE COUNT ..DMXH: if typ eq Q2030 strate&dn defl 0 ; 10 uS cyls&dn defl 512 heads&dn defl 6 fixed&dn defl true ;fixed drive endif iREAD EQU 20H ; Read sector command CWRITE EQU 30H ; Write command CFORM EQU 50H ; Format track ; ;*** Status and error ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port WPC EQU HDCBASE+1 ; Write precomp port HDCERR EQU WPC ; Error port  EXCLUSION SEMAPHORE CALL SIGNAL## ;SIGNAL PROCESS AS READY POP AF ;RESTORE RETURN CODE RET ;DONE ; ..DD: LD A,(IXefl 8 endm x defl 0 rept hddsks dsktyp %x,hd%x x defl x+1 endm dstdef macro dn ; Disk specifcation table defi DW ..DMXH ;SEMAPHORE P/D HEAD DW ..DMXH ; HDCSPH: ;HDC SEMAPHORE DW 0 ;SEMAPHORE COUNT ..HDCH: DW ..HDCH ;SEMAf typ eq Q2040 strate&dn defl 0 ; 10 uS cyls&dn defl 512 heads&dn defl 8 fixed&dn defl true ;fixed drive endif if t bits ; hdbsy equ 80h ;hard disk busy hdrdy equ 40h ;hard disk ready hdskcp equ 10h ;seek complete ; inter equ 8 ; SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; Sector number CYLLO EQU HDCBASE+4 ; Cylinder low CYLHI EQU HDCBA+PDRFCN) ;GET PD REQ FUNCTION NUMBER OR A ;PD REQ FUNCTION NUMBER=0? JP Z,RDDISK ;IF SO, CONTINUE DEC A ;PD REQ FUNCnation macro .lall dst&dn: db 5 or (80h and fixed&dn) ; Block size 4K bytes dw dks&dn ; Total blocks db dir&dn ; DirePHORE P/D HEAD DW ..HDCH ; dmaptr: ds 2 ;temporary dma pointer storage sector: ds 1 ;temporary sector storage seccnt: yp eq M4010 strate&dn defl 0 ; 10 uS cyls&dn defl 480 heads&dn defl 2 fixed&dn defl true ;fixed drive endif if typ hard disk sector interleave factor secs equ 16 ;Physical sectors per track per head ; ; COMMON /?INIT?/ ;LOCATE IN INITI< TION NUMBER=1? JP Z,WRDISK ;IF SO, CONTINUE DEC A ;PD REQ FUNCTION NUMBER=2? JP Z,RETDST ;IF SO, CONTINUE DEC A ;Pet and send sector to drive and 0fh out (secno),A ld L,(IX+pdrtrk) ;get and send cylinder to drive ld H,(IX+pdrtrk+1) X+pdrdst),A ; otherwise zero dst pointer ld (IX+pdrdst+1),A ret ; and return dstrdy: ld A,(IX+pdrdrv) ;get requested value ret ;and leave ; wrdisk: call rwini ;initialize pointers wrdsk1: call rwset ;set up parameters or A ;did  i secto siz (51 byte) or B ; and drive out (sdh),A ;send to controller or 0ffh ;set worked flag ret selnrdy:an error ld A,cread ;send read command out (comnd),A push IX ;save IX call wthdc ;wait until done in A,(status) D REQ FUNCTION NUMBER=3? JP Z,RETRDY ;IF SO, CONTINUE DEC A ;PD REQ FUNCTION NUMBER=4? JP Z,FORMAT ;IF SO, CONTINUE  ld A,L out (cyllo),A ld A,H out (cylhi),A jp rtrdy1 ;go set head and drive and return ready status ; rwini: ld L,(I drive ld B,A ;and save for mult add A,A ;*2 add A,A ;*4 add A,B ;*5 add A,A ;*10 add A,B ;*11 ld HL,dit work ld A,0ffh ;preset error return ret z ;return if there was an error ld A,cwrite ;send write command out (com xor 0 ;return not ready ret ; retrdy: call rwini ;do initialization rtrdy1: call selhdsk ;select the proper drive  rra ;any errors pop IX ld A,0ffh ret c ;if so leave ld C,hdcdata ;set up port address ld HL,(dmaptr) ;get dmaRET ;ELSE, DONE ; selhdsk: ld A,(IX+pdrdrv) ;get requested drive cp hddsks ;make sure valid drive number jp nc,selX+pdrdma) ;get dma address ld H,(IX+pdrdma+1) ; ld (dmaptr),HL ;save into local storage ld A,(IX+pdrsec) ;get sector nstbase ;get base address of dst tables ld E,A ;make offset 16 bits ld D,0 add HL,DE ; and put together ld (IX+pdrdsnd),A ld B,0 ;set transfer count ld c,hdcdata ;set up port address ld HL,(dmaptr) ;get dma address otir ;send dat ret z ;leave if bad drive in A,(status) ;find out if ready and hdrdy ret z ;return if not or 0ffh ; otherwise s address ld B,0 ;set transfer count inir ;get data inir ld (dmaptr),HL ;save dma address ld HL,sector inc (HL)nrdy ;exit if not rlca ;put drive into proper place for command rlca rlca ld B,A ;save drive ld A,(sector) ;getumber ld (sector),A ld A,(IX+pdrsc) ;get sector count ld (seccnt),A ret ; rddisk: call rwini ;initialize pointers t),L ;save for return ld (IX+pdrdst+1),H or 0ffh ;set valid return flag ret ; and leave ; rwset: ld A,(sector) ;ga otir ld (dmaptr),HL ;save dma address push IX call wthdc ;wait until done in A,(status) rra ;any errors poet ready return value ret ; and leave ; retdst: call retrdy ;is drive ready or A jr nz,dstrdy ;if so skip ld (I ;update pointers and counters inc HL dec (HL) jr nz,rddsk1 ;if more to do, do it xor A ; otherwise set good return sector to define head srl a srl a srl a srl a and 07h ;keep only significant part o 20 or (eccbit and ecc) ;purddsk1: call rwset ;set up parameters or A ;did it work ld A,0ffh ;preset error return ret z ;return if there was = p IX ld A,0ffh ret c ;if so leave ld HL,sector inc (HL) ;update pointers and counters inc HL dec (HL) jr nz,wrEATE POLL ROUTINUE CALL HDCPR ;EXECUTE POLL ROUTINE LD HL,HDCSPH ;GET SEMAPHORE JP WAIT## ;DISPATCH IF NECESSARY Any errors? LD A,0FFH ; Preload error return ret C ; If so, call it quits xor A ; Otherwise set good return ret j 4fa@+ ȊihH I* li()`{)*Ͱ` q>4`9*՛f"RLCA OR 20H or (eccbit and ecc) ; OR in sector size ld B,A ; Save it ld A,(IX+pdrsec) ;get track to define head and TR@%9%PDSKIN@ dd$I@ ?INIT?+nF|vi2` ` pp<\ -h͢@QfKt[xxdsk1 ;if more to do, do it xor A ; otherwise set good return value ret ;and leave ; format:: ;Figure all the needed x defl 0 dstbase: rept hddsks ;define disk specification tables ; for all hard drives on controller dstdef %x  ; And leave ; HDCPOLL: DW 0 ;POLL ROUTINE DW 0 ; HDCPR: IN A,(STATUS) ;GET DRIVE STATUS AND A ;CONTROLLER BUS07h ;keep only significant part or B OUT (SDH),A ; Format LD A,CFORM ; Issue format command OUT (COMND),A LD B,0 =eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM& format paramters ;Get cylinder and head LD A,(IX+PDRSC) ; Get sector count OUT (SECNT),A ld L,(IX+pdrtrk) ;get and sen x defl x+1 endm end Y? RET M ;IF SO, DONE LD HL,HDCPOLL ;ELSE, GET POLL ROUTINE ADDRESS CALL UNLINK## ;UNLINK POLL ROUTINE LD HL,HDCSPH  ; Get transfer size 0 = 256 ld C,HDCDATA XOR A ; Get bad block bits OUT (SECNO),A ; Start on sector 0 DATALP: OUT (C}i7+7M" e02Yd` | iۮVmnm8X0 v! j i+,2Ͱ` q>4`9*՛f"d cylinder to drive ld H,(IX+pdrtrk+1) ld A,L out (cyllo),A ld A,H out (cylhi),A LD L,(IX+PDRDMA) ; Get address of t8#U6p0 7Í| %~qu69|c4 ^C`Mͯ`Nd@`4<02|ۧ  ;GET SEMAPHORE JP SIGNAL## ;SIGNAL PROCESS AS READY ; wthdc: LD DE,HDCPOLL ;GET POLL ROUTINE ADDRESS CALL LNKPOL## ;CR),A OUTI JR NZ,DATALP ; Continue till sector full FWAIT: IN A,(STATUS) ; Wait for format AND A JP M,FWAIT RRA ;  +6|lppF54 q7M&}i7+t nmvnaA{M TR@%9%PDSKIN@ dd$I@ ?INIT?+nF|vi2` ` pp<\ -h͢@QfKt[xx=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&+(_ Can't write boot tracks Operation successfu !\>>2^ Reading source file:* R=eT*[ ҩ`p8: ,~`;@iKfِm*d6b!djp@nӸ5?Ht:XnAӠ5dpqM&}i7+7M" e02Yd` | iۮVmnm8X0 v! j i+,2Ͱ` q>4`9*՛f">!(S<:\_ Reading boot tracks:2bͿ*l"<:l=2c>2b!p"lVbʼ:t!@)=KuC}i7+7M" e02Yd` | iۮVmnm8X0 v! j i+,2Ͱ` q>4`9*՛f" +6|lppF54 q7M&}i7+t nmvnaA{Mo! z> 8  >O0h"j>8*<B2bÿ=2c>2b!p"lVb(C:t!@) +6|lppF54 q7M&}i7+t nmvnaA{M4`9*՛f"1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KTR@%9%PDSKIN@ dd$I@ ?INIT?+nF|vi2` ` pp<\ -h͢@QfKt[xx=KuCh"jKyx(Sl*R!"d"fVb*d#"d*l[j"l*y+"y| !x ~#j 4fa@*  ȊihH I* li()`{)*Ͱ` q>4`9*՛f"ve specified7:] (%?8%(\ Can't find source file{͠0 Not enough memory]( Can't read boot tracks=(? B0KC:( [0!' #"* (,*#"+))[R%! 6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ !> ZhZqZhh)Zh3Zq>8*]}o"k@ 7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:PM 1 = OSLOAD ? SelectReadFile not found error: file (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:>o! z> 8  >O0R}??2y2::G:(7*KB7?[*R}?:2*"*E}o"xG!<[23>L~ÃG3x(OxA}<: |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $zi` n&\\CC!:" ::: 3>Lûþ~ÃG3x(OxAO3F#Nů  SYS: Which .SYS file to load 0 = C |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 B0KC:( [0!' #"* (,*#"+))[R%! ylinder $, Sector $, Drive $>ͳ8͍!> .#Zh3Zq=ZhhIZhSZzi` n&<CC!: :::>͓8ͿmPM 1 = OSLOAD ? SelectReadFile not found error: file ͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:@ q>8*]}o"k@ R}??2 y2"::G:(7*KB7?[*R}?:2*"*E}o"xG!\3>L(#~HÃG3x(OxA,(0W}_nfRut=RDM!C76! [36:G6!w0 B0KC:( [0!' #"* (,*#"+))[R%! 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*Kylinder $, Sector $, Drive $[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $Qzi` n& ͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:B0KC:( [0!' #"* (,*#"+))[R%! 6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ ylinder $, Sector $, Drive $CTCY!:b :T:U:`>8],4!> nPM 1 = OSLOAD ? SelectReadFile not found error: file (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:>o! z> 8  >O06!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ cZhsZq}ZhhZhZq>8*Y]}o"[k@ R}??2`y2b:P:SG:V7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<: |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K>o! z> 8  >O0(7*TKWB7?[[*YR}?:S2V*T"W*YE}o"[xG![Q2P HD1001 Error $ on Head $, CA ͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ  q!*T~(ͭ8͏ͷ:K2N>2>2SKc> 2P> :SG /_~(!: *E:N{ >ͳ8͍!> .#Zh3Zq=ZhhIZhSZ7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:PM 1 = OSLOAD ? SelectReadFile not found error: file (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' >o:~W!{> " OC > S>O3 _!c(  :P= L{(({ZZ:HhZ:NhZ:RhZZ>2P ~ q>8*]}o"k@ R}??2 y2"::G:(7*KB7?[*R}?:2*"*E}o"xG!\3>L ~ÒÃG3x(OxA}<: |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K ( w:K2LF8 <2Ny2R:KW:D*GKIB(7:LGz?"V*G"I:KG2LxG![E2DG![2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $Ezi` n&?@/ _      y3>L~ÃG3x(OxAO3F#Nů  SYS: Which .SYS file to load 0 = CB0KC:( [0!' #"* (,*#"+))[R%! > z:(8 XZd>w(>>w~Can't recognize density of disk in$Read$ylinder $, Sector $, Drive $2Hy2KY  5"T~G:RG~ > 2P:HO y~ 8zi` n&\\CC!:" ::: PM 1 = OSLOAD ? SelectReadFile not found error: file B Write$Seek$ error on track $ sector $ side $ drive $ $ |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*Kylinder $, Sector $, Drive $zi` n&<CC!: :::>͓8Ϳm:s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z;͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = CB0KC:( [0!' #"* (,*#"+))[R%! 6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ !> ZhZqZhh)Zh3Zq>8*]}o"k@ ͂. % *z;))))*s;& "z;( <ͭ *z;:s;AO>/ͭ2 O :s;A<<ͭ2 d :s;A<:s;Zo >Z<ͭ:s;XO>PM 1 = OSLOAD ? SelectReadFile not found error: file !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:>o:~W!{> " OC > S>O3R}??2y2::G:(7*KB7?[*R}?:2*"*E}o"xG!<[2 :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M 7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K>o! z> 8  >O0 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $3>Lûþ~ÃG3x(OxA z:(8 XZd>w(>>w~Can't recognize density of disk in$Read$2Hy2KY  5"T~G:RG~ > 2P:HO y~ 8>o:~W!{> " OC > S>O3PM 1 = OSLOAD ? SelectReadFile not found error: file !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:Write$Seek$ error on track $ sector $ side $ drive $ $ q!*T~(ͭ8͏ͷ:K2N>2>2SKc> 2P> :SG /_~(!: *E:N{ 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' :s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z; _!c(  :P= L{(({ZZ:HhZ:NhZ:RhZZ>2P ~ B0KC:( [0!' #"* (,*#"+))[R%! 3>L ~ÒÃG3x(OxA,(0W}_nfRut=RDM!C76! [36:G6!w0 ͂. % *z;))))*s;& "z;( <ͭ *z;:s;AO>/ͭ2 O :s;A<<ͭ2 d :s;A<:s;Zo >Z<ͭ:s;XO> ( w:K2LF8 <2Ny2R:KW:D*GKIB(7:LGz?"V*G"I:KG2LxG![E2DG!!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:Ezi` n&?@/ _      y͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M D (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' :s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z; _!c(  :P= L{(({ZZ:HhZ:NhZ:RhZZ>2P ~ B0KC:( [0!' #"* (,*#"+))[R%! 3>L ~ÒÃG3x(OxA,(0W}_nfRut=RDM!C76! [36:G6!w0 ͂. % *z;))))*s;& "z;( <ͭ *z;:s;AO>/ͭ2 O :s;A<<ͭ2 d :s;A<:s;Zo >Z<ͭ:s;XO> ( w:K2LF8 <2Ny2R:KW:D*GKIB(7:LGz?"V*G"I:KG2LxG![E2DG!!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:Ezi` n&?@/ _      y͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M > z:(8 XZd>w(>>w~Can't recognize density of disk in$Read$(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' 2Hy2KY  5"T~G:RG~ > 2P:HO y~ 8>o! z> 8  >O0PM 1 = OSLOAD ? SelectReadFile not found error: file MWrite$Seek$ error on track $ sector $ side $ drive $ $ |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0  q!*T~(ͭ8͏ͷ:K2N>2>2SKc> 2P> :SG /_~(!: *E:N{ 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*K7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:E ͘!4͘ !͙>O3F#Nů  SYS: Which .SYS file to load 0 = C!!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ q>8*]}o"k@ R}??2 y2"::G:(7*KB7?[*R}?:2*"*E}o"xG!\>ͳ8͍!> .'Zh7ZqAZhhMZhWZ7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:PM 1 = OSLOAD ? SelectReadFile not found error: file (#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!' >o! z> 8  >O0[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $q>8*]}o"k@ R}??2$y2&::G:(7*KB7[*z7?R}?:2*"*E}o"xG!3>L~ÃG3x(OxA}<: |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*Kylinder $, Sector $, Drive $`[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $zi` n&\\1KCC!:" ::: 3>L~ÃG3x(OxAO3F#Nů  SYS: Which .SYS file to load 0 = CB0KC:( [0!' #"* (,*#"+))[R%! 6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ ylinder $, Sector $, Drive $>ͳ8͍!> .#Zh3Zq=ZhhIZhSZzi` n&``1CC!:& :::$PM 1 = OSLOAD ? SelectReadFile not found error: file F FORMAT ;BASIC FORMAT MODULE FMTTSD ;INITIALIZATION FOR TARBELL SINGLE DENSITY FMTWD ;TRACK FORMATTING FOR WESTE LXI H,RTCISR CALL INTENA# LXI H,RTCNIT ;GET INITIALIZATION CODE ADDRESS JMP DEALOC# ;DE-ALLOCATE INITIALIZATION CODE ;MuSYS CORP." ; ; COPYRIGHT (C) 1981, SOFTWARE 2000, INC. ; ; PORTIONS COPYRIGHT (C) 1981, MuSYS CORP. ; ; AUTHORS: RONALD  JMP INTXIT# ;WE ARE DONE WITH IT ; .XSYM .END YTIC# ;SERVICE DISPATCHER DELAY MANAGER MVI A,IVEC ;TELL WHICH INTERRUPTRN DIGITAL BASIC FORMAT MODULE FMTTSD ;INITIALIZATION FOR TARBELL SINGLE DENSITY FMTWD ;TRACK FORMATTING FOR WESTE NITLEN = .-RTCNIT ;INITIALIZATION CODE LENGTH ; RTCISR: SSPD INTSP# ;SAVE STACK POINTER LXI SP,INTSTK# ;SET UP AUX STACK E. RAIKES ; MICHAEL D. BUSCH ; ; FOR MuSYS CORP.: WILLIAM A. SCHULTZ ; ; VERSION: 10/03/81 ; .IDENT RTCE80 ;MODULE ID PUSH PSW ;SAVE REGISTERS PUSH B PUSH D PUSH H LXI H,TICCNT ;GET TICK COUNTER INR M ;INCREMENT TICK COUNTER MOV A, ; IVEC = 3 ;INTERRUPT VECTOR NUMBER ; .LOC .DATA.# ;LOCATE IN DATA AREA ; TICCNT: .BYTE 0 ;TICK COUNTER ; .LOC .PROGN #`=I%9XSU RTCNIT%! C@` @<Fh6)ʈ1 M ;GET TICK COUNT CPI 60 ;SECONDS COUNT REACHED? JRC ..NSEC ;IF NOT, CONTINUE MVI M,0 ;ELSE, RESET TICK COUNTER CALL RTC.# ;LOCATE IN PROGRAM AREA ; .WORD NITLEN+2 ;INITIALIZATION CODE LENGTH ; RTCNIT::MVI A,IVEC ;INITIALIZE INTERRUPT VECTOR )ʊjP 'Jjhq /)ʋ *.PAGE 100 .TITLE "MuDOS OPERATING SYSTEM - EXP/80 REAL-TIME-CLOCK ROUTINES" .SBTTL "COPYRIGHT (C) 1981, SOFTWARE 2000, INC. & SEC# ;SERVICE REAL TIME CLOCK MANAGER ..NSEC: CALL DLYTIC# ;SERVICE DISPATCHER DELAY MANAGER MVI A,IVEC ;TELL WHICH INTERRUPTG H I J K L