TITLE 'FORMAT - CP/M-85 FORMAT UTILITY 19 SEP 83' FALSE EQU 0 TRUE EQU 1 ASM86 EQU FALSE ;** EXTRA PSEUDO OPS FOR USE WITH MAC ; RB MACRO A DS A ENDM RW MACRO A DS 2*A ENDM ;** ;* MACRO COMINP - Command line input ;* ;* Macro to bypass console prompts and read from command line ;* ;* Bill Earl 10/18/81 ;* ;* DATUM = address of desired input data ;* PROCED = place to continue after acquiring data ;* IGNOR = place to continue if no command line ;* COMINP MACRO DATUM, PROCED, IGNOR LDA COMLIN ;; is there a command line ANA A ;; JZ IGNOR ;; no, read from console LDA DATUM ;; yes, load it into A JMP PROCED ;; take it and run ENDM ;** ;* MACRO QUERY ;* ;* CHECKS TO SEE IF NO QUERY MODE, ;* IF SO, SKIPS OVER USER PROMPT ;* QUERY MACRO RESUME LDA NOQFLG ANA A JNZ RESUME ENDM ;** ;* MACRO TCHECK ;* ;* TYPE CHECK OF DISK ;* TCHECK MACRO DRT LOCAL TC1 LDA TFLG ANA A JZ TC1 CPI DRT TC1 JNZ TMMERR ENDM PAGE BIAS EQU 0 ;** CP/M-85 SYSTEM EQUATES ; ; OS VALUES CCPL EQU 0800H ;LENGTH OF CCP BDOSL EQU 0E00H ;LENGTH OF BDOS ; RESERVED LOCATIONS IN PAGE ZERO ORG BIAS BOOT RB 3 ;JUMP TO WARM START ENTRY IOBYTE RB 1 ;IOBYTE DFTDRV RB 1 ;CURRENT EFAULT DRIVE BDOS RB 3 ;JUMP TO BDOS INT1 RB 8 ;INTERRUPT LOCATION 1 INT2 RB 8 ;INTERRUPT LOCATION 2 INT3 RB 8 ;INTERRUPT LOCATION 3 INT4 RB 8 ;INTERRUPT LOCATION 4 INT5 RB 8 ;INTERRUPT LOCATION 5 INT6 RB 8 ;INTERRUPT LOCATION 6 (RESERVED) INT7 RB 8 ;INTERRUPT LOCATION 7 (USED BY DDT) BSCR RB 16 ;16 BYTE SCRATCH AREA FOR BIOS RB 12 ;12 BYTES NOT USED BUT RESERVED TFCB RB 36 ;TRANSIENT DEFAULT FCB TFCB2 EQU TFCB+16 ;TRANSIENT 2ND FILENAME TBUFF RB 128 ;DEFAULT DISK BUFFER TPA RB 0 ;START OF TRANSIENT PROGRAM AREA ; HEATH PAGE ZERO LOCATIONS IF ASM86 ORG OFFSET INT1+3 ENDIF IF NOT ASM86 ORG INT1+3 ENDIF TICCNT RW 2 ;32 BIT TIMER TIC COUNTER TIMEFLG RB 1 ;TIMER 2 FLAG (0=RUNNING , 1=TIME OUT) IF ASM86 ORG OFFSET INT2 ENDIF IF NOT ASM86 ORG INT2 ENDIF COMREG RB 0 ;BIOS88 COMMUNICATION REGION COMFUNC RB 1 ; BIOS FUNCTION VALUE = (#-CBOOT)/3 COMRA RB 1 ; (A) COMRBC RW 0 ; (BC) COMRC RB 1 ; (C) COMRB RB 1 ; (B) COMRDE RW 0 ; (DE) COMRE RB 1 ; (E) COMRD RB 1 ; (D) COMRHL RW 0 ; (HL) COMRL RB 1 ; (L) COMRH RB 1 ; (H) COMWHO RB 1 ;WHICH PROCESSOR IS RUNNING ; ZPSPPS5 = 8085 ; ZPSPPS8 = 8088 IF ASM86 ORG OFFSET INT4 + 3 ENDIF IF NOT ASM86 ORG INT4 + 3 ENDIF LPENHF RB 1 ;LIGHT PEN HIT FLAG (<>0 = HIT) LPENPOS RW 1 ;LIGHT PEN POSITION LPENHIT RB 1 ;LIGTH PEN HIT REGISTER IMAGE BDMAP EQU BSCR+00H ;DRIVE MAP (MAX OF 8 ENTRIES 0-7) IF ASM86 BBIOS EQU WORD PTR BSCR+0EH ;TRUE ADDRESS FOR START OF BIOS ENDIF IF NOT ASM86 BBIOS EQU BSCR+0EH ;TRUE ADDRESS FOR START OF BIOS ENDIF ; CP/M FUNCTIONS RESET EQU 0 ;SYSTEM RESET RDCON EQU 1 ;READ CONSOLE WRCON EQU 2 ;WRITE CONSOLE RDRDR EQU 3 ;READ READER WRPUN EQU 4 ;WRITE PUNCH WRLST EQU 5 ;WRITE LIST DCONIO EQU 6 ;DIRECT CONSOLE I/O (2) IOSTAT EQU 7 ;INTERROGATE I/O STATUS ASTAT EQU 8 ;ALTER I/O STATUS PRCONB EQU 9 ;PRINT CONSOLE BUFFER RDCONB EQU 10 ;READ CONSOLE BUFFER CCSTAT EQU 11 ;CHECK CONSOLE STATUS LDH EQU 12 ;LIFT DISK HEAD CPMVER EQU LDH ;GET CP/M VERSION (2) RDS EQU 13 ;RESET DISK SYSTEM SELDSK EQU 14 ;SELECT DISK OPEN EQU 15 ;OPEN FILE CLOSE EQU 16 ;CLOSE FILE S1ST EQU 17 ;SEARCH FIRST SNXT EQU 18 ;SEARCH NEXT DELETE EQU 19 ;DELETE FILE READ EQU 20 ;READ RECORD WRITE EQU 21 ;WRITE RECORD CREATE EQU 22 ;CREATE FILE RENAME EQU 23 ;RENAME FILE ILOG EQU 24 ;INTERROGATE LOGIN IDSK EQU 25 ;INTERROGATE DISK SETDMA EQU 26 ;SET DMA ADDRESS IALLOC EQU 27 ;INTERROGATE ALLOCATION WPD EQU 28 ;WRITE PROTECT DISK GROV EQU 29 ;GET READ/ONLY VECTOR SFA EQU 30 ;SET FILE ATTRIBUTES GADPB EQU 31 ;GET ADDR OF DPB SGUSR EQU 32 ;SET/GET USER CODE READRR EQU 33 ;READ RANDOM RECORD WRITERR EQU 34 ;WRITE RANDOM RECORD CFSIZE EQU 35 ;COMPUTE FILE SIZE SRR EQU 36 ;SET RANDOM RECORD RESDRV EQU 37 ;RESET DRIVE WRITERZ EQU 40 ;WRITE RANDOM WITH ZERO FILL ; BIOS ENTRY POINTS. ; GIVEN AS DISPLACEMENTS FROM WARM BOOT ENTRY POINT WHOSE ; ADDRESS IS USUALLY AT LOCATION BOOT+1. ; TO COMPUTE DISPLACEMENTS FROM VALUE STORED AT 'BBIOS' ; SUBTRACT 'CBOOT'. EG. DISPLACEMENT FOR WARM BOOT = WBOOT-CBOOT CBOOT EQU -0003H ;COLD BOOT WBOOT EQU 0000H ;WARM BOOT CONST EQU 0003H ;CONSOLE STATUS CONIN EQU 0006H ;CONSOLE INPUT CONOUT EQU 0009H ;CONSOLE OUTPUT LSTOUT EQU 000CH ;LIST OUTPUT PUNOUT EQU 000FH ;PUNCH OUTPUT RDRIN EQU 0012H ;READER INPUT HOME EQU 0015H ;HOME DISK SETDSK EQU 0018H ;SET (SELECT) DISK DRIVE SETTRK EQU 001BH ;SET TRACK NUMBER SETSEC EQU 001EH ;SET SECTOR NUMBER SDMA EQU 0021H ;SET DMA ADDRESS BREAD EQU 0024H ;READ SELECTED SECTOR BWRITE EQU 0027H ;WRITE SELECTED SECTOR BLSTST EQU 002AH ;CHECK LIST DEVICE STATUS BSECTRN EQU 002DH ;SECTOR TRANSLATE ROUTINE BFMT EQU 0030H ;FORMAT BRDTRK EQU 0033H ;READ TRACK BWRTRK EQU 0036H ;WRITE TRACK BWPC EQU 0039H ;WRITE PROTECT CHECK BCBD EQU 003CH ;CLEAR BUFFERS FOR DRIVE BPEEK EQU 003FH ;PEEK 8088 MEMORY FUNCTION BPOKE EQU 0042H ;POKE 8088 MEMORY FUNCTION ; BIOS WRITE TYPES BWRNOR EQU 0 ;NORMAL WRITE BWRDIR EQU 1 ;WRITE TO A DIRECTORY SECTOR BRWUA1 EQU 2 ;WRITE TO 1ST SECTOR OF UNALLOC BLOCK ; FILE CONTROL BLOCK ORG 0 FCBDN RB 1 ;DISK NAME FCBFN RB 8 ;FILE NAME FCBFNL EQU 8 ;FILE NAME LENGTH FCBFT RB 3 ;FILE TYPE FCBFTL EQU 3 ;FILE TYPE LENGTH FCBRO EQU FCBFT+0 ;R/O FLAG FCBROF EQU 10000000B ; R/O FLAG VALUE FCBSYS EQU FCBFT+1 ;SYS FLAG FCBSYSF EQU 10000000B ; SYS FLAG VALUE FCBARC EQU FCBFT+2 ;ARCHIVE FLAG FCBARCF EQU 10000000B ; ARCHIVE FLAG VALUE FCBEX RB 1 ;EXTENT RB 1 FCBRWF RB 1 ;R/W FLAG FCBRWFF EQU 10000000B ; R/W FLAG VALUE FCBRC RB 1 ;RECORD COUNT FCBDM RB 16 ;DISK ALLOCATION MAP FCBNR RB 1 ;NEXT RECORD TO BE READ OR WRITTEN FCBLS EQU 33 ;FCB LENGTH FOR SEQUENTIAL I/O FCBRR RB 3 ;RANDOM RECORD POINTER FCBLR EQU 36 ;FCB LENGTH FOR RANDOM I/O ;** CHARACTER I/O TABLE DEFINITIONS ; ORG 0 ; TABLE CIOTBL RB 0 CIOBP RB 1 ;BASE PORT CIOBR RW 1 ;BAUD RATE CIOF1 RB 1 ;FLAG BYTE 1 CIOF2 RB 1 ;FLAG BYTE 2 CIOIM RB 1 ;INPUT READY MASK CIOIPM RB 1 ;INPUT READY POLARITY MASK CIOOM RB 1 ;OUTPUT READY MASK CIOOPM RB 1 ;OUTPUT READY POLARITY MASK CIOECNT RB 1 ;# OF CHARACTERS BEFORE SENDING CIOECTR RB 1 ;CHARACTER COUNTER FOR SENDING CIONCHR RB 1 ;SEND NULLS AFTER THIS CHARACTER CIONCNT RB 1 ;# OF NULLS TO SEND CIONCTR RB 1 ;NULL COUNTER CIOVAL1 RB 1 ;DEVICE DEPENDANT VALUE 1 CIOVAL2 RB 1 ;DEVICE DEPENDANT VALUE 2 CIOVAL3 RB 1 ;DEVICE DEPENDANT VALUE 3 CIOVAL4 RB 1 ;DEVICE DEPNEDANT VALUE 4 CIOVAL5 RB 1 ;DEVICE DEPENDANT VALUE 5 CIOVAL6 RB 1 ;DEVICE DEPENDANT VALUE 6 CIOVAL7 RB 1 ;DEVICE DEPENDANT VALUE 7 CIOVAL8 RB 1 ;DEVICE DEPENDANT VALUE 8 CIOIN RW 1 ;ADDRESS OF DEVICE INIT ROUTINE CIOIS RW 1 ;ADDRESS OF INPUT INPUT STATUS ROUTINE CIOID RW 1 ;ADDRESS OF INPUT DATA ROUTINE CIOOS RW 1 ;ADDRESS OF INPUT OUTPUT STATUS ROUTINE CIOOD RW 1 ;ADDRESS OF OUTPUT DATA ROUTINE IF ASM86 CIOTBLL EQU OFFSET $-OFFSET CIOTBL ;LENGTH OF CIO TABLE ENDIF IF NOT ASM86 CIOTBLL EQU $-CIOTBL ;LENGTH OF CIO TABLE ENDIF ; FLAG BYTE 1 CIOSPI EQU 00000001B ;STRIP PARITY BIT ON INPUT CIOSPO EQU 00000010B ;STRIP PARITY BIT ON OUTPUT CIOMLI EQU 00000100B ;MAP LOWER CASE ON INPUT CIOMLO EQU 00001000B ;MAP LOWER CASE ON OUTPUT CIOEAH EQU 00010000B ;USE / HANDSHAKING CIODCH EQU 00100000B ;USE / HANDSHAKING CIOFO EQU 01000000B ;FAST OUTPUT ; FLAG BYTE 2 CIOW4A EQU CIOEAH ; SENT, WAITING FOR CIOW4D EQU CIODCH ;WAITING FOR ;** DEFINITION OF LOCATIONS AT THE HEAD OF THE BIOS FOR CP/M-85 ; ; * * * N O T E * * * ; ; IF THE BIOS IS ALTERED, THEN THIS FILE MUST ALSO BE UPDATED. ; BVERSN EQU 102 ;VERSION # FOR CURRENT BIOS ; USE THIS EQUATE IN USER PROGRAMS ; THAT WISH TO KNOW VERSION # ; THEY WERE ASSEMBLED FOR BREVSN EQU ' ' ;REVISION LETTER BMO EQU 09 ;DATE BDY EQU 27 BYR EQU 83 NDRIVES EQU 6 ;MAXIMUM NUMBER OF DRIVE TABLES ; ORG 0048H ;SKIP BIOS JUMP VECTOR CODE BIOSVER RB 1 ;BIOS VERSION DEFIOB RB 1 ;DEFAULT I/O BYTE MODE RB 1 ;MODE FLAGS BYTE BSIZE RB 1 ;BIOS SIZE IN PAGES BEND RW 1 ;ENDING ADDR OF BIOS + 1 HECNT RW 1 ;HARD ERROR COUNT (SINCE COLD BOOT) SECNT RW 1 ;SOFT ERROR COUNT (SINCE COLD BOOT) NDISKS RB 1 ;NUMBER OF DISK POSSIBLE IN THIS BIOS ; AUTO EXEC COMMAND BUFFERS AUTOCBC RB 41 ;COLD BOOT AUTO COMMAND AUTOWBC RB 41 ;WARM BOOT AUTO COMMAND ; CHARACTER I/O TABLES CRTTBL RB CIOTBLL ;CRT: (KEYBOARD/DISPLAY) SERATBL RB CIOTBLL ;SERIAL PORT A SERBTBL RB CIOTBLL ;SERIAL PORT B PPRTTBL RB CIOTBLL ;PARALLEL PRINTER PORT DUMMYTBL RB CIOTBLL ;DUMMY UNIT ; DISK PARAMETER ENTRY TABLES DPEBASE RB 0 ;START OF DISK PARAMETER ENTRY TABLES ;** SOFTWARE BOOT CODE DEFINITIONS ; SBCSBC EQU 0 ;LOGICAL SECTOR # OF SBC ORG 0 SBCJMP RB 3 ;JUMP TO SOFTWARE BOOT CODE SBCVER RB 1 ;SOFTWARE BOOT CODE VERSION NUMBER SBCREV RB 1 ;SOFTWARE BOOT CODE REVISION NUMBER SBCDBS RB 27 ;DEFAULT BOOT STRING SBCBSA RB 3 ;SECTOR ADDR OF BAD SECTOR TABLE A SBCBSB RB 3 ;SECTOR ADDR OF BAD SECTOR TABLE B SBCSBA RB 3 ;SECTOR ADDR OF SUPER BLOCK A SBCSBB RB 3 ;SECTOR ADDR OF SUPER BLOCK B SBCSSZ RW 1 ;SECTOR SIZE SBCSPT RW 1 ;SECTORS PER TRACK SBCTPC RW 1 ;TRACKS PER CYLINDER SBCCPV RW 1 ;CYLINDERS PER VOLUME SBCSPS RW 1 ;SECTORS PER REGION SBCVSZ RB 3 ;VOLUME SIZE (SECTORS PER VOLUME) SBCNSL RB 1 ;NUMBER OF REGIONS - 1 SBCCSA RW 1 ;CHECKSUM: SUPER BLOCK A SBCCSB RW 1 ;CHECKSUM: SUPER BLOCK B SBCCBA RW 1 ;CHECKSUM: BAD SECTOR TABLE A SBCCBB RW 1 ;CHECKSUM: BAD SECTOR TABLE B SBCSDP RB 12 ;SET DRIVE PARAMETERS SBCFUS RB 3 ;FIRST USER SECTOR NUMBER SBCDATE RB 6 ;DATE PARTITIONED SBCCRC RW 1 ;CRC OF SBC (ASSUMIN SBCCRC=0) RB 39 ;RESERVED SBCLEN EQU 0080H ;SBC LENGTH ; SUPER BLOCK DEFINITIONS SPBNE EQU 16 ;NUMBER OF ENTRIES ORG 0 SPBPNL EQU 16 ;MAXIMUM LENGTH OF PARTITION NAME SPBPN RB SPBPNL ;PARTITION NAME SPBOSL EQU 10 ;MAXIMUM LENGTH OF OS NAME SPBOS RB SPBOSL ;OS NAME SPBFLG RB 1 ;FLAG BYTE SPBFSN RB 3 ;FIRST SECTOR # OF PARTITION ; (LOW,MID,HIGH) SPBPEL EQU 30 ;LENGTH OF ENTRY ; SUPER BLOCK FLAG BYTE SPBFPNF EQU 10000000B ;PARTITION NOT FORMATTED ; BAD SECTOR TABLE SBCBEL EQU 3 ;LENGTH OF ENTRY ;** Z207 EQUATES ; ; PORT ASSIGNMENTS FDBASE EQU 0B0H ;BASE PORT ADDRESS FDCMD EQU FDBASE ;1797 COMMAND REGISTER FDSTA EQU FDBASE ; STATUS REGISTER FDTRK EQU FDBASE+1 ; TRACK REGISTER FDSEC EQU FDBASE+2 ; SECTOR REGISTER FDDAT EQU FDBASE+3 ; DATA REGISTER FDCON EQU FDBASE+4 ;DISK CONTROL PORT FDAS EQU FDBASE+5 ;AUX STATUS PORT ; COMMANDS FDCRST EQU 000H ;RESTORE FDCSEK EQU 010H ;SEEK FDCSTP EQU 020H ;STEP FDCSTI EQU 040H ;STEP IN FDCSTO EQU 060H ;STEP OUT FDCRDS EQU 080H ;READ SECTOR FDCWRS EQU 0A0H ;WRITE SECTOR FDCRDA EQU 0C0H ;READ ADDRESS FDCRDT EQU 0E0H ;READ TRACK FDCWRT EQU 0F0H ;WRITE TRACK FDCFI EQU 0D0H ;FORCE INTERRUPT ; TYPE 1 COMMAND FLAGS FDFUTR EQU 00010000B ;UPDATE TRACK REGISTER FDFHLB EQU 00001000B ;HEAD LOAD AT BEGINNING FDFVRF EQU 00000100B ;VERIFY FLAGS ; TYPE 1 COMMAND STEP RATE FLAGS FDFSRM EQU 00000011B ;STEP RATE MASK FDFS6 EQU 00000000B ;STEP RATE 6(3) MS FDFS12 EQU 00000001B ; 12(6) FDFS20 EQU 00000010B ; 20(10) FDFS30 EQU 00000011B ; 30(15) ; TYPE 2&3 COMMAND FLAGS FDFMRF EQU 00010000B ;MULTIPLE RECORD FLAG FDFSLF EQU 00001000B ;SECTOR LENGTH FLAG FDFDLF EQU 00000100B ;30 MS DELAY FDFSS1 EQU 00000010B ;SELECT SIDE 1 FDFDDM EQU 00000001B ;DELETED DATA MARK ; TYPE 4 COMMAND FLAGS FDFINI EQU 00000000B ;TERMINATE WITH NO INTERRUPT FDFII0 EQU 00000001B ;NOT READY TO READY TRANSITION FDFII1 EQU 00000010B ;READY TO NOT READY TRANSITION FDFII2 EQU 00000100B ;INDEX PULSE FDFII3 EQU 00001000B ;IMMEDIATE INTERRUPT ; STATUS FLAGS FDSNRD EQU 10000000B ;NOT READY FDSWPV EQU 01000000B ;WRITE PROTECT VIOLATION FDSHLD EQU 00100000B ;HEAD IS LOADED FDSRTE EQU 00100000B ;RECORD TYPE FDSWTF EQU 00100000B ;WRITE FAULT FDSSEK EQU 00010000B ;SEEK ERROR FDSRNF EQU 00010000B ;RECORD NOT FOUND FDSCRC EQU 00001000B ;CRC ERROR FDSTK0 EQU 00000100B ;FOUND TRACK 0 FDSLDT EQU 00000100B ;LOST DATA FDSIND EQU 00000010B ;INDEX HOLE FDSDRQ EQU 00000010B ;DRQ FDSBSY EQU 00000001B ;BUSY ; INFO RETURNED BY A READ ADDRESS COMMAND FDRATRK EQU 0 ;TRACK FDRASID EQU 1 ;SIDE FDRASEC EQU 2 ;SECTOR FDRASL EQU 3 ;SECTOR LENGTH FDRACRC EQU 4 ;2 BYTE CRC FDRAL EQU 6 ;LENGTH OF READ ADDRESS INFO ; DISK HEADER SECTOR LENGTH VALUES FDSL128 EQU 0 ;SECTOR LENGTH 128 FDSL256 EQU 1 ;SECTOR LENGTH 256 FDSL512 EQU 2 ;SECTOR LENGTH 512 FDSL1K EQU 3 ;SECTOR LENGTH 1024 ; CONTROL REGISTER FLAGS CONDS EQU 00000011B ;DRIVE SELECT BITS CONDS8 EQU 00000100B ;0=5 1/4" , 1=8" CONDSEN EQU 00001000B ;DRIVE SELECT ENABLE CONPC EQU 00010000B ;WRITE PRE-COMPENSATION ; 5 1/4" 0=YES , 1=NO ; 8" 0=ALL TRACKS , 1=TRACKS 44-76 CON5FS EQU 00100000B ;5 1/4" FAST STEP CONWE EQU 01000000B ;ENABLE WAIT FOR DRQ OR IRQ CONSD EQU 10000000B ;ENABLE SINGLE DENSITY ; AUXILARY STATUS REGISTER FLAGS ASIRQ EQU 00000001B ;1797 INTERRUPT REQUEST ASMO EQU 00000010B ;5 1/4" MOTOR ON AS96T EQU 00001000B ;5 1/4" DRIVES ARE 96TPI AS5PC EQU 00010000B ;5 1/4" DRIVES NEED WRITE PRE-COMPENSATION AS2S EQU 01000000B ;SELECTED 8" DRIVE CONTAINS 2 SIDED MEDIA ASDRQ EQU 10000000B ;1797 DRQ ; MISCELLANEOUS VALUES NTRKS37 EQU 40 ;# TRACKS SINGLE DENSITY 5 1/4" (48 TPI) NTRKD37 EQU 80 ;# TRACKS DOUBLE DENSITY 5 1/4" (96 TPI) NTRK837 EQU 77 ;NUMBER OF TRACKS 8" NSBT37 EQU 52 ;NUMBER OF CP/M RECORDS TO BE LOADED AT BOOT ;** Z217 EQUATES ; WINSPT EQU 18 ;# PHYSICAL SECTORS PER TRACK WICSZ EQU 512 ;CELL SIZE USED ;* PORT ASSIGNMENTS WIPBASE EQU 0AEH ;BASE PORT WIPCMD EQU WIPBASE+0 ; COMMAND WIPSTAT EQU WIPBASE+0 ; HARDWARE STATUS WIPRES EQU WIPBASE+1 ; RESET WIPINTA EQU WIPBASE+1 ; INTERRUPT ACKNOWLEDGE/HARDWARE STATUS ;* HARDWARE STATUS REGISTER WISINT EQU 10000000B ;INTERRUPT PENDING WISBUSY EQU 01000000B ;BUSY WISBM EQU 00100000B ;BURST MODE WISTMA EQU 00010000B ;TMA IN PROGRESS WISERR EQU 00001000B ;ERROR WISIERR EQU 00000100B ;IMMEDIATE MODE ERROR WISPAUS EQU 00000010B ;PAUSED WISDONE EQU 00000001B ;DONE ;* DIRECT MODE COMMANDS WISETUP EQU 08H ;SETUP WIEXEC EQU 10H ;EXECUTE WIPAUS EQU 18H ;PAUSE WICONT EQU 20H ;CONTINUE ;* CONTROL BLOCK COMMANDS WIRECAL EQU 00H ;RECALIBRATE WISTAT EQU 01H ;STATUS WIWRL EQU 10H ;WRITE LOGICAL WIRDL EQU 11H ;READ LOGICAL WISEKL EQU 13H ;SEEK LOGICAL WIFMTD EQU 20H ;FORMAT DRIVE WIFMTT EQU 21H ;FORMAT TRACK WISDP EQU 22H ;SET DRIVE PARAMETERS WIWRA EQU 30H ;WRITE ABSOLUTE WIRDA EQU 31H ;READ ABSOLUTE WISEKA EQU 33H ;SEEK ABSOLUTE ;* FORMAT OF COMMANDS ; TYPE 0 & 1 ORG 0 WI01BLK RB 0 WI01OP RB 1 ;COMMAND OP CODE WI01DHS RB 1 ;BIT 7-5 -- DRIVE SELECT ; 4-0 -- HIGH BYTE OF LOG SECTOR # WI01D EQU 11100000B ; DRIVE SELECT MASK WI01HS EQU 00011111B ; HIGH BYTE OF LOG SECTOR # MASK WI01MS RB 1 ;MIDDLE BYTE OF LOGICAL SECTOR # WI01LS RB 1 ;LOW BYTE OF LOGICAL SECTOR # WI01SC RB 1 ;SECTOR COUNT WI01HT RB 1 ;HIGH BYTE OF DATA TMA ADDRESS WI01MT RB 1 ;MIDDLE BYTE OF DATA TMA ADDRESS WI01LT RB 1 ;LOW BYTE OF DATA TMA ADDRESS WI01HN RB 1 ;HIGH BYTE OF NEXT COMMAND ADDRESS WI01MN RB 1 ;MIDDLE BYTE OF NEXT COMMAND ADDRESS WI01LN RB 1 ;LOW BYTE OF NEXT COMMAND ADDRESS WI01FLG RB 1 ;FLAGS WI01EEC RB 1 ;ERROR CODE WI01EDH RB 1 ;BIT 7-5 -- DRIVE SELECT ; 4-0 -- HIGHT BYTE OF LOG SECTOR # WI01ED EQU 11100000B ; ERROR DRIVE SELECT MASK WI01EHS EQU 00011111B ; ERROR HIGH BYTE OF LOG SECTOR # MASK WI01EMS RB 1 ;ERROR MIDDLE BYTE OF LOGICAL SECTOR # WI01ELS RB 1 ;ERROR LOW BYTE OF LOGICAL SECTOR # IF ASM86 WI01BKL EQU OFFSET $ - OFFSET WI01BLK ENDIF IF NOT ASM86 WI01BKL EQU $-WI01BLK ENDIF IF WI01BKL NE 16 %: TYPE 0 & 1 COMMAND BLOCK IS WRONG LENGTH ENDIF ; TYPE 2 ORG 0 WI2BLK RB 0 WI2OP RB 1 ;COMMAND OP CODE WI2DH RB 1 ;BIT 7-5 -- DRIVE SELECT ; 2-0 -- (MAX) HEAD # WI2D EQU 11100000B ; DRIVE SELECT MASK WI2H EQU 00000111B ; HEAD # MASK WI2HMC RB 1 ;HIGH BYTE OF MAX CYLINDER # WI2LMC RB 1 ;LOW BYTE OF MAX CYLINDER # WI2HRWC RB 1 ;HIGH BYTE OF RWC CYLINDER # WI2LRWC RB 1 ;LOW BYTE OF RWC CYLINDER # WI2HPC RB 1 ;HIGH BYTE OF PRE-COMP CYLINDER # WI2LPC RB 1 ;LOW BYTE OF PRE-COMP CYLINDER # WI2SR RB 1 ;STEP RATE (LSB = 20uS) WI2ECC RB 1 ;ECC SPAN WI2CSIF RB 1 ;BIT 6 -- CELL SIZE ; 4-0 -- INTERLEAVE FACTOR WI2CS EQU 01000000B ; CELL SIZE MASK WI2CS5 EQU 00000000B ; CELL SIZE = 512 BYTES/LOG SECTOR WI2CS1K EQU 01000000B ; CELL SIZE = 1024 BYTES/LOG SECTOR WI2IF EQU 00011111B ; INTERLEAVE FACTOR MASK WI2FC RB 1 ;FILL CHARACTER WI2EEC RB 1 ;ERROR CODE WI2EHS RB 1 ;BIT 7-5 -- ERROR HEAD # ; 4-0 -- ERROR SECTOR # WI2EH EQU 11100000B ; ERROR HEAD # MASK WI2ES EQU 00011111B ; ERROR SECTOR # MASK WI2EHC RB 1 ;ERROR HIGH BYTE OF CYLINDER # WI2ELC RB 1 ;ERROR LOW BYTE OF CYLINDER # IF ASM86 WI2BLKL EQU OFFSET $ - OFFSET WI2BLK ENDIF IF NOT ASM86 WI2BLKL EQU $-WI2BLK ENDIF IF WI2BLKL NE 16 %: TYPE 2 COMMAND BLOCK IS WRONG LENGTH ENDIF ; TYPE 3 ORG 0 WI3BLK RB 0 WI3OP RB 1 ;COMMAND OP CODE WI3DH RB 1 ;BIT 7-5 -- DRIVE SELECT ; 2-0 -- HEAD # WI3D EQU 11100000B ; DRIVE SELECT MASK WI3H EQU 00000111B ; HEAD # MASK WI3HC RB 1 ;HIGH BYTE OF CYLINDER # WI3LC RB 1 ;LOW BYTE OF CYLINDER # WI3S RB 1 ;SECTOR # WI3HT RB 1 ;HIGH BYTE OF DATA TMA ADDRESS WI3MT RB 1 ;MIDDLE BYTE OF DATA TMA ADDRESS WI3LT RB 1 ;LOW BYTE OF DATA TMA ADDRESS WI3HN RB 1 ;HIGH BYTE OF NEXT COMMAND ADDRESS WI3MN RB 1 ;MIDDLE BYTE OF NEXT COMMAND ADDRESS WI3LN RB 1 ;LOW BYTE OF NEXT COMMAND ADDRESS WI3FLG RB 1 ;FLAGS WI3EEC RB 1 ;ERROR CODE WI3EHS RB 1 ;BIT 7-5 -- ERROR HEAD # ; 4-0 -- ERROR SECTOR # WI3EH EQU 11100000B ; ERROR HEAD # MASK WI3ES EQU 00011111B ; ERROR SECTOR # MASK WI3EHC RB 1 ;ERROR HIGH BYTE OF CYLINDER # WI3ELC RB 1 ;ERROR LOW BYTE OF CYLINDER # IF ASM86 WI3BLKL EQU OFFSET $ - OFFSET WI3BLK ENDIF IF NOT ASM86 WI3BLKL EQU $-WI3BLK ENDIF IF WI3BLKL NE 16 %: TYPE 3 COMMAND BLOCK IS WRONG LENGTH ENDIF ; COMMAND BLOCK FLAG BYTE WIFINTE EQU 10000000B ;INTERRUPTS ENABLED WIFBM EQU 01000000B ;USE BURST MODE TMA WIFIPCC EQU 00100000B ;IGNORE PAUSE AND CONTINUE COMMANDS WIFIDR EQU 00000100B ;DISABLE RETRIES WIFDECC EQU 00000010B ;DISABLE ECC WIFCHN EQU 00000001B ;CHAIN NEXT COMMAND IMMEDIATELY ;* FORMAT OF STATUS RETURNED BY 01 COMMAND ORG 0 WISBLK RB 0 WISFLG RB 1 ;FLAG BYTE WISDR EQU 00000100B ; BIT 2 -- DRIVE READY WISACC EQU 00000010B ; 1 -- ACCESSED WISSC EQU 00000001B ; 0 -- SEEK COMPLETE WISHMC RB 1 ;HIGH BYTE OF MAX CYLINDER # WISLMC RB 1 ;LOW BYTE OF MAX CYLINDER # WISHRWC RB 1 ;HIGH BYTE OF RWC CYLINDER # WISLRWC RB 1 ;LOW BYTE OF RWC CYLINDER # WISHPC RB 1 ;HIGH BYTE OF PRE-COMP CYLINDER # WISLPC RB 1 ;LOW BYTE OF PRE-COMP CYLINDER # WISHCC RB 1 ;HIGH BYTE OF CURRENT CYLINDER # WISLCC RB 1 ;LOW BYTE OF CURRENT CYLINDER # WISSR RB 1 ;STEP RATE (LSB = 20uS) RB 1 ;RESERVED WISIF RB 1 ;INTERLEAVE FACTOR WISCS RB 1 ;CELL SIZE WISCS5 EQU 1 ; = 512 BYTES/LOG SECTOR WISCS1K EQU 2 ; = 1024 BYTES/LOG SECTOR WISMH RB 1 ;MAX HEAD # WISFC RB 1 ;FILL CHARACTER RB 1 ;RESERVED IF ASM86 WISBLKL EQU OFFSET $ - OFFSET WISBLK ENDIF IF NOT ASM86 WISBLKL EQU $-WISBLK ENDIF IF WISBLKL NE 16 %: STATUS BLOCK IS WRONG LENGTH ENDIF ;* ERROR CODES WIENE EQU 00H ;NO ERROR WIEDNR EQU 01H ;DRIVE NOT READY WIENSC EQU 02H ;NO SEEK COMPLETE WIENT0 EQU 03H ;NO TRACK 0 WIENI EQU 04H ;NO INDEX WIENDS EQU 05H ;NO DRIVE SELECT WIEHNF EQU 10H ;HEADER ADDRESS MARK NOT FOUND WIESEK EQU 11H ;SEEK ERROR (BAD CYLINDER # IN HEADER) WIESNF EQU 12H ;SECTOR NOT FOUND WIEECCH EQU 13H ;ECC ERROR IN HEADER WIEDNF EQU 14H ;DATA ADDRESS MARK NOT FOUND WIENECC EQU 15H ;NONCORRECTABLE ECC ERROR IN DATA FIELD WIEECC EQU 16H ;CORRECTABLE ECC ERROR IN DATA FIELD WIEWF EQU 17H ;WRITE FAULT WIEIOP EQU 20H ;ILLEGAL OP CODE WIEIDA EQU 21H ;ILLEGAL DISK ADDRESS WIEFMTP EQU 22H ;FORMAT PROTECTED WIEWRP EQU 23H ;WRITE PROTECTED WIEMISC EQU 30H ;MISCELLANEOUS ERROR WIEDIAG EQU 40H ;ERROR DURING DIAGNOSTIC WIEPNA EQU 80H ;PARTION NOT ASSIGNED WIESNWP EQU 81H ;SECTOR NOT WITHIN PARTITION ;* CP/M RELATED VALUES WIRPS EQU WICSZ/128 ;CP/M RECORDS PER SECTOR WIRPT EQU WIRPS*WINSPT ;CP/M RECORDS PER TRACK WINST EQU 1 ;# OF SYSTEM TRACKS WINSYS EQU WINST*WINSPT ;# SECTORS IN SYSTEM TRACK(S) WIMIN EQU 1024/WICSZ*64+WINSYS ;MINIMUM # USEABLE SECTORS WIMAX EQU 1024/WICSZ*8*1024+WINSYS ;MAX # USEABLE SECTORS ;** DISK PARAMETER TABLE EQUATES ; ; DISK PARAMETER ENTRY DESCRIPTION ORG 0 DPEXLT RW 1 ;SECTOR TRANSLATE TABLE ADDRESS RW 3 DPEDIRB RW 1 ;DIRECTORY BUFFER ADDRESS DPEDPB RW 1 ;DISK PARAMETER BLOCK ADDRESS DPECSV RW 1 ;CHECKSUM VECTOR ADDRESS DPEALV RW 1 ;ALLOCATION VECTOR ADDRESS DPEHTH RB 8 ;HEATH EXTENSIONS DPEL EQU 24 ;LENGTH OF DISK PARAMETER ENTRY ; HEATH EXTENSIONS DPEFLAG EQU DPEHTH+0 ;FLAGS DPETYPE EQU 11100000B ;BIT 7-5 = DEVICE TYPE DPENE EQU 00000000B ; NON-EXISTENT DPEZ207 EQU 00100000B ; Z207 DPEZ217 EQU 01000000B ; Z217 DPE48RO EQU 00010000B ;BIT 4 -- FOR Z207 ; 48 TPI MEDIA IN 96 TPI DRIVE (R/O) DPE96T EQU 00001000B ;BIT 3 -- 0=48 TPI DRIVE 1=96 TPI DRIVE DPEASGN EQU 00001000B ;BIT 3 -- FOR Z217 WINCHESTER DISK ; 0=UNASSIGNED A PARTITION ; 1=ASSIGNED A PARTITION DPET0SD EQU 00000100B ;BIT 2 -- 1=TRACK 0 IS SINGLE DENSITY DPEDD EQU 00000010B ;BIT 1 -- 0=SINGLE DENSITY 1=DOUBLE DPELSIO EQU 00000010B ;BIT 1 -- Z217 LOGICAL SECTOR I/O DPE2S EQU 00000001B ;BIT 0 -- 0=SINGLE SIDED 1=DOUBLE DPEPRIM EQU 00000001B ;BIT 0 -- Z217 PRIMARY DPE FOR UNIT DPEUNIT EQU DPEHTH+1 ;UNIT SELECT VALUE DPERPS EQU DPEHTH+2 ;CP/M RECORDS PER PHYSICAL SECTOR DPERPAB EQU DPEHTH+3 ;CP/M RECORDS PER ALLOCATION BLOCK DPETRK EQU DPEHTH+4 ;TRACK COUNTER DPEUNK EQU 10000000B ; TRACK POSITION UNKNOWN DPELPB EQU DPEHTH+4 ;Z217 LOWER PARTITION BOUNDARY (LOG SECTOR #) DPESEK EQU DPEHTH+5 ;MOTOR SPEED AND SEEK SPEED ;BIT 3-0 = SEEK SPEED VALUE DPEFS EQU 01000000B ;BIT 6 = FAST STEP FOR Z207 DPEMO EQU 10000000B ;BIT 7 = MOTOR UP TO SPEED FLAG ; 0=1 SEC 1=250 MSEC DPEUPB EQU DPEHTH+6 ;Z217 UPPER PARTITION BOUNDARY + 1 DPEFLG2 EQU DPEHTH+6 ;2ND FLAG BYTE DPEHLS EQU 00000100B ;BIT 2 DRIVE HAS HEAD LOAD SELONOID DPEIMG EQU 00000010B ;BIT 1 IMAGINARY DRIVE DPE96TM EQU 00000001B ;BIT 0 0=48 TPI MEDIA 1=96 TPI MEDIA DPELUN EQU DPEHTH+7 ;LAST LOGICAL UNIT MOUNTED DPELOG EQU 11110000B ; CP/M LOGICAL DRIVE NAME FOR THIS ENTRY DPEREAL EQU 00001111B ; FOR IMAGINARY DRIVE, LOGICAL DRIVE NAME ; FOR CORRESPONDING REAL DRIVE DPEMNT EQU 00001111B ; FOR REAL DRIVE, LOGICAL DRIVE NAME FOR ; CURRENLY MOUNTED DISK DPEHL EQU 8 ;LENGTH OF HEATH EXTENSION ; DISK PARAMETER BLOCK ORG 0 DPBSPT RW 1 ;SECTORS PER TRACK DPBBSH RB 1 ;BLOCK SHIFT FACTOR DPBBLM RB 1 ;BLOCK MASK DPBEXM RB 1 ;EXTENT MASK DPBDSM RW 1 ;TOTAL # OF BLOCKS - 1 DPBDRM RW 1 ;# OF DIRECTORY ENTRIES - 1 DPBAL0 RB 1 ;INITIAL AL0 VALUE DPBAL1 RB 1 ;INITIAL AL1 VALUE DPBCKS RW 1 ;SIZE OF DIRECTORY CHECK VECTOR DPBOFF RW 1 ;NUMBER OF SYSTEM TRACKS DPBL EQU 15 ;LENGTH OF DISK PARAMETER BLOCK ;** HEATH CP/M DISK LABEL DEFINITIONS ; ; DISK LABELS ARE USED ON MOST DATA DISKS AND ; ON ALL SYSGEN'ED (BOOTABLE) DISKS. ; TO MAINTAIN COMPATIBILITY WITH OLDER RELEASES OF CP/M, ; THE 5 1/4" HARD SECTOR AND 8" SOFT SECTOR FLOPPY DATA DISKS ; DO NOT USE LABELS. ; ; THE LABEL RESIDES ON THE 1ST SECTOR OF TRACK 0, SIDE 0. ; ; AT THE END OF THE LABEL IS A CHECKSUM. ; FOR VERSION # 0 OF THE LABEL, THE CHECKSUM IS CALCULATED ; BY ADDING UP THE VALUES IN THE LABEL PRIOR TO THE CHECKSUM SLOT ; A BYTE AT A TIME, THEN TAKING THE ONE'S COMPLEMENT OF THE SUM. ; LABVER EQU 0 ;CURRENT FORM # FOR LABEL LABBUF EQU 0 ;SLOT FOR JUMP INSTRUCTION AROUND LABEL BDTYPE EQU LABBUF+3 ;SLOT FOR DRIVE TYPE LABEL EQU LABBUF+4 LABTYP EQU LABEL+0 ;SLOT FOR LABEL TYPE LABHTH EQU LABTYP+1 ;SLOT FOR HEATH EXTENSIONS TO DPE LABDPB EQU LABHTH+DPEHL ;SLOT FOR DISK PARAMETER BLOCK LABCS EQU LABDPB+DPBL ;CHECKSUM LABLEN EQU LABCS-LABEL+1 ;LABEL LENGTH ;** ASCII CONTROL CHARACTER EQUATES ; CTLC EQU 003H ;CONTROL-C CTLQ EQU 011H ;CONTROL-Q CTLS EQU 013H ;CONTROL-S CTLZ EQU 01AH ;CONTROL-Z ACK EQU 006H ; BELL EQU 007H ;BELL CPMEOF EQU CTLZ ;ASCII FILE EOF MARK CPMEOM EQU '$' ;CP/M END-OF-MESSAGE SYMBOL CR EQU 00DH ;CARRIAGE RETURN ESC EQU 01BH ;ESCAPE ETX EQU CTLC ; DC1 EQU CTLQ ; DC3 EQU CTLS ; LF EQU 00AH ;LINE FEED NULL EQU 000H ;NULL PAGE ORG TPA START JMP FORMAT DB 'Copyright 1982 @Heath/Zenith' SIGNON DB CR,LF,'CP/M-85 Format Version 2.2.' DB BVERSN/100+'0',(BVERSN/10 MOD 10)+'0',(BVERSN MOD 10)+'0' DB CR,LF,'$' SIGNON1 DB CR,LF,'This program is used to initialize a disk.' DB CR,LF DB 'All information currently on the disk will be destroyed.' DB CR,LF DB 'Is that what you want? (y/n): $' DS 40 STACK EQU $ FORMAT: LXI SP,STACK MVI C,PRCONB ;PRINT ISSUE MESSAGE LXI D,SIGNON CALL BDOS LHLD BBIOS ;Q. CORRECT VERSION OF BIOS LXI D,BIOSVER DAD D MOV A,M CPI BVERSN JZ FMT00 ; BR IF YES MVI C,PRCONB LXI D,BADBIOS CALL BDOS JMP BOOT FMT00: LDA TBUFF CPI 0 JZ FMT0 ; NO COMMAND LINE MVI A,TRUE STA COMLIN ;YES THERE IS A COMMAND LINE CALL CLINT ;CALL COMMAND LINE INTERPRETER/WME FMT0: QUERY FMT2 MVI C,PRCONB ;print sign on message. Continue? LXI D,SIGNON1 CALL BDOS FMT1: MVI C,RDCON ;Read reply CALL BDOS CALL TOUPPER ;convert character to upper case CPI 'Y' JZ FMT2 ;Yes continue. JMP FMT5 FMT2: COMINP DRIVID,FMT2A0,FMT20A FMT20A: MVI C,PRCONB ;which drive are we using LXI D,WHICH CALL BDOS MVI C,RDCON ;Read Drive ID CALL BDOS FMT2A0: CALL TOUPPER STA DRIVID ;SAVE UPPERCASE TRANSLATED VALUE STA DRMSGA STA FPARTD CPI 'A' ;Range Check JC FMT2AA CPI 'Z'+1 JC FMT2A FMT2AA: CPI CTLC JZ FMT5 MVI C,PRCONB ;Error- out of range (A..Z) LXI D,ERRMSG CALL BDOS JMP FMT3B FMT2A: STA PROMPTA ;save drive letter in message CALL WKIND ;go determine drive type JNC FMT2AB ;BR IF VALID DRIVE TYPE MVI C,PRCONB LXI D,DRMSG CALL BDOS JMP FMT3B FMT2AB: LDA DRIVID ;KEEP TRACK IF SYSTEM DISK REMOVED CPI 'A' JNZ FMT3 MVI A,1 STA SYSDSK FMT3: CALL DISPATCH ;FORMAT DISK JC FMT9 FMT3B COMINP DRIVID,FMT5,FMT3BA ;EXIT IF SUBMIT JOB FMT3BA: MVI C,PRCONB LXI D,AMWMSG ;any more work CALL BDOS FMT4A MVI C,RDCON CALL BDOS CALL TOUPPER CPI 'Y' JZ FMT2 FMT5: LDA SYSDSK ;Q. WAS SYSTEM DISK INVOLVED ORA A JZ BOOT MVI C,PRCONB LXI D,LVEMSG CALL BDOS MVI C,RDCON CALL BDOS JMP BOOT FMT9: CALL FWPC ;Q. DISK WRITE PROTECTED LXI D,WPEMSG ORA A JNZ FMT9A ; BR IF YES LXI D,BMSG FMT9A: MVI C,PRCONB CALL BDOS JMP FMT3B TOUPPER CPI 061H ;is not lower case RC CPI '{' RNC SUI 020H RET ERRMSG: DB CR,LF,'OPTION NOT AVAILABLE',CR,LF,BELL,'$' PAGE ;** WKIND - DETERMINES DRIVE TYPE AND SELECTS UNIT ; WKIND: SUI 'A' ;GET CP/M DRIVE # MOV C,A CALL FSETDSK ;SELECT DRIVE MOV A,H ;Q. SELECT ERROR ORA L JZ WKERR ; BR IF NO DRIVE SHLD DPEPTR ;SAVE POINTER TO DPE XCHG LXI H,DPEFLG2 ;IMAGINARY FLAG DAD D MOV A,M STA FLAG2 LXI H,DPEDPB ;GET DPB POINTER DAD D CALL HLIHL SHLD DPBPTR LXI H,DPEHTH ;GET HEATH FLAGS DAD D MOV A,M STA DRTYPE INX H ;GET UNIT SELECT MOV A,M STA AIOUNI ORA A ;CLEAR CARRY TO INDICATE NO ERROR RET WKERR: STC ;INDICATE ERROR RET ;** FSETDSK - GETS DISK TABLE POINTER IN (HL) ; ; ENTRY: (C)=CP/M DRIVE # ; EXIT: (HL)=POINTER (IF 0 THEN ERROR) ; USES: ALL ; FSETDSK: LHLD BBIOS LXI D,SETDSK-CBOOT DAD D MVI E,1 PCHL ;** FSETTRK - SET CP/M TRACK # ; ; ENTRY: (BC)=DESIRED CP/M TRACK # ; EXIT: NONE ; USES: ALL ; FSETTRK: LHLD BBIOS LXI D,SETTRK-CBOOT DAD D PCHL ;** FSETSEC - SET CP/M SECTOR # ; ; ENTRY: (BC)=DESIRED CP/M SECTOR # ; EXIT: NONE ; USES: ALL ; FSETSEC: LHLD BBIOS LXI D,SETSEC-CBOOT DAD D PCHL ;** FSETDMA - SET DMA ; ; ENTRY: (BC)=DMA ; EXIT: NONE ; USES: ALL ; FSETDMA: LHLD BBIOS LXI D,SDMA-CBOOT DAD D PCHL ;** FREAD - READ CP/M SECTOR ; ; ENTRY: NONE ; EXIT: (A)=ERROR STATUS ; USES: ALL ; FREAD: LHLD BBIOS LXI D,BREAD-CBOOT DAD D PCHL ;** FWRITE - WRITE CP/M SECTOR ; ; ENTRY: (C)=WRITE MODE ; EXIT: (A)=ERROR STATUS ; USES: ALL ; FWRITE: LHLD BBIOS LXI D,BWRITE-CBOOT DAD D PCHL ;** FFORMAT - FORMAT DISK ; ; ENTRY: (C)=VERIFY FLAG (0=NO , 1=YES) ; EXIT: (A)=STATUS BYTE ; USES: ALL ; FFORMAT: LHLD BBIOS LXI D,BFMT-CBOOT DAD D PCHL ;** FWRTRK - WRITE TRACK ; ; ENTRY: NONE ; EXIT: (A)=ERROR STATUS ; USES: ALL ; FWRTRK: LHLD BBIOS LXI D,BWRTRK-CBOOT DAD D PCHL ;** FWPC - WRITE PROTECT CHECK ; ; ENTRY: NONE ; EXIT: (A)=WRITE PROTECT STATUS (0=NO , 1=YES) ; USES: ALL ; FWPC: LHLD BBIOS LXI D,BWPC-CBOOT DAD D PCHL ;** FCBD - CLEAR BUFFER FOR DRIVE ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; FCBD: LHLD BBIOS LXI D,BCBD-CBOOT DAD D PCHL PAGE ; ; FORMAT H37. ; F37: LDA AIOUNI ;Q. 5 1/4" DRIVE ANI CONDS8 JNZ F370 ; BR IF NO MVI A,'D' ; YES - DENSITY IS DOUBLE JMP F3700A F370: COMINP CLIDENS,F3700A,F3700 F3700: MVI C,PRCONB LXI D,WDSDMSG CALL BDOS MVI C,RDCON CALL BDOS F3700A: CALL TOUPPER MVI B,0 CPI 'S' JZ F371 MVI B,DPEDD CPI 'D' JZ F371 MVI C,PRCONB LXI D,ERRMSG CALL BDOS JMP F370 F371: MOV A,B STA DENSITY LDA AIOUNI ;Q. 8" DRIVE ANI CONDS8 JZ F371A ; BR IF NOT MVI A,'2' ; YES - SAY DOUBLE SIDED (ACTUAL FORMAT WILL JMP F371A2 ; WORK OFF OF INDEX HOLE PLACEMENT) F371A: COMINP CLISIDS,F371AB,F371AA F371AA MVI C,PRCONB LXI D,WSMSG CALL BDOS MVI C,RDCON CALL BDOS F371AB CALL TOUPPER F371A2: MVI B,0 CPI '1' JZ F371B MVI B,DPE2S CPI '2' JZ F371B MVI C,PRCONB LXI D,ERRMSG CALL BDOS JMP F371A F371B: MOV A,B STA SIDES QUERY F372 MVI C,PRCONB ;ASK TO INSERT DISK LXI D,PROMPT CALL BDOS MVI C,PRCONB ;ASK IF READY LXI D,PROMPT1 CALL BDOS MVI C,RDCON CALL BDOS CPI CR JNZ F3748 ; BR IF NOT READY F372: CALL F377 ;FILL IN DPE & DPB XRA A ;CLEAR WORK VALUES STA TRACK MVI B,NTRK837 ;DETERMINE # CP/M TRACKS LDA AIOUNI ANI CONDS8 JNZ F3721 MVI B,NTRKS37 LDA DRTYPE ANI DPE96T JZ F3721 MVI B,NTRKD37 F3721: LDA SIDES CPI DPE2S MVI A,0 JNZ F3722 MOV A,B F3722: ADD B STA DSKTKS LHLD DPEPTR ;FORCE RESTORE BY SETTING TRACK POINTER LXI B,DPETRK ; TO UNKNOWN DAD B MVI M,DPEUNK ; IF 8" DRIVE AND TRACK 0 / SIDE 0 IS SINGLE DENSITY ; THEN FORMAT TRACK 0 / SIDE 0 LDA AIOUNI ;Q. 8" DRIVE ANI CONDS8 JZ F374 ; BR IF NOT LDA DRTYPE ;Q. CP/M TRACK 0 SINGLE DENSITY ANI DPET0SD JZ F374 ; BR IF NOT LXI H,F37STBL ;BUILD TRACK IMAGE CALL F378 CALL F375 ;FORMAT TRACK ORA A ;Q. ERROR JNZ F3749 ; BR IF ERROR ; FORMAT SURFACE(S). F374: LXI H,F37D2TB ;DETERMINE WHICH TABLE TO USE LDA AIOUNI ; TO BUILD TRACK IMAGE ANI CONDS8 JZ F3741 LXI H,F37STBL LDA DENSITY CPI DPEDD JNZ F3741 LXI H,F37DTBL F3741: CALL F378 ;BUILD TRACK IMAGE F3742: CALL F375 ;FORMAT TRACK ORA A ;Q. ERROR JZ F3743 ; BR IF NOT CPI FDSNRD ;IF NOT READY ERROR ON 8" DRIVE AND TRYING JNZ F3749 ; TO FORMAT DOUBLE SIDED, THEN SWITCH LDA AIOUNI ; TO SINGLE SIDED AND TRY AGAIN ANI CONDS8 JZ F3749 LDA TRACK CPI 1 JNZ F3749 LDA SIDES CPI DPE2S JNZ F3749 XRA A STA SIDES JMP F372 ; F3743: LDA TRACK ;Q. ALL TRACKS DONE LXI H,DSKTKS CMP M JNZ F3742 ; BR IF NOT ;* FORM LABEL AND WRITE IT TO TRACK 0 / SECTOR 1 / SIDE 0 CALL WRLAB JC F3749 ;BR IF ERROR ; ALL DONE. F3748: XRA A RET ;RETURN INDICATING NO ERRORS ; ERROR F3749: STC ;INDICATE ERROR RET ;** FORMAT TRACK ; F375: CALL F378Y ;SET TRACK/SIDE/SECTOR VALUES IN TRACK IMAGE LDA TRACK ;SET DESIRED CP/M TRACK # MOV C,A MVI B,0 CALL FSETTRK LXI B,BUFFER ;SET DMA CALL FSETDMA MVI C,1 ;FORMAT TRACK LDA FAST ORA A JZ F3751 MVI C,0 F3751: CALL FFORMAT ;FORMAT TRACK ORA A ;Q. ERROR RNZ ; RET IF ERROR LXI H,TRACK ;BUMP TRACK COUNTER INR M RET ;* FILL DPE & DPB F377: MVI B,0 ;DETERMINE WHICH TABLE TO USE LDA AIOUNI ANI CONDS8 JNZ F3771 LDA DRTYPE ANI DPE96T JZ F3772 MVI B,2 JMP F3772 F3771: MVI B,4 LDA DENSITY CPI DPEDD JNZ F3772 MVI B,6 F3772: LDA SIDES CPI DPE2S JNZ F3773 INR B F3773: MOV A,B MVI E,F37TBLL CALL MUL88 LXI D,F37TBL DAD D XCHG ;(DE)=TABLE ADDRESS LHLD DPEPTR LXI B,DPEHTH DAD B XCHG ;(DE)=DPE POINTER , (HL)=TABLE POINTER LDAX D ;DPE FLAG BYTE 1 ANI 0FFH-(DPE48RO+DPEDD+DPE2S) ORA M MOV B,A LDA DRTYPE MOV C,A LDA AIOUNI ; Q. 8" DRIVE ANI CONDS8 JZ F3773A ; BR IF NOT MOV A,B ANI NOT DPET0SD MOV B,A MOV A,C ANI NOT DPET0SD MOV C,A LDA DENSITY ; Q. DOUBLE DENSITY REQUESTED CPI DPEDD JNZ F3773A ; BR IF NOT LDA CLID0 ; Q. FORMAT TRACK 0 DOUBLE DENSITY CPI 0 JNZ F3773A ; BR IF YES MOV A,B ; SET FLAG FOR TRACK 0 SINGLE DENSITY ORI DPET0SD MOV B,A MOV A,C ORI DPET0SD MOV C,A F3773A: MOV A,B STAX D MOV A,C STA DRTYPE INX D ;CP/M RECORDS PER SECTOR INX D INX H MOV A,M STAX D INX D ;CP/M RECORDS PER ALLOCATION BLOCK INX H MOV A,M STAX D INX D ;MEDIA TPI INX D INX D INX H LDAX D ANI 0FFH-DPE96TM ORA M STAX D INX H ;FILL IN DPB XCHG LHLD DPBPTR XCHG MVI B,DPBL CALL MOVEIT RET ;* BUILD TRACK IMAGE F378: MOV E,M ;GET TRACK OFFSET INX H MOV D,M XCHG SHLD F37C XCHG INX H ;GET LENGTH OF SECTOR AMOUNT-2 MOV E,M INX H MOV D,M XCHG SHLD F37D XCHG INX H ;BUILD SKEW TABLE MOV B,M ; SKEW FACTOR INX H MOV A,M ; SPT STA DSKSPT MOV C,A PUSH H LXI H,F37SKEW CALL INTRLV POP D LXI H,BUFFER ;START OF TRACK IMAGE F378A2: INX D ;FILL IN FRONT END GAP LDAX D ;GET AMOUNT ORA A ;CHECK IF END OF FRONT END GAP INFO JZ F378A3 ; BR IF IT IS MOV B,A INX D LDAX D ;GET VALUE CALL F378X ;FILL JMP F378A2 F378A3: SHLD F37B ;SAVE START OF SECTORS PUSH D ;SAVE START OF SECTOR DESCRIPTORS LDA DSKSPT ;GET SECTORS PER TRACK MOV C,A F378B: POP D ;FILL IN FOR A SECTOR PUSH D F378C: INX D LDAX D ANA A JZ F378D ;BR IF END OF SECTOR DESCRIPTORS MOV B,A INX D LDAX D CALL F378X JMP F378C F378D: DCR C JNZ F378B POP B ;DISCARD ADDR OF SECTOR DESCRIPTORS F378E: INX D ;FILL REQUIRED GAP IV AMOUNT LDAX D MOV B,A INX D LDAX D CALL F378X F378F: INX D ;FILL OPTIONAL GAP IV AMOUNT LDAX D ANA A JZ F378G MOV B,A INX D LDAX D CALL F378X JMP F378F F378G: RET ; FILL AREA OF LENGTH (B) WITH VALUE (A) STARTING AT ADDRESS (HL) F378X: MOV M,A INX H DCR B JNZ F378X RET ; FILL IN TRACK/SIDE/SECTOR VALUES FOR THIS ITERATION IN TRACK IMAGE. F378Y: LDA TRACK ;CALCULATE PHYSICAL TRACK / SIDE VALUES MOV B,A MVI C,0 LDA SIDES CPI DPE2S JNZ F378Y1 MOV A,B ANA A RAR MOV B,A JNC F378Y1 MVI C,1 F378Y1: MOV A,B STA F37E MOV A,C STA F37F LHLD F37C XCHG LHLD F37B DAD D LXI B,F37SKEW ;(BC) = ADDR OF SKEW TABLE F378Y3: LDAX B ANA A RZ ;RET IF END OF SECTORS LDA F37E ;GET TRACK MOV M,A INX H LDA F37F ;GET SIDE MOV M,A INX H LDAX B ;GET SECTOR MOV M,A INX B XCHG LHLD F37D DAD D JMP F378Y3 F37B DS 2 ;ADDR OF 1ST SECTOR IN BUFFER F37C DS 2 ;OFFSET INTO 1ST SECTOR F37D DS 2 ;SIZE OF SECTOR - 2 F37E DS 1 ;PHYSICAL TRACK # F37F DS 1 ;PHYSICAL SIDE VALUECONTROL REG IMAGE F37SKEW DS 27 ;SKEW TABLE SPACE F37STBL DS 0 ;8" SINGLE DENSITY TRACK FORMAT TABLE DW 7 ;OFFSET INTO SECTOR AREA OF TRACK # DW 184 ;LENGTH OF SECTOR AREA MINUS 2 DB 1 ;INTERLEAVE FACTOR DB 26 ;SECTORS PER TRACK DB 40,0FFH ;TRACK HEADER GAP DB 6,0 DB 1,0FCH DB 26,0FFH DB 0 DB 6,0 ;SECTOR AREA (REPEAT FOR SPT) DB 1,0FEH DB 4,0 DB 1,0F7H DB 11,0FFH DB 6,0 DB 1,0FBH DB 128,0E5H DB 1,0F7H DB 27,0FFH DB 0 DB 24,0FFH ;REQUIRED GAP IV AMOUNT DB 255,0FFH ;OPTIONAL GAP IV AMOUNT DB 124,0FFH DB 0 F37DTBL DS 0 ;8" DOUBLE DENSITY 26x256 TRACK FORMAT TABLE DW 16 DW 368 DB 1,26 DB 80,04EH DB 12,0 DB 3,0F6H DB 1,0FCH DB 50,04EH DB 0 DB 12,0 DB 3,0F5H DB 1,0FEH DB 3,0 DB 1,1 DB 1,0F7H DB 22,04EH DB 12,0 DB 3,0F5H DB 1,0FBH DB 128,0E5H DB 128,0E5H DB 1,0F7H DB 54,04EH DB 0 DB 24,04EH DB 255,04EH DB 255,04EH DB 255,04EH DB 121,04EH DB 0 F37D2TB DS 0 ;5 1/4" DOUBLE DENSITY 8x512 TRACK FORMAT TABLE DW 16 DW 650 DB 1,8 DB 80,04EH DB 12,0 DB 3,0F6H DB 1,0FCH DB 50,04EH DB 0 DB 12,0 DB 3,0F5H DB 1,0FEH DB 3,0 DB 1,2 DB 1,0F7H DB 22,04EH DB 12,0 DB 3,0F5H DB 1,0FBH DB 128,0E5H DB 128,0E5H DB 128,0E5H DB 128,0E5H DB 1,0F7H DB 80,04EH DB 0 DB 24,04EH DB 255,04EH DB 255,04EH DB 255,04EH DB 255,04EH DB 15,04EH DB 0 ; H37 DISK DESCRIPTORS FOR LABEL. ; ; DB DENSITY/SIDES FLAGS ; DB CP/M RECORDS PER SECTOR ; DB CP/M RECORDS PER ALLOCATION BLOCK ; DB MEDIA TPI FLAG ; DW SECTORS PER TRACK ; DB BLOCK SHIFT FACTOR ; DB BLOCK MASK ; DB EXTENT MASK ; DW # OF BLOCKS - 1 ; DW # OF DIRECTORY ENTRIES - 1 ; DW AL1*256+AL0 ; DW LENGTH OF CHECKSUM VECTOR ; DW # OF SYSTEM TRACKS ; F37TBL DS 0 ;5 1/4" DOUBLE DENSITY (8x512)/SINGLE SIDED/48 TPI DB DPEDD,4,8,0 DW 32 DB 3,7,0 DW 151,127,00F0H,32,2 F37TBLL EQU $-F37TBL ;5 1/4" DOUBLE DENSITY (8x512)/DOUBLE SIDED/48 TPI DB DPEDD+DPE2S,4,16,0 DW 32 DB 4,15,1 DW 155,255,00F0H,64,2 ;5 1/4" DOUBLE DENSITY (8x512)/SINGLE SIDED/96 TPI DB DPEDD,4,16,DPE96TM DW 32 DB 4,15,1 DW 155,127,00C0H,32,2 ;5 1/4" DOUBLE DENSITY (8x512)/DOUBLE SIDED/96 TPI DB DPEDD+DPE2S,4,16,DPE96TM DW 32 DB 4,15,0 DW 315,255,00F0H,64,2 ;8" SINGLE DENSITY / SINGLE SIDED DB 0,1,8,0 DW 26 DB 3,7,0 DW 242,63 DB 0C0H,0 DW 16,2 ;8" SINGLE DENSITY / DOUBLE SIDED DB DPE2S,1,16,0 DW 26 DB 4,15,1 DW 246,127 DB 0C0H,0 DW 32,2 ;8" DOUBLE DENSITY / SINGLE SIDED DB DPEDD,2,16,0 DW 52 DB 4,15,1 DW 242,127 DB 0C0H,0 DW 32,2 ;8" DOUBLE DENSITY / DOUBLE SIDED DB DPEDD+DPE2S,2,16,0 DW 52 DB 4,15,0 DW 493,255 DB 0F0H,0 DW 64,2 PAGE ;** FORMAT Z217 ; F217: MVI C,SGUSR ;GET CURRENT USER CODE MVI E,0FFH CALL BDOS STA F217UC MVI C,SGUSR ;RESET USER CODE TO 31 MVI E,31 ; TO HIDE FILE CALL BDOS LHLD DPEPTR ;Q. PARTITION ASSIGNED LXI D,DPEFLAG DAD D MOV A,M ANI DPEASGN JZ F21799 ; BR IF NOT MVI C,PRCONB ;INFORM USER LXI D,FMTPART CALL BDOS QUERY F2171 MVI C,PRCONB ;ASK IF READY LXI D,PROMPT1 CALL BDOS MVI C,RDCON CALL BDOS CPI CR JNZ F21798 ; BR IF NOT F2171: CALL FCBD ;CLEAR BIOS BUFFERS FOR DRIVE CALL F21780 ;FILL IN DPB & CALC VALUES JC F21799 ; BR IF ERROR ;* COMPUTE # CP/M RECORDS TO CLEAR. ; (# CP/M RECORDS) = (# DIRECTORY ALLOCATION BLOCKS) SHL (BSH) + ; (# RECORDS FOR SYSTEM TRACK(S)) LHLD DPBPTR ;GET # ALLOCATION BLOCKS FOR DIRECTORY LXI B,DPBAL0 DAD B CALL HLIHL MVI B,0 F2172: MOV A,H ANA A RAL MOV H,A MOV A,L RAL MOV L,A JNC F2172A INR B JMP F2172 F2172A: LHLD DPBPTR ;GET BLOCK SHIFT FACTOR LXI D,DPBBSH DAD D MOV A,M MVI H,0 ;(HL) = # ALLOCATION BLOCKS MOV L,B ; FOR DIRECTORY SHLD F217DAB ;SAVE FOR LATER F2172B: DAD H DCR A JNZ F2172B ;(HL) = # CP/M RECORDS FOR DIRECTORY LXI D,WINST*WIRPT ;(DE) = # CP/M RECORDS FOR SYSTEM TRK DAD D SHLD F217C1 ;(HL) = # CP/M RECORDS TO CLEAR ;* WRITE 0E5H TO ALL SECTORS TO BE CLEARED MVI A,0E5H ;FILL SECTOR BUFFER WITH 0E5H MVI B,128 LXI H,BUFFER CALL F378X LXI B,BUFFER ;SET DMA CALL FSETDMA LXI H,0 ;INIT TRACK # SHLD F217TRK LXI H,1 ;INIT SECTOR # SHLD F217SEC F21710: LHLD F217TRK ;SET TRACK MOV B,H MOV C,L CALL FSETTRK LHLD F217SEC ;SET SECTOR MOV B,H MOV C,L CALL FSETSEC MVI C,BWRNOR ;WRITE SECTOR CALL FWRITE ORA A ;Q. ERROR JNZ F21799 ; BR IF ERROR LHLD F217SEC ;GET CP/M SECTOR # JUST WRITTEN XCHG ;(DE)=CP/M SECTOR # LXI H,WIRPT CALL CPHLDE ;Q. JUST WROTE LAST SECTOR OF TRACK JNZ F21712 ; BR IF NO LXI D,0 ;RESET SECTOR # LHLD F217TRK ;INCREMENT TRACK # INX H SHLD F217TRK F21712: XCHG ;(HL)=SECTOR # INX H ;BUMP SECTOR # SHLD F217SEC LHLD F217C1 ;LOOP DCX H SHLD F217C1 MOV A,H ORA L JNZ F21710 ;* WRITE LABEL TO 1ST SECTOR OF DISK CALL WRLAB JC F21799 ;BR IF ERROR ;* BUILD A FILE WITH THE BAD SECTORS OF THIS PARTITION ALLOCATED ; TO THIS FILE SO THEY CAN'T BE USED. LDA PROMPTA ;GET DRIVE SUI 'A'-1 ;CONVERT TO 1-N STA F217FCB+FCBDN ;PLACE IN FCB CALL F217RDB ;READ IN BAD SECTOR TABLE JC F21799 ; BR IF ERROR LXI H,0 ;INIT LAST ALLOCATION BLOCK MARKED BAD SHLD F217LAB XRA A ;INIT ALLOCATION BLOCK COUNTER STA F217C2 F2175A: CALL F21750 ;GET NEXT ENTRY IN TABLE JZ F2175C ; BR IF NO MORE ENTRIES XCHG ;(DE)=BAD SECTOR # LHLD F217LB ;CHECK AGAINST SECTOR # FOR CALL SUBHLDE ; START OF PARTITION JC F2175A ; BR IF BAD SECTOR PRIOR TO START XCHG ;(DE)=BAD SECTOR DISPLACEMENT FROM ; START OF PARTITTION LXI H,WINSYS ;(HL)=# SECTORS FOR SYSTEM TRACKS CALL SUBHLDE ;(HL)=BAD SECTOR DISPLACEMENT FROM ; SYSTEM TRACKS JC F21799 ;ERROR IF BAD SECTOR IS WITHIN ; SYSTEM TRACKS XCHG ;(DE)=BAD SECTOR DISPLACEMENT LHLD DPBPTR ;CALCULATE ALLOCATION BLOCK # LXI B,DPBBSH ; AB = (DE) SHR (BSH-2) DAD B MOV B,M DCR B DCR B IF WICSZ NE 512 %: SECTOR SIZE NE 512 ENDIF XCHG CALL F21770 ;(HL)=ALLOCATION BLOCK # XCHG ;(DE)=ALLOCATION BLOCK # LHLD F217DAB ;(HL)=# AB'S FOR DIRECTORY XCHG ;(DE)=# AB'S FOR DIRECTORY ;(HL)=AB # OF BAD SECTOR CALL CPHLDE ;Q. BAD SECTOR WITHIN DIRECTORY JC F21799 ; BR IF YES XCHG ;(DE)=AB # OF BAD SECTOR LHLD DPBPTR LXI B,DPBDSM ;CHECK AGAINST MAX BLOCK # DAD B ; FOR THIS PARTITION CALL HLIHL MOV A,H STA F217H ;SAVE HIGH ORDER VALUE OF DSM INX H XCHG ;(DE)=MAX BLOCK # + 1 ;(HL)=BAD BLOCK # CALL CPHLDE JNC F2175A ; BR IF PAST END OF PARTITION XCHG ;(DE)=BAD BLOCK # LHLD F217LAB ;CHECK TO SEE IF SAME AS LAST BAD CALL CPHLDE ; BLOCK # JZ F2175A ; BR IF YES XCHG ;(HL)=BAD BLOCK # SHLD F217LAB ;SAVE AS LAST BAD BLOCK # XCHG ;(DE)=BAD BLOCK # ; ADD BAD BLOCK # TO DISK MAP FOR THE CURRENT DIRECTORY ENTRY. LDA F217C2 ;GET MAP COUNTER CPI 16 ;Q. MAP FULL JNZ F2175B ; BR IF NOT PUSH D ;DIRECTORY ENTRY FULL CALL F21760 ; WRITE IT TO DISK POP D JC F21799 ; BR IF ERROR XRA A ;ZERO MAP COUNTER F2175B: LXI H,F217MAP ;PLACE BAD BLOCK # INTO MAP CALL DADA MOV M,E INX H MOV M,D LXI H,F217C2 ;BUMP MAP COUNTER INR M LDA F217H ;CHECK DSM TO SEE IF SINGLE OR ORA A ; DOUBLE BYTE MAP VALUES JZ F2175A ; BR IF SINGLE (DSM <= 255) INR M JMP F2175A ; DONE BUILDING DIRECTORY ENTRIES BAD SECTORS. F2175C: CALL F21760 ;WRITE DIRECTORY ENTRY JC F21799 ; BR IF ERROR LXI H,F217FCB+FCBRO ;SET ATTRIBUTES TO R/O & SYS MOV A,M ORI FCBROF MOV M,A INX H MOV A,M ORI FCBSYSF MOV M,A MVI C,SFA LXI D,F217FCB CALL BDOS ;* JMP F21798 ;* GET NEXT ENTRY FOR BAD SECTOR TABLE. ; ; ENTRY: 'F217BSE'=TABLE POINTER ; EXIT: PSW/Z 0=ENTRY PRESET , 1=NO MORE ENTRIES ; (HL) = BAD SECTOR # ; USES: ALL ; F21750: LHLD F217BSE ;GET TABLE POINTER TO NEXT ENTRY MOV C,M ;GET LOW ORDER BYTE INX H MOV B,M ;GET MIDDLE ORDER BYTE INX H INX H ;HIGH ORDER BYTE IS NOT USED SHLD F217BSE ;SAVE TABLE POINTER FOR NEXT TIME MOV H,B ;MOVE BAD SECTOR # TO (HL) MOV L,C MOV A,H ;SET PSW/Z FLAG ORA L RET ;* WRITE DIRECTORY ENTRY TO DISK. ; ; ENTRY: 'F217C2'=MAP COUNTER ; 'F217FCB'=DIRECTORY ENTRY ; EXIT: 'F217C2'=MAP COUNTER ZEROED ; 'F217FCB'=DIRECTORY ENTRY UPDATED FOR NEXT EXTENT ; USES: ALL ; F21760: LDA F217C2 ;Q. MAP COUNTER = 0 ORA A RZ ; RET IF YES -- DIR ENTRY IS EMPTY MVI C,RDS ;RESET DISK SYSTEM CALL BDOS MVI C,CREATE ;MAKE FILE FOR THIS ENTRY LXI D,F217FCB CALL BDOS INR A ;CHECK FOR ERROR STC RZ ; RET IF ERROR MVI B,16 ;MOVE MAP TO FCB LXI H,F217MAP LXI D,F217FCB+FCBDM F21761: MOV A,M STAX D MVI M,0 INX H INX D DCR B JNZ F21761 LHLD DPBPTR ;SET EXTENT NUMBER BYTE LXI B,DPBEXM DAD B LDA F217FCB+FCBEX ADD M STA F217FCB+FCBEX CPI 32 ;EXTENT NUMBER > MAX JC F21762 ; BR IF NOT SUI 32 ; MAKE EXTENT # MODULUS 32 STA F217FCB+FCBEX LXI H,F217FCB+FCBRWF ; INC MODULE NUMBER INR M F21762: MVI A,128 ;SET RECORD COUNT TO FULL STA F217FCB+FCBRC LXI H,F217FCB+FCBRWF ;CLEAR 'FILE WRITE FLAG' MOV A,M ANI 0FFH-FCBRWFF MOV M,A MVI C,CLOSE ;CLOSE FILE LXI D,F217FCB CALL BDOS INR A ;CHECK FOR ERROR STC RZ ; RET IF ERROR LXI H,F217FCB+FCBEX ;SET EXTENT NUMBER FOR NEXT TIME INR M XRA A ;CLEAR MAP COUNTER STA F217C2 RET ;* ROUTINE TO DO POWER OF 2 DIVISION BY SHIFTING RIGHT. ; ENTRY: (B) = SHIFT COUNT ; (HL) = VALUE TO BE DIVIDED ; EXIT: (HL) = RESULT ; USES: A,F,B,H,L F21770: MOV A,H ANA A RAR MOV H,A MOV A,L RAR MOV L,A DCR B JNZ F21770 RET ;* CALCULATE DPE HEATH EXTENSIONS AND DISK PARAMETER BLOCK VALUES F21780: ; CALCULATE # SECTORS WITHIN PARTITION. LHLD DPEPTR ;GET LAST SECTOR # + 1 LXI B,DPEUPB DAD B CALL HLIHL INX H XCHG ;(DE) = LAST SECTOR # + 1 LHLD DPEPTR ;GET BEGINNING SECTOR # LXI B,DPETRK DAD B CALL HLIHL SHLD F217LB CALL SUBHLDE ;(HL) = # SECTORS IN PARTITION LXI D,WIMIN ;CHECK AGAINST MINIMUM ALLOWABLE CALL CPHLDE JNC F21781 ; BR IF >= MINIMUM MVI C,PRCONB ;PRINT ERROR MESSAGE IF < MINIMUM LXI D,MINMSG CALL BDOS STC ;INDICATE ERROR RET F21781: LXI D,WIMAX+1 ;CHECK AGAINST MAXIMUM USEABLE CALL CPHLDE JC F21782 ; BR IF <= MAXIMUM MVI C,PRCONB ;ISSUE WARNING MESSAGE LXI D,MAXMSG CALL BDOS LXI H,WIMAX ;ONLY ALLOW MAXIMUM USEABLE F21782: SHLD F217NS ;SAVE # SECTORS WITHIN PARTITION ; SEARCH PARAMETER TABLE TO FIND ENTRY THAT THE PARTITION'S # USEABLE ; SECTORS >= TABLE ENTRY'S # SECTORS. LXI H,F217TBL ;(HL) = TABLE POINTER F21783: MOV E,M ;GET # SECTORS FROM TABLE INX H MOV D,M PUSH H LHLD F217NS ;GET PARTITION'S # USEABLE SECTORS CALL CPHLDE ;COMPARE POP H JNC F21784 ; BR IF >= LXI D,F217TBLL-1 ;BUMP TO NEXT TABLE ENTRY DAD D JMP F21783 ;CHECK NEXT ENTRY ; PLACE INFO INTO THE HEATH EXTENSION AREA OF THE DRIVE'S ; DISK PARAMETER ENTRIES TABLE. F21784: XCHG ;(DE) = F217 TABLE POINTER LHLD DPEPTR ;(HL) = DISK PARAMETER ENTRY TABLE PTR LXI B,DPERPAB ;CP/M RECORDS PER ALLOCATION BLOCK DAD B INX D LDAX D MOV M,A ; PLACE INFO INTO THE DRIVE'S DISK PARAMETER BLOCK. LHLD DPBPTR ;(HL) = DISK PARAMETER BLOCK POINTER LXI B,WIRPT ;CP/M RECORDS PER TRACK MOV M,C INX H MOV M,B INX D ;BLOCK SHIFT FACTOR INX H LDAX D MOV M,A INX D ;BLOCK MASK INX H LDAX D MOV M,A INX D ;EXTENT MASK INX H LDAX D MOV M,A INX D ;# DIRECTORY ENTRIES - 1 INX H INX H INX H LDAX D MOV M,A INX D INX H LDAX D MOV M,A INX D ;AL0 INX H LDAX D MOV M,A INX D ;AL1 INX H LDAX D MOV M,A XRA A ;CHECKSUM VECTOR LENGTH INX H MOV M,A INX H MOV M,A LXI B,WINST ;# OF SYSTEM TRACKS INX H MOV M,C INX H MOV M,B ; CALCULATE DISK PARAMETER BLOCK 'DSM' VALUE. ; DSM = ( [# USEABLE SECTORS] - [# SYSTEM SECTORS] ) / ; [# SECTORS PER ALLOCATION BLOCK] - 1 LHLD F217NS LXI D,-WINSYS DAD D XCHG LHLD DPBPTR LXI B,DPBBSH DAD B MOV B,M DCR B DCR B IF WICSZ NE 512 %: CELL SIZE IS NOT 512 -- DO NOT DCR TWICE ENDIF XCHG ;(DE) = POINTER INTO DPB ;(HL) = VALUE TO BE DIVIDED CALL F21770 XCHG ;(DE) = QUOTIENT ;(HL) = POINTER INTO DPB DCX D LXI B,DPBDSM-DPBBSH ;PLACE RESULT INTO DISK PARM BLOCK DAD B MOV M,E INX H MOV M,D XRA A ;INDICATE NO ERROR RET ;* NO ERROR F21798: XRA A JMP F217100 ;* ERROR F21799: STC ;* DONE FORMATTING Z217 F217100: PUSH PSW MVI C,SGUSR ;RESTORE USER CODE LDA F217UC MOV E,A CALL BDOS CALL FCBD ;CLEAR BIOS BUFFER FOR DRIVE POP PSW RET ;* READ IN BAD SECTOR TABLE F217RDB: CALL FCBD ;CLEAR BUFFERS LHLD DPEPTR ;INDICATE TO LOGICAL I/O LXI D,DPEFLAG DAD D MOV A,M ORI DPELSIO MOV M,A LXI B,0 ;READ SBC LXI D,1 LXI H,BUFFER CALL F217RD JC F217RDB9 ; BR IF ERROR LHLD BUFFER+SBCBSA ;GET LOGICAL SECTOR # OF BAD SEC TABLE MOV B,H ;COMPUTE TRACK # MOV C,L LXI D,WINSPT CALL C$DU66 SHLD F217TRK MVI A,WIRPS ;COMPUTE CP/M SECTOR # = PHYSICAL CALL C$MU86 ; SECTOR # * CP/M RECORDS PER INX H ; PHYSICAL SECTOR + 1 SHLD F217SEC LXI H,BUFFER ;SET BUFFER ADDRESS SHLD F217BSE MVI A,WIRPS*2 ;ASSUME TABLE WILL FIT IN STA F217C2 ; 2 PHYSICAL SECTORS F217RDB1: LHLD F217TRK ;GET TRACK # MOV B,H MOV C,L LHLD F217SEC ;GET CP/M SECTOR # XCHG LHLD F217BSE ;GET BUFFER FWA CALL F217RD ;READ 128 BYTES JC F217RDB9 ; BR IF ERROR LHLD F217SEC ;Q. END OF TRACK LXI D,WIRPT CALL CPHLDE JNZ F217RDB3 ; BR IF NOT LHLD F217TRK ;BUMP TRACK # INX H SHLD F217TRK LXI H,0 F217RDB3: INX H ;BUMP CP/M SECTOR # SHLD F217SEC LHLD F217BSE ;BUMP BUFFER ADDRESS LXI D,128 DAD D SHLD F217BSE LXI H,F217C2 ;LOOP AND READ DCR M JNZ F217RDB1 LXI H,BUFFER ;INIT BAD SECTOR TABLE ENTRY POINTER SHLD F217BSE XRA A ;INDICATE NO ERROR F217RDB9: PUSH PSW ;SAVE CARRY FLAG (ERROR INDICATOR) LHLD DPEPTR ;TURN OFF DOING LOGICAL SECTOR I/O FLAG LXI D,DPEFLAG DAD D MOV A,M ANI 0FFH-DPELSIO MOV M,A CALL FCBD ;CLEAR BUFFERS POP PSW ;RETRIEVE ERROR INDICATOR RET ;* READ CP/M SECTOR FROM DISK ; ; ENTRY: (BC) = TRACK # ; (DE) = CP/M SECTOR # (1 TO SPT) ; (HL) = BUFFER FWA ; EXIT: PSW/C 0=NO ERROR , 1=ERROR ; USES: ALL ; F217RD: PUSH H PUSH D CALL FSETTRK ;SET TRACK POP B ;SET CP/M SECTOR CALL FSETSEC POP B ;SET DMA CALL FSETDMA CALL FREAD ;READ SECTOR ORA A ;Q. ERROR RZ ; RET IF NO ERROR STC ;INDICATE ERROR OCCURRED RET ;* PARAMETER TABLE CONTAINING ; 1) HEATH EXTENSION VALUES ; 2) DISK PARAMETER BLOCK VALUES ; ; FORMAT OF TABLE: ; BYTE # DESCRIPTION ; ------ ---------------------------------------------------- ; 0-1 # SECTORS -- THIS ENTRY IS USED IF PARTITION'S ; # USEABLE SECTORS >= ; 2 CP/M RECORDS PER ALLOCATION BLOCK ; 3 BLOCK SHIFT FACTOR ; 4 BLOCK MASK ; 5 EXTENT MASK ; 6-7 # OF DIRECTORY ENTRIES - 1 ; 8 AL0 ; 9 AL1 ; F217TBL DS 0 DW 1024/WICSZ*4*1024+WINSYS+1 ;4 MEG < X <= 8 MEG DB 32,5,31,1 DW 1023 DB 0FFH,000H F217TBLL EQU $-F217TBL ;TABLE ENTRY LENGTH DW 1024/WICSZ*1*1024+WINSYS+1 ;1 MEG < X <= 4 MEG DB 16,4,15,0 DW 511 DB 0FFH,000H DW 1024/WICSZ*512+WINSYS+1 ;512K < X <= 1 MEG DB 16,4,15,0 DW 255 DB 0F0H,000H DW 1024/WICSZ*256+WINSYS+1 ;256K < X <= 512K DB 16,4,15,1 DW 127 DB 0C0H,000H DW WIMIN ;MINIMUM <= X <= 256K DB 8,3,7,0 DW 63 DB 0C0H,000H FMTPART DB CR,LF,CR,LF,'Will format partition assigned to drive ' FPARTD DB '?:',CR,LF,CPMEOM MINMSG DB CR,LF,BELL,'PARTION IS SMALLER THAN MINIMUM ALLOWABLE ' DB 'SIZE',CR,LF,CPMEOM MAXMSG DB CR,LF,BELL,'PARTITION IS LARGER THAN CP/M MAXIMUM SIZE' DB ' -- ONLY 8 MEG USEABLE',CR,LF,CPMEOM F217NS DS 2 ;# USEABLE SECTORS F217TRK DS 2 ;TRACK # F217SEC DS 2 ;SECTOR # F217DAB DS 2 ;# DIRECTORY ALLOCATION BLOCKS F217C1 DS 2 ;LOOP COUNTER F217C2 DS 1 ;COUNTER F217BS DS 2 ;BAD SECTOR TABLE SECTOR # F217BSE DS 2 ;BAD SECTOR TABLE POINTER F217LAB DS 2 ;LAST ALLOCATION BLOCK MARKED BAD F217LB DS 2 ;PARTITION LOWER BOUND F217H DS 1 ;HIGH ORDER BYTE OF DSM F217UC DS 1 ;USER CODE F217FCB DB 0,'BADBLOCKSYS',0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 F217MAP DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 PAGE ; ; INTRLV -- CONSTRUCTS A SECTOR INTERLEAVE TABLE ; ; ENTRY: (B) = INTERLEAVE FACTOR ; (C) = SECTORS PER TRACK ; (HL) = ADDR OF TABLE ; USES: ALL ; ; CONDITIONAL VARIABLE 'INTERACT' IF 1 ALLOWS INTERLEAVE FACTOR ; TO BE ENTERED FROM CONSOLE INSTEAD OF PASSED IN REG B. ; INTERACT EQU 0 INTRLV: MOV A,C ;SAVE SPT STA INTRLVA STA INTRLVB ;ALSO AS COUNTER SHLD INTRLVC ;SAVE ADDR OF TABLE INR C ;BUMP (C) FOR TEST & INITIALIZATION MOV A,B ;CHECK FOR VALID INTERLEAVE FACTOR ANA A JZ INTRLV1 ; BR IF ZERO -- INVALID CMP C JC INTRLV2 ; BR IF <= SPT -- VALID INTRLV1: MVI B,1 ;SET INTERLEAVE FACTOR TO 1 INTRLV2: XRA A ;INIT INTERLEAVE TABLE TO ZEROES INTRLV2A: MOV M,A INX H DCR C JNZ INTRLV2A IF INTERACT MVI C,PRINTF LXI D,INTRLVMSG CALL BDOS MVI C,RDCON CALL BDOS SUI '0' MOV B,A JMP INTRLV3 INTRLVMSG: DB 13,10,'ENTER INTERLEAVE FACTOR: $' ENDIF INTRLV3: MVI C,0 ;(C) = TABLE DISPLACEMENT MVI D,1 ;(D) = SECTOR # INTRLV4: MOV A,C LXI H,INTRLVA CMP M JC INTRLV5 SUB M ;MODULO SPT MOV C,A INTRLV5: LHLD INTRLVC CALL DADA MOV A,M ANA A JZ INTRLV6 INR C JMP INTRLV4 INTRLV6: MOV M,D INR D MOV A,C ADD B MOV C,A LXI H,INTRLVB DCR M JNZ INTRLV4 RET INTRLVA DS 1 ;SPT INTRLVB DS 1 ;LOOP COUNTER INTRLVC DS 2 ;ADDR OF TABLE PAGE ;C$DU66 -- UNSIGNED 16 / 16 DIVISION. ; ; (HL)=(BC)/(DE) ; ; ENTRY: (BC),(DE) PRESET ; EXIT: (HL) = RESULT ; (DE) = REMAINDER ; USES: ALL C$DU66: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D MOV A,D ORA E JZ DU665 ;IF DIVIDE BY 0 XRA A ; SHIFT (DE) LEFT UNTIL: ; ; 1) DE > BL ; 2) OVERFLOW DU661: MOV H,D MOV L,E DAD B JNC DU662 ;IS TOO LARGE INR A MOV H,D MOV L,E DAD H XCHG JC DU661 ; (DE) OVERFLOWED PUT IT BACK XCHG DCR A ;REMOVE EXTRA COUNT ; READY TO START SUBTRACTING. (A)=LOOP COUNT DU662: MOV H,B ; (HL) = WORKING VALUE MOV L,C LXI B,0 ; (BC) = RESULT DU663: PUSH PSW DAD D JC DU664 ;IF SUBTRACT OK MOV A,L ;ADD BACK IN SUB E MOV L,A MOV A,H SBB D MOV H,A DU664: MOV A,C RAL MOV C,A MOV A,B RAL MOV B,A ; RIGHT SHIFT (DE) STC MOV A,D RAR MOV D,A MOV A,E RAR MOV E,A POP PSW DCR A JP DU663 ;IF NOT DONE DU665: XCHG ;(DE)=REMAINDER MOV H,B ;(HL)=RESULT MOV L,C RET ;C$MU86 -- 8 BY 16 BIT MULTIPLICATION ; ; ENTRY: (A) = MULTIPLIER ; (DE)= MULTIPLICAND ; EXIT: (HL)= RESULT ; 'Z' SET IF NOT OVERFLOW ; USES: A,F,H,L ; C$MU86: LXI H,0 ;(HL) = RESULT ACCUMULATOR PUSH B MOV B,H ;(B) = OVERFLOW FLAG MU860: ORA A ;CLEAR CARRY MU861: RAR JNC MU862 ;IF NOT TO ADD DAD D JNC MU862 ;NOT OVERFLOW INR B MU862: ORA A JZ MU863 ;IF DONE XCHG DAD H XCHG JNC MU861 ;LOOP IF NOT OVERFLOW INR B JMP MU860 MU863: ORA B ;SET *Z* FLAG IF NOT OVERFLOW POP B RET ; ; CPHLDE -- COMPARE (HL) TO (DE) ; ; USES: A,F ; CPHLDE: MOV A,H CMP D RNZ MOV A,L CMP E RET ; ; DADA -- ADD (A) TO (HL) ; ; USES: A,F,H,L ; DADA: ADD L MOV L,A RNC INR H RET ; ; DISPATCH - CALL APPROPRIATE FORMATTING ROUTINE ; DISPATCH: LDA DRTYPE RLC RLC RLC ANI DPETYPE SHR 5 ADD A LXI H,FMTRTN CALL DADA CALL HLIHL MOV A,H ORA L RZ PCHL ; ; HLIHL -- LOAD HL FROM SLOT POINTED TO BY HL ; ; USES: A,H,L ; HLIHL: MOV A,M INX H MOV H,M MOV L,A RET ; ;* WRLAB - FORM LABEL AND WRITE IT TO 1ST SECTOR OF DISK ; ; ENTRY: NONE ; EXIT: PSW/C = 0 IF NO ERROR , 1 IF ERROR ; USES: ALL ; WRLAB: MVI A,0E5H ;CLEAR 128 BYTES OF BUFFER TO 0E5H MVI B,128 LXI H,BUFFER CALL F378X MVI A,LABVER ;INSERT CURRENT FORM # STA BUFFER+LABTYP ; MOVE HEATH EXTENSIONS TO LABEL LHLD DPEPTR ;GET ADDR OF HEATH EXTENSIONS LXI D,DPEHTH DAD D ;(HL) = HEATH EXTENSIONS LXI D,BUFFER+LABHTH ;(DE) = LABEL AREA MVI B,DPEHL ;LENGTH OF HEATH EXTENSIONS CALL MOVEIT ; MOVE DPB TO LABEL LHLD DPBPTR LXI D,BUFFER+LABDPB MVI B,DPBL CALL MOVEIT ; XRA A ;CALCULATE CHECKSUM FOR LABEL LXI H,BUFFER+LABEL MVI B,LABLEN-1 WRLAB5: ADD M INX H DCR B JNZ WRLAB5 CMA MOV M,A ;PLACE CHECKSUM INTO LABEL ; WRITE LABEL TO DISK. LXI B,0 ;SET DESIRED CP/M TRACK # CALL FSETTRK LXI B,1 ;SET DESIRED CP/M SECTOR # CALL FSETSEC LXI B,BUFFER ;SET DMA CALL FSETDMA MVI C,BWRDIR ;WRITE SECTOR CALL FWRITE ORA A ;Q. ERROR RZ ; RET IF NO ERROR STC ;INDICATE ERROR RET ; ; MOVEIT -- MOVE BLOCK OF MEMORY ; ; ENTRY: (HL)=SOURCE ADDRESS ; (DE)=DESTINATION ADDRESS ; (B)=COUNT ; EXIT: NONE ; USES: ALL ; MOVEIT: MOV A,M STAX D INX H INX D DCR B JNZ MOVEIT RET ; ; SUBHLDE -- (HL)=(DE)-(HL) ; ; USES: A,F,H,L ; SUBHLDE: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ;* ; TMMERR -TYPE MISMATCH ERROR ; TMMERR MVI C,PRCONB LXI D,MMERR CALL BDOS JMP BOOT ;*** ;* CLINT - COMMAND LINE INTERPRETER ;* BILL EARL 10/12/81 ;* ;* PARSES COMMAND LINE OPTIONS ;* BYPASSES USER PROMPT SECTION ;* SYNTAX ERRORS OR INVALID FIELDS ;* CAUSE ERROR MESSAGE AND EXIT FROM ;* PROGRAM ;* ;* ENTRY: ;* COMMAND LINE COUNT AT TBUFF ;* COMMAND LINE AT TBUFF + 1 ;* ;* EXIT: ;* COMMAND LINE COUNT = 0 ;* ;* USES: ALL REGISTERS ;* ;* CALLS: RDOPT, WKIND ;* CLINT LDA TBUFF ;BYTECOUNT MOV B,A ;BYTECOUNT IN B LXI H,TBUFF+1 ;ADDR OF START OF STRING CALL CSCAN ;FIND DEVICE NAME CPI TNAME ;IS IT A NAME? JNZ CLI0 ;NOT A NAME MOV A,B ;ACCUMULATOR <= BYTECOUNT STA TBUFF ;UPDATE BYTECOUNT SHLD CURSOR ;UPDATE STRING POINTER LDAX D ;GET DRIVE ID STA DRIVID ;STORE IT IN DRIVID JMP CLI1 ; ; DEVICE ERROR CLI0 LDAX D STA DRMSGA ;ERRONEOUS DRIVE NAME MVI C,PRCONB LXI D,DRMSGA ;DEVICE ERROR MESSAGE CALL BDOS CALL RDQUIT CLI1 CALL RDOPT ;READ FORMAT OPTIONS RET ;END OF COMMAND LINE INTERPRETER ;** ;* RDOPT - READ OPTIONS ;* BILL EARL 10/12/81 ;* ;* COMMAND LINE INTERPRETER ROUTINE TO FIND AND SET OPTIONS ;* ;* ENTRY: ;* POINTER TO COMMAND STRING AT CURSOR ;* LENGTH OF COMMAND STRING AT TBUFF ;* ;* EXIT: ;* ;* USES: ALL REGISTERS ;* ;* CALLS: CSCAN ;* RDOPT LDA TBUFF ;GET BYTECOUNT MOV B,A ;PUT IT IN B LHLD CURSOR ;GET STRING POINTER CALL CSCAN ; CPI TEOL ;END OF LINE? JZ RDEXIT ; CPI TLBR ;BEGINNING OF OPTIONS JNZ RDOP9 ;SYNTAX ERROR ; MAIN LOOP RDOP0 CALL CSCAN ;GET OPTION CPI TNAME ;IS IT VALID? JNZ RDOP9 ;SYNTAX ERROR ; DECODE SECTION RDOP1 LDAX D ;GET FIRST CHAR. CALL TOUPPER CPI 'F' ;FAST? JNZ RDOP2 ; FAST OPTION SELECTED STA FAST ;SET FAST FLAG JMP RDOP6 ;NEXT OPTION RDOP2 CPI 'N' ;NOQUERY? JNZ RDOP2A MVI A,TRUE STA NOQFLG JMP RDOP6 RDOP2A CPI 'D' ;DOUBLE FACTOR? JNZ RDOP2B STA FACTOR ;SET FACTOR JMP RDOP4 ;GET PARAMETER RDOP2B CPI 'S' ;SINGLE FACTOR? JNZ RDOP2C STA FACTOR JMP RDOP4 RDOP2C CPI '1' ;ONE SIDE JNZ RDOP2D STA FACTOR JMP RDOP3 RDOP2D CPI '2' ;TWO SIDES JNZ RDOP10 STA FACTOR RDOP3 INX D ;IT BETTER BE SIDES! LDAX D ;GET NEXT CHAR CALL TOUPPER CPI 'S' ;IS IT SIDES JNZ RDOP10 ;OPTION ERROR. NOT SIDES LDA FACTOR STA CLISIDS ;STORE # OF SIDES JMP RDOP6 RDOP4 INX D ;NEXT CHAR LDAX D ;LOAD IT CPI 'D' ;DENSITY? JNZ RDOP5 ;BR IF NOT LDA FACTOR ;GET FACTOR STA CLIDENS ;PUT IT IN DENSITY BYTE JMP RDOP6 ;NEXT OPTION RDOP5 CPI '0' ;POSSIBLE TRACK 0 DOUBLE DENSITY JNZ RDOP10 ; BR IF NOT LDA FACTOR CPI 'D' JNZ RDOP10 STA CLIDENS MVI A,1 STA CLID0 ; ; END OF OPTION DECODE, GET NEXT OPTION ; RDOP6 INX D LDAX D ;LOOK AT NEXT CHAR CPI ']' ; JZ RDOP6A ; CPI ' ' ; JZ RDOP6A ; CPI ',' ; JNZ RDOP10 ;ERROR, EXTRA CHARACTERS RDOP6A CALL CSCAN ;LOOK FOR MORE CPI TRBR ;RIGHT BRACKET? JZ RDEXIT ; CPI TCOMMA ;IS IT A COMMA? JZ RDOP0 ; JMP RDOP9 ;SYNTAX ERROR; RDEXIT RET ;END OF READ OPTIONS ; ERROR HANDLING ; SYNTAX ERROR RDOP9 MVI C,PRCONB ; LXI D,SYNMSG ;SYNTAX ERROR MESSAGE CALL BDOS ; JMP RDQUIT ;FATAL ERROR ; ILLEGAL OPTION RDOP10 MVI C,PRCONB ; LXI D,OPTMSG ;OPTION ERROR MESSAGE CALL BDOS ; ; JMP RDQUIT ;FATAL ERROR RDQUIT JMP BOOT ;WARM BOOT ;*** CSCAN - Scanner for CP/M command lines ; ; CSCAN is called to get the next token from a CP/M ; command line. ; ; Protocol CALL CSCAN ; ; Entry (HL) = addr of current position in string ; (B) = number of bytes to end of string ; ; Exit (HL) = updated to addr of byte after token ; (B) = updated to number of bytes left in string ; (DE) = addr of beginning of token ; (C) = length of token in bytes ; (A) = token type ; ; the token types are: ; TNAME - a name ; TEQUAL - an equal sign ; TLBR - an "[" ; TRBR - an "]" ; TCOMMA - a comma ; TEOL - the end of the command line ; TILG - an illegal token(ie anything else) ; ; Uses all registers ; ; Revision ; 10/14/81 dtp - new CSCAN XRA A ; Clear A to zero STA CSCSTA ; STATE = 0 STA CSCTSZ ; TOKSIZ = 0 SHLD CSCSTP ; Save string ptr ; ; Main processing loop ; (B = bytes left) CSC00 MOV A,B ; Test if bytes left is zero ANA A JZ CSC02 ; If bytes left is zero(char class is zero) ; Compute character class LHLD CSCSTP ; Get string ptr MOV A,M ; Get a byte from the string ANI 7FH ; Remove parity bit, if present LXI H,CSCCLT ; Get addr of class table ADD L ; Compute offset in table MOV L,A ; STORE IT IN L JNC CSC01 ; If no carry INR H ; Propagate carry CSC01 MOV A,M ; Get character class CSC02 STA CSCCLS ; Save class ; Compute addr of scan table entry given state and class LDA CSCSTA ; Get current state MVI E,CSCNCL ; Get number of classes CALL MUL88 ; Compute STATE*NCLASS LDA CSCCLS ; Get current class ADD L ; Compute STATE*NCLASS + CLASS MOV L,A ; STORE IT IN L JNC CSC03 ; If no carry INR H ; Propagate carry CSC03 DAD H ; Compute 2*(STATE*NCLASS + CLASS) LXI D,CSCSNT ; Get addr of scan table DAD D ; Compute addr of scan table entry ; Get scan table entry MOV A,M ; Get action (SCANTAB.ACT) INX H ; Point to second byte MOV C,M ; Get argument (SCANTAB.ARG) ; Decode and perform actions RAR ; Test to set token start JNC CSC04 ; If not LHLD CSCSTP ; Get string ptr SHLD CSCTKP ; TOKPTR = STRPTR CSC04 RAR ; Test to incr token size JNC CSC05 ; If not LXI H,CSCTSZ ; Get addr of TOKSIZ INR M ; TOKSIZ = TOKSIZ + 1 CSC05 RAR ; Test to incr string position JNC CSC06 ; If not LHLD CSCSTP ; Get string ptr INX H ; STRPTR = STRPTR + 1 SHLD CSCSTP ; Store string ptr DCR B ; BYTESLEFT = BYTESLEFT - 1 CSC06 ANI CSCAMK ; Isolate transition type JNZ CSC07 ; If "RETURN" transition ; "GOTO" transition MOV A,C ; Get SCANTAB.ARG STA CSCSTA ; STATE = SCANTAB.ARG JMP CSC00 ; Do forever ; "RETURN" transition CSC07 MOV D,C ; Save token type LDA CSCTSZ ; Get token size MOV C,A ; To proper reg MOV A,D ; Token type to proper reg LHLD CSCTKP ; Get token ptr XCHG ; To proper regs (DE) LHLD CSCSTP ; Get string ptr RET ; Return to caller ; Define the variables CSCSTA DS 1 ; STATE - the state of the finite state machine CSCCLS DS 1 ; CLASS - the class of the current character CSCSTP DS 2 ; STRPTR - ptr to current character in string CSCTKP DS 2 ; TOKPTR - ptr to token in string CSCTSZ DS 1 ; TOKSIZ - token size ; Define constants and tables TNAME EQU 1 ; Name token TEQUAL EQU 2 ; Equal sign token TLBR EQU 3 ; Left brace token TRBR EQU 4 ; Right brace token TCOMMA EQU 5 ; Comma token TEOL EQU 6 ; End-of-line token TILG EQU 7 ; Illegal type token CSCACR EQU 08H ; "RETURN" action CSCACG EQU 00H ; "GOTO" action CSCACS EQU 01H ; Set token start action CSCACA EQU 02H ; Increase token size action CSCACI EQU 04H ; Increase string ptr action CSCAMK EQU 01H ; Action mask CSCNST EQU 2 ; Number of states CSCNCL EQU 8 ; Number of character classes ; The character classes and the character class table CSCEOL EQU 0 ; End of line class CSCILG EQU 1 ; Illegal character class CSCEQU EQU 2 ; Equal sign class CSCLBR EQU 3 ; Left brace class CSCRBR EQU 4 ; Right brace class CSCBNK EQU 5 ; Blank/tab class CSCCOM EQU 6 ; Comma class CSCNAM EQU 7 ; Name class ; for each of the 128 characters, define which class in which it belongs CSCCLT DB CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG ; 00-07 DB CSCILG,CSCBNK,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG ; 08-15 DB CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG ; 16-23 DB CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG,CSCILG ; 24-31 DB CSCBNK,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 32-39 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCCOM,CSCNAM,CSCNAM,CSCNAM ; 40-47 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 48-55 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCEQU,CSCNAM,CSCNAM ; 56-63 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 64-71 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 72-79 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 80-87 DB CSCNAM,CSCNAM,CSCNAM,CSCLBR,CSCNAM,CSCRBR,CSCNAM,CSCNAM ; 88-95 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 96-03 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 04-11 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 12-19 DB CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM,CSCNAM ; 20-27 ; The Scanner State table CSCSNT DB CSCACS+CSCACA+CSCACI+CSCACR,TEOL ; CSCEOL DB CSCACS+CSCACA+CSCACI+CSCACR,TILG ; CSCILG DB CSCACS+CSCACA+CSCACI+CSCACR,TEQUAL ; CSCEQU DB CSCACS+CSCACA+CSCACI+CSCACR,TLBR ; CSCLBR DB CSCACS+CSCACA+CSCACI+CSCACR,TRBR ; CSCRBR DB CSCACI+CSCACG,0 ; CSCBNK DB CSCACS+CSCACA+CSCACI+CSCACR,TCOMMA ; CSCCOM DB CSCACS+CSCACA+CSCACI+CSCACG,1 ; CSCNAM DB CSCACR,TNAME ; CSCEOL DB CSCACR,TNAME ; CSCILG DB CSCACR,TNAME ; CSCEQU DB CSCACR,TNAME ; CSCLBR DB CSCACR,TNAME ; CSCRBR DB CSCACR,TNAME ; CSCBNK DB CSCACR,TNAME ; CSCCOM DB CSCACA+CSCACI+CSCACG,1 ; CSCNAM *** MUL88 - Multiply 8X8 Unsigned * * MUL88 Multiplies a 8 bit value by a 8 bit value * to give a 16 bit result. * * ENTRY (A) = Multiplier * (E) = Multiplicand * * EXIT (HL) = result * * Uses A,D,E,H,L * * Revision * 10/15/81 dtp - converted form MUL86 MUL88 LXI H,0 ; Result = 0 MOV D,H ; Clear D to 0 ANA A ; CLEAR CARRY ; For each bit that is on in the multiplier, add the multiplicand ; raised to the appropriate power of two to the result. ; (Cy = 0) MUL00 RAR ; Look at next bit in multiplier JNC MUL01 ; If bit zero DAD D ; Add in current multiplicand MUL01 ORA A ; See if finished(any bits left) RZ ; If done XCHG ; Swap result and current multiplicand DAD H ; Mult multiplicand by 2 XCHG ; Put back in proper regs JMP MUL00 ; Continue PAGE BADBIOS DS 0 DB 'Incorrect version of the BIOS',CR,LF,CPMEOM WHICH DB CR,LF,CR,LF DB 'Which drive do you wish to use for this operation?' DB ': $' WDSDMSG: DB CR,LF,CR,LF DB 'Which density? (S=single, D=double): $' WSMSG: DB CR,LF,CR,LF DB 'Number of sides? (1=single, 2=double): $' DRMSG: DB CR,LF,BELL DB 'Drive ' DRMSGA DB ' ' DB ' not available in current configuration.' DB CR,LF,'$' PROMPT: DB CR,LF,CR,LF DB 'Put the disk you wish to be formatted in drive ' PROMPTA DB '0','.$' PROMPT1 DB CR,LF DB 'Press RETURN to begin, anything else to abort.',CR,LF,'$' WPMSG: DB CR,LF,BELL DB 'Unable to format this disk. It is write protected.$' AMWMSG: DB CR,LF DB 'Do you have more disks to format? (y/n): $' LVEMSG: DB CR,LF DB 'Place a bootable disk in drive A and press any character:' DB '$' WPEMSG DB CR,LF,'Disk is write protected' BMSG DB CR,LF,BELL,'Unable to format this disk.',CR,LF,'$' SYNMSG DB CR,LF,BELL,'ILLEGAL COMMAND SYNTAX',CR,LF,'$' OPTMSG DB CR,LF,BELL,'ILLEGAL FORMAT OPTION',CR,LF,'$' MMERR DB CR,LF,BELL,'DISK IS NOT OF TYPE SPECIFIED',CR,LF,'$' FMTRTN DS 0 DW 0 DW F37 DW F217 DW 0 DW 0 DW 0 DW 0 DW 0 CURSOR DW 0 ;COMMAND STRING INDEX COMLIN DB FALSE ;COMMAND LINE FLAG NOQFLG DB FALSE ;NO QUERY FLAG FACTOR DB 0 ;COMMAND STRING OPTION FACTOR (S,D,1,2) CLID0 DB 0 ;TRACK 0 DOUBLE DENSITY FLAG CLIDENS DB 'D' ;COMMAND STRING DENSITY RESULT CLISIDS DB '2' ;COMMAND STRING SIDES RESULT DRIVID DB 'Z' ;COMMAND LINE DRIVE ID SYSDSK DB 0 ;SYSTEM DISK INVOLVED FLAG TFLG DB 0 ;DISK TYPE CHECK. DEFAULT NO CARE. FAST DB 0 ;fast flag defaults to off DENSITY DB 0 ;density to be used DPEPTR DS 2 ;DISK PARAMETER ENTRIES POINTER DPBPTR DS 2 ;DISK PARAMETER BLOCK POINTER DSKTKS DS 1 ;number of tracks DSKSPT DS 1 ;SECTORS PER TRACK TRACK DS 1 ;TRACK COUNTER SIDES DS 1 ;# SIDES AIOUNI DS 1 DRTYPE DS 1 FLAG2 DS 1 BUFFER EQU $ END START PER TRACK TRACK DS 1 ;TRACK COUNTER SIDES DS