ÙYÀÀF¥L¥ASCII LIB $ùÀ¥BIOS85 ASMI¿&À¥BIOS88 A86W oÌÀ ¥BIOSDEF LIBc 80À ¥BIOSREL ASMmBêŠÀ ¥CIOTABLELIB¯ˆúÀ ¥CPM85SYSLIB½'çÏÀ ¥DEF6821 LIBä SÀ¥DEF8253 LIBðêaÀ¥DEF8259ALIB÷ÝŒÀ¥EP2DEF LIBu À¥EXTRA85 LIBuÄÀ¥EXTRAOPSLIB#¢À¥FORMAT ASM")^À¥LABDEF LIBKBœÀ¥SBCDEF LIBS ,zÀ¥TIMEDRVRLIB`}­À¥TIMERDEFLIBxèÀ¥Z207DEF LIB{ªaÀ ¥Z207DRVRLIB–û42À"¥Z217DEF LIB‘:b€À#¥Z217DRVRLIBËYµ‘À%¥ZDPEDEF LIB$À&¥ZGDPDEF LIB: `HÀ'¥ZINT LIBGy/À)¥ZKEYBD LIBKø3À*¥ZMEMMAP LIBRs;À+¥ZMTR100 LIBY$éÀ,¥ZPORTS LIBg ÍíÀ.¥ÿÿÿÿÿÿÿÿÿÿ ;** 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  TITLE 'CP/M-85 BIOS (8085 CODE PORTION) 10 MAR 83' ;*** ; ; THIS IS THE 8085 CODED PORTION OF THE BIOS FOR CP/M-85. ; IT RESIDES IN THE FILE 'BIOS85.SYS'. ; TRUE EQU 1 FALSE EQU 0 ASM86 EQU FALSE REL0 EQU TRUE ;*** MACROS ; ;** EXTRA PSEUDO OPS FOR USE WITH MAC ; RB MACRO A DS A ENDM RW MACRO A DS 2*A ENDM ;*** EQUATES ; ;** Z-MACHINE MEMORY MAP UTILIZATION EQUATES ; BOOTORG EQU 0400H ;BOOT CODE LOAD ADDRESS BCODEL EQU 256+32 ;MAXIMUM BOOT CODE LENGTH BLDR88 EQU BOOTORG+BCODEL ;BIOS LOADER (8088 PORTION) BLDR88L EQU 64 ;MAXIMUM BIOS LOADER (8088) LENGTH B88STK EQU 2*1024 ;8088 STACK AREA B88DAT EQU B88STK ;MONITOR ROM DATA AREA START ADDR BIOS88 EQU 4*1024 ;WHERE 8088 CODE OF BIOS WILL RESIDE BLDRP0 EQU 16*1024 ;BIOS LOADER PAGE ZERO BIAS VALUE IF REL0 BLOADER EQU 0000H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF IF NOT REL0 BLOADER EQU 0100H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF BLDR85L EQU 8*128-BCODEL-BLDR88L ;MAXIMUM BIOS LOADER (8085) LENGTH BOOT85 EQU 0000H ;WHERE 8085 STARTS AFTER PROCESSOR SWAP SWISWAP EQU 0FEH ;SWI FOR SWAPPING PROCESSORS SWAPVEC EQU SWISWAP*4 ; VECTOR ADDRESS 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 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 ; 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 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 ; 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 101 ;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 03 ;DATE BDY EQU 10 BYR EQU 83 NDRIVES EQU 6 ;MAXIMUM NUMBER OF DRIVE TABLES ; ORG 0042H ;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 ;** 6821 PERIPHERAL INTERFACE ADAPTER EQUATES ; ; REGISTER DISPLACEMENTS PIADATA EQU 0 ;PERIPHERAL DATA REGISTER A PIADDRA EQU 0 ;DATA DIRECTION REGISTER A PIACTLA EQU 1 ;CONTROL REGISTER A PIADATB EQU 2 ;PERIPHERAL DATA REGISTER B PIADDRB EQU 2 ;DATA DIRECTION REGISTER B PIACTLB EQU 3 ;CONTROL REGISTER B ; CONTROL WORD FORMAT PIAC1 EQU 00000011B ;CONTROL OF CA1(CB1) INTERRUPT LINE PIAC10 EQU 00H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS DISABLED PIAC11 EQU 01H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS ENABLED PIAC12 EQU 02H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS DISABLED PIAC13 EQU 03H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS ENABLED PIADDAC EQU 00000100B ;DATA DIRECTION ACCESS CONTROL BIT ; 0=DATA DIRECTION REG , 1=PERIPHERAL DATA REG PIAC2 EQU 00111000B ;CONTROL OF CA2(CB2) ; INPUT MODES PIAC20 EQU 00H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS DISABLED PIAC21 EQU 08H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS ENABLED PIAC22 EQU 10H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS DISABLED PIAC23 EQU 18H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS ENABLED ; OUTPUT MODES PIAC24 EQU 20H ; 0 ON R(W) OPERATION , 1 ON ACTIVE CA1(CB1) PIAC25 EQU 28H ; 0 ON R(W) OPERATION , 1 ON E AFTER DESELECT PIAC26 EQU 30H ; RESET PIAC27 EQU 38H ; SET PIAIRQ2 EQU 01000000B ;IRQ FOR CA2(CB2) PIAIRQ1 EQU 10000000B ;IRQ FOR CA1(CB1) ;** EP2DEF -- EQUATES FOR ENHANCED PROGRAMMABLE COMMUNICATION ; INTERFACE CHIP 2661-2. ; ; PORT DISPLACEMENTS EPDATA EQU 0 ;DATA EPSTAT EQU 1 ;STATUS EPSYN EQU 1 ;SYN1/SYN2/DLE EPMODE EQU 2 ;MODE EPCMD EQU 3 ;COMMAND ; STATUS REGISTER EPTXR EQU 00000001B ;TRANSMITTER READY EPRXR EQU 00000010B ;RECEIVER READY EPTXE EQU 00000100B ;TRANSMITTER EMPTY EPDSC EQU 00000100B ;DATA SET CHANGE EPPE EQU 00001000B ;PARITY ERROR EPOE EQU 00010000B ;OVERRUN ERROR EPFE EQU 00100000B ;FRAME ERROR EPSD EQU 00100000B ;SYNC DETECTED EPDCD EQU 01000000B ;DATA CARRIER DETECT EPDSR EQU 10000000B ;DATA SET READY ; MODE REGISTER 1 EPMBRF EQU 00000011B ;MODE AND BAUDRATE FACTOR EPS1X EQU 000H ; SYNCHRONOUS 1X RATE EPA1X EQU 001H ; ASYNCHRONOUS 1X RATE EPA16X EQU 002H ; ASYNCHRONOUS 16X RATE EPA64X EQU 003H ; ASYNCHRONOUS 64X RATE EPCL EQU 00001100B ;CHARACTER LENGTH EPCL5 EQU 000H ; LENGTH 5 EPCL6 EQU 004H ; LENGTH 6 EPCL7 EQU 008H ; LENGTH 7 EPCL8 EQU 00CH ; LENGTH 8 EPPC EQU 00010000B ;PARITY CONTROL (0=DISABLED , 1=ENABLED) EPPT EQU 00100000B ;PARITY TYPE (0=ODD , 1=EVEN) EPASBL EQU 11000000B ;ASYNCHRONOUS STOP BIT LENGTH EPSB1 EQU 040H ; LENGTH 1 EPSB15 EQU 080H ; LENGTH 1.5 EPSB2 EQU 0C0H ; LENGTH 2 EPSTC EQU 01000000B ;SYNCHRONOUS TRANSPARENCY CONTROL ; (0=NORMAL , 1=TRANSPARENT) EPNSC EQU 10000000B ;NUMBER OF SYNC CHARACTERS ; (0=DOUBLE , 1=SINGLE) ; MODE REGISTER 2 EPBRS EQU 00001111B ;BAUD RATE SELECTION EPMR2U EQU 11110000B ;SEE TEXT ; COMMAND REGISTER EPTXEN EQU 00000001B ;TRANSMITTER ENABLE EPDTR EQU 00000010B ;DATA TERMINAL READY EPRXEN EQU 00000100B ;RECEIVER ENABLE EPSBRK EQU 00001000B ;SEND BREAK (ASYNC) EPSDLE EQU 00001000B ;SEND DLE (SYNC) EPRESE EQU 00010000B ;RESET STATUS ERRORS EPRTS EQU 00100000B ;REQUEST TO SEND EPOM EQU 11000000B ;OPERATING MODE EPNORM EQU 000H ; NORMAL EPOM1 EQU 040H ; MODE 1 EPOMLL EQU 080H ; LOCAL LOOP BACK EPOMRL EQU 0C0H ; REMOTE LOOP BACK ; BAUDRATE SELECTION VALUES EPB455 EQU 0 ;45.5 EPB050 EQU 1 ;50 EPB075 EQU 2 ;75 EPB110 EQU 3 ;110 EPB134 EQU 4 ;134.5 EPB150 EQU 5 ;150 EPB300 EQU 6 ;300 EPB600 EQU 7 ;600 EPB120 EQU 8 ;1200 EPB180 EQU 9 ;1800 EPB200 EQU 10 ;2000 EPB240 EQU 11 ;2400 EPB480 EQU 12 ;4800 EPB960 EQU 13 ;9600 EPB192 EQU 14 ;19200 EPB384 EQU 15 ;38400 ;** 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 ;** Z-MACHINE PORT ASSIGNMENTS ; ZVIDEO EQU 0D8H ;VIDEO 68A21 ZCRTC EQU 0DCH ;VIDEO 6845 CRTC ZLPEN EQU 0DEH ;LIGHT PEN COUNTER ZGDP EQU 0E0H ;GENERAL DATA PORT (68A21) ZTIMER EQU 0E4H ;8253 TIMER ZSERA EQU 0E8H ;SERIAL A ZSERB EQU 0ECH ;SERIAL B Z8259AS EQU 0F0H ;8259A SLAVE Z8259AM EQU 0F2H ;8259A MASTER ZKEYBD EQU 0F4H ;KEYBOARD ZTSTAT EQU 0FBH ;TIMER STATUS ZMCL EQU 0FCH ;MEMORY CONTROL LATCH ZHAL EQU 0FDH ;HI-ADDRESS LATCH ZPSP EQU 0FEH ;PROCESSOR SWAP PORT ZDIPSW EQU 0FFH ;DIP SWITCHES ; MEMORY CONTROL LATCH ZMCLMS EQU 00000011B ;MAP SELECT MASK ZMS0 EQU 000H ; MAP SELECT 0 ZMS1 EQU 001H ; MAP SELECT 1 ZMS2 EQU 002H ; MAP SELECT 2 ZMS3 EQU 003H ; MAP SELECT 3 ZMCLRM EQU 00001100B ;MONITOR ROM MAPPING ZRM0 EQU 000H ; POWER UP MODE - ROM EVERYWHERE ON READS ZRM1 EQU 004H ; ROM AT THE TOP 8K OF EVERY 64K ZRM2 EQU 008H ; ROM AT THE TOP 8K OF THE 8088'S ADDR SPACE ZRM3 EQU 00CH ; DISABLE ROM ZMCLP EQU 00110000B ;PARITY HANDLING ZMCLPZ EQU 00010000B ; 0=SET PARITY TO THE ZERO STATE ZMCLPK EQU 00100000B ; 0=DISABLE PARITY CHECKING CIRCUITRY ; HI-ADDRESS LATCH ZHAL85 EQU 11111111B ;8085 MASK ZHAL88 EQU 00001111B ;8088 MASK ; PROCESSOR SWAP PORT ZPSPPS EQU 10000000B ;PROCESSOR SELECT (0=8085 , 1=8088) ZPSPPS5 EQU 000H ; SELECT 8085 ZPSPPS8 EQU 080H ; SELECT 8088 ZPSPGIS EQU 00000010B ;GENERATE INTERRUPT ON SWAPPING ZPSPI88 EQU 00000001B ;8088 PROCESSES ALL INTERRUPTS ;** Z-100 GENERAL DATA PORT DEFINITIONS ; ; HARDWARE IS A 6821 ; ; PORT ASSIGNMENTS GDPDATA EQU ZGDP+PIADATA ;DATA PORT A GDPDDRA EQU ZGDP+PIADDRA ;DATA DIRECTION PORT A GDPCTLA EQU ZGDP+PIACTLA ;CONTROL PORT A GDPDATB EQU ZGDP+PIADATB ;DATA PORT B GDPDDRB EQU ZGDP+PIADDRB ;DATA DIRECTION PORT B GDPCTLB EQU ZGDP+PIACTLB ;CONTROL PORT B ; CONTROL PORT A ASSIGNMENTS GDPCAV EQU PIAC12+PIAC23+PIADDAC ;INITIALIZATION VALUE LPENSI EQU PIAIRQ1 ;CA1 = LIGHT PEN STROBE ; INTERRUPT ON 0->1 VSYNCI EQU PIAIRQ2 ;CA2 = VERTICAL SYNC ; INTERRUPT ON 0->1 ; DATA DIRECTION PORT A ASSIGNMENTS GDPDDAV EQU 10101111B ; DATA PORT A ASSIGNMENTS PPRTM10 EQU 00000011B ;PRINTER D1-D0 MASK PPRTSTB EQU 00000100B ;PRINTER STROBE (OUTPUT ACTIVE LOW) PPRTPRM EQU 00001000B ;PRINTER PRIME (OUTPUT ACTIVE LOW) VSYNC EQU 00010000B ;VERTICAL SYNC (INPUT ACTIVE HIGH) VSYNCE EQU 00100000B ;VERT SYNC TO CA2 (0=DISABLE, 1=ENABLE) LPEN EQU 01000000B ;LIGHT PEN SWITCH (INPUT ACTIVE HIGH) LPENSE EQU 10000000B ;LIGHT PEN STROBE TO CA1 (0=DISABLE, 1=ENABLE) ; CONTROL PORT B ASSIGNMENTS GDPCBV EQU PIAC12+PIAC20+PIADDAC ;INITIALIZATION VALUE PRTACKI EQU PIAIRQ1 ;CB1 = PRINTER ACKNOWLEDGE ; NO INTERRUPT ON 0->1 PRTBSYI EQU PIAIRQ2 ;CB2 = PRINTER BUSY ; NO INTERRUPT ON 1->0 ; DATA DIRECTION PORT B ASSIGNMENTS GDPBDDV EQU 11111100B ; DATA PORT B ASSIGNMENTS PPRTBSY EQU 00000001B ;PRINTER BUSY (INPUT ACTIVE HIGH) PPRTFLT EQU 00000010B ;PRINTER FAULT (INPUT ACTIVE LOW) PPRTM72 EQU 11111100B ;PRINTER D7-D2 MASK ;** Z-MACHINE KEYBOARD DEFINITIONS ; ; PORT ASSIGNMENTS ZKEYBDD EQU ZKEYBD+0 ;DATA ZKEYBDC EQU ZKEYBD+1 ;COMMAND ZKEYBDS EQU ZKEYBD+1 ;STATUS ; STATUS REGISTER ZKEYOBF EQU 00000001B ;OUTPUT BUFFER FULL ZKEYIBF EQU 00000010B ;INPUT BUFFER FULL ; COMMANDS ZKEYRES EQU 000H ;RESET ZKEYARO EQU 001H ;AUTOREPEAT ON ZKEYARF EQU 002H ;AUTOREPEAT OFF ZKEYKCO EQU 003H ;KEY CLICK ON ZKEYKCF EQU 004H ;KEY CLICK OFF ZKEYCF EQU 005H ;CLEAR FIFO ZKEYCLK EQU 006H ;CLICK ZKEYBEP EQU 007H ;BEEP ZKEYEK EQU 008H ;ENABLE KEYBOARD ZKEYDK EQU 009H ;DISABLE KEYBOARD ZKEYUDM EQU 00AH ;KEY UP/DOWN MODE ZKEYNSM EQU 00BH ;NORMAL SCAN MODE ZKEYEI EQU 00CH ;ENABLE INTERRUPTS ZKEYDI EQU 00DH ;DISABLE INTERRUPTS ; SPECIAL KEYS ZKEYBRK EQU 0AAH ;BREAK KEY ;** MISCELLANEOUS EQUATES IF REL0 ORG 0000H ELSE ORG 0100H ENDIF BIOSORG EQU $ CCPORG EQU BIOSORG-BDOSL-CCPL ;ORIGIN FOR CCP CCPAUTO EQU CCPORG ; ENTRY TO CCP FOR AUTO EXEC COMMAND CCPNORM EQU CCPORG+3 ; NORMAL ENTRY TO CCP CCPCMD EQU CCPORG+7 ; BUFFER FOR AUTO EXEC COMMAND AUTOCL EQU 40 ; MAX COMMAND LENGTH BDOSORG EQU BIOSORG-BDOSL ;ORIGIN FOR BDOS BDOSE EQU BDOSORG+6 ; ENTRY TO BDOS MIJMP EQU 0C3H ;8080 'JMP' INSTRUCTION PAGE ;** BIOS JUMP VECTORS ; JMP CBOOTE ;COLD BOOT ENTRY JMP WBOOTE ;WARM BOOT JMP CONSTE ;CONSOLE STATUS JMP CONINE ;CONSOLE INPUT JMP CONOUTE ;CONSOLE OUTPUT ENTRY JMP LSTOUTE ;LIST OUTPUT JMP PUNOUTE ;PUNCH OUTPUT JMP RDRINE ;READER INPUT JMP HOMEE ;HOME HEAD ENTRY JMP SETDSKE ;SET DISK ENTRY JMP SETTRKE ;SET TRACK ENTRY JMP SETSECE ;SET SECTOR ENTRY JMP SETDMAE ;SET DMA ENTRY JMP READE ;READ CP/M SECTOR ENTRY JMP WRITEE ;WRITE CP/M SECTOR ENTRY JMP LSTSTE ;LIST STATUS JMP SECTRNE ;SECTOR TRANSLATE ENTRY JMP FORMATE ;FORMAT JMP RDTRKE ;READ TRACK JMP WRTRKE ;WRITE TRACK JMP WPCE ;WRITE PROTECT CHECK JMP CLRBUFD ;CLEAR BUFFERS FOR DRIVE PAGE ;** BIOS HEADER TABLES ; DB BVERSN ;BIOS VERSION DB 00010101B ;DEFAULT I/O BYTE XMODE DB 0 ;MODE FLAGS DB (BIOSEND-BIOSORG+256)/256 ;BIOS SIZE IN PAGES DW BIOSEND ;ENDING ADDR OF BIOS + 1 DW 0 ;HARD ERROR COUNT (SINCE COLD BOOT) DW 0 ;SOFT ERROR COUNT (SINCE COLD BOOT) DB NDRIVES ;NUMBER OF DRIVES POSSIBLE IN THIS BIOS ; AUTO EXEC COMMAND BUFFERS ACBC DB 0 ;COLD BOOT AUTO COMMAND DS AUTOCL AWBC DB 0 ;WARM BOOT AUTO COMMAND DS AUTOCL ; CHARACTER I/O DEVICE TABLES XCRTTBL DS 0 ;CRT: TABLE DB 0 DW 0 DB 0,0 DB 0FFH,0 DB 0,0 DB 0,0 DB 0,0,0 DB 0,0,0,0,0,0,0,0 DW 0,0,0,0,0 IF $-XCRTTBL NE CIOTBLL %: CRT: CIO TABLE IS NOT CORRECT ENDIF TTYTBL DS 0 ;TTY: (SERIAL PORT A) DB ZSERA DW EPB480 DB 0,0 DB EPRXR,0 DB EPDCD+EPTXR,0 DB 0,0 DB 0,0,0 DB EPSB1+EPCL8+EPA16X DB 070H DB EPNORM+EPRTS+EPRESE+EPRXEN+EPDTR+EPTXEN DB 0,0,0,0,0 DW 0,0,0,0,0 IF $-TTYTBL NE CIOTBLL %: TTY: CIO TABLE IS NOT CORRECT ENDIF UL1TBL DS 0 ;UC1: , UR1: , UP1: , UL1: (SERIAL PORT B) DB ZSERB DW EPB300 DB 0,0 DB EPDSR+EPDCD+EPRXR,0 DB EPDSR+EPDCD+EPTXR,0 DB 0,0 DB 0,0,0 DB EPSB1+EPCL8+EPA16X DB 070H DB EPNORM+EPRTS+EPRESE+EPRXEN+EPDTR+EPTXEN DB 0,0,0,0,0 DW 0,0,0,0,0 IF $-UL1TBL NE CIOTBLL %: UL1: CIO TABLE IS NOT CORRECT ENDIF LPTTBL DS 0 ;LPT: (GENERAL DATA PORT PARALLEL PRINTER) DB 0 DW 0 DB 0,0 DB 0,0 DB PPRTBSY,PPRTBSY DB 0,0 DB 0,0,0 DB LPENSE+VSYNCE+PPRTPRM+PPRTSTB DB GDPDDAV DB GDPCAV DB 0 DB GDPBDDV DB GDPCBV DB 0,0 DW 0,0,0,0,0 IF $-LPTTBL NE CIOTBLL %: LPT: CIO TABLE IS NOT CORRECT ENDIF XDUMMY DS 0 ;DUMMY UNIT DB 0 DW 0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0,0 DB 0,0,0,0,0,0,0,0 DW 0,0,0,0,0 IF $-XDUMMY NE CIOTBLL %: DUMMY CIO TABLE IS NOT CORRECT ENDIF ; DISK PARAMETER ENTRY TABLES IF $-BIOSORG NE DPEBASE %: BIOS HEADER IS NOT CORRECT ENDIF DPE1A DS 0 ;PHYSICAL DRIVE 0 -- Z207 5 1/4" DW 0,0,0,0 DW DIRBUF DW DPB1A DW CSV1A DW ALV1A DB DPEZ207+DPEDD DB 0 DB 0 DB 0 DB DPEUNK DB DPEMO+FDFS6 DB 0 DB 0 IF $-DPE1A NE DPEL %: DPE1A IS INCORRECT LENGTH ENDIF DPE1B DS 0 ;PHYSICAL DRIVE 1 -- Z207 5 1/4" DW 0,0,0,0 DW DIRBUF DW DPB1B DW CSV1B DW ALV1B DB DPEZ207+DPEDD DB 1 DB 0 DB 0 DB DPEUNK DB DPEMO+FDFS6 DB 0 DB 0 IF $-DPE1B NE DPEL %: DPE1B IS INCORRECT LENGTH ENDIF DPE1C DS 0 ;PHYSICAL DRIVE 2 -- Z207 8" DW XLATE1,0,0,0 DW DIRBUF DW DPB1C DW CSV1C DW ALV1C DB DPEZ207+DPET0SD+DPEDD DB CONPC+CONDS8+0 DB 0 DB 0 DB DPEUNK DB FDFS6 DB DPEHLS DB 0 IF $-DPE1C NE DPEL %: DPE1C IS INCORRECT LENGTH ENDIF DPE1D DS 0 ;PHYSICAL DRIVE 3 -- Z207 8" DW XLATE2,0,0,0 DW DIRBUF DW DPB1D DW CSV1D DW ALV1D DB DPEZ207+DPET0SD+DPEDD DB CONPC+CONDS8+1 DB 0 DB 0 DB DPEUNK DB FDFS6 DB DPEHLS DB 0 IF $-DPE1D NE DPEL %: DPE1D IS INCORRECT LENGTH ENDIF DPE2A DS 0 ;Z217 -- PARTITION 1 DW 0,0,0,0 DW DIRBUF DW DPB2A DW 0 DW ALV2A DB DPEZ217+DPEPRIM DB 0 DB WIRPS DB 0 DB 0 DB 0 DB 0 DB 0 IF $-DPE2A NE DPEL %: DPE2A IS INCORRECT LENGTH ENDIF DPE2B DS 0 ;Z217 -- PARTITION 2 DW 0,0,0,0 DW DIRBUF DW DPB2B DW 0 DW ALV2B DB DPEZ217 DB 0 DB WIRPS DB 0 DB 0 DB 0 DB 0 DB 0 IF $-DPE2B NE DPEL %: DPE2B IS INCORRECT LENGTH ENDIF PAGE ;** COLD BOOT ENTRY ; ; ENTRY: NONE ; EXIT: (C)=DEFAULT DRIVE # ('A:') ; VIA: AUTO ON ; AUTO OFF ; USES: ALL ; CBOOTE: LXI SP,STACK ;INIT STACK POINTER MVI A,(CBOOT-CBOOT)/3 ;SET FUNCTION # IN SPECIAL LOCATION STA BLDRP0+COMFUNC ; SINCE COLD BOOTING FROM BIOS LOADER CALL SWAP881 ;8088 CODE DOES MOST OF THE INITIALIZATION MVI C,0 ;DEFAULT DRIVE IS 'A:' LXI D,ACBC ;POINTER TO AUTO COMMAND BUFFER JMP WB1 ;MERGE WITH WARM BOOT CODE ;** WARM BOOT ENTRY ; ; ENTRY: NONE ; EXIT: (C)=DEFAULT DRIVE # ; VIA: AUTO ON ; AUTO OFF ; USES: ALL ; WBOOTE: LXI SP,STACK ;INIT STACK POINTER MVI A,(WBOOT-CBOOT)/3 ;SET FUNCTION # CALL SWAP88 ;8088 CODES DOES MOST OF WARM BOOT LDA DFTDRV ;GET DEFAULT DRIVE MOV C,A LXI D,AWBC ;POINTER TO AUTO COMMAND BUFFER WB1: MVI A,MIJMP ;SET PAGE ZERO VALUES LXI H,BIOSORG+3 STA BOOT SHLD BOOT+1 LXI H,BDOSE STA BDOS SHLD BDOS+1 LDAX D ;CHECK IF AUTO SHOULD BE DONE ORA A JZ CCPNORM ; BR IF NO LDA CCPCMD-1 ;FILL COMMAND BUFFER WITH NULLS LXI H,CCPCMD+1 WB2: MVI M,0 INX H DCR A JNZ WB2 LDAX D ;MOVE AUTO COMMAND TO CCP MOV B,A ; COMMAND BUFFER INR B LXI H,CCPCMD WB3: LDAX D MOV M,A INX D INX H DCR B JNZ WB3 JMP CCPAUTO ;BR TO CCP ENTRY FOR AUTO ;** CONSOLE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (A)=STATUS ; 0=NO CHARACTER AVAILABLE , 0FFH=CHARACTER AVAILABLE ; USES: ALL ; CONSTE: MVI A,(CONST-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** CONSOLE INPUT ENTRY ; ; ENTRY: NONE ; EXIT: (A)=CHARACTER FROM CONSOLE ; USES: ALL ; CONINE: MVI A,(CONIN-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** CONSOLE OUTPUT ENTRY ; ; ENTRY: (C)=CHARACTER ; EXIT: NONE ; USES: ALL CONOUTE: MVI A,(CONOUT-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** LIST OUTPUT ENTRY ; ; ENTRY: (C)=CHARACTER ; EXIT: NONE ; USES: ALL ; LSTOUTE: MVI A,(LSTOUT-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** PUNCH OUTPUT ENTRY ; ; ENTRY: (C)=CHARACTER ; EXIT: NONE ; USES: ALL ; PUNOUTE: MVI A,(PUNOUT-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** READER INPUT ENTRY ; ; ENTRY: NONE ; EXIT: (A)=CHARACTER READ FROM READER ; USES: ALL ; RDRINE: MVI A,(RDRIN-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** SET DISK DRIVE ENTRY ; ; ENTRY: (C)=DRIVE NUMBER ; (E)=LSB INDICATES 1ST TIME SELECTION ; 0=1ST TIME , 1=SUBSEQUENT TIMES ; EXIT: (HL)=ADDRESS OF DPE FOR DRIVE ; =0 IF ERROR ; USES: ALL ; SETDSKE: LXI H,XLATES ;ADDRESS OF XLATE TABLE ADDRESSES MVI A,(SETDSK-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** HOME HEAD ENTRY ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL HOMEE: MVI A,(HOME-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** SET TRACK NUMBER ENTRY ; ; ENTRY: (BC)=TRACK NUMBER ; EXIT: NONE ; USES: ALL ; SETTRKE: MVI A,(SETTRK-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** SET SECTOR NUMMBER ENTRY ; ; ENTRY: (BC)=SECTOR NUMBER ; EXIT: NONE ; USES: ALL ; SETSECE: MVI A,(SETSEC-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** SET DMA ADDRESS ; ; ENTRY: (BC)=ADDRESS ; EXIT: NONE ; USES: ALL ; SETDMAE: MVI A,(SDMA-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** READ CP/M SECTOR ENTRY ; ; ENTRY: NONE ; EXIT: (A)=ERROR CODE ; 0=NO ERROR , 1=ERROR ; USES: ALL ; READE: MVI A,(BREAD-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** WRITE CP/M SECTOR ENTRY ; ; ENTRY: (C)=TYPE OF WRITE ; 0=NORMAL WRITE ; 1=WRITE TO A DIRECTORY SECTOR ; 2=1ST WRITE TO A SECTOR IN AN UNALLOCATED BLOCK ; EXIT: (A)=ERROR CODE ; 0=NO ERROR , 1=ERROR ; USES: ALL ; WRITEE: MVI A,(BWRITE-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** CHECK LIST DEVICE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (A)=STATUS ; 0=NOT READY , 0FFH=READY ; USES: ALL ; LSTSTE: MVI A,(BLSTST-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** SECTOR TRANSLATE ENTRY ; ; ENTRY: (BC)=SECTOR NUMBER ; (DE)=POINTER TO TRANSLATE TABLE ; EXIT: (HL)=TRANSLATED SECTOR NUMBER ; USES: ALL ; SECTRNE: MVI A,(BSECTRN-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** FORMAT ENTRY ; ; ENTRY: (C)=VERIFY FLAG (0=NO , 1=YES) ; EXIT: (A)=STATUS BYTE ; USES: ALL ; FORMATE: MVI A,(BFMT-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** READ TRACK ENTRY ; ; ENTRY: NONE ; EXIT: (A)=ERROR STATUS ; USES: ALL ; RDTRKE: MVI A,(BRDTRK-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** WRITE TRACK ENTRY ; ; ENTRY: NONE ; EXIT: (A)=ERROR STATUS ; USES: ALL ; WRTRKE: MVI A,(BWRTRK-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** WRITE PROTECT CHECK ; ; ENTRY: NONE ; EXIT: (A)=STATUS (0=R/W , 1=R/O) ; USES: ALL ; WPCE: MVI A,(BWPC-CBOOT)/3 ;SET FUNCTION # JMP SWAP88 ;RETURN VIA 'SWAP88' ;** CLEAR BUFFERS FOR DRIVE ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; CLRBUFD: MVI A,(BCBD-CBOOT)/3 ;SET FUNCTION # ; JMP SWAP88 ;RETURN VIA 'SWAP88' IF $ NE SWAP88 %: SWAP88 MUST BE NEXT ENDIF PAGE ;* SWAP88 -- SWAP TO 8088 PROCESSOR ; ; ENTRY: (A)=FUNCTION # ; EXIT: (A),(HL)=VALUES PASSED BACK IN COMMUNICATION REGION ; USES: ALL ; SWAP88: STA COMFUNC ;SAVE FUNCTION # IN COM REGION SHLD COMRHL ;STORE (HL) IN COM REGION MOV H,B ;STORE (BC) IN COM REGION MOV L,C SHLD COMRBC XCHG ;STORE (DE) IN COM REGION SHLD COMRDE SWAP881: DI ;INSURE INTERRUPTS IN 8085 ARE OFF MVI A,ZPSPPS5 ;TURN OFF 8088'S PROCESSING OF INT'S OUT ZPSP MVI A,ZPSPPS8 ;8088 PROCESSOR GETTING CONTROL STA COMWHO OUT ZPSP ;SWAP PROCESSOR TO 8088 LDA COMRA ;RETRIEVE (A) LHLD COMRHL ;RETRIEVE (HL) RET PAGE ;** DATA STORAGE ; XLATES DS 0 ;XLATE TABLE ADDRESSES DW 0 ; NO XLATE DW XLATE1 ; 8" SINGLE DENSITY DW XLATE2 ; 8" DOUBLE DENSITY XLATE1 DS 0 ;8" SINGLE DENSITY SECTOR TRANSLATE TABLE DB 1,7,13,19,25 DB 5,11,17,23 DB 3,9,15,21 DB 2,8,14,20,26 DB 6,12,18,24 DB 4,10,16,22 XLATE2 DS 0 ;8" DOUBLE DENSITY SECTOR TRANSLATE TABLE DB 1,2,19,20,37,38 DB 3,4,21,22,39,40 DB 5,6,23,24,41,42 DB 7,8,25,26,43,44 DB 9,10,27,28,45,46 DB 11,12,29,30,47,48 DB 13,14,31,32,49,50 DB 15,16,33,34,51,52 DB 17,18,35,36 PATCH DS 64 ;PATCH AREA DIRBUF DS 128 DPB1A DS DPBL CSV1A DS 64 ALV1A DS 77 DPB1B DS DPBL CSV1B DS 64 ALV1B DS 77 DPB1C DS DPBL CSV1C DS 64 ALV1C DS 77 DPB1D DS DPBL CSV1D DS 64 ALV1D DS 77 DPB2A DS DPBL ALV2A DS 256 DPB2B DS DPBL ALV2B DS 256 DS 8 ;STACK AREA STACK DS 0 BIOSEND EQU $-1 END  77 DP TITLE 'CP/M-85 BIOS (8088 CODE PORTION) 10 MAR 83' ;*** ; ; THIS IS THE 8088 CODED PORTION OF THE BIOS FOR CP/M-85. ; IT RESIDES IN THE FILE 'BIOS88.SYS'. ; FALSE EQU 0 TRUE EQU NOT FALSE ASM86 EQU TRUE EXPER EQU FALSE REL0 EQU 0 WAIT EQU TRUE ;*** EQUATES ; INCLUDE ZMEMMAP.LIB INCLUDE ASCII.LIB INCLUDE DEF6821.LIB INCLUDE DEF8253.LIB INCLUDE DEF8259A.LIB INCLUDE EP2DEF.LIB INCLUDE SBCDEF.LIB INCLUDE TIMERDEF.LIB INCLUDE Z207DEF.LIB INCLUDE Z217DEF.LIB INCLUDE ZINT.LIB INCLUDE ZMTR100.LIB INCLUDE ZPORTS.LIB INCLUDE ZGDPDEF.LIB INCLUDE ZKEYBD.LIB ;** MISCELLANEOUS EQUATES ; INCLUDE EXTRAOPS.LIB ;* DEVICE DRIVER ENTRY JUMP VECTOR OFFSETS ; DDSEL EQU 0 ;SELECT DDRDT EQU 3 ;READ TRACK DDWRT EQU 6 ;WRITE TRACK DDMNT EQU 9 ;MOUNT DDFMT EQU 12 ;FORMAT DDWPC EQU 15 ;WRITE PROTECT CHECK ;* DISK OPERATIONS IN PROGRESS FLAGS ; DSKOPS EQU 00000001B ;1ST TIME AFTER WARM BOOT SELECTION DSKOPR EQU 00000010B ;READ DSKOPW EQU 00000100B ;WRITE DSKOPRA EQU 00001000B ;READ ADDRESS HEADER DSKOPF EQU 00010000B ;FORMAT DSKOPWP EQU 00100000B ;WRITE PROTECT CHECK DSKOPI EQU 01000000B ;INIT DSKOPRD EQU 10000000B ;READY ;* DISK BUFFER HANDLING DEFINITIONS ; DSEG BUFCNT EQU 4 ;NUMBER OF BUFFERS ; BUFFER HEADER INFO ORG 0 BUFHDR RB 0 BUFFWD RW 1 ;FORWARD CHAIN POINTER BUFBAK RW 1 ;BACKWARD CHAIN POINTER BUFDRV RB 1 ;DRIVE # BUFPDRV RB 1 ;MAPPED DRIVE # (PHYSICAL TABLE #) BUFDPE RW 1 ;ADDRESS OF DPE BUFTRK RW 1 ;TRACK # BUFWRF RB 1 ;BUFFER DIRTY FLAG BUFSECF RW 1 ;ADDRESS OF DIRTY SECTOR FLAGS BUFERR RB 1 ;TRACK ERROR FLAG BUFERRF RW 1 ;ADDRESS OF SECTOR ERROR FLAGS BUFBUF RW 1 ;ADDRESS OF BUFFER AREA BUFHDRL EQU OFFSET $ - OFFSET BUFHDR ;LENGTH OF BUFFER HEADER INFO EJECT ;*** EQUATES FOR INFO IN EXTRA SEGMENT ; ESEG BIAS EQU 0 INCLUDE CPM85SYS.LIB INCLUDE CIOTABLE.LIB INCLUDE BIOSDEF.LIB INCLUDE ZDPEDEF.LIB INCLUDE LABDEF.LIB EJECT ;*** COLD BOOT ENTRY ; CSEG ORG BIOS88 CBOOTE: CLI ;INSURE I'M NOT DISTURBED ; INITIALIZE PARITY GENERATION PUSH DS PUSH ES MOV AL,ZMCLPZ+ZRM2 ;TURN OFF PARITY CHECKING OUT ZMCL,AL OUT 098H,AL OUT 099H,AL OUT 09AH,AL OUT 09BH,AL OUT 09CH,AL OUT 09DH,AL OUT 09EH,AL OUT 09FH,AL XOR AX,AX ;START AT SEGMENT 0 MEMIL: MOV DS,AX ;SET UP SEGMENT REGISTERS MOV ES,AX MOV AX,.0 ;GET FIRST WORD MOV BX,AX ;SAVE A COPY INC AX ;BUMP VALUE INC WORD PTR .0 ;BUMP MEMORY CMP AX,.0 ;Q. ARE THEY THE SAME JNE MEMIC ; BR IF NOT MOV .0,BX ;RESTORE VALUE XOR SI,SI ;SET UP REGS FOR MOVE XOR DI,DI MOV CX,08000H ;GET NUMBER OF WORDS TO MOVE REP MOVSW ;MOVE WORDS ONTO THEMSELVES MEMIC: MOV AX,DS ;POINT TO NEXT SEGMENT ADD AX,01000H JNZ MEMIL ; LOOP IF NO WRAP AROUND POP ES POP DS MOV AL,ZMCLPK+ZMCLPZ+ZRM2 ;TURN ON PARITY CHECKING OUT ZMCL,AL OUT 098H,AL OUT 099H,AL OUT 09AH,AL OUT 09BH,AL OUT 09CH,AL OUT 09DH,AL OUT 09EH,AL OUT 09FH,AL ; INITIALIZE ALL VECTORS (EXCEPT WHERE MONITOR DATA SEGMENT INFO ; IS) TO POINT TO WILD INTERRUPT HANDLER MOV BX,OFFSET INTWILD ;INITIALIZE VECTORS FOR WILD INTERRUPT MOV .0,BX MOV .2,CS MOV SI,0 MOV DI,4 MOV CX,(256-2)*4/2 CLD REP MOVSW ; INITIALIZE SOFTWARE INTERRUPT VECTORS MOV BX,OFFSET INTDIV0 ;DIVIDE BY ZERO MOV .0,BX MOV .2,CS MOV BX,OFFSET INTSWAP ;SWAP PROCESSORS MOV .SWAPVEC,BX MOV .SWAPVEC+2,CS ; INITIALIZE HARDWARE INTERRUPT VECTORS LEA SI,HINTVO MOV DI,ZINTMT*4 MOV CX,18 CLD INHV: MOVSW ADD DI,2 LOOP INHV ; INITIALIZE MASTER 8259A MOV AL,ICW1OP+ICW1LT+ICW1ADI+ICW1I4 OUT Z8259AM+ICW1,AL ;LEVEL TRIGGERED, ADI OF 4 MOV AL,ZINTMT OUT Z8259AM+ICW2,AL ;BASE TRAP VECTOR MOV AL,1 SHL ZINTSLV OUT Z8259AM+ICW3,AL ;INDICATE SLAVE IR LINE MOV AL,ICW4SFN+ICW4UPM OUT Z8259AM+ICW4,AL ;SPECIAL FULLY NESTED, 8086 PROCESSOR MOV AL,0FFH-(1 SHL ZINTKD)-(1 SHL ZINTTIM)-(1 SHL ZINTEI) OUT Z8259AM+OCW1,AL ;ENABLE ONLY DESIRED IR LINES ; INITIALIZE SLAVE 8259A MOV AL,ICW1OP+ICW1LT+ICW1ADI+ICW1I4 OUT Z8259AS+ICW1,AL ;LEVEL TRIGGERED, ADI OF 4 MOV AL,ZINTST OUT Z8259AS+ICW2,AL ;BASE TRAP VECTOR MOV AL,ZINTSLV OUT Z8259AS+ICW3,AL ;SLAVE ID MOV AL,ICW4UPM OUT Z8259AS+ICW4,AL ;8086 PROCESSOR MOV AL,0FFH OUT Z8259AS+OCW1,AL ;DISABLE ALL IR LINES ; MOVE ROM MONITOR DATA AREA TO BANK 0 PUSH DS MOV SI,0 ;GET SOURCE ADDRESS FOR MOVE MOV AX,.MTRDSEG MOV OMDSEG,AX MOV DS,AX MOV DI,B88DAT ;GET DESTINATION ADDRESS FOR MOVE MOV CX,MTRDSZ ;GET BYTE COUNT CMP CX,BIOS88-B88DAT ;Q. LARGER THAN ALLOCATED SPACE JBE MVMTRDA ; BR IF NOT POP DS ;MEMORY MAP LAYOUT ONLY ALLOWS LEA SI,MTRMSG ; A MAXIMUM MONITOR DATA AREA CALL PMSG ; SIZE JMP SYSHLT MVMTRDA: CLD ;SET FORWARD DIRECTION REP MOVSB ;DO MOVE MOV AX,B88DAT/16 ;POINT TO NEW LOCATION OF DATA AREA MOV DS,AX MOV MTRDXMTC,MTRSKBD ;INITIALIZE KEYBOARD HANDLER MOV MTRDXMTC+2,MTRSEG ; TO USE MY QUEUE MOV MTRSXMTC,OFFSET PUTKEY MOV MTRSXMTC+2,CS POP DS MOV WORD PTR .MTRDSEG,B88DAT/16 ;UPDATE MONITOR DSEG SLOT ; NOW SETUP CP/M-85 SYSTEM IN BANK 1 MOV AX,64/16*1024 ;FROM NOW ON EXTRA SEGMENT MOV ES,AX ; WILL POINT TO BANK 1 MOV BANK1,AX ;SAVE VALUE MOV AL,1 ;SET HIGH ADDR LATCH TO BANK 1 FOR 8085 OUT ZHAL,AL MOV SI,BLDRP0 ;MOVE PAGE ZERO MOV DI,0 MOV CX,256/2 CLD REP MOVSW MOV SI,BBIOS ;MOVE CCP, BDOS, & BIOS SUB SI,CCPL+BDOSL MOV CCPORG1,SI MOV DI,SI MOV CX,SI NEG CX INC CX SHR CX,1 CLD REP MOVSW MOV BX,BBIOS ;SET DEFAULT I/O BYTE MOV AL,DEFIOB[BX] MOV IOBYTE,AL ; MOVE CP/M CCP & BDOS AGAINST TOP OF BANK 0 ; TO PROVIDE MORE ROOM FOR DISK BUFFERS MOV SI,CCPORG1 ADD SI,CCPL+BDOSL-1 MOV DI,0FFFFH MOV CX,CCPL+BDOSL PUSH ES MOV AX,DS MOV ES,AX STD REP MOVSB POP ES INC DI MOV CCPORG0,DI ; CALL ALTCHR ;HANDLE ALTERNATE CHARACTER FONTS ; INITIALIZE CHARACTER I/O PORTS CALL INCRT ;CRT: CALL INSERA ;SERIAL PORT A CALL INSERB ;SERIAL PORT B CALL INPPRT ;LIGHTPEN, VSYNC , & PARALLEL PRINTER CALL INDUMMY ;DUMMY I/O ; CALL INTIM ;INITIALIZE TIMER MOV COMWHO,ZPSPPS8 ;INDICATE WHICH PROCESSOR HAS CONTROL STI ;ALLOW INTERRUPTS NOW ; INITIALIZE HOST BUFFERING SCHEME CMP CCPORG0,B88END ;Q. ENOUGH MEMORY JNB CBINBUF ; BR IF YES LEA SI,BUFMSG ; OTHERWISE PRINT ERROR MESSAGE CALL PMSG JMP SYSHLT CBINBUF: CALL INBUF ;INIT BUFFERING ; INITIALIZE LOGICAL DRIVE TO PHYSICAL DRIVE MAP PUSH ES MOV ES,.MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA MOV AL,ES: MTRBI ;GET BOOT DEVICE INDEX # CMP ES: MTRBI,2 ;Q. Z217 BOOTED POP ES JNE CBINDRV1 ; BR IF NOT CALL IN217 CALL IN207 JMPS PSIGNON CBINDRV1: CALL IN207 CALL IN217 ; PRINT SIGNON MESSAGE PSIGNON: LEA SI,SIGNON CALL PMSG ; INT SWISWAP ;SWAP TO 8085 PROCESSOR EJECT ;** WARM BOOT ENTRY ; ; MOVE 'CCP' AND 'BDOS' FROM BANK 0 TO BANK 1. ; THIS REPLACES THE NEED TO READ THE DISK ON WARM BOOT. ; WBOOTE: CALL CLRBUFA ;CLEAR ALL HOST BUFFERS MOV SI,CCPORG0 ;SOURCE ADDR OF CCP & BDOS IN BANK 0 MOV DI,CCPORG1 ;DESTINATION ADDR IN BANK 1 MOV CX,(CCPL+BDOSL)/2 ;WORD COUNT CLD ;SET DIRECTION FORWARD REP MOVSW RET ;** CONSOLE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (AL),'COMRA'=STATUS ; 0=NO CHARACTER AVAILABLE , 0FFH=CHARACTER AVAILABLE ; USES: ALL ; CONSTE: MOV AL,IOBYTE ;GET IOBYTE VALUE SHL AL,1 ;ADJUST VALUE CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW CRTTBL DW 0 DW SERBTBL TEST BX,BX ;Q. SPECIAL CASE BAT: JNZ CONSTE1 ; BR IF NOT MOV AL,IOBYTE ;GET IOBYTE VALUE SHR AL,1 ;ADJUST VALUE CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW DUMMYTBL DW SERBTBL DW CRTTBL CONSTE1: CALL ISCIO ;CALL CIO HANDLER MOV COMRA,AL ;PUT STATUS IN COM REGION RET ;** CONSOLE INPUT ENTRY ; ; ENTRY: NONE ; EXIT: (AL),'COMRA'=CHARACTER READ FROM CONSOLE ; USES: ALL ; CONINE: MOV AL,IOBYTE ;GET IOBYTE VALUE SHL AL,1 ;ADJUST VALUE CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW CRTTBL DW 0 DW SERBTBL TEST BX,BX ;Q. SPECIAL CASE BAT: JZ RDRINE ; BR IF YES CALL IDCIO ;CALL CIO HANDLER MOV COMRA,AL ;PUT CHARACTER IN COM REGION RET ;** CONSOLE OUTPUT ENTRY ; ; ENTRY: 'COMRC'=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; CONOUTE: MOV AL,IOBYTE ;GET IOBYTE VALUE SHL AL,1 ;ADJUST VALUE MOV CL,COMRC ;GET CHARACTER CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW CRTTBL DW 0 DW SERBTBL TEST BX,BX ;Q. SPECIAL CASE BAT: JZ LSTOUTE ; BR IF YES JMP ODCIO ;RETURN VIA CIO HANDLER ;** LIST OUTPUT ENTRY ; ; ENTRY: 'COMRC'=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; LSTOUTE: MOV AL,IOBYTE ;GET IOBYTE VALUE MOV CL,5 ;ADJUST VALUE SHR AL,CL MOV CL,COMRC ;GET CHARACTER CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW CRTTBL DW PPRTTBL DW SERBTBL JMP ODCIO ;RETURN VIA CIO HANDLER ;** PUNCH OUTPUT ENTRY ; ; ENTRY: 'COMRC'=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; PUNOUTE: MOV AL,IOBYTE ;GET IOBYTE VALUE MOV CL,3 ;ADJUST VALUE SHR AL,CL MOV CL,COMRC ;GET CHARACTER CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW DUMMYTBL DW SERBTBL DW CRTTBL JMP ODCIO ;RETURN VIA CIO HANDLER ;** READER INPUT ENTRY ; ; ENTRY: NONE ; EXIT: (AL),'COMRA'=CHARACTER READ ; USES: ALL ; RDRINE: MOV AL,IOBYTE ;GET IOBYTE VALUE SHR AL,1 ;ADJUST VALUE CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW DUMMYTBL DW SERBTBL DW CRTTBL CALL IDCIO ;CALL CIO HANDLER MOV COMRA,AL ;PUT CHARACTER IN COM REGION RET ;** HOME HEAD ENTRY ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; HOMEE: CALL CHKDBD ;Q. ANY DIRTY BUFFERS FOR REQ DRIVE TEST AL,AL JNZ HOMEE1 ; BR IF YES CALL CLRBUFD ;FORCE PHYSICAL I/O HOMEE1: MOV AX,0 ;SET REQUESTED TRACK # = 0 JMP SETTRKE1 ;JOIN SET TRACK CODE ;** SET DISK DRIVE ENTRY ; ; ENTRY: 'COMRC'=REQUESTED DRIVE ; 'COMRE'=LSB INDICATES 1ST TIME SINCE WARM BOOT SELECT ; 0=1ST TIME , 1=SUBSEQUENT TIMES ; 'COMRHL'=ADDRESS OF XLATE TABLE ADDRESSES ; EXIT: 'COMRHL'=RESULTS ; 0=ERROR , NOT 0=NO ERROR ; USES: ALL ; SETDSKE: MOV AL,COMRC ;GET REQUESTED DRIVE # MOV REQDRV,AL ;SAVE IT MOV BX,BBIOS ;CHECK IF IN RANGE CMP AL,NDISKS[BX] JAE SETDSKE5 ; BR IF NOT CBW ;CONVERT LOGICAL DRIVE # TO MOV BX,AX ; PHYSICAL DRIVE # MOV AL,BDMAP[BX] MOV PHYDRV,AL MOV BL,DPEL ;COMPUTE ADDRESS OF DPE MUL BL ADD AX,OFFSET DPEBASE ADD AX,BBIOS MOV PHYDPE,AX ;SAVE IT TEST COMRE,1 ;CHECK IF 1ST LOGIN JNZ SETDSKE9 ; BR IF NOT CALL CLRBUFD ;CLEAR HOST BUFFERS FOR THIS DRIVE MOV PREREAD,0 ;INDICATE DON'T DO PREREAD CALL SETUP ;GET A BUFFER TO USE CMP BUFERR[BX],0 ;Q. ABORT JNE SETDSKEA ; BR IF YES MOV AX,COMRHL ;GET ADDRESS OF XLATE TABLE ADDRESSES MOV XLATES,AX MOV AL,DDSEL ;CALL DEVICE DRIVER TO DO SELECT CALL DRVR CALL CLRBUFD ;GIVE BACK BUFFER CMP PHYDPE,0 ;Q. ERROR JNE SETDSKE9 ; BR IF NO ERROR RETURN BY DRIVER ; ERROR DURING SETDSK SETDSKE5: MOV AL,REQDRV ;CHECK IF REQUESTED DRIVE CMP AL,DFTDRV ; WAS TO BE DEFAULT DRIVE JNE SETDSKE6 ; BR IF NOT MOV DFTDRV,0 ;FORCE DEFAULT DRIVE TO 'A:' SETDSKE6: MOV PHYDPE,0 ;INDICATE ERROR (ADDR OF DPE = 0) ; RETURN ADDRESS OF DPE TO CALLER SETDSKE9: MOV AX,PHYDPE MOV COMRHL,AX RET ; ERROR DURING SETUP SETDSKEA: CALL CLRBUFD ;GIVE BACK BUFFER JMPS SETDSKE5 ;** SET TRACK ENTRY ; ; ENTRY: 'COMRBC'=TRACK # ; EXIT: NONE ; USES: ALL ; SETTRKE: MOV AX,COMRBC ;GET TRACK # SETTRKE1: MOV REQTRK,AX ;SAVE AS REQUESTED CP/M TRACK # RET ;** SET SECTOR ENTRY ; ; ENTRY: 'COMRBC'=SECTOR # (IN RANGE 1 TO SPT) ; EXIT: NONE ; USES: ALL ; ; *** NOTE *** ; IT IS ASSUMED ON ENTRY THAT THE SECTOR NUMBER IS IN THE RANGE 1 TO ; 'CP/M SECTORS PER TRACK'. THEREFORE, ONLY THE VALUE PASSED ; IN REGISTER C IS USED. ; INTERNALLY THE BIOS WANTS SECTOR NUMBERS IN THE RANGE ; 0 TO SPT-1. THEREFORE, BEFORE SAVING THE SECTOR NUMBER, ; IT IS DECREMENTED. ; SETSECE: MOV AL,COMRC ;GET SECTOR # DEC AL ;PUT INTO RANGE 0 TO SPT-1 XOR AH,AH ;ZERO HIGH ORDER BYTE MOV REQSEC,AX ;SAVE AS REQUESTED CP/M SECTOR # RET ;** SET DMA ENTRY ; ; ENTRY: 'COMRBC'=DMA POINTER ; EXIT: NONE ; USES: ALL ; SETDMAE: MOV AX,COMRBC ;GET DMA POINTER MOV DMAPTR,AX ;SAVE AS DMA POINTER RET ;** READ CP/M SECTOR ENTRY ; ; ENTRY: NONE ; EXIT: 'COMRA'=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; READE: MOV PREREAD,1 ;DO PREREAD CALL SETUP ;CALL R/W COMMON SETUP ROUTINE CMP BUFERR[BX],0 ;Q. ERROR DURING SETUP JNE READE1 ; BR IF YES ; HOST BUFFER CONTAINS REQUESTED CP/M SECTOR. ; COPY IT TO USER BUFFER. MOV SI,BUFBUF[BX] ;COMPUTE START OF REQ CP/M SECTOR ADD SI,AX ; IN HOST BUFFER MOV DI,DMAPTR ;GET DMA POINTER REP MOVSW ;MOVE DATA FROM HOST TO USER BUFFER ; CALL CPSEC ;INDICATE ERROR STATUS OR DSKOP,DSKOPR CALL ABTIGN AND DSKOP,NOT DSKOPR READE1: MOV AL,BUFERR[BX] MOV COMRA,AL RET ;** WRITE CP/M SECTOR ENTRY ; ; ENTRY: 'COMRC'=TYPE OF WRITE ; 0=NORMAL WRITE ; 1=WRITE TO A DIRECTORY SECTOR ; 2=1ST WRITE TO A SECTOR IN AN UNALLOCATED BLOCK ; EXIT: 'COMRA'=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; WRITEE: MOV PREREAD,1 ;DO PREREAD CALL SETUP ;CALL R/W COMMON SETUP ROUTINE CMP BUFERR[BX],0 ;Q. ERROR DURING SETUP JNE WRITEE5 ; BR IF YES ; HOST BUFFER CONTAINS TRACK FOR REQUESTED CP/M SECTOR. ; COPY THE SECTOR FROM USER BUFFER TO HOST BUFFER. MOV SI,DMAPTR ;GET DMA POINTER MOV DI,BUFBUF[BX] ;COMPUTE START OF REQ CP/M SECTOR ADD DI,AX ; IN HOST BUFFER CALL EXDSES ;EXCHANGE DS AND ES REP MOVSW ;MOVE DATA FROM USER TO HOST BUFFER CALL EXDSES ;RESTORE DS AND ES ; MARK PHYSICAL SECTOR AND HOST WRITE BUFFER AS DIRTY CALL CPSEC ;MARK WHICH HOST WRITE BUFFER MOV DI,BUFSECF[BX] ADD DI,PHYSEC MOV BYTE PTR [DI],1 ; PHYSICAL SECTOR IS DIRTY MOV BUFWRF[BX],1 ;INDICATE HOST BUFFER IS DIRTY ; CHECK FOR ABORT IF ERROR ON PREREAD CALL CPSEC OR DSKOP,DSKOPR CALL ABTIGN AND DSKOP,NOT DSKOPR CMP BUFERR[BX],0 JNE WRITEE5 ; IF TYPE OF WRITE IS A DIRECTORY WRITE, ; THEN FLUSH ALL HOST BUFFERS FOR REQUESTED DRIVE. MOV AL,COMRC ;CHECK TYPE OF WRITE CMP AL,BWRDIR JNE WRITEE5 ; BR IF NOT DIRECTORY WRITE CALL FLUSHD ;FLUSH BUFFERS JMPS WRITEE6 ; WRITEE5: MOV AL,BUFERR[BX] ;INDICATE ERROR STATUS WRITEE6: MOV COMRA,AL RET ;** CHECK LIST DEVICE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (AL),'COMRA'=STATUS ; 0=NOT READY , 0FFH=READY ; USES: ALL ; LSTSTE: MOV AL,IOBYTE ;GET IOBYTE VALUE MOV CL,5 ;ADJUST VALUE SHR AL,CL CALL GETCIO ;GET APPROPRIATE CIO TABLE ENTRY DW SERATBL DW CRTTBL DW PPRTTBL DW SERBTBL CALL OSCIO ;CALL CIO HANDLER MOV COMRA,AL ;PUT STATUS IN COM REGION RET ;** SECTOR TRANSLATE ENTRY ; ; ENTRY: 'COMRBC'=LOGICAL SECTOR NUMBER (IN RANGE 0 TO SPT-1) ; 'COMRDE'=ADDRESS OF SECTOR TABLE ; EXIT: 'COMRHL'=TRANSLATED CP/M SECTOR NUMBER (IN RANGE 1 TO SPT) ; USES: ALL ; SECTRNE: MOV BX,COMRBC MOV SI,COMRDE TEST SI,SI JZ SECTRNE1 MOV BL,ES:[BX+SI] XOR BH,BH JMPS SECTRNE2 SECTRNE1: INC BX SECTRNE2: MOV COMRHL,BX RET ;** FORMAT - FORMAT ENTRY ; ; ENTRY: 'COMRC'=VERIFY FLAG (0=NO , 1=YES) ; EXIT: 'COMRA'=STATUS BYTE ; USES: ALL ; FORMATE: CALL CLRBUFD ;CLEAR HOST BUFFERS FOR THIS DRIVE MOV PREREAD,0 ;DON'T PREREAD CALL SETUP ;GET A BUFFER TO USE MOV AL,0FFH CMP BUFERR[BX],0 ;Q. ERROR DURING SETUP JNE FORMATE1 ; BR IF YES MOV AL,COMRC ;GET VERIFY FLAG MOV FVFLG,AL MOV AL,DDFMT ;CALL DEVICE DRIVER TO DO FORMAT CALL DRVR XOR AL,AL ;ASSUME NO ERROR STATUS CMP BUFERR[BX],0 ;Q. ERROR JE FORMATE1 ; BR IF NOT MOV AL,ERRTYP ;GET ERROR STATUS BYTE FORMATE1: MOV COMRA,AL ;PLACE STATUS BYTE INTO COM REGION CALL CLRBUFD ;GIVE BACK BUFFER RET ;** READ TRACK ENTRY ; ; ENTRY: NONE ; EXIT: 'COMRA'=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; RDTRKE: MOV PREREAD,0 ;INDICATE NO PREREAD CALL SETUP ;CALL R/W COMMON SETUP ROUTINE CMP BUFERR[BX],0 ;Q. ERROR DURING SETUP JNE RDTRKE1 ; BR IF YES MOV AL,DDRDT ;FORCE PHYSICAL READ OF TRACK CALL DRVR ; HOST BUFFER CONTAINS REQUESTED CP/M TRACK. ; COPY IT TO USER BUFFER. MOV SI,BUFDPE[BX] ;COMPUTE # BYTES TO COPY MOV SI,DPEDPB[SI] MOV AX,DPBSPT[SI] MOV CL,7 SHL AX,CL MOV CX,AX MOV SI,BUFBUF[BX] ;GET START OF HOST BUFFER MOV DI,DMAPTR ;GET DMA POINTER REP MOVSB ;MOVE DATA FROM HOST TO USER BUFFER ; RDTRKE1: MOV AL,BUFERR[BX] ;INDICATE ERROR STATUS MOV COMRA,AL RET ;** WRITE TRACK ENTRY ; ; ENTRY: NONE ; EXIT: 'COMRA'=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; WRTRKE: MOV PREREAD,0 ;INDICATE NO PREREAD CALL SETUP ;CALL R/W COMMON SETUP ROUTINE CMP BUFERR[BX],0 ;Q. ERROR DURING SETUP JNE WRTRKE3 ; BR IF YES ; COPY THE TRACK FROM USER BUFFER TO HOST BUFFER MOV SI,BUFDPE[BX] ;COMPUTE # BYTES MOV SI,DPEDPB[SI] MOV AX,DPBSPT[SI] PUSH AX MOV CL,7 SHL AX,CL MOV CX,AX MOV SI,DMAPTR ;GET DMA POINTER MOV DI,BUFBUF[BX] ;GET START OF HOST BUFFER CALL EXDSES ;EXCHANGE DS AND ES REP MOVSB ;MOVE DATA FROM USER TO HOST BUFFER CALL EXDSES ;RESTORE DS AND ES ; MARK PHYSICAL SECTORS AND HOST BUFFER AS DIRTY POP AX ;COMPUTE # PHYSICAL SECTORS PER TRACK MOV DI,BUFDPE[BX] CMP REQTRK,0 JNE WRTRKE1 TEST DPEFLAG[DI],DPET0SD JZ WRTRKE1 MOV AL,26 JMPS WRTRKE2 WRTRKE1: DIV DPERPS[DI] WRTRKE2: CBW MOV CX,AX MOV AL,1 ;SET DIRTY SECTOR FLAGS MOV DI,BUFSECF[BX] CLD CALL EXDSES REP STOSB CALL EXDSES MOV BUFWRF[BX],1 ;INDICATE HOST BUFFER IS DIRTY ; CALL FLUSH ;FLUSH BUFFER WRTRKE3: MOV AL,BUFERR[BX] ;INDICATE ERROR STATUS MOV COMRA,AL RET ;** WRITE PROTECT CHECK ; ; ENTRY: NONE ; EXIT: 'COMRA'=STATUS (0=R/W , 1=R/O) ; USES: ALL ; WPCE: LEA BX,DMYHDR ;USE DUMMY BUFFER HEADER MOV AL,REQDRV MOV BUFDRV[BX],AL MOV AL,PHYDRV MOV BUFPDRV[BX],AL MOV AX,PHYDPE MOV BUFDPE[BX],AX MOV AL,DDWPC ;CALL DEVICE DRIVER TO DO CHECK CALL DRVR MOV AL,BUFERR[BX] ;GET RETURN VALUE MOV COMRA,AL RET EJECT ;*** DISK BUFFER HANDLING ROUTINES ; ;** SETUP -- COMMON R/W ROUTINE SETUP CODE ; ; ENTRY: 'REQDRV'=REQUESTED DRIVE # ; 'PHYDPE'=ADDRESS OF DPE FOR REQUESTED DRIVE ; 'REQTRK'=REQUESTED TRACK # ; EXIT: HOST BUFFER CONTAINS REQUESTED TRACK ; (BX)=ADDRESS OF BUFFER HEADER INFO ; (AX)=DISPLACEMENT OF REQUESTED CP/M SECTOR INTO HOST BUFFER ; (CX)=128/2=64 ; DIRECTION FLAG CLEARED TO FORWARD DIRECTION ; USES: AX,CX,DI ; ; *** NOTE *** ; ; IF A 1ST TIME SELECT OPERATION IS IN PROGRESS, THEN NO PHYSICAL ; READ IS DONE. IN THIS CASE, THIS ROUTINE ONLY SERVES TO ; AQUIRE A FREE BUFFER TO BE USED BY THE DEVICE SELECTION ; ROUTINES FOR THEIR OWN PURPOSES. ; SETUP: CALL FNDBUF ;Q. REQUESTED TRACK IN ANY HOST BUFFERS MOV BUFERR[BX],0 ;CLEAR ERROR FLAG JNC SETUP1 ; BR IF YES CALL FLUSH ;FLUSH LEAST RECENTLY USED HOST BUFFER CMP BUFERR[BX],0 ;Q. ERROR DURING FLUSH JNE SETUP2 ; BR IF YES ; SET BUFFER HEADER INFO FOR REQUESTED TRACK MOV AL,REQDRV ;DRIVE # MOV BUFDRV[BX],AL MOV AL,PHYDRV ;MAPPED DRIVE # (PHYSICAL TABLE #) MOV BUFPDRV[BX],AL MOV AX,PHYDPE ;ADDRESS OF DPE MOV BUFDPE[BX],AX MOV AX,REQTRK ;TRACK # MOV BUFTRK[BX],AX ; CLEAR ERROR SECTOR FLAGS XOR AL,AL MOV DI,BUFERRF[BX] MOV CX,ERRFLGL CALL EXDSES REP STOSB CALL EXDSES ; CMP PREREAD,0 ;Q. SHOULD I DO PREREAD JE SETUP2 ; BR IF NO MOV AL,DDRDT ;DO PHYSICAL READ AND FILL HOST BUFFER CALL DRVR ; REQUESTED TRACK IS IN A HOST BUFFER. ; SET MOVE VALUES. SETUP1: MOV AX,REQSEC ;CALCULATE DISPLACEMENT MOV CL,7 SHL AX,CL MOV CX,64 ;WORD COUNT CLD ;CLEAR FOR FORWARD DIRECTION MOV BUFERR[BX],0 ;INSURE ERROR FLAG IS CLEARED SETUP2: RET ;** FNDBUF -- FIND HOST BUFFER TO USE ; ; ENTRY: 'REQDRV'=DRIVE # ; 'REQTRK'=TRACK # ; EXIT: PSW/C=STATUS ; 0=REQUESTED TRACK IS IN HOST BUFFER TO BE USED. ; HEADER INFO FOR BUFFER IS ON TOP OF BUFFER STACK ; 1=NOT FOUND. ; HEADER INFO FOR THE LEAST RECENTLY USED BUFFER ; IS PLACED ON TOP OF BUFFER STACK SO IT CAN BE ; FLUSHED AND THEN USED ; USES: AL,BX,DX ; FNDBUF: MOV AL,REQDRV ;REQUESTED DRIVE # MOV DX,REQTRK ;REQUESTED TRACK # MOV BX,FSTBUF ;INIT POINTER FNDBUF1: TEST BX,BX ;Q. NO MORE BUFFER HEADERS JZ FNDBUF3 ; BR IF NOT CMP AL,BUFDRV[BX] ;Q. MATCH ON REQUESTED DRIVE JNE FNDBUF2 ; BR IF NOT CMP DX,BUFTRK[BX] ;Q. MATCH ON REQUESTED TRACK JE FNDBUF4 ; BR IF YES FNDBUF2: MOV BX,BUFFWD[BX] ;FOLLOW CHAIN TO NEXT INFO ELEMENT JMPS FNDBUF1 FNDBUF3: MOV BX,LSTBUF ;POINT TO LAST ELEMENT STC ;INDICATE NOT FOUND FNDBUF4: PUSHF ;SAVE FOUND STATUS CALL PSHBUF ;PLACE BUFFER TO BE USED ON TOP OF STACK POPF ;RESTORE FOUND STATUS RET ;** INBUF -- INITIALIZE BUFFER HEADERS ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX,CX,SI,DI ; INBUF: MOV FSTBUF,0 ;INIT 1ST ELEMENT POINTER MOV LSTBUF,0 ;INIT LAST ELEMENT POINTER MOV CX,BUFCNT ;# OF BUFFERS LEA BX,HEADER ;START OF HEADER AREA LEA SI,SECFLG ;START OF DIRTY SECTOR FLAG AREA LEA DX,ERRFLG ;START OF SECTOR ERROR FLAG AREA LEA DI,BUFFER ;START OF BUFFER AREA INBUF1: MOV BUFSECF[BX],SI ;INIT ADDRESS OF DIRTY SECTOR FLAG AREA MOV BUFERRF[BX],DX ;INIT ADDRESS OF SECTOR ERROR FLAG AREA MOV BUFBUF[BX],DI ;INIT ADDRESS OF BUFFER AREA PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BX MOV DI,0 ;INSERT HEADER AT END CALL INSBUF POP BX CALL CLRBUF ;CLEAR BUFFER HEADER POP DI POP SI POP DX POP CX POP BX ADD BX,BUFHDRL ;BUMP POINTERS ADD SI,SECFLGL ADD DX,ERRFLGL ADD DI,BUFFERL LOOP INBUF1 ;LOOP FOR # OF BUFFERS RET ;** CLRBUFA - CLEAR ALL HOST BUFFER HEADERS ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX ; CLRBUFA: MOV BX,FSTBUF ;GET POINTER TO FIRST HEADER IN CHAIN CLRBUFA1: TEST BX,BX ;Q. AT END OF CHAIN JZ CLRBUFA2 ; BR IF YES CALL CLRBUF ;CLEAR THIS BUFFER HEADER MOV BX,BUFFWD[BX] ;CHAIN TO NEXT HEADER JMPS CLRBUFA1 CLRBUFA2: RET ;** CLRBUFD - CLEAR ALL HOST BUFFER HEADERS FOR REQUESTED DRIVE ; ; ENTRY: 'REQDRV'=REQUESTED DRIVE # ; EXIT: NONE ; USES: AX,BX ; CLRBUFD: MOV BX,FSTBUF ;POINT TO 1ST HEADER ELEMENT CLRBUFD1: TEST BX,BX ;Q. ANY MORE BUFFERS JZ CLRBUFD3 ; BR IF NOT MOV AL,REQDRV ;Q. BUFFER FOR REQUESTED DRIVE CMP AL,BUFDRV[BX] JE CLRBUFD2 ; BR IF YES MOV BX,BUFFWD[BX] ;SKIP TO NEXT ENTRY JMPS CLRBUFD1 CLRBUFD2: CALL CLRBUF ;CLEAR BUFFER MOV AX,BUFFWD[BX] ;REMEMBER WHO SHOULD BE NEXT PUSH AX CALL POPBUF ;POP BUFFER STACK POP BX ;GET NEXT ENTRY JMPS CLRBUFD1 CLRBUFD3: RET ;** CHKDBD -- CHECK FOR ANY DIRTY BUFFERS FOR REQUESTED DRIVE ; ; ENTRY: 'REQDRV'=REQUESTED DRIVE # ; EXIT: (AL)=STATUS 0=NO DIRTY BUFFERS , 1=DIRTY BUFFER(S) ; USES: AX,BX ; CHKDBD: XOR AH,AH ;ZERO WORK REG MOV AL,REQDRV ;GET REQUESTED DRIVE # MOV BX,FSTBUF ;START OF BUFFER HEADERS CHKDBD1: TEST BX,BX ;Q. ANY MORE BUFFERS JZ CHKDBD3 ; BR IF NOT CMP AL,BUFDRV[BX] ;Q. BUFFER FOR REQUESTED DRIVE JNE CHKDBD2 ; BR IF NOT OR AH,BUFWRF[BX] ;ACCUMULATE DIRTY FLAGS CHKDBD2: MOV BX,BUFFWD[BX] ;SKIP TO NEXT ENTRY JMPS CHKDBD1 CHKDBD3: MOV AL,AH ;MOVE RESULT TO (AL) RET ;** FLUSHD -- FLUSH ALL BUFFERS FOR REQUESTED DRIVE ; ; ENTRY: 'REQDRV'=REQUESTED DRIVE # ; EXIT: (AL)=ERROR STATUS (0=OK , 1=ABORT) ; USES: AL,BX ; FLUSHD: MOV FLDERR,0 ;CLEAR ERROR FLAG MOV BX,FSTBUF ;START OF BUFFER HEADERS FLUSHD1: TEST BX,BX ;Q. ANY MORE BUFFERS JZ FLUSHD3 ; BR IF NOT MOV AL,REQDRV ;Q. BUFFER FOR REQUESTED DRIVE CMP AL,BUFDRV[BX] JNE FLUSHD2 ; BR IF NOT MOV AL,FLDERR ;PROPAGATE ABORT STATUS OR BUFERR[BX],AL CALL FLUSH ;FLUSH BUFFER MOV AL,BUFERR[BX] ;ACCUMULATE ERROR STATUS OR FLDERR,AL FLUSHD2: MOV BX,BUFFWD[BX] ;FOLLOW CHAIN TO NEXT ELEMENT JMPS FLUSHD1 FLUSHD3: MOV AL,FLDERR ;GET ERROR STATUS RET ;* CLRBUF -- CLEAR BUFFER HEADER ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: AL,CX,SI,DI ; ; *** NOTE *** ; ; IF A BUFFER WAS NOT FLUSHED BEFORE BEING CLEARED AND ; IF IT WAS DIRTY, THEN THE DATA IS LOST. ; CLRBUF: MOV BUFDRV[BX],-1 ;CLEAR DRIVE # MOV BUFWRF[BX],0 ;CLEAR DIRTY BUFFER FLAG XOR AL,AL ;CLEAR DIRTY SECTOR FLAGS MOV DI,BUFSECF[BX] MOV CX,SECFLGL CLD CALL EXDSES REP STOSB CALL EXDSES RET ;* FLUSH -- FLUSH BUFFER WHOSE HEADER INFO IS ON TOP OF THE STACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: NONE ; FLUSH: TEST BUFWRF[BX],1 ;CHECK IF HOST BUFFER IS DIRTY JZ FLUSH1 ; BR IF NOT MOV AL,DDWRT ;GO WRITE TRACK CALL DRVR MOV BUFWRF[BX],0 ;INDICATE HOST WRITE BUFFER IS CLEAN FLUSH1: RET ;* PSHBUF -- PUSH DOWN BUFFER HEADER INFO STACK AND PLACE COPY ; OF HEADER INFO OF BUFFER TO BE USED ON TOP OF STACK. ; ; ENTRY: (BX)=ADDRESS OF HEADER INFO FOR HOST BUFFER TO BE USED ; EXIT: NONE ; USES: DI ; PSHBUF: CMP BX,FSTBUF ;Q. ALREADY ON TOP OF STACK JE PSHBUF1 ; BR IF YES CALL DELBUF ;REMOVE FROM STACK MOV DI,FSTBUF ;REINSERT ON TOP OF STACK CALL INSBUF PSHBUF1: RET ;* POPBUF -- POP UP BUFFER HEADER INFO STACK AND COPY ; HEADER INFO FOR BUFFER USED TO BOTTOM OF STACK. ; ; ENTRY: (BX)=ADDRESS OF HEADER INFO FOR HOST BUFFER TO BE USED ; EXIT: NONE ; USES: DI ; POPBUF: CMP BX,LSTBUF ;Q. ALREADY BOTTOM OF STACK JE POPBUF1 ; BR IF YES CALL DELBUF ;REMOVE FROM CURRENT POSITION MOV DI,0 ;REINSERT AT BOTTOM OF STACK CALL INSBUF POPBUF1: RET ;* DELBUF -- DELETE ELEMENT FROM BUFFER STACK ; ; ENTRY: (BX)=POINTER TO ELEMENT TO BE DELETED ; EXIT: NONE ; USES: SI,DI ; DELBUF: MOV DI,BUFFWD[BX] ;GET POINTER TO NEXT ELEMENT MOV SI,BUFBAK[BX] ;GET POINTER TO PREVIOUS ELEMENT TEST SI,SI ;Q. FIRST ELEMENT JNZ DELBUF1 ; BR IF NOT MOV FSTBUF,DI ;SET NEXT ELEMENT AS FIRST ELEMENT JMPS DELBUF2 DELBUF1: MOV BUFFWD[SI],DI ;CHAIN PREVIOUS ELEMENT TO NEXT ELEMENT DELBUF2: TEST DI,DI ;Q. LAST ELEMENT JNZ DELBUF3 ; BR IF NOT MOV LSTBUF,SI ;SET PREVIOUS ELEMENT AS LAST ELEMENT JMPS DELBUF4 DELBUF3: MOV BUFBAK[DI],SI ;CHAIN NEXT ELEMENT TO PREVIOUS ELEMENT DELBUF4: RET ;* INSBUF -- INSERT BUFFER HEADER INFO INTO STACK ; ; ENTRY: (BX)=ADDRESS OF ELEMENT TO BE INSERTED ; (DI)=ADDRESS OF ELEMENT TO BE INSERTED IN FRONT OF ; EXIT: NONE ; USES: SI ; ; *** NOTE *** ; ; IF (DI)=0 THEN INSERTION IS DONE AFTER LAST ELEMENT ; INSBUF: TEST DI,DI ;Q. INSERT AT END JNZ INSBUF3 ; BR IF NO ; INSERT AFTER LAST ELEMENT MOV SI,LSTBUF ;GET POINTER TO LAST ELEMENT TEST SI,SI ;Q. ANY ELEMENTS JNZ INSBUF1 ; BR IF YES MOV FSTBUF,BX ;SET ELEMENT AS FIRST ELEMENT JMPS INSBUF2 INSBUF1: MOV BUFFWD[SI],BX ;CHAIN LAST ELEMENT TO ELEMENT INSBUF2: MOV BUFFWD[BX],0 ;SET ELEMENT'S FORWARD POINTER MOV BUFBAK[BX],SI ;CHAIN ELEMENT TO LAST ELEMENT MOV LSTBUF,BX ;SET ELEMENT AS LAST ELEMENT RET ; INSERT IN FRONT OF ELEMENT POINTED TO BY (DI) INSBUF3: MOV SI,BUFBAK[DI] ;GET POINTER TO PREVIOUS ELEMENT TEST SI,SI ;Q. ANY PREVIOUS ELEMENT JNZ INSBUF4 ; BR IF YES MOV FSTBUF,BX ;SET ELEMENT AS FIRST ELEMENT JMPS INSBUF5 INSBUF4: MOV BUFFWD[SI],BX ;CHAIN PREVIOUS ELEMENT TO ELEMENT INSBUF5: MOV BUFBAK[BX],SI ;CHAIN ELEMENT TO PREVIOUS ELEMENT MOV BUFBAK[DI],BX ;CHAIN NEXT ELEMENT TO ELEMENT MOV BUFFWD[BX],DI ;CHAIN ELEMENT TO NEXT ELEMENT RET EJECT ;** DRVR - DISK DRIVER DISPATCHER ; ; ENTRY: (AL)=ENTRY JUMP VECTOR OFFSET ; (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: NONE ; USES: AX,CL,SI,DI ; DRVR: PUSH AX MOV LSIO,0 ;CLEAR LOGICAL SECTOR I/O FLAG ;* INSURE CORRECT DISK IS INSERTED IN REQUESTED DRIVE MOV SI,BUFDPE[BX] ;GET ADDRESS OF REQUESTED DRIVE'S DPE MOV AL,DPEFLAG[SI] ;NOT ALL DEVICES ARE PERMITTED AND AL,DPETYPE ; IMAGINARY DRIVES CMP AL,DPEZ217 JNE DRVR0 ; BR IF NOT Z217 MOV LSIO,1 ;INDICATE LOGICAL I/O DEVICE JMPS DRVR5 DRVR0: TEST DPEFLG2[SI],DPEIMG ;Q. IMAGINARY DRIVE JZ DRVR1 ; BR IF NOT MOV AL,DPELUN[SI] ;POINT TO CORRESPONDING REAL DRIVE AND AL,DPEREAL MOV AH,DPEL MUL AH ADD AX,OFFSET DPEBASE ADD AX,BBIOS MOV SI,AX DRVR1: MOV AL,DPELUN[SI] ;GET LOGICAL/MOUNTED VALUE MOV AH,AL ;SAVE IT AND AL,DPEMNT ;MASK FOR MOUNTED VALUE CMP AL,BUFPDRV[BX] ;Q. MOUNTED EQUAL REQUESTED JE DRVR5 ; BR IF YES AND AH,DPELOG ;UPDATE MOUNTED VALUE OR AH,BUFPDRV[BX] ; TO REFLECT WHICH DISK IS MOUNTED MOV DPELUN[SI],AH ; IN REAL UNIT ; PRINT MESSAGE AND REQUEST THAT DISK BE INSERTED INTO DRIVE MOV AL,BUFDRV[BX] ;PLACE REQUESTED DRIVE NAME INTO MSG ADD AL,'A' MOV MNMSGA,AL MOV CL,4 ;PLACE REAL DRIVE NAME INTO MESSAGE SHR AH,CL ADD AH,'A' MOV MNMSGB,AH PUSH BX LEA SI,MNMSG ;PRINT MESSAGE CALL PMSG DRVR3: CALL GETCHR ;WAIT FOR CMP AL,CR JE DRVR4 MOV COMRC,BELL CALL CONOUTE JMPS DRVR3 DRVR4: LEA SI,CRLF CALL PMSG POP BX MOV AL,DDMNT ;CALL DEVICE DRIVER TO MOUNT DISK CALL DRVR6 ;* DISPATCH TO DEVICE DRIVER DRVR5: POP AX ;RESTORE ENTRY JUMP VECTOR OFFSET DRVR6: MOV AH,0 MOV DI,AX MOV SI,BUFDPE[BX] ;FETCH DEVICE TYPE MOV AL,DPEFLAG[SI] MOV CL,5 SHR AL,CL CBW ;ADJUST FOR DISPATCH TABLE ENTRY LENGTH SHL AX,1 MOV SI,AX MOV SI,DRVRTBL[SI] ;GET OFFSET OF START OF DEVICE DRIVER CMP SI,0 ;Q. DUMMY DRIVER JE DRVR7 ; BR IF YES ADD SI,DI ;ADD ENTRY JUMP VECTOR OFFSET JMP SI ;GOTO DEVICE DRIVER DRVR7: RET EJECT INCLUDE Z207DRVR.LIB EJECT INCLUDE Z217DRVR.LIB EJECT INCLUDE TIMEDRVR.LIB EJECT ;*** GENERAL PURPOSE CHARACTER I/O HANDLER ; ;* GETCIO - GET APPROPRIATE CIO TABLE ENTRY ; ; ENTRY: (AL)='IOBYTE' SHIFTED SO BITS 1-2 CONTAIN THE PERTINENT VALUE ; ((SP))=START OF ADDRESS OFFSET TABLE ; EXIT: (BX)=ADDRESS OF CIO TABLE ENTRY ; USES: AX,BX ; ; *** NOTE *** ; THE TABLE CONSISTS OF 4 DW STATEMENTS, WHICH EQUALS 8 BYTES ; GETCIO: AND AX,06H ;MASK FOR ONLY BITS 1-2 POP BX ;GET START OF TABLE ADD AX,BX ;MOVE POINTER TO APPROPRIATE ENTRY ADD BX,8 ;MODIFY RETURN ADDRESS TO SKIP PUSH BX ; AROUND TABLE MOV BX,AX MOV BX,CS: WORD PTR [BX] ;GET VALUE IN TABLE TEST BX,BX ;Q. SPECIAL CASE JZ GETCIO1 ; BR IF YES ADD BX,BBIOS ;ADJUST FOR WHERE BIOS IS IN MEMORY GETCIO1: RET ;* CLRCIO - CLEAR CIO TABLE FLAGS/VALUES ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: NONE ; USES: NONE ; CLRCIO: AND CIOF2[BX],NOT (CIOW4A+CIOW4D) MOV CIOECTR[BX],0 MOV CIONCTR[BX],0 RET ;* ISCIO - INPUT STATUS ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=STATUS ; 0=NO CHARACTER AVAILBLE , 0FFH=CHARACTER AVAILBLE ; USES: AL ; ISCIO: CALL CIOIS[BX] ;INPUT STATUS BYTE FROM DEVICE AND AL,CIOIM[BX] ;USE INPUT READY MASK XOR AL,CIOIPM[BX] ;ADJUST FOR POLARITY CMP AL,CIOIM[BX] ;CHECK IF READY MOV AL,0FFH ; ASSUME READY JE ISCIO1 ; BR IF READY XOR AL,AL ; OTHERWISE SHOW NOT READY ISCIO1: RET ;* IDCIO - INPUT DATA ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=CHARACTER READ ; USES: AL ; IDCIO: CALL ISCIO ;WAIT FOR CHARACTER AVAILABLE TEST AL,AL JZ IDCIO CALL CIOID[BX] ;INPUT DATA TEST CIOF1[BX],CIOSPI ;Q. STRIP PARITY JZ IDCIO1 ; BR IF NOT AND AL,07FH ; OTHERWISE STRIP PARITY IDCIO1: TEST CIOF1[BX],CIOMLI ;CHECK IF I SHOULD MAP LOWER CASE JZ IDCIO2 ; BR IF NOT CALL UPC ; OTHERWISE DO MAPPING IDCIO2: RET ;* OSCIO - OUTPUT STATUS ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=STATUS ; 0=NOT READY , 0FFH=READY ; USES: AL ; OSCIO: CALL CIOOS[BX] ;INPUT STATUS BYTE FROM DEVICE AND AL,CIOOM[BX] ;USE OUTPUT READY MASK XOR AL,CIOOPM[BX] ;ADJUST FOR POLARITY CMP AL,CIOOM[BX] ;CHECK IF READY ; JNE OSCIO8 ; BR IF BUSY JE $+5 JMP OSCIO8 ; HANDLE / PROTOCOL OSCIO2: TEST CIOF1[BX],CIOEAH ;Q. USING / HANDSHAHKING JZ OSCIO3 ; BR IF NOT TEST CIOF2[BX],CIOW4A ;Q. WAITING FOR JNZ OSCIO2A ; BR IF YES MOV AL,CIOECTR[BX] ;Q. TIME TO SEND CMP AL,CIOECNT[BX] JB OSCIO4 ; BR IF NOT MOV CIOECTR[BX],0 ;REINITIALIZE COUNTER MOV AL,ETX ;SEND CALL CIOOD[BX] OR CIOF2[BX],CIOW4A ;SHOW WAITING FOR JMP OSCIO8 ;JUMP TO BUSY EXIT OSCIO2A: CALL ISCIO ;CHECK INPUT STATUS TEST AL,AL ;Q. CHARACTER AVAILABLE JZ OSCIO8 ; BR IF NOT CALL CIOID[BX] ;INPUT CHARACTER AND AL,07FH ;STRIP PARITY BIT CMP AL,ACK ;Q. JNE OSCIO8 ; BR IF NOT AND CIOF2[BX],0FFH-CIOW4A ;SHOW NOT WAITING FOR JMPS OSCIO4 ; HANDLE / PROTOCOL OSCIO3: TEST CIOF1[BX],CIODCH ;Q. USING / HANDSHAKING JZ OSCIO4 ; BR IF NOT CALL ISCIO ;INPUT STATUS TEST AL,AL ;Q. CHARACTER AVAILABLE JZ OSCIO3C ; BR IF NOT CALL CIOID[BX] ;INPUT CHARACTER AND AL,07FH ;STRIP PARITY BIT OSCIO3A: CMP AL,DC1 ;Q. JNE OSCIO3B ; BR IF NOT AND CIOF2[BX],0FFH-CIOW4D ;SHOW NOT WAITING FOR JMPS OSCIO4 OSCIO3B: CMP AL,DC3 ;Q. JNE OSCIO3C ; BR IF NOT OR CIOF2[BX],CIOW4D ;SHOW WAITING FOR JMPS OSCIO8 OSCIO3C: TEST CIOF2[BX],CIOW4D ;Q. WAITING FOR JNZ OSCIO8 ; BR IF YES ; HANDLE SENDING NULLS OSCIO4: CMP CIONCTR[BX],0 ;Q. ANY NULLS LEFT TO SEND JE OSCIO9 ; BR IF NOT DEC CIONCTR[BX] ;DECREMENT NULL COUNTER MOV AL,NULL ;SEND ANOTHER NULL CALL CIOOD[BX] ; SHOW AS BUSY OSCIO8: XOR AL,AL RET ; SHOW AS READY OSCIO9: MOV AL,0FFH RET ;* ODCIO - OUTPUT DATA ; ; ENTRY: (CL)=CHARACTER ; (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: NONE ; USES: AL ; ; *** NOTE *** ; ; THE DEVICE OUTPUT ROUTINE MUST NOT DESTROY REGISTER (CL) OR (BX). ; ODCIO: CALL OSCIO ;WAIT UNTIL READY TEST AL,AL JZ ODCIO MOV AL,CL TEST CIOF1[BX],CIOSPO ;Q. STRIP PARITY JZ ODCIO1 ; BR IF NOT AND AL,07FH ODCIO1: TEST CIOF1[BX],CIOMLO ;Q. MAP LOWER CASE ON OUTPUT JZ ODCIO2 ; BR IF NOT CALL UPC ; OTHERWISE DO MAPPING ODCIO2: CALL CIOOD[BX] ;OUTPUT CHARACTER CMP CL,CIONCHR[BX] ;Q. SHOULD I SEND NULLS JNE ODCIO3 ; BR IF NOT MOV AL,CIONCNT[BX] ;GET NUMBER OF NULLS TO BE SENT MOV CIONCTR[BX],AL ;PLACE IN NULL COUNTER ODCIO3: INC CIOECTR[BX] ;COUNT CHARACTER CMP CL,ESC ;Q. JNE ODCIO4 ; BR IF NOT MOV AL,CIOECNT[BX] ; IF YES - THEN INSURE SUB AL,3 ; ETX/ACK HANDSHAKING IS DELAYED CMP CIOECTR[BX],AL JB ODCIO4 MOV CIOECTR[BX],AL ODCIO4: RET EJECT ;*** DEVICE DRIVERS ; ;** CRT: (KEYBOARD/DISPLAY) ; ;* INCRT - INITIALIZATION ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX ; INCRT: PUSHF ;INSURE INTERRUPTS ARE DISABLED CLI ; DURING INIT LEA BX,CRTTBL ;GET ADDRSS OF CIO TABLE ENTRY ADD BX,BBIOS CALL CLRCIO ;CLEAR CIO TABLE FLAGS MOV CIOIN[BX],OFFSET INCRT ;ADDRESS OF INIT ROUTINE MOV CIOIS[BX],OFFSET ISCRT ;ADDRESS OF INPUT INPUT STATUS BYTE MOV CIOID[BX],OFFSET IDCRT ;ADDRESS OF INPUT DATA BYTE MOV CIOOS[BX],OFFSET DUMMY ;ADDRESS OF INPUT OUTPUT STATUS BYTE MOV CIOOD[BX],OFFSET ODCRT ;ADDRESS OF OUTPUT DATA BYTE CALL FLCRT ;FLUSH TYPEAHEAD BUFFER POPF ;RESTORE INTERRUPT STATUS RET ;* FLCRT - FLUSH CRT: TYPE AHEAD BUFFER ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; FLCRT: PUSH AX PUSH BX PUSHF ;DISABLE INTERRUPTS CLI FLCRT1: IN AL,ZKEYBDS ;DISABLE KEYBOARD TEST AL,ZKEYIBF JNZ FLCRT1 MOV AL,ZKEYDK OUT ZKEYBDC,AL FLCRT2: IN AL,ZKEYBDS ;CLEAR FIFO TEST AL,ZKEYIBF JNZ FLCRT2 MOV AL,ZKEYCF OUT ZKEYBDC,AL FLCRT3: IN AL,ZKEYBDS ;CLEAR OUTPUT BUFFER TEST AL,ZKEYIBF JNZ FLCRT3 IN AL,ZKEYBDD MOV KEYCNT,0 ;INIT BUFFER HANDLING VALUES LEA BX,KEYBUF MOV KEYPUT,BX MOV KEYGET,BX POPF ;RESTORE INTERRUPT STATUS PUSHF ;Q. INTERRUPTS ENABLED POP AX TEST AH,002H JZ FLCRT4 ; BR IF NOT MOV AX,250*250 ;WAIT IN CASE KEY WAS DEPRESSED CALL WDLY ; DURING FLUSH CALL WDLY FLCRT4: MOV AL,ZKEYEK ;RE-ENABLE KEYBOARD OUT ZKEYBDC,AL POP BX POP AX RET ;* ISCRT - INPUT INPUT STATUS BYTE ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=STATUS ; 0=NO DATA AVAILABLE , 0FFH=DATA IN TYPE-AHEAD BUFFER ; USES: AL ; ISCRT: MOV AL,KEYCNT ;GET TYPE-AHEAD CHARACTER COUNT TEST AL,AL ;Q. ANY CHARACTERS AVAILABLE JZ ISCRT1 ; BR IF NOT MOV AL,0FFH ; INDICATE AVAILABLE ISCRT1: RET ;* IDCRT - GET DATA BYTE FROM TYPE-AHEAD BUFFER ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=DATA BYTE ; USES: AL ; IDCRT: CALL ISCRT ;Q. ANY AVAILABLE TEST AL,AL JZ IDCRT2 ; BR IF NOT PUSHF ;DISABLE INTERRUPTS WHILE FETCHING CLI ; CHARACTER PUSH BX MOV BX,KEYGET ;FETCH GET POINTER MOV AL,[BX] ;FETCH CHARACTER DEC KEYCNT ;DECREMENT CHARACTER COUNTER INC BX ;BUMP GET POINTER CMP BX,OFFSET KEYBUF + KEYBUFL ;Q. TIME TO WRAP POINTER JB IDCRT1 ; BR IF NOT LEA BX,KEYBUF ; WRAP POINTER TO BEGINNING IDCRT1: MOV KEYGET,BX ;SAVE UPDATED GET POINTER POP BX POPF IDCRT2: RET ;* ODCRT - OUTPUT DATA ; ; ENTRY: (AL)=CHARACTER ; (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: NONE ; USES: NONE ; ODCRT: PUSHA CALLFI MTRSCRT,MTRSEG ;CALL ROM MONITOR ROUTINE POPA RET ;* PUTKEY - PUT DATA BYTE INTO TYPE-AHEAD BUFFER ; ; ENTRY: (AL)=CHARACTER ; (CS)=CODE SEGMENT VALUE ; EXIT: NONE ; USES: (AL) ; ; THIS ROUTINE IS CALLED BY THE ROM MONITOR AT INTERRUPT TIME PUTKEY: PUSH BX CMP CS:KEYCNT,KEYBUFL ;Q. BUFFER FULL JB PUTKEY2 ; BR IF NOT PUTKEY1: IN AL,ZKEYBDS ;SEND BEEP TO INDICATE BUFFER FULL TEST AL,ZKEYIBF JNZ PUTKEY1 MOV AL,ZKEYBEP OUT ZKEYBDC,AL JMPS PUTKEY4 PUTKEY2: MOV BX,CS:KEYPUT ;GET PUT POINTER MOV CS:[BX],AL ;PUT CHARACTER INTO BUFFER INC CS:KEYCNT ;BUMP CHARACTER COUNTER INC BX ;BUMP PUT POINTER CMP BX,OFFSET KEYBUF + KEYBUFL ;Q. TIME TO WRAP POINTER JB PUTKEY3 ; BR IF NOT LEA BX,CS:KEYBUF ; WRAP POINTER TO BEGINNING PUTKEY3: MOV CS:KEYPUT,BX ;SAVE UPDATED PUT POINTER PUTKEY4: POP BX RETF ;** SERIAL PORT A DEVICE DRIVER ; ;* INSERA - INITIALIZATION ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX ; INSERA: PUSHF ;INSURE INTERRUPTS ARE DISABLED CLI ; DURING INIT LEA BX,SERATBL ;GET ADDRESS OF CIO ENTRY ADD BX,BBIOS CALL CLRCIO ;CLEAR CIO TABLE FLAGS MOV CIOIN[BX],OFFSET INSERA ;ADDRESS OF INIT ROUTINE MOV CIOIS[BX],OFFSET IS2661 ;ADDRESS OF INPUT INPUT STATUS ROUTINE MOV CIOID[BX],OFFSET ID2661 ;ADDRESS OF INPUT DATA ROUTINE MOV CIOOS[BX],OFFSET IS2661 ;ADDRESS OF INPUT OUTPUT STATUS ROUTINE MOV CIOOD[BX],OFFSET OD2661 ;ADDRESS OF OUTPUT DATA ROUTINE CALL IN2661 ;CALL DEVICE INIT ROUTINE POPF ;RESTORE INTERRUPT STATUS RET ;** SERIAL PORT B DEVICE DRIVER ; ;* INSERB - INITIALIZATION ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX ; INSERB: PUSHF ;INSURE INTERRUPTS ARE DISABLED CLI ; DURING INIT LEA BX,SERBTBL ;GET ADDRESS OF CIO ENTRY ADD BX,BBIOS CALL CLRCIO ;CLEAR CIO TABLE FLAGS MOV CIOIN[BX],OFFSET INSERB ;ADDRESS OF INIT ROUTINE MOV CIOIS[BX],OFFSET IS2661 ;ADDRESS OF INPUT INPUT STATUS ROUTINE MOV CIOID[BX],OFFSET ID2661 ;ADDRESS OF INPUT DATA ROUTINE MOV CIOOS[BX],OFFSET IS2661 ;ADDRESS OF INPUT OUTPUT STATUS ROUTINE MOV CIOOD[BX],OFFSET OD2661 ;ADDRESS OF OUTPUT DATA ROUTINE CALL IN2661 ;CALL DEVICE INIT ROUTINE POPF ;RESTORE INTERRUPT STATUS RET ;** 2661 COMMON DEVICE DRIVER ROUTINES ; ;* IS2661 - INPUT INPUT/OUTPUT STATUS BYTE ; ; ENTRY: (BX)=ADDRESS OF CIO ENTRY ; EXIT: (AL)=STATUS BYTE ; USES: AL,DX ; IS2661: XOR DH,DH ;GET STATUS PORT # MOV DL,CIOBP[BX] ADD DX,EPSTAT IN AL,DX ;GET STATUS RET ;* ID2661 - INPUT DATA BYTE ; ; ENTRY: (BX)=ADDRESS OF CIO ENTRY ; EXIT: (AL)=DATA BYTE ; USES: AL,DX ; ID2661: XOR DH,DH ;GET DATA PORT # MOV DL,CIOBP[BX] ADD DX,EPDATA IN AL,DX ;INPUT DATA RET ;* OD2661 - OUTPUT DATA BYTE ; ; ENTRY: (AL)=DATA BYTE ; (BX)=ADDRESS OF CIO ENTRY ; EXIT: NONE ; USES: DX ; OD2661: XOR DH,DH ;GET DATA PORT # MOV DL,CIOBP[BX] ADD DX,EPDATA OUT DX,AL ;OUTPUT DATA RET ;* IN2661 - INITIALIZE ; ; ENTRY: (BX)=ADDRESS OF CIO ENTRY ; EXIT: NONE ; USES: AL,DX ; IN2661: PUSH CX XOR CH,CH ;GET BASE PORT # MOV CL,CIOBP[BX] XOR AL,AL ;SHUT DOWN 2661 MOV DX,EPCMD ADD DX,CX OUT DX,AL IN AL,DX ;RESET MODE REGISTER POINTER MOV AL,CIOVAL1[BX] ;SET MODE REGISTER 1 MOV DX,EPMODE ADD DX,CX OUT DX,AL MOV AL,CIOVAL2[BX] ;SET MODE REGISTER 2 OR AL,BYTE PTR CIOBR[BX] OUT DX,AL MOV AL,CIOVAL3[BX] ;SET COMMAND REGISTER MOV DX,EPCMD ADD DX,CX OUT DX,AL MOV DX,EPDATA ;FLUSH INPUT BUFFER ADD DX,CX IN AL,DX IN AL,DX POP CX RET ;** PARALLEL PRINTER DRIVER ; ;* INPPRT - INITIALIZE PARALLEL PRINTER PORT ; ; ENTRY: NONE ; EXIT: NONE ; USES: AL,BX ; INPPRT: PUSHF ;INSURE INTERRUPTS ARE DISABLED CLI ; DURING INIT LEA BX,PPRTTBL ;GET ADDRESS OF CIO ENTRY ADD BX,BBIOS CALL CLRCIO ;CLEAR CIO TABLE FLAGS MOV CIOIN[BX],OFFSET INPPRT ;ADDR OF INIT ROUTINE MOV CIOIS[BX],OFFSET DUMMY ;ADDR OF INPUT INPUT STATUS ROUTINE MOV CIOID[BX],OFFSET IDDUMMY ;ADDR OF INPUT DATA ROUTINE MOV CIOOS[BX],OFFSET OSPPRT ;ADDR OF INPUT OUTPUT STATUS ROUTINE MOV CIOOD[BX],OFFSET ODPPRT ;ADDR OF OUTPUT DATA ROUTINE ; DO PORT A FIRST XOR AL,AL ;ACCESS DATA DIRECTION REG OUT GDPCTLA,AL OUT GDPDDRA,AL ;SET ALL BITS AS INPUTS MOV AL,PIADDAC ;ACCESS PERIPHERAL DATA REG OUT GDPCTLA,AL MOV AL,CIOVAL1[BX] ;SET OUTPUT LATCHES OUT GDPDATA,AL XOR AL,AL ;ACCESS DATA DIRECTION REG OUT GDPCTLA,AL MOV AL,CIOVAL2[BX] ;SET DATA DIRECTION REG OUT GDPDDRA,AL MOV AL,CIOVAL3[BX] ;SET CONTROL PORT VALUE OUT GDPCTLA,AL IN AL,GDPDATA ;CLEAR ANY PENDING INTERRUPTS IN AL,ZDIPSW ;FIRE E-CLOCK MOV AL,CIOVAL1[BX] ;CLEAR LPEN & VSYNC STROBE FLIP-FLOPS AND AL,NOT (LPENSE+VSYNCE) OUT GDPDATA,AL OR AL,LPENSE+VSYNCE OUT GDPDATA,AL ; DO PORT B NEXT XOR AL,AL ;ACCESS DATA DIRECTION REG OUT GDPCTLB,AL OUT GDPDDRB,AL ;SET ALL BITS AS INPUTS MOV AL,PIADDAC ;ACCESS PERIPHERAL DATA REG OUT GDPCTLB,AL MOV AL,CIOVAL4[BX] ;SET OUTPUT LATCHES OUT GDPDATB,AL XOR AL,AL ;ACCESS DATA DIRECTION REG OUT GDPCTLB,AL MOV AL,CIOVAL5[BX] ;SET DATA DIRECTION REG OUT GDPDDRB,AL MOV AL,CIOVAL6[BX] ;SET CONTROL PORT VALUE OUT GDPCTLB,AL IN AL,GDPDATB ;CLEAR ANY PENDING INTERRUPTS IN AL,ZDIPSW ;FIRE E-CLOCK POPF ;RESTORE INTERRUPT STATUS RET ;* OSPPRT - INPUT OUTPUT STATUS BYTE ; ; ENTRY: (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: (AL)=STATUS BYTE ; USES: AL ; OSPPRT: IN AL,GDPDATB ;INPUT STATUS RET ;* ODPPRT - OUTPUT DATA BYTE ; ; ENTRY: (AL)=DATA ; (BX)=ADDRESS OF CIO TABLE ENTRY ; EXIT: NONE ; USES: AH ; ODPPRT: PUSHF ;DISABLE INTERRUPTS WHILE PLAYING CLI ; WITH PORTS MOV AH,AL ;SAVE (AL) OUT GDPDATB,AL ;PLACE PORT B DATA IN OUTPUT LATCH AND AL,PPRTM10 ;MASK FOR PORT A DATA OR AL,CIOVAL1[BX] ;OR IN NON-ASSERTED VALUES FOR OTHER ; PORT A OUTPUT BITS OUT GDPDATA,AL ;PLACE PORT A DATA IN OUTPUT LATCH AND AL,0FFH-PPRTSTB ;GENERATE STROBE OUT GDPDATA,AL OR AL,PPRTSTB OUT GDPDATA,AL MOV AL,AH ;RESTORE (AL) POPF ;RESTORE INTERRUPT STATUS RET ;** DUMMY DEVICE DRIVER ; ;* INDUMMY - INITIALIZATION ; ; ENTRY: NONE ; EXIT: NONE ; USES: BX ; INDUMMY: LEA BX,DUMMYTBL ;GET ADDRESS OF CIO TABLE ENTRY ADD BX,BBIOS CALL CLRCIO ;CLEAR CIO TABLE FLAGS MOV CIOIN[BX],OFFSET INDUMMY ;ADDRESS OF INIT ROUTINE MOV CIOIS[BX],OFFSET DUMMY ;ADDRESS OF INPUT INPUT STATUS BYTE MOV CIOID[BX],OFFSET IDDUMMY ;ADDRESS OF INPUT DATA ROUTINE MOV CIOOS[BX],OFFSET DUMMY ;ADDRESS OF INPUT OUTPUT STATUS BYTE MOV CIOOD[BX],OFFSET DUMMY ;ADDRESS OF OUTPUT DATA ROUTINE RET ;* DUMMY - DUMMY I/O (NOP) ; ; ENTRY: NONE ; EXIT: (AL)=STATUS BYTE ; USES: AL ; DUMMY: RET ;NOP ;* IDDUMMY - INPUT DATA BYTE ; ; ENTRY: NONE ; EXIT: (AL)=DATA BYTE ; USES: AL ; IDDUMMY: MOV AL,CPMEOF ;ALWAYS CP/M ASCII END-OF-FILE RET EJECT ;*** INTERRUPT HANDLERS ; ;** INTDIV0 - DIVIDE BY 0 ; INTDIV0: PUSHA LEA SI,DIV0MSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** INTPBE - PARITY OR BUSS ERROR HANDLER ; INTPBE: PUSHA LEA SI,PBEMSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** INTLVK - LIGHTPEN, VSYNC, & KEYBOARD HANDLER ; INTLVK: PUSHA IN AL,GDPCTLA ;Q. INTERRUPT FROM PIA TEST AL,LPENSI+VSYNCI JZ INTKEY ; BR IF NOT MOV AH,AL ;SAVE STATUS ;* LIGHTPEN HANDLER TEST AH,LPENSI ;Q. LIGHTPEN STROBE INTERRUPT JZ INTV ; BR IF NOT ;NO LIGHT PEN HANDLER AT THIS TIME ;* VSYNC HANDLER INTV: TEST AH,VSYNCI ;Q. VSYNC INTERRUPT JZ INTV1 ; BR IF NOT IN AL,GDPDATA ;CLEAR INTERRUPT AND GET DATA TEST AL,VSYNC ;Q. VSYNC STILL PRESENT JZ INTV1 ; BR IF NOT CALLFI MTRTINT,MTRSEG ;CALLF ROM MONITOR ROUTINE ; CLEAR LIGHTPEN STROBE / VERTICAL SYNC INTERRUPTS AND RE-ARM FLIP-FLOPS INTV1: IN AL,GDPDATA ;READ PIA DATA AND AL,NOT (LPENSE+VSYNCE) ;CLEAR LIGHTPEN / VSYNC FLIP-FLOPS OUT GDPDATA,AL IN AL,ZDIPSW ;DUMMY I/O TO FIRE E-CLOCK IN AL,GDPDATA ;ENABLE LIGHTPEN / VSYNC FLIP-FLOPS OR AL,LPENSE+VSYNCE OUT GDPDATA,AL ;* INTKEY - KEYBOARD HANDLER INTKEY: MOV AX,CS ;GET DS MOV DS,AX IN AL,ZKEYBDS ;GET STATUS BYTE TEST AL,ZKEYOBF ;Q. CHARACTER AVAILABLE JZ INTKEY3 ; BR IF NOT IN AL,ZKEYBDD ;INPUT CHARACTER CMP KEYCNT,KEYBUFF ;Q. KEY BUFFER ALREADY FULL JB INTKEY2 ; BR IF NOT FULL INTKEY1: IN AL,ZKEYBDS ;BUFFER FULL, SEND BEEP TEST AL,ZKEYIBF JNZ INTKEY1 MOV AL,ZKEYBEP OUT ZKEYBDC,AL JMPS INTKEY3 INTKEY2: CALLFI MTRDKBD,MTRSEG ;PASS CHARACTER TO ROM MONITOR HANDLER INTKEY3: POPA JMP INTX2 ;EXIT VIA COMMON IRET EXIT ;** INTSWAP - SWAP TO 8085 PROCESSOR ; INTSWAP: MOV COMWHO,ZPSPPS5+ZPSPI88 ;INDICATE 8085 WILL GET CONTROL JMP INTX3 ;GOTO TO INTERRUPT EXIT ROUTINE ;** INTWILD - WILD INTERRUPT ; INTWILD: PUSHA LEA SI,WILDMSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** SYSDMP - DUMP REGISTERS AT INTERRUPT ; SYSDMP: PUSH DI LEA DI,DMPAX ;AX CALL HEXW POP AX ;DI LEA DI,DMPDI CALL HEXW POP AX ;PC LEA DI,DMPIP CALL HEXW POP AX ;CS LEA DI,DMPCS CALL HEXW POP AX ;FLAGS LEA DI,DMPFLG CALL HEXW MOV AX,DS ;DS LEA DI,DMPDS CALL HEXW MOV AX,ES ;ES LEA DI,DMPES CALL HEXW MOV AX,SS ;SS LEA DI,DMPSS CALL HEXW MOV AX,SP ;SP LEA DI,DMPSP CALL HEXW MOV AX,BX ;BX LEA DI,DMPBX CALL HEXW MOV AX,CX ;CX LEA DI,DMPCX CALL HEXW MOV AX,DX ;DX LEA DI,DMPDX CALL HEXW MOV AX,SI ;SI LEA DI,DMPSI CALL HEXW MOV AX,BP ;BP LEA DI,DMPBP CALL HEXW LEA SI,DMPMSG ;PRINT DUMP CALL PMSG ;** HALT SYSTEM ; SYSHLT: LEA SI,HLTMSG ;PRINT MESSAGE CALL PMSG CALLFI MTRTINT,MTRSEG ;CALLF ROM MONITOR TO INSURE SCROLLING CLI ;INSURE MACHINE HALTS HLT ;** INTX - INTERRUPT EXIT ROUTINES ; ; INTX1 - ENTERED WHEN HARDWARE SLAVE INTERRUPT ; INTX2 - ENTERED WHEN HARDWARE MASTER INTERRUPT ; INTX3 - ENTERED WHEN SOFTWARE INTERRUPT ; ; EXIT FOR HARDWARE SLAVE INTERRUPT INTX1: PUSH AX MOV AL,OCW2OP+OCW2EOI ;ISSUE NON-SPECIFIC EOI OUT Z8259AS+OCW2,AL MOV AL,OCW3OP+OCW3RIS ;READ ISR OUT Z8259AS+OCW3,AL IN AL,Z8259AS+OCW3 TEST AL,AL ;Q. ANY OTHER SLAVE INT'S IN SERVICE POP AX JNZ INTX3 ; BR IF YES - SKIP EOI TO MASTER ; EXIT FOR HARDWARE MASTER INTERRUPT INTX2: PUSH AX MOV AL,OCW2OP+OCW2EOI ;ISSUE NON-SPECIFIC EOI OUT Z8259AM+OCW2,AL POP AX ; EXIT FOR SOFTWARE INTERRUPTS INTX3: PUSH BP PUSH ES MOV ES,CS:BANK1 CMP COMWHO,ZPSPPS8 ;8088 PROCESSOR SHOULD GET CONTROL JE INTIRET ; BR IF YES MOV BP,SP ;MODIFY RETURN ADDRESS MOV 4[BP],OFFSET SWAP85 ; TO GOTO SWAP OUTPUT MOV 6[BP],CS ; INSTRUCTION MOV AL,COMWHO ;FETCH SWAP OUTPUT DATA VALUE ; INTIRET: POP ES POP BP IRET ;DO RETURN FROM INTERRUPT EJECT ;*** SUBROUTINES ; ;** ABTIGN - HANDLE ABORT/IGNORE ALTERNATIVE FOR HARD DISK ERRORS ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER ; 'PHYSEC'=PHYSICAL SECTOR # ; EXIT: 'BUFERR[BX]'=ABORT STATUS (0=NO , 1=YES) ; USES: AX,SI,DI ; ABTIGN: TEST DSKOP,DSKOPS ;Q. ERROR DURING 1ST TIME SELECT JNZ ABTIGN2 ; BR IF YES MOV BUFERR[BX],0 ;ASSUME NO ERROR MOV DI,BUFERRF[BX] ;GET ERROR STATUS BYTE ADD DI,PHYSEC MOV AL,[DI] CMP AL,0 ;Q. ERROR JE ABTIGN2 ; BR IF NO ERROR PUSH BX PUSH DI CALL ERRRPT ;REPORT ERROR LEA SI,AIMSG CALL PMSG CALL GETCHR ;GET RESPONSE PUSH AX LEA SI,CRLF CALL PMSG POP AX POP DI POP BX CMP AL,CTLC ;Q. ABORT RESPONSE JNE ABTIGN1 ; BR IF NO MOV BUFERR[BX],1 ;INDICATE ABORT JMPS ABTIGN2 ABTIGN1: MOV BYTE PTR [DI],0 ;INDICATE IGNORE ERROR ABTIGN2: RET ;** ALTCHR -- HANDLE ALTERNATE CHARACTER FONTS ; ; ENTRY: ; EXIT: NONE ; USES: ALL ; ALTCHR: CMP BBIOS-2,0 ;Q. ALTERNATE CHARACTER SET REQUESTED ; JE ALTCHR9 ; BR IF NOT JNE $+5 JMP ALTCHR9 PUSH DS MOV DS,.MTRDSEG ;DS=>MONITOR DATA AREA CMP MTRFNTL,ALTFNTL ;Q. WILL ROM FONT TABLE FIT IN MY AREA JBE ALTCHR1 ; BR IF YES POP DS LEA SI,FNTMSG ;PRINT ERROR MESSAGE CALL PMSG JMP SYSHLT ; MOVE ROM FONT TABLE TO MY AREA ALTCHR1: CLD LEA DI,ALTFNT MOV CX,MTRFNTL MOV SI,MTRFONT MOV AX,MTRFONT+2 POP DS ;DS=>BIOS PUSH ES MOV ES,AX ;ES=>ROM FONT TABLE CALL EXDSES ;DS=>ROM FONT TABLE , ES=>BIOS REP MOVSB CALL EXDSES ;DS=>BIOS , ES=>ROM FONT TABLE ; MAKE CHANGES TO KEYBOARD MAP POP ES ;ES=>8085 BANK MOV SI,BBIOS-2 PUSH ES MOV ES,.MTRDSEG ;ES=>MONITOR DATA AREA ALTCHR2: LODSW CMP AX,0FFFFH JE ALTCHR3 MOV DI,AX AND DI,0FFH MOV ES: MTRKMAP[DI],AH JMPS ALTCHR2 ; MAKE CHANGES TO FONT TABLE ALTCHR3: MOV AX,DS MOV ES,AX ;ES=>BIOS ALTCHR4: LODSB CMP AL,0FFH JE ALTCHR5 MOV AH,9 MUL AH LEA DI,ALTFNT ADD DI,AX MOV CX,9 REP MOVSB JMPS ALTCHR4 ; MAKE CHANGES TO DISPLAY MAP ALTCHR5: MOV ES,.MTRDSEG ;ES=>MONITOR DATA AREA ALTCHR6: LODSW CMP AX,0FFFFH JE ALTCHR7 MOV DI,AX AND DI,0FFH MOV ES: MTRDMAP[DI],AH JMPS ALTCHR6 ; ALTCHR7: MOV ES: MTRFONT,OFFSET ALTFNT MOV ES: MTRFONT+2,DS ;UPDATE FONT TABLE VECTOR POP ES ;ES=>8085 BANK ALTCHR9: RET ;** CBTFIL - FILL THE LOGICAL TO PHYSICAL MAPPING TABLE FOR REAL DRIVES. ; THEN DO THE SAME FOR THE IMAGINARY DRIVES PLUS SET UP THE ; IMAGINARY'S LINK TO HIS CORRESPONDING REAL DRIVE. ; ; ENTRY: (CH)=# DRIVES ; (CL)=STARTING UNIT # ; (DH)=STARTING DRIVE MAP # ; 'CBIC'=NEXT LOGICAL DRIVE # TO BE ASSIGNED ; EXIT: 'CBIC' UPDATED ; USES: ALL ; CBTFIL: MOV CBTIA,0 ;INIT CBTIA CBTFIL1: PUSH CX PUSH DX MOV CBTFA,0 ;INDICATE REAL DRIVE CYCLE CALL CBTF ;HANDLE REAL DRIVES POP DX POP CX MOV CBTFA,1 ;INDICATE IMAGINARY CYCLE ;* THIS SECTION OF CODE IS RAN THROUGH TWICE. ; FIRST TIME IS FOR HANDLING THE REAL DRIVES. ; SECOND TIME IS FOR HANDLING THE IMAGINARY DRIVES. CBTF: MOV DL,CH ;COPY # OF DRIVES CBTF1: MOV AL,CL ;GET THIS DRIVES NUMBER MOD (# DRIVES) CBW DIV CH ADD AH,DH ;COMPUTE DISK ENTRY TABLE TO USE MOV CBIB,AH PUSH CX MOV AL,DPEL ;GET ADDRESS OF TABLE ENTRY MUL AH ADD AX,OFFSET DPEBASE ADD AX,BBIOS MOV BP,AX TEST DPEFLG2[BP],DPEIMG ;Q. IMAGINARY DRIVE JNZ CBTF3 ; BR IF YES ; HANDLE REAL DRIVE IS THIS IS REAL DRIVE CYCLE CMP CBTFA,0 ;Q. REAL DRIVE CYCLE JNE CBTF4 ; BR IF NOT CMP CBTIA,0 ;IF THIS IS 1ST REAL DRIVE ENCOUNTERED JNE CBTF25 ; THEN REMEMBER ITS TABLE ADDRESS MOV CBTIA,BP CBTF25: MOV CH,CBIC MOV CL,4 SHL CH,CL OR CH,CBIB MOV DPELUN[BP],CH ;PLACE LOGICAL/REAL IN DPELUN SLOT CALL CBTF6 ;MAP DRIVE JMPS CBTF4 ; HANDLE IMAGINARY DRIVE IF THIS IS THE IMAGINARY DRIVE CYCLE CBTF3: CMP CBTFA,0 ;Q. IMAGINARY DRIVE CYCLE JE CBTF4 ; BR IF NOT CMP CBTIA,0 ;Q. ANY REAL DRIVES FOR THIS DRIVE TYPE JNE CBTF31 ; BR IF YES MOV DPEFLAG[BP],DPENE ; OTHERWISE CHANGE DRIVE TYPE TO MOV BX,BBIOS ; NONEXISTANT DRIVE AND DECREMENT DEC NDISKS[BX] ; # CP/M DRIVES JMPS CBTF4 CBTF31: CALL CBTF6 ;MAP DRIVE MOV SI,CBTIA ;MOVE THE REAL DRIVE'S HEATH EXTENSIONS ADD SI,OFFSET DPEHTH ; INTO THIS IMAGINARY DRIVE'S TABLES MOV DI,BP ADD DI,OFFSET DPEHTH PUSH CX MOV CX,DPEHL PUSH DS MOV AX,ES MOV DS,AX REP MOVSB POP DS POP CX OR DPEFLG2[BP],DPEIMG ;REMARK AS IMAGINARY DRIVE MOV CH,CBIC ;REENTER LOGICAL DRIVE # MOV CL,4 SHL CH,CL AND DPELUN[BP],DPEREAL OR DPELUN[BP],CH ; CBTF4: POP CX INC CL ;ROUND ROBIN TO NEXT DRIVE DEC DL ;COUNT THIS ONE AS DONE JZ $+5 JMP CBTF1 RET ;* PLACE MAPPED DRIVE # INTO MAP DRIVE TABLE ; 'CBIB'=MAPPED DRIVE # CBTF6: LEA BX,BDMAP ;CALCULATE MAP TABLE ENTRY ADDRESS MOV AL,CBIC CBW ADD BX,AX MOV AL,CBIB MOV ES: [BX],AL ;PLACE MAPPED DRIVE # THERE INC CBIC ;BUMP VALUE NEXT LOGICAL DRIVE # RET ;** CHKLAB - CHECK CHECKSUM OF LABEL ; ; ENTRY: (SI)=ADDRESS OF LABEL ; EXIT: PSW/Z=STATUS ; 0=BAD CHECKSUM , 1=GOOD CHECKSUM ; USES: AL,CX,SI ; CHKLAB: XOR AL,AL ;ZERO ACCUMULATOR MOV CX,LABLEN ;COUNT CHKLAB1: ADD AL,[SI] ;ADD VALUES INC SI LOOP CHKLAB1 INC AL ;INC CHECKSUM VALUE AND SET/RESET PSW/Z RET ;** CPSEC - CALCULATE PHYSICAL SECTOR ; ; ENTRY: 'REQSEC'=REQUESTED CP/M SECTOR # ; (BX)=ADDRESS OF BUFFER HEADER ; EXIT: (AX),'PHYSEC'=PHYSICAL SECTOR # ; USES: AX,DI ; CPSEC: MOV AX,REQSEC MOV DI,BUFDPE[BX] CMP REQTRK,0 JNE CPSEC1 TEST DPEFLAG[DI],DPET0SD JNZ CPSEC2 CPSEC1: DIV DPERPS[DI] CBW CPSEC2: MOV PHYSEC,AX RET ;** DISPATCHER ; SWAP85: OUT ZPSP,AL ;OUTPUT SWAP VALUE TO SWAP PORT JMPS DISPATCH ;FLUSH PIPELINE DISPATCH: XOR BH,BH MOV BL,COMFUNC ;GET BIOS FUNCTION # CMP BX,TABLEL ;CHECK RANGE JA SWAP851 ; BR IF OUT OF RANGE SHL BX,1 CALL TABLE[BX] ;CALL APPROPRIATE HANDLER SWAP851: INT SWISWAP ;SWAP TO 8085 PROCESSOR ; UNUSED DISPATCH ENTRY UNUSED: RET ;** ERRRPT - REPORT DISK ERRORS ; ; ENTRY: (AL)=ERROR STATUS BYTE ; (BX)=ADDRESS OF BUFFER HEADER INFO ; 'PHYTRK'=TRACK # ; 'PHYSEC'=SECTOR # ; 'PHYSID','PHYSIDN'=SIDE INFO ; 'LSIO'=FLAG INDICATING LOGICAL SECTOR I/O RATHER THAN ; TRACK/SIDE/SECTOR ; EXIT: NONE ; USES: CX,SI,DI ; ERRRPT: TEST DSKOP,DSKOPS ;Q. ERROR DURING 1ST TIME SELECT ; JNZ ERRRPT4 ; BR IF YES JZ $+5 JMP ERRRPT4 PUSH AX LEA DI,ERRMSG6 ;STATUS BYTE CALL HEXB PUSH ES ;'READ' OR 'WRITE' ERROR MOV AX,DS MOV ES,AX LEA SI,RDEMSG TEST DSKOP,NOT (DSKOPR+DSKOPRA) JZ ERRRPT1 LEA SI,WREMSG ERRRPT1: LEA DI,ERRMSG1 MOV CX,5 CLD REP MOVSB POP ES MOV AL,BUFDRV[BX] ;DRIVE NAME ADD AL,'A' MOV ERRMSG2,AL PUSH BX ;PRINT ERROR MSG SO FAR LEA SI,ERRMSG CALL PMSG POP BX CMP LSIO,1 ;Q. LOGICAL SECTOR I/O DEVICE JE ERRRPT2A ; BR IF YES MOV AX,PHYTRK ;TRACK # LEA DI,ERRMSG3 CALL HEXW XOR AL,AL ;SIDE # MOV DI,BUFDPE[BX] TEST DPEFLAG[DI],DPE2S JZ ERRRPT2 MOV AL,PHYSIDN ERRRPT2: LEA DI,ERRMSG4 CALL HEXN PUSH BX ;AGAIN PRINT ERROR MSG SO FAR LEA SI,ERRMSG7 CALL PMSG POP BX ERRRPT2A: TEST DSKOP,DSKOPR+DSKOPW ;SECTOR # JZ ERRRPT3 MOV AX,PHYSEC INC AX CMP LSIO,1 JNE ERRRPT2B ADD AX,PHYTRK DEC AX ERRRPT2B: LEA DI,ERRMSG5 CALL HEXW PUSH BX ;AGAIN PRINT ERROR MSG SO FAR LEA SI,ERRMSG8 CALL PMSG POP BX ERRRPT3: PUSH BX LEA SI,CRLF CALL PMSG POP BX POP AX ERRRPT4: RET ;** EXDSES -- EXCHANGE DS AND ES ; EXDSES: PUSH DS PUSH ES POP DS POP ES RET ;** GETCHR - GET CHARACTER FROM CON: (FLUSHING TYPEAHEAD BUFFER ; BEFORE HAND IF NECESSARY ; ; ENTRY: NONE ; EXIT: (AL)=CHARACTER ; USES: AL ; GETCHR: MOV AL,IOBYTE ;GET IOBYTE AND AL,003H ;Q. CON:=CRT: CMP AL,1 JNE GETCHR1 ; BR IF NOT CALL FLCRT ;FLUSH CRT: TYPE AHEAD BUFFER GETCHR1: JMP CONINE ;RETURN VIA 'CONINE' ;** HEXW, HEXB, HEXN - CONVERT HEX VALUES TO ASCII ; ; HEXW - WORD ; ENTRY: (AX)=HEX VALUE ; ; HEXB - BYTE ; ENTRY: (AL)=HEX VALUE ; ; HEXN - LOW ORDER NIBBLE ; ENTRY: (AL)=HEX VALUE ; ; ENTRY: (DI)=ADDRESS OF START OF OUTPUT AREA TO RECEIVE ASCII ; EXIT: NONE ; USES: AX,DI ; HEXW: XCHG AL,AH CALL HEXB MOV AL,AH HEXB: PUSH AX SHR AL,1 SHR AL,1 SHR AL,1 SHR AL,1 CALL HEXN POP AX HEXN: AND AL,00FH ADD AL,090H DAA ADC AL,040H DAA MOV [DI],AL INC DI RET ;** PMSG -- PRINT MESSAGE ON CONSOLE ; ; ENTRY: (SI)=ADDRESS OF MESSAGE ENDING WITH 'CPMEOM' CHARACTER ; THE 'CPMEOM' CHARACTER IS NOT PRINTED ; EXIT: NONE ; USES: ALL ; PMSG: LODSB CMP AL,CPMEOM JZ PMSG1 MOV COMRC,AL CALL CONOUTE JMPS PMSG PMSG1: RET ;** UPC - TRANSLATE (AL) TO UPPERCASE ; ; ENTRY: (AL)=CHARACTER ; EXIT: (AL)=TRANSLATED CHARACTER ; USES: AL ; UPC: CMP AL,'a' ;CHECK IF LOWER CASE JB UPC1 CMP AL,'z' JA UPC1 ; BR IF NOT AND AL,05FH ;TRANSLATE TO UPPERCASE UPC1: RET EJECT ;*** DATA STORAGE ; X EQU OFFSET $ DSEG ORG X MTRMSG RB 0 ;ROM MONITOR DATA AREA TOO LARGE DB CR,LF,'MONITOR ROM DATA AREA IS TOO LARGE',CPMEOM FNTMSG RB 0 ;ROM FONT TABLE TOO LARGE DB CR,LF,'MONITOR ROM FONT TABLE IS LARGER THAN BIOS ' DB 'FONT TABLE AREA',CPMEOM BUFMSG RB 0 ;NOT ENOUGH MEMORY FOR DISK BUFFERS DB CR,LF,'NOT ENOUGH MEMORY FOR DISK BUFFERS',CPMEOM SIGNON RB 0 ;SIGNON MESSAGE DB CR,LF,LF DB 'CP/M-85 VERSION 2.2' IF EXPER DB 'x' ENDIF IF NOT EXPER DB '.' ENDIF DB BVERSN/100+'0',(BVERSN MOD 100)/10+'0',(BVERSN MOD 10)+'0' IF BREVSN NE ' ' DB BREVSN ENDIF DB ' ' DB BMO/10+'0',(BMO MOD 10)+'0','/' DB BDY/10+'0',(BDY MOD 10)+'0','/' DB BYR/10+'0',(BYR MOD 10)+'0' DB CR,LF,LF,CPMEOM MNMSG RB 0 ;MOUNT MESSAGE DB CR,LF,'PUT DISK ' MNMSGA DB '? IN DRIVE ' MNMSGB DB '?: AND PRESS RETURN',CPMEOM ERRMSG RB 0 ;HARD DISK ERROR MESSAGE DB CR,LF,LF,'HARD ' ERRMSG1 DB '????? ERROR ON DRIVE ' ERRMSG2 DB '?: STATUS ' ERRMSG6 DB '??',CPMEOM ERRMSG7 DB ' TRACK ' ERRMSG3 DB '???? SIDE ' ERRMSG4 DB '?',CPMEOM ERRMSG8 DB ' SECTOR ' ERRMSG5 DB '????',CPMEOM RDEMSG DB 'READ ' WREMSG DB 'WRITE' AIMSG DB 'PRESS TO ABORT, TO IGNORE: ',CPMEOM CRLF RB 0 DB CR,LF,CPMEOM TIMERRM RB 0 ;TIMER BROKE MSG DB BELL,CR,LF,'THE TIMER IS BROKE',CR,LF,CPMEOM DIV0MSG RB 0 ;DIVIDE BY 0 ERROR MESSAGE DB CR,LF,LF,'DIVIDE BY ZERO INTERRUPT',CR,LF,LF,CPMEOM PBEMSG RB 0 ;PARITY OR BUSS ERROR MESSAGE DB CR,LF,LF,'ERROR - MEMORY PARITY OR BUSS',CR,LF,LF,CPMEOM WILDMSG RB 0 ;WILD INTERRUPT MESSAGE DB CR,LF,LF,'WILD INTERRUPT',CR,LF,LF,CPMEOM DMPMSG RB 0 ;REGISTER DUMP DB 'F =' DMPFLG DB '???? IP=' DMPIP DB '???? CS=' DMPCS DB '???? DS=' DMPDS DB '???? ES=' DMPES DB '???? SS=' DMPSS DB '???? SP=' DMPSP DB '????',CR,LF,'AX=' DMPAX DB '???? BX=' DMPBX DB '???? CX=' DMPCX DB '???? DX=' DMPDX DB '???? DI=' DMPDI DB '???? SI=' DMPSI DB '???? BP=' DMPBP DB '????',CPMEOM HLTMSG RB 0 ;SYSTEM HALT MESSAGE DB CR,LF,LF,'SYSTEM HALT',CR,LF,LF,CPMEOM HINTVO RW 0 ;HARDWARE INTERRUPT VECTOR OFFSET TABLE DW OFFSET INTPBE ; MASTER 0 DW OFFSET INTWILD ; MASTER 1 DW OFFSET INTTIM ; MASTER 2 DW OFFSET INTWILD ; MASTER 3 DW OFFSET INTWILD ; MASTER 4 DW OFFSET INTWILD ; MASTER 5 DW OFFSET INTLVK ; MASTER 6 DW OFFSET INTWILD ; MASTER 7 DW OFFSET INTWILD ; SLAVE 0 DW OFFSET INTWILD ; SLAVE 1 DW OFFSET INTWILD ; SLAVE 2 DW OFFSET INTWILD ; SLAVE 3 DW OFFSET INTWILD ; SLAVE 4 DW OFFSET INTWILD ; SLAVE 5 DW OFFSET INTWILD ; SLAVE 6 DW OFFSET INTWILD ; SLAVE 7 DW OFFSET INTX2 ; MASTER EXIT ROUTINE DW OFFSET INTX1 ; SLAVE EXIT ROUTINE DRVRTBL RW 0 ;DEVICE DRIVER DISPATCH TABLE DW 0 ; NON-EXISTANT DW OFFSET DRVR207 ; Z207 DW OFFSET DRVR217 ; Z217 DW 0 DW 0 DW 0 DW 0 DW 0 TABLE RW 0 ;DISPATCH TABLE DW OFFSET UNUSED ; COLD BOOT DW OFFSET WBOOTE ; WARM BOOT DW OFFSET CONSTE ; CONSOLE STATUS DW OFFSET CONINE ; CONSOLE INPUT DW OFFSET CONOUTE ; CONSOLE OUTPUT DW OFFSET LSTOUTE ; LIST OUTPUT DW OFFSET PUNOUTE ; PUNCH OUTPUT DW OFFSET RDRINE ; READER INPUT DW OFFSET HOMEE ; HOME HEAD DW OFFSET SETDSKE ; SET DISK DRIVE DW OFFSET SETTRKE ; SET TRACK DW OFFSET SETSECE ; SET SECTOR DW OFFSET SETDMAE ; SET DMA DW OFFSET READE ; READ CP/M SECTOR DW OFFSET WRITEE ; WRITE CP/M SECTOR DW OFFSET LSTSTE ; LIST STATUS DW OFFSET SECTRNE ; SECTOR TRANSLATE DW OFFSET FORMATE ; FORMAT DW OFFSET RDTRKE ; READ TRACK DW OFFSET WRTRKE ; WRITE TRACK DW OFFSET WPCE ; WRITE PROTECT CHECK DW OFFSET CLRBUFD ; CLEAR BUFFERS FOR DRIVE TABLEL EQU (OFFSET $ - OFFSET TABLE)/2 CBIC DB 0 ;LOGICAL DRIVE # (DRIVE TABLE FILL) DSKOP DB 0 ;DISK OPERATIONS IN PROGRESS DEVCTL DB 0 ;1797 DEVICE CONTROL REGISTER SIDE207 DB FDFSS1 ;1797 SIDE SELECT VALUE LAST USED ; Z207 8" DRIVE TABLES TBL207 RW 0 DW Z2071S ;SINGLE DENSITY / SINGLE SIDED / 128 DW 0 ;SINGLE DENSITY / SINGLE SIDED / 256 DW 0 ;SINGLE DENSITY / SINGLE SIDED / 512 DW 0 ;SINGLE DENSITY / SINGLE SIDED /1024 DW Z2072S ;SINGLE DENSITY / DOUBLE SIDED / 128 DW 0 ;SINGLE DENSITY / DOUBLE SIDED / 256 DW 0 ;SINGLE DENSITY / DOUBLE SIDED / 512 DW 0 ;SINGLE DENSITY / DOUBLE SIDED /1024 DW 0 ;DOUBLE DENSITY / SINGLE SIDED / 128 DW Z2071D1 ;DOUBLE DENSITY / SINGLE SIDED / 256 DW 0 ;DOUBLE DENSITY / SINGLE SIDED / 512 DW Z2071D2 ;DOUBLE DENSITY / SINGLE SIDED /1024 DW 0 ;DOUBLE DENSITY / DOUBLE SIDED / 128 DW Z2072D1 ;DOUBLE DENSITY / DOUBLE SIDED / 256 DW 0 ;DOUBLE DENSITY / DOUBLE SIDED / 512 DW Z2072D2 ;DOUBLE DENSITY / DOUBLE SIDED /1024 Z2071S DB 1,1,8 ;SINGLE DENSITY / SINGLE SIDED / 128 DW 26 DB 3,7,0 DW 242,63 DB 0C0H,0 DW 16,2 Z2072S DB 1,1,16 ;SINGLE DENSITY / DOUBLE SIDED / 128 DW 26 DB 4,15,1 DW 246,127 DB 0C0H,0 DW 32,2 Z2071D1 DB 2,2,16 ;DOUBLE DENSITY / SINGLE SIDED / 256 DW 52 DB 4,15,0 DW 242,127 DB 0C0H,0 DW 32,2 Z2071D2 DB 0,8,16 ;DOUBLE DENSITY / SINGLE SIDED /1024 DW 64 DB 4,15,0 DW 299,127 DB 0C0H,0 DW 32,2 Z2072D1 DB 2,2,16 ;DOUBLE DENSITY / DOUBLE SIDED / 256 DW 52 DB 4,15,0 DW 493,255 DB 0F0H,0 DW 64,2 Z2072D2 DB 0,8,16 ;DOUBLE DENSITY / DOUBLE SIDED /1024 DW 64 DB 4,15,0 DW 607,255 DB 0F0H,0 DW 64,2 ; PATCH RB 128 ;PATCH AREA ; BANK1 RW 1 ;SEGMENT ADDRESS FOR BANK 1 CCPORG0 RW 1 ;CP/M-85 CCP ORIGIN IN BANK 0 COPY CCPORG1 RW 1 ;CP/M-85 CCP ORIGIN IN BANK 1 CBTFA RB 1 ;DRIVE TABLE FILL CYCLE INDICATOR CBTIA RW 1 ;ADDRESS OF REAL DRIVE DPE CBIB RB 1 ;MAPPED DRIVE # DMAPTR RW 1 ;DMA ADDRESS FVFLG RB 1 ;FORMAT VERIFY FLAG HSTPTR RW 1 ;HOST BUFFER POINTER LSIO RB 1 ;LOGICAL SECTOR I/O FLAG PHYDRV RB 1 ;PHYSICAL DRIVE # PHYDPE RW 1 ;PHYSICAL DPE PHYSID RB 1 ;PHYSICAL SIDE PHYSIDN RB 1 ;PHYSICAL SIDE NUMBER PHYTRK RW 1 ;PHYSICAL TRACK PHYSEC RW 1 ;PHYSICAL SECTOR REQDRV RB 1 ;REQUESTED DRIVE REQTRK RW 1 ;REQUESTED TRACK REQSEC RW 1 ;REQUESTED SECTOR SECCNT RB 1 ;PHYSICAL SECTORS PER TRACK SEC1ST RB 1 ;1ST SECTOR # FOR OPERATION COUNT RW 1 ;BYTES PER PHYSICAL SECTOR RETRIES RB 1 ;I/O RETRY COUNTER HLDDLYF RB 1 ;1797 DELAY FLAG ERRTYP RB 1 ;ERROR TYPE (STATUS BYTE) XLATES RW 1 ;ADDRESS OF XLATE TABLE ADDRESSES RDABUF RB FDRAL ;READ ADDRESS BUFFER OMDSEG RW 1 ;ORIGINAL MONITOR DATA SEGMENT VALUE PREREAD RB 1 ;DO PREREAD FLAG FLDERR RB 1 ;FLUSH DRIVE ERROR ACCUMULATOR PTICCNT RW 1 ;PREVIOUS TIMER 1 COUNT ; KEYBOARD TYPE-AHEAD BUFFER KEYCNT RB 1 ;CHARACTER COUNT KEYPUT RW 1 ;PUT POINTER KEYGET RW 1 ;GET POINTER KEYBUF RB 80 ;BUFFER KEYBUFL EQU OFFSET $ - OFFSET KEYBUF ;BUFFER SIZE KEYBUFF EQU KEYBUFL-10 ;KEYBOARD BUFFER FULL VALUE ; ALTERNATE CHARACTER FONT TABLE ALTFNTL EQU (256-32)*9 ;LENGTH ALTFNT RB ALTFNTL ;AREA IF OFFSET $ GE BLDRP0 %: BIOS88 TOO LARGE ENDIF ; DISK BUFFER AND BUFFER HANDLING STORAGE FSTBUF RW 1 ;POINTER TO FIRST ELEMENT LSTBUF RW 1 ;POINTER TO LAST ELEMENT DMYHDR RB BUFHDRL ;DUMMY BUFFER HEADER HEADER RB BUFCNT*BUFHDRL ;DISK BUFFER HEADER INFO STACK SECFLGL EQU 26 SECFLG RB BUFCNT*SECFLGL ;DIRTY SECTOR FLAGS (1=DIRTY) ERRFLGL EQU 26 ERRFLG RB BUFCNT*ERRFLGL ;SECTOR ERROR FLAGS BUFFERL EQU 9*1024 BUFFER RB BUFCNT*BUFFERL ;BUFFER AREAS B88END EQU OFFSET $ END  ;** 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 101 ;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 03 ;DATE BDY EQU 10 BYR EQU 83 NDRIVES EQU 6 ;MAXIMUM NUMBER OF DRIVE TABLES ; ORG 0042H ;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  TITLE 'CP/M-85 BIOS RELOCATOR 06 APR 1982' ;*** ; ; CP/M-85 BIOS RELOCATOR. ; ; THIS CODE RESIDES IN THE FILE 'BIOS85.SYS' ALONG WITH THE 8085 ; CODED PORTION OF THE REAL BIOS. THE BIOS LOADER READS THE FILE ; INTO MEMORY, THEN TRANSFERS CONTROL TO THIS RELOCATOR TO PLACE ; THE 8085 CODED PORTION OF THE REAL BIOS INTO ITS PROPER SPOT ; IN MEMORY. ; REL0 EQU 0 ASM86 EQU 0 ;** EXTRA PSEUDO OPS FOR USE WITH MAC ; RB MACRO A DS A ENDM RW MACRO A DS 2*A ENDM ;*** EQUATES ; ;** Z-MACHINE MEMORY MAP UTILIZATION EQUATES ; BOOTORG EQU 0400H ;BOOT CODE LOAD ADDRESS BCODEL EQU 256+32 ;MAXIMUM BOOT CODE LENGTH BLDR88 EQU BOOTORG+BCODEL ;BIOS LOADER (8088 PORTION) BLDR88L EQU 64 ;MAXIMUM BIOS LOADER (8088) LENGTH B88STK EQU 2*1024 ;8088 STACK AREA B88DAT EQU B88STK ;MONITOR ROM DATA AREA START ADDR BIOS88 EQU 4*1024 ;WHERE 8088 CODE OF BIOS WILL RESIDE BLDRP0 EQU 16*1024 ;BIOS LOADER PAGE ZERO BIAS VALUE IF REL0 BLOADER EQU 0000H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF IF NOT REL0 BLOADER EQU 0100H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF BLDR85L EQU 8*128-BCODEL-BLDR88L ;MAXIMUM BIOS LOADER (8085) LENGTH BOOT85 EQU 0000H ;WHERE 8085 STARTS AFTER PROCESSOR SWAP SWISWAP EQU 0FEH ;SWI FOR SWAPPING PROCESSORS SWAPVEC EQU SWISWAP*4 ; VECTOR ADDRESS BIAS EQU BLDRP0 ;** 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 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 ; 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 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 ;** MISCELLANEOUS EQUATES ; BIOSREL EQU TPA+128 ;ORIGIN FOR RELOCATOR RELMODL EQU TPA+1 ;SLOT FOR LENGTH OF RELOCATABLE MODULE RELMOD EQU TPA+256 ;START OF RELOCATABLE MODULE PAGE ;*** MAIN PROGRAM ; ORG BIOSREL LXI SP,TPA ;INIT (SP) ; COMPUTE RELOCATION FACTOR LHLD BBIOS ;GET ADDR OF BIOS MEMORY AREA MOV A,H ;SAVE HIGH ORDER BYTE AS STA RELFCT ; THE RELOCATION FACTOR ; COPY RELOCATABLE BIOS TO BIOS MEMORY AREA XCHG ;(DE) = ADDR OF BIOS MEMORY AREA LHLD RELMODL ;GET RELOCATABLE MODULE LENGTH MOV B,H MOV C,L LXI H,RELMOD ;GET START OF RELOCATABLE MODULE COPY: MOV A,M ;DO COPY STAX D INX H INX D DCX B MOV A,B ORA C JNZ COPY ; DO RELOCATION LHLD RELMODL ;COMPUTE START OF RELOCATION TABLE MOV B,H ; (BC)=# OF BYTES IN MOV C,L ; RELOCATABLE MODULE LXI H,RELMOD DAD B XCHG ;(DE)=START OF RELOCATION TABLE LHLD BBIOS XCHG ;(DE)=START OF BIOS MEMORY AREA ;(HL)=RELOCATION TABLE POINTER RELOC1: PUSH H ;SAVE THE RELOCATION TABLE POINTER MOV H,M ;GET NEXT RELOCATION TABLE BYTE MVI L,8 ; WHICH CONTAINS RELOCATION FOR 8 ADDRS RELOC2: MOV A,H ;GET THE RELOCATION BYTE RAL ;ROTATE LEFT MOV H,A ;RESAVE IT JNC RELOC3 ;IF NO CARRY, THEN NO NEED TO ADJUST LDAX D ;GET BIOS BYTE ADI 0 ;ADJUST BYTE BY RELOCATION FACTOR RELFCT EQU $-1 STAX D ;REPLACE BIOS BYTE WITH UPDATED VALUE RELOC3: INX D ;POINT TO NEXT BIOS BYTE DCX B ;COUNT THIS BYTE AS DONE MOV A,B ;IS ENTIRE MODULE RELOCATED ORA C JZ DOCOLD ;BR IF DONE DCR L ;RELOCATION BYTE COUNTER JNZ RELOC2 ;BR IF MORE INFO IN THIS BYTE POP H ;RECAL POINTER TO RELOCATION TABLE INX H ;BUMP POINTER JMP RELOC1 ;CONTINUE RELOCATION ; DONE WITH RELOCATION. DO COLD BOOT. DOCOLD: LHLD BBIOS ;GET ADDR OF BIOS MEMORY AREA PCHL ;1ST INSTRUCTION THERE IS ; JUMP TO COLD BOOT IF ($-BIOSREL) GT 128 %: RELOCATOR IS TOO LARGE ENDIF END ;1ST INSTRUCTION THERE IS ; JUMP TO COLD BOOT IF ($-BIOSREL) GT 128 %: RELO ;** 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 ; FLAG BYTE 2 CIOW4A EQU CIOEAH ; SENT, WAITING FOR CIOW4D EQU CIODCH ;WAITING FOR ;** 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 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 ; 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 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  ;** 6821 PERIPHERAL INTERFACE ADAPTER EQUATES ; ; REGISTER DISPLACEMENTS PIADATA EQU 0 ;PERIPHERAL DATA REGISTER A PIADDRA EQU 0 ;DATA DIRECTION REGISTER A PIACTLA EQU 1 ;CONTROL REGISTER A PIADATB EQU 2 ;PERIPHERAL DATA REGISTER B PIADDRB EQU 2 ;DATA DIRECTION REGISTER B PIACTLB EQU 3 ;CONTROL REGISTER B ; CONTROL WORD FORMAT PIAC1 EQU 00000011B ;CONTROL OF CA1(CB1) INTERRUPT LINE PIAC10 EQU 00H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS DISABLED PIAC11 EQU 01H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS ENABLED PIAC12 EQU 02H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS DISABLED PIAC13 EQU 03H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS ENABLED PIADDAC EQU 00000100B ;DATA DIRECTION ACCESS CONTROL BIT ; 0=DATA DIRECTION REG , 1=PERIPHERAL DATA REG PIAC2 EQU 00111000B ;CONTROL OF CA2(CB2) ; INPUT MODES PIAC20 EQU 00H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS DISABLED PIAC21 EQU 08H ; ACTIVE TRANSITION 1->0 ; IRQ PIN IS ENABLED PIAC22 EQU 10H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS DISABLED PIAC23 EQU 18H ; ACTIVE TRANSITION 0->1 ; IRQ PIN IS ENABLED ; OUTPUT MODES PIAC24 EQU 20H ; 0 ON R(W) OPERATION , 1 ON ACTIVE CA1(CB1) PIAC25 EQU 28H ; 0 ON R(W) OPERATION , 1 ON E AFTER DESELECT PIAC26 EQU 30H ; RESET PIAC27 EQU 38H ; SET PIAIRQ2 EQU 01000000B ;IRQ FOR CA2(CB2) PIAIRQ1 EQU 10000000B ;IRQ FOR CA1(CB1)  ;** DEF8253 - 8253 PROGRAMMABLE INTERVAL TIMER DEFINITIONS ; ; PORT DISPLACEMENTS PITC0 EQU 000H ;COUNTER 0 PITC1 EQU 001H ;COUNTER 1 PITC2 EQU 002H ;COUNTER 2 PITCW EQU 003H ;CONTROL WORD ; CONTROL WORD PITSC EQU 11000000B ;SELECT COUNTER PITSC0 EQU 000H ; 0 PITSC1 EQU 040H ; 1 PITSC2 EQU 080H ; 2 PITRL EQU 00110000B ;READ/LOAD PITRLCL EQU 000H ; COUNTER LATCHING OPERATION PITRLMB EQU 010H ; MSB PITRLLB EQU 020H ; LSB PITRLW EQU 030H ; WORD PITM EQU 00001110B ;MODE PITMITC EQU 000H ; 0 - INTERRUPT ON TERMINAL COUNT PITMP1S EQU 002H ; 1 - PROGRAMMABLE ONE SHOT PITMRG EQU 004H ; 2 - RATE GENERATOR PITMSW EQU 006H ; 3 - SQUARE WAVE RATE GENERATOR PITMSTS EQU 008H ; 4 - SOFTWARE TRIGGERED STROBE PITMHTS EQU 00AH ; 5 - HARDWARE TRIGGERED STROBE PITBCD EQU 00000001B ;0 = 16 BIT BINARY COUNTER ;1 = 4 DIGIT BCD COUNTER  ;** 8259A EQUATES ; ; REGISTER DISPLACEMENTS ICW1 EQU 0 ;ICW1 ICW2 EQU 1 ;ICW2 ICW3 EQU 1 ;ICW3 ICW4 EQU 1 ;ICW4 OCW1 EQU 1 ;OCW1 OCW2 EQU 0 ;OCW2 OCW3 EQU 0 ;OCW3 ; ICW1 REGISTER FLAGS ICW1A EQU 11100000B ;A7-A5 ICW1OP EQU 00010000B ;1=ICW1 , 0=OCW'S ICW1LT EQU 00001000B ;TRIGGER MODE (0=EDGE , 1=LEVEL) ICW1ADI EQU 00000100B ;CALL INTERVAL (0=8 , 1=4) ICW1SNG EQU 00000010B ;0=CASCADE , 1=SINGLE ICW1I4 EQU 00000001B ;ICW4 (0=NOT USED , 1=USED) ; ICW3 REGISTER FLAGS (MASTER DEVICE) ICW3S0 EQU 00000001B ;IR INPUT 0 HAS SLAVE ICW3S1 EQU 00000010B ;IR INPUT 1 HAS SLAVE ICW3S2 EQU 00000100B ;IR INPUT 2 HAS SLAVE ICW3S3 EQU 00001000B ;IR INPUT 3 HAS SLAVE ICW3S4 EQU 00010000B ;IR INPUT 4 HAS SLAVE ICW3S5 EQU 00100000B ;IR INPUT 5 HAS SLAVE ICW3S6 EQU 01000000B ;IR INPUT 6 HAS SLAVE ICW3S7 EQU 10000000B ;IR INPUT 7 HAS SLAVE ; ICW3 REGISTER FLAGS (SLAVE DEVICE) ICW3SID EQU 00000111B ;SLAVE ID MASK ; ICW4 REGISTER FLAGS ICW4SFN EQU 00010000B ;1=SPECIAL FULLY NESTED MODE ICW4BMS EQU 00001000B ;BUFFERED MODE SLAVE ICW4BMM EQU 00001100B ;BUFFERED MODE MASTER ICW4AE EQU 00000010B ;AUTO EOI ICW4UPM EQU 00000001B ;MICRO-PROCESSOR MODE ; (0=8080/85 , 1=8086/88) ; OCW1 REGISTER (INTERRUPT MASK REGISTER) ; 0=ENABLED , 1=DISABLED OCW1IM0 EQU 00000001B ;IR0 OCW1IM1 EQU 00000010B ;IR1 OCW1IM2 EQU 00000100B ;IR2 OCW1IM3 EQU 00001000B ;IR3 OCW1IM4 EQU 00010000B ;IR4 OCW1IM5 EQU 00100000B ;IR5 OCW1IM6 EQU 01000000B ;IR6 OCW1IM7 EQU 10000000B ;IR7 ; OCW2 REGISTER OCW2OP EQU 00000000B ;OCW2 OCW2R EQU 10000000B ;PRIORITY ROTATION OCW2SL EQU 01000000B ;SELECT A SPECIFIC LEVEL OCW2EOI EQU 00100000B ;END OF INTERRUPT COMMAND OCW2L EQU 00000111B ;IR LEVEL TO BE ACTED UPON ; OCW3 REGISTER OCW3OP EQU 00001000B ;OCW3 OCW3RSM EQU 01000000B ;RESET SPECIAL MASK MODE OCW3SSM EQU 01100000B ;SET SPECIAL MASK MODE OCW3P EQU 00000100B ;POLL COMMAND OCW3RIR EQU 00000010B ;READ IR REG OCW3RIS EQU 00000011B ;READ IS REG  ;** EP2DEF -- EQUATES FOR ENHANCED PROGRAMMABLE COMMUNICATION ; INTERFACE CHIP 2661-2. ; ; PORT DISPLACEMENTS EPDATA EQU 0 ;DATA EPSTAT EQU 1 ;STATUS EPSYN EQU 1 ;SYN1/SYN2/DLE EPMODE EQU 2 ;MODE EPCMD EQU 3 ;COMMAND ; STATUS REGISTER EPTXR EQU 00000001B ;TRANSMITTER READY EPRXR EQU 00000010B ;RECEIVER READY EPTXE EQU 00000100B ;TRANSMITTER EMPTY EPDSC EQU 00000100B ;DATA SET CHANGE EPPE EQU 00001000B ;PARITY ERROR EPOE EQU 00010000B ;OVERRUN ERROR EPFE EQU 00100000B ;FRAME ERROR EPSD EQU 00100000B ;SYNC DETECTED EPDCD EQU 01000000B ;DATA CARRIER DETECT EPDSR EQU 10000000B ;DATA SET READY ; MODE REGISTER 1 EPMBRF EQU 00000011B ;MODE AND BAUDRATE FACTOR EPS1X EQU 000H ; SYNCHRONOUS 1X RATE EPA1X EQU 001H ; ASYNCHRONOUS 1X RATE EPA16X EQU 002H ; ASYNCHRONOUS 16X RATE EPA64X EQU 003H ; ASYNCHRONOUS 64X RATE EPCL EQU 00001100B ;CHARACTER LENGTH EPCL5 EQU 000H ; LENGTH 5 EPCL6 EQU 004H ; LENGTH 6 EPCL7 EQU 008H ; LENGTH 7 EPCL8 EQU 00CH ; LENGTH 8 EPPC EQU 00010000B ;PARITY CONTROL (0=DISABLED , 1=ENABLED) EPPT EQU 00100000B ;PARITY TYPE (0=ODD , 1=EVEN) EPASBL EQU 11000000B ;ASYNCHRONOUS STOP BIT LENGTH EPSB1 EQU 040H ; LENGTH 1 EPSB15 EQU 080H ; LENGTH 1.5 EPSB2 EQU 0C0H ; LENGTH 2 EPSTC EQU 01000000B ;SYNCHRONOUS TRANSPARENCY CONTROL ; (0=NORMAL , 1=TRANSPARENT) EPNSC EQU 10000000B ;NUMBER OF SYNC CHARACTERS ; (0=DOUBLE , 1=SINGLE) ; MODE REGISTER 2 EPBRS EQU 00001111B ;BAUD RATE SELECTION EPMR2U EQU 11110000B ;SEE TEXT ; COMMAND REGISTER EPTXEN EQU 00000001B ;TRANSMITTER ENABLE EPDTR EQU 00000010B ;DATA TERMINAL READY EPRXEN EQU 00000100B ;RECEIVER ENABLE EPSBRK EQU 00001000B ;SEND BREAK (ASYNC) EPSDLE EQU 00001000B ;SEND DLE (SYNC) EPRESE EQU 00010000B ;RESET STATUS ERRORS EPRTS EQU 00100000B ;REQUEST TO SEND EPOM EQU 11000000B ;OPERATING MODE EPNORM EQU 000H ; NORMAL EPOM1 EQU 040H ; MODE 1 EPOMLL EQU 080H ; LOCAL LOOP BACK EPOMRL EQU 0C0H ; REMOTE LOOP BACK ; BAUDRATE SELECTION VALUES EPB455 EQU 0 ;45.5 EPB050 EQU 1 ;50 EPB075 EQU 2 ;75 EPB110 EQU 3 ;110 EPB134 EQU 4 ;134.5 EPB150 EQU 5 ;150 EPB300 EQU 6 ;300 EPB600 EQU 7 ;600 EPB120 EQU 8 ;1200 EPB180 EQU 9 ;1800 EPB200 EQU 10 ;2000 EPB240 EQU 11 ;2400 EPB480 EQU 12 ;4800 EPB960 EQU 13 ;9600 EPB192 EQU 14 ;19200 EPB384 EQU 15 ;38400  ;** EXTRA PSEUDO OPS FOR USE WITH MAC ; RB MACRO A DS A ENDM RW MACRO A DS 2*A ENDM  ;** EXTRA OPCODE DEFINITIONS ; ; JMP IMMEDIATE CODEMACRO JMPI A:D DB 0E9H RELW A ENDM ; JMPF IMMEDIATE CODEMACRO JMPFI A:D,B:D DB 0EAH DW A DW B ENDM ; CALL IMMEDIATE CODEMACRO CALLI A:D DB 0E8H RELW A ENDM ; CALLF IMMEDIATE CODEMACRO CALLFI A:D,B:D DB 09AH DW A DW B ENDM ; PUSH ALL REGS (EXCEPT SP,SS,CS) CODEMACRO PUSHA DB 050H ;PUSH AX DB 053H ;PUSH BX DB 051H ;PUSH CX DB 052H ;PUSH DX DB 055H ;PUSH BP DB 056H ;PUSH SI DB 057H ;PUSH DI DB 01EH ;PUSH DS DB 006H ;PUSH ES ENDM ; POP ALL REGS (USED AFTER 'PUSHA') CODEMACRO POPA DB 007H ;POP ES DB 01FH ;POP DS DB 05FH ;POP DI DB 05EH ;POP SI DB 05DH ;POP BP DB 05AH ;POP DX DB 059H ;POP CX DB 05BH ;POP BX DB 058H ;POP AX ENDM  TITLE 'FORMAT - CP/M-85 FORMAT UTILITY 02 MAR 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 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 ; 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 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 ; 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 101 ;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 03 ;DATE BDY EQU 10 BYR EQU 83 NDRIVES EQU 6 ;MAXIMUM NUMBER OF DRIVE TABLES ; ORG 0042H ;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 STAX D 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,10 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,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 JC F21799 ; BR IF ERROR POP D 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 RDOP10 ;OPTION ERROR LDA FACTOR ;GET FACTOR STA CLIDENS ;PUT IT IN DENSITY BYTE ; JMP RDOP6 ;NEXT OPTION ; ; 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) 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 1 ;# SIDES AIOUNI DS 1 DRTYPE DS 1 FLAG2 DS 1 BUFFER EQU $ ;** 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  ;** 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 ;*** TIMER DRIVER ; ;** INITIALIZATION ; INTIM: PUSHF CLI ; MAKE SURE ALL COUNTER READ CYCLES ARE COMPLETED IN AL,ZTIMER+PITC0 IN AL,ZTIMER+PITC0 IN AL,ZTIMER+PITC1 IN AL,ZTIMER+PITC1 IN AL,ZTIMER+PITC2 IN AL,ZTIMER+PITC2 ; INIT COUNTER MODES MOV AL,PITSC0+PITRLW+PITMSW OUT ZTIMER+PITCW,AL ;COUNTER 0 - SQUARE WAVE GENERATOR MOV AL,PITSC1+PITRLW+PITMITC OUT ZTIMER+PITCW,AL ;COUNTER 1 - EVENT COUNTER MOV AL,PITSC2+PITRLW+PITMITC OUT ZTIMER+PITCW,AL ;COUNTER 2 - INT ON TERMINAL COUNT ; INIT COUNTER VALUES XOR AL,AL ;TIMER 1 OUT ZTIMER+PITC1,AL OUT ZTIMER+PITC1,AL MOV AX,TIMEVAL ;TIMER 0 OUT ZTIMER+PITC0,AL MOV AL,AH OUT ZTIMER+PITC0,AL ; WAIT FOR FIRST RISING CLOCK FROM COUNTER 0 MOV AL,NOT TIMERS0 OUT ZTSTAT,AL XOR CX,CX INTIM1: IN AL,ZTSTAT TEST AL,TIMERS0 LOOPZ INTIM1 JCXZ TIMERR ; CLEAR ANY PENDING INTERRUPTS MOV AL,NOT (TIMERS0+TIMERS2) OUT ZTSTAT,AL ; INIT WORK VARIABLES MOV TIMEFLG,0 MOV PTICCNT,0 MOV TICCNT,0 MOV TICCNT+2,0 POPF RET ;* TIMER NOT RUNNING TIMERR: LEA SI,TIMERRM CALL PMSG HLT ;** TIMER INTERRUPT HANDLER ; INTTIM: PUSHA ;SAVE ALL REGS MOV AX,CS ;GET DS VALUE MOV DS,AX MOV ES,BANK1 ;GET ES VALUE ; CHECK CAUSE OF INTERRUPT IN AL,ZTSTAT ;GET CAUSE OF TIMER INTERRUPT TEST AL,TIMERS0 ;Q. IS IT TIMER 0 JNZ TIM0INT ; BR IF YES TEST AL,TIMERS2 ;Q. IS IT TIMER 2 JNZ TIM2INT ; BR IF YES ;* TIMER INTERRUPT HANDLER EXIT TIMINTX: POPA JMP INTX2 ;* HANDLE TIMER 0 INTERRUPTS TIM0INT: MOV AL,PITSC1+PITRLCL OUT ZTIMER+PITCW,AL ;LATCH COUNTER 1 VALUE IN AL,ZTIMER+PITC1 ;GET COUNTER 1 VALUE MOV AH,AL IN AL,ZTIMER+PITC1 XCHG AH,AL XCHG PTICCNT,AX ;(AX)=PREVIOUS COUNTER VALUE ;'PTICCNT'=CURRENT COUNTER VALUE SUB AX,PTICCNT ;(AX)=# TIC'S ADD TICCNT,AX ;ADD # TIC'S TO 32 BIT TIC COUNTER ADC TICCNT+2,0 MOV AL,NOT TIMERS0 ;CLEAR INTERRUPT OUT ZTSTAT,AL JMPS TIMINTX ;* HANDLE TIMER 2 INTERRUPTS TIM2INT: MOV TIMEFLG,1 ;SET FLAG MOV AL,NOT TIMERS2 ;CLEAR INTERRUPT OUT ZTSTAT,AL JMPS TIMINTX ;** DELAY ROUTINES USING TIMER 2 ; ; MAXIMUM DELAY IS 65536*4 uS (~262 mS) ; ; COUNTER VALUE FOR N mS = N*250 ; COUNTER VALUE FOR N uS = (N+3)/4 ;* WDLY - SET TIMER AND WAIT ; ; ENTRY: (AX)=COUNTER VALUE ; EXIT: NONE ; USES: NONE ; WDLY: CALL NWDLY ;SET TIMER WDLY1: CMP TIMEFLG,0 ;Q. TIME UP JE WDLY1 ; BR IF NOT RET ;* NWDLY - SET TIMER RUNNING AND DO NOT WAIT ; ; ENTRY: (AX)=COUNTER VALUE ; EXIT: NONE ; USES: NONE ; NWDLY: PUSH AX MOV AL,PITSC2+PITRLW+PITMITC OUT ZTIMER+PITCW,AL ;SET MODE (ALSO STOPS TIMER 2) POP AX PUSHF ;DISABLE INTERRUPTS CLI MOV TIMEFLG,0 ;CLEAR TIMER 2 FLAG OUT ZTIMER+PITC2,AL ;INSERT TIMER COUNTER VALUE XCHG AL,AH OUT ZTIMER+PITC2,AL XCHG AL,AH POPF ;RESTORE INTERRUPT STATUS RET  ;** Z-MACHINE TIMER DEFINITIONS ; ; TIMER STATUS FLAGS TIMERS0 EQU 00000001B ;TIMER 0 INTERRUPT TIMERS2 EQU 00000010B ;TIMER 2 INTERRUPT ; TIMER VALUES TIMEVAL EQU 2500 ;10 mS DIVIDE BY N VALUE TINTRVL EQU 10 ;TIMER 1 INTERVAL (IN mS)  ;** 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 ;*** Z207 DEVICE DRIVER ; ;** DRIVER ENTRY JUMP VECTORS ; DRVR207: JMP SEL207 ;SELECT JMP RDT207 ;READ TRACK JMP WRT207 ;WRITE TRACK JMP MNT207 ;MOUNT JMP FMT207 ;FORMAT JMP WPC207 ;WRITE PROTECT CHECK ;** INITIALIZE DRIVE TABLES ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; IN207: ;* RESTORE THE HEAD ON EACH DRIVE TO DETERMINE IF IT EXISTS MOV CX,4 ;# OF Z207 DRIVES LEA BP,DPEBASE ;START ADDRESS OF Z207 DPE'S ADD BP,BBIOS OR DSKOP,DSKOPI ;INDICATE INIT IN PROGRESS IN2071: PUSH CX CALL DS207 ;SELECT DRIVE CALL RST207 ;RESTORE HEAD TEST AL,FDSTK0 ;Q. TRACK 0 INDICATION JNZ IN2073 ; BR IF YES OR DPEFLG2[BP],DPEIMG ;FLAG DRIVE AS IMAGINARY IN2073: TEST DPEUNIT[BP],CONDS8 ;Q. 8" DRIVE JNZ IN2074 ; BR IF YES IN AL,FDAS ;DETERMINE IF 5 1/4" DRIVE IS TEST AL,AS96T ; 48 OR 96 TPI AND INDICATE THIS JZ IN2074 ; IN TABLE OR DPEFLAG[BP],DPE96T IN2074: ADD BP,DPEL ;BUMP TO NEXT DRIVE TABLE POP CX LOOP IN2071 ;LOOP AND CHECK ALL DRIVES AND DSKOP,NOT DSKOPI ;INDICATE INIT DONE CALL DONE207 ;TURN OFF DRIVES ;* DO DRIVE MAPPING & REAL/IMAGINARY TABLE INITIALIZATION PUSH ES MOV ES,.MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA MOV CL,ES: MTRBU ;GET BOOT DEVICE UNIT # MOV AL,ES: MTRBI ;GET BOOT DEVICE INDEX # POP ES CMP AL,1 ;Q. BOOT DEVICE WAS 8" DRIVE JE IN2076 ; BR IF YES ; BOOT DEVICE WAS 5 1/4" DRIVE; BUILD 5 1/4" TABLES THEN 8" TABLES MOV CH,2 ;# DRIVE TABLES MOV DH,0 ;START OF 5 1/4" TABLES CALL CBTFIL ;FILL IN TABLES MOV CL,0 ;UNIT # MOV CH,2 ;# DRIVE TABLES MOV DH,2 ;START OF 8" TABLES CALL CBTFIL ;FILL IN TABLES RET ; BOOT DEVICE WAS 8" DRIVE; BUILD 8" TABLES THEN 5 1/4" TABLES IN2076: MOV CH,2 ;# DRIVE TABLES MOV DH,2 ;START OF 8" TABLES CALL CBTFIL ;FILL IN TABLES MOV CL,0 ;UNIT # MOV CH,2 ;# DRIVE TABLES MOV DH,0 ;START OF 5 1/4" TABLES CALL CBTFIL ;FILL IN TABLES RET ;** SELECT DRIVE FOR 1ST LOGIN ; ; ENTRY: 'PHYDPE'=ADDRESS OF DPE FOR DRIVE ; (BX)=POINTER TO BUFFER HEADER INFO ; 'XLATES'=ADDRESS OF XLATE TABLE ADDRESSES ; EXIT: 'PHYDPE'=STATUS ; 0=ERROR , OTHERWISE SAME AS ON ENTRY ; USES: AX,CX,BP,SI,DI ; SEL207: OR DSKOP,DSKOPS ;INDICATE SELECT OPERATION IN PROGRESS MOV BP,BUFDPE[BX] MOV DPETRK[BP],DPEUNK ;INDICATE DRIVE HEAD POSITION UNKNOWN TEST DPEUNIT[BP],CONDS8 ;Q. 8" DRIVE JZ $+5 JMP SEL2075 ; BR IF 8" DRIVE ;* SELECT ROUTINE FOR 5 1/4" DRIVES ; READ LABEL MOV PHYTRK,0 ;LABEL IS ON TRACK 0 MOV PHYSID,0 ; SIDE 0 MOV PHYSEC,0 ; 1ST SECTOR CALL RDY2070 ;READY CHECK CMP BUFERR[BX],0 ;Q. DRIVE NOT READY ; JE SEL2079 ; BR IF NOT READY JNE $+5 JMP SEL2079 MOV BUFERR[BX],0 ;CLEAR ERROR FLAG CALL DS207 ;SELECT DRIVE CALL RST207 ;RESTORE HEAD MOV COUNT,1024 ;MAXIMUM SECTOR LENGTH MOV DI,BUFBUF[BX] ;USE HOST BUFFER CALL RDS207 ;TRY READING LABEL AT DENSITY TEST AL,AL ; CURRENTLY INDICATED IN TABLES JZ SEL2072 ; BR IF ABLE TO READ LABEL SECTOR XOR DEVCTL,CONSD ;UNABLE TO READ LABEL SECTOR MOV AL,DEVCTL ; CHANGE TO OTHER DENSITY OUT FDCON,AL MOV DI,BUFBUF[BX] ;TRY TO READ LABEL SECTOR AGAIN CALL RDS207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 SEL2072: MOV SI,BUFBUF[BX] ;CHECK CHECKSUM OF LABEL ADD SI,LABEL CALL CHKLAB ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 ; MOVE LABEL INFO TO DPE'S HEATH EXTENSIONS MOV SI,BUFBUF[BX] AND DPEFLAG[BP],DPETYPE+DPE96T MOV AL,LABHTH+(OFFSET DPEFLAG)-(OFFSET DPEHTH) [SI] AND AL,DPEDD+DPE2S OR DPEFLAG[BP],AL ;FLAG BYTE #1 MOV AL,LABHTH+(OFFSET DPERPS)-(OFFSET DPEHTH) [SI] MOV DPERPS[BP],AL ;CP/M RECORDS PER PHYSICAL SECTOR MOV AL,LABHTH+(OFFSET DPERPAB)-(OFFSET DPEHTH) [SI] MOV DPERPAB[BP],AL ;CP/M RECORDS PER ALLOCATION BLOCK AND DPEFLG2[BP],NOT DPE96TM MOV AL,LABHTH+(OFFSET DPEFLG2)-(OFFSET DPEHTH) [SI] AND AL,DPE96TM OR DPEFLG2[BP],AL ;FLAG BYTE #2 ; IF LABEL INDICATES THAT THE MEDIA IS DOUBLE SIDED, THEN ; CHECK OUT THE DRIVE FOR DOUBLE SIDED CAPABILITY TEST DPEFLAG[BP],DPE2S ;Q. DOUBLE SIDED MEDIA JZ SEL2073 ; BR IF NOT MOV PHYSID,FDFSS1 ;TRY TO READ A SECTOR HEADER LEA DI,RDABUF ; ON 2ND SIDE CALL RDA207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 CMP RDABUF+FDRASID,1 ;CHECK SIDE INFO ; JNE SEL2079 ; BR IF NOT 2ND SIDE JE $+5 JMP SEL2079 ; STEP IN 2 TRACKS, READ ADDRESS, AND STEP BACK OUT 2 TRACKS. ; IF READ ADDRESS FINDS TRACK 1 INSTEAD OF TRACK 2, ; THEN ASSUME 48 TPI MEDIA GENERATED ; ON A 48 TPI DRIVE WAS INSERTED INTO THE 96 TPI DRIVE; THEREFOR, ; USE AS A R/O DISK WITH DOUBLE STEPPING. ; ; THERE ARE TWO 48 TPI MEDIA FORMATS THAT ARE SUPPORTED ON ; A 96 TPI DRIVE. ; 1) MEDIA WAS FORMATTED ON A 96 TPI DRIVE AND ONLY USES ; THE FIRST HALF OF THE DISK SURFACE. (E.G. A 48 TPI MEDIA ; IS DUPLICATED ONTO MEDIA IN A 96 TPI DRIVE) ; 2) MEDIA WAS FORMATTED ON A 48 TPI DRIVE. THE HARDWARE ; GROUP HAS INFORMED ME THAT THE 96 TPI DRIVE CAN RELIABLY ; READ SUCH MEDIA BUT CANNOT WRITE ON IT. TO GO BETWEEN ; TRACKS IT IS NECESSARY TO DOUBLE THE NUMBER OF STEPS. ; ; THE FOLLOWING ARE THE POSSIBLE OUTCOMES OF THE READ ADDRESS ; MEDIA DRIVE DRIVE OUTCOME ; FORMAT GENERATED ON INSERTED IN TRACK ; ------ ------------ ----------- ------- ; 48 TPI 48 TPI 48 TPI 2 ; 48 TPI 48 TPI 96 TPI 1 ; 48 TPI 96 TPI 48 TPI ERROR ; 48 TPI 96 TPI 96 TPI 2 ; 96 TPI 96 TPI 48 TPI ERROR ; 96 TPI 96 TPI 96 TPI 2 ; SEL2073: MOV PHYTRK,2 ;STEP IN TWO TRACKS CALL SDT207 MOV PHYSID,0 ;DO READ ADDRESS LEA DI,RDABUF CALL RDA207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 CMP RDABUF+FDRATRK,2 ;CHECK IF TRACK 2 JE SEL2073A ; BR IF YES ; 1) 48 TPI MEDIA GENERATED ON 48 TPI ; DRIVE INSERTED INTO 48 TPI DRIVE ; 2) 48 TPI MEDIA GENERATED ON 96 TPI ; DRIVE INSERTED INTO 96 TPI DRIVE ; 3) 96 TPI MEDIA INSERTED IN 96 TPI CMP RDABUF+FDRATRK,1 ;CHECK IF TRACK 1 ; JNE SEL2079 ; BR IF NOT (ERROR) JE $+5 JMP SEL2079 OR DPEFLAG[BP],DPE48RO ;SET FLAG TO INDICATE 48 TPI MEDIA ; GENERATED ON 48 TPI DRIVE INSERTED ; INTO 96 TPI DRIVE. THE MEDIA ; IS TREATED AS R/O SEL2073A: CALL RST207 ;STEP OUT TWO TRACKS BY DOING RESTORE ; MOVE LABEL INFO TO DISK PARAMETER BLOCK MOV SI,BUFBUF[BX] ADD SI,LABDPB MOV DI,DPEDPB[BP] MOV CX,DPBL CLD REP MOVSB JMP SEL2078 ;* SELECT FOR 8" DRIVE SEL2075: MOV PHYTRK,2 ;ATTEMPT TO READ ADDRESS HEADER MOV PHYSID,0 ; ON PHYSICAL TRACK #2 SIDE 0 CALL DS207 ; AT THE CURRENT DENSITY IN CALL RST207 ; THE DRIVE'S DPE CALL SDT207 LEA DI,RDABUF CALL RDA207 TEST AL,AL JZ SEL2076 ;BR IF ABLE TO READ XOR DPEFLAG[BP],DPEDD ;CHANGE TO OTHER DENSITY XOR DEVCTL,CONSD MOV AL,DEVCTL OUT FDCON,AL LEA DI,RDABUF ;ATTEMPT TO READ ADDRESS HEADER CALL RDA207 ; AT OTHER DENSITY TEST AL,AL JNZ SEL2079 ;BR IF ERROR ; UPDATE REST OF DPE SEL2076: AND DPEFLAG[BP],0FFH-DPE2S ;# OF SIDES IN AL,FDAS ;ASK DRIVE HOW MANY SIDES TEST AL,AS2S JZ SEL2076A OR DPEFLAG[BP],DPE2S SEL2076A: MOV SI,DPEDD+DPE2S ;COMPUTE ADDRESS OF TABLE CONTAINING AND SI,WORD PTR DPEFLAG[BP] ; INFO FOR UPDATE IF (DPEDD NE 2) OR (DPE2S NE 1) %: DPEDD MUST BE 2 AND DPE2S MUST BE 1 ENDIF SHL SI,1 SHL SI,1 XOR AH,AH MOV AL,RDABUF+FDRASL ADD SI,AX SHL SI,1 MOV SI,TBL207[SI] ;GET ADDRESS OF UPDATE INFO TEST SI,SI ;CHECK FOR NOT SUPPORTED FORMAT JZ SEL2079 ; BR IF NOT SUPPORTED XOR AH,AH ;XLATE TABLE ADDRESS LODSB SHL AX,1 MOV DI,XLATES ADD DI,AX MOV AX,ES:[DI] MOV DPEXLT[BP],AX LODSB ;CP/M RECORDS PER PHYSICAL SECTOR MOV DPERPS[BP],AL LODSB ;CP/M RECORDS PER ALLOCATION BLOCK MOV DPERPAB[BP],AL MOV DI,DPEDPB[BP] ;DPB MOV CX,DPBL CLD REP MOVSB ;* DONE WITH SELECT OPERATION SEL2078: AND DSKOP,NOT DSKOPS ;INDICATE DONE WITH SELECT OPERATION JMP DONE207 ;RETURN VIA 'DONE207' ;* ERROR OCCURRED SEL2079: MOV PHYDPE,0 ;INDICATE ERROR JMPS SEL2078 ;** READ TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,DI ; RDT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK CALL S1S207 ;SET 1ST SECTOR TO READ MOV DI,BUFBUF[BX] ;BUFFER ADDRESS ADD DI,AX RDT2071: CMP PREREAD,0 ;Q. DOING PREREAD JNE RDT2072 ; BR IF YES CMP BUFERR[BX],0 ;Q. ABORT JNE RDT2073 ; BR IF YES RDT2072: CALL RDS207 ;READ NEXT SECTOR RDT2073: ADD DI,COUNT ;BUMP BUFFER POINTER INC PHYSEC ;BUMP PHYSICAL SECTOR # MOV AL,BYTE PTR PHYSEC ;CHECK IF SECTOR # WRAPAROUND CMP AL,SECCNT JB RDT2074 ; BR IF NOT XOR AX,AX ; OTHERWISE START AT BEGINNING MOV PHYSEC,AX MOV DI,BUFBUF[BX] RDT2074: CMP AL,SEC1ST ;CHECK IF ALL OF TRACK READ JNE RDT2071 ; BR IF NOT JMP DONE207 ;RETURN THRU 'DONE207' ;** WRITE TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,SI,DI ; WRT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK CALL S1S207 ;SET 1ST SECTOR TO WRITE MOV SI,BUFBUF[BX] ;BUFFER ADDRESS ADD SI,AX WRT2071: MOV DI,BUFSECF[BX] ;CHECK IF PHYSICAL SECTOR IS DIRTY ADD DI,PHYSEC TEST BYTE PTR [DI],1 JZ WRT2073 ; BR IF IT IS NOT MOV BYTE PTR [DI],0 ;CLEAR DIRTY SECTOR FLAG CMP BUFERR[BX],0 ;Q. ABORT JNE WRT2073 ; BR IF YES -- SKIP PHYSICAL WRITE CALL WRS207 ;WRITE SECTOR WRT2073: ADD SI,COUNT ;SKIP BUFFER POINTER TO NEXT SECTOR INC PHYSEC ;BUMP PHYSICAL SECTOR # MOV AL,BYTE PTR PHYSEC ;CHECK IF SECTOR # WRAPAROUND CMP AL,SECCNT JB WRT2074 ; BR IF NOT XOR AX,AX ; OTHERWISE SET TO START MOV PHYSEC,AX MOV SI,BUFBUF[BX] WRT2074: CMP AL,SEC1ST ;CHECK IF ALL OF TRACK WRITTEN JNE WRT2071 ; BR IF NOT CALL WBS207 ;WAIT FOR WRITE GATE TURN OFF JMP DONE207 ;RETURN THRU 'DONE207' ;** MOUNT ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: DI ; MNT207: MOV DI,BUFDPE[BX] ;SET TRACK POSITION TO UNKNOWN MOV DPETRK[DI],DPEUNK RET ;** FORMAT TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; 'FVFLG'=VERIFY FLAG ; 'DMAPTR'=ADDRESS OF TRACK IMAGE ; EXIT: 'ERROR'=ERROR STATUS ; USES: AX,CX,DX,SI ; FMT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK OR DSKOP,DSKOPF ;INDICATE FORMAT OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER TEST DPEUNIT[BP],CONDS8 ;Q. TIME FOR SPECIAL CHECK JZ FMT2071 ; IF 8" DRIVE CMP PHYTRK,0 ; TRACK 0 JNE FMT2071 ; CMP PHYSID,FDFSS1 ; SIDE 1 JNE FMT2071 ; BR IF NOT IN AL,FDAS ;Q. IS DOUBLE SIDED DISKETTE INSERTED TEST AL,AS2S JNZ FMT2071 ; BR IF YES MOV AL,FDSNRD ; ELSE -- FLAGS AS NOT READY ERROR JMPS FMT2072 FMT2071: MOV AL,PHYSID ;GET SIDE SELECT FLAG OR AL,FDCWRT ; OR IN COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FLAG FOR NEXT I/O MOV SI,DMAPTR ;GET ADDRESS OF TRACK IMAGE MOV CX,12000 ;USE LARGE COUNT MOV DX,ES ;DATA SEGMENT TO USE CALL WR207 ;USE LOW LEVEL WRITE ROUTINE TEST AL,AL ;Q. ERROR JZ FMT2073 ; BR IF NOT CALL WBS207 ;WAIT BEFORE STEPPING FMT2072: CALL ERR207 ;Q. SHOULD I RETRY JNC FMT2071 ; BR IF YES AND DSKOP,NOT DSKOPF ; OTHERWISE EXIT JMP FMT2074 FMT2073: AND DSKOP,NOT DSKOPF ;INDICATE FORMAT OPERATION OVER CMP FVFLG,0 ;Q. SHOULD I VERIFY JZ FMT2074 ; BR IF NOT MOV PREREAD,0 CALL RDT207 ;TRY READING TRACK FMT2074: JMP DONE207 ;** WRITE PROTECT CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=R/W , 1=R/O ; USES: AL,BP ; WPC207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE OR DSKOP,DSKOPWP ;INDICATE WRITE PROTECT OPERATION CALL DS207 ;SELECT DRIVE MOV AL,FDCFI+FDFINI ;FORCE TYPE 1 STATUS OUT FDCMD,AL PUSH AX MOV AX,(60+3)/4 CALL WDLY POP AX WPC2071: IN AL,FDSTA ;WAIT FOR CONTROLLER NOT BUSY TEST AL,FDSBSY JNZ WPC2071 AND AL,FDSWPV ;ISOLATE WRITE PROTECT BIT MOV AL,0 ;ASSUME R/W JZ WPC2072 ; BR IF R/W MOV AL,1 ;INDICATE R/O WPC2072: MOV BUFERR[BX],AL ;RETURN VALUE AND DSKOP,NOT DSKOPWP ;INDICATE WRITE PROTECT OP DONE JMP DONE207 ;RET VIA 'DONE207' ;** READY CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER ; EXIT: 'BUFERR[BX]'=STATUS (0=NOT READY , 1=READY) ; USES: AL,DX,BP ; RDY207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE CALL RDY2070 JMP DONE207 RDY2070: MOV BUFERR[BX],0 ;ASSUME NOT READY OR DSKOP,DSKOPRD ;INDICATE READY CHECK IN PROGRESS CALL DS207 ;SELECT DRIVE MOV DX,5000/TINTRVL+1 ;COMPUTE TIMEOUT COUNT (5 SEC) ADD DX,TICCNT MOV AL,FDCFI+FDFII2 ;WAIT FOR INDEX HOLE TRANSITION OUT FDCMD,AL PUSH AX MOV AX,(60+3)/4 CALL WDLY POP AX RDY2071: CMP DX,TICCNT ;Q. TIMEOUT JE RDY2073 ; BR IF YES IN AL,FDAS ;Q. INDEX HOLE FOUND TEST AL,ASIRQ JZ RDY2071 ; BR IF NOT RDY2072: IN AL,FDSTA ;WAIT FOR 1797 TO GO NOT BUSY TEST AL,FDSBSY JNZ RDY2072 MOV BUFERR[BX],1 ;INDICATE DRIVE READY RDY2073: AND DSKOP,NOT DSKOPRD ;INDICATE READY CHECK DONE RET ;* READ SECTOR ; ; ENTRY: 'PHYSEC'=SECTOR # ; (DI)=BUFFER POINTER ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX ; RDS207: OR DSKOP,DSKOPR ;INDICATE READ OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV AL,BYTE PTR PHYSEC ;GET SECTOR # INC AL ;PUT INTO RANGE 1 TO SPT OUT FDSEC,AL ;TELL CONTROLLER RDS2071: MOV AL,PHYSID ;GET SIDE SELECT VALUE OR AL,FDCRDS+FDFSLF ;FORM COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,COUNT ;GET COUNT MOV DI,HSTPTR ;GET BUFFER POINTER CALL RD207 ;USE LOW LEVEL READ ROUTINE AND AL,NOT FDSRTE ;MASK ERROR CODE TEST AL,AL ;CHECK FOR ERROR JZ RDS2073 ; BR IF NO ERROR CALL ERR207 ;CHECK IF I SHOULD DO RETRY JNC RDS2071 ; BR IF YES CMP PREREAD,0 ;Q. IS THIS A PREREAD OPERATION JNE RDS2074 ; BR IF YES CALL ABTIGN ;HANDLE ABORT/IGNORE RDS2074: MOV AL,ERRTYP ;RESTORE ERROR CODE RDS2073: MOV DI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPR ;INDICATE READ OPERATION DONE RET ;* LOW LEVEL READ ROUTINE ; ; ENTRY: (AL)=COMMAND ; (DI)=BUFFER POINTER ; (CX)=COUNT ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX,CX,DI ; RD207: MOV AH,AL ;SAVE COMMAND IN AL,FDDAT ;CLEAR ANY PENDING DRQ IF WAIT MOV AL,DEVCTL ;ENABLE WAIT STATE I/O OR AL,CONWE OUT FDCON,AL ENDIF CLD ;FORWARD DIRECTION CALL EXDSES ;NEED ES: TO POINT TO MY BANK PUSHF ;DISABLE INTERRUPTS CLI MOV AL,AH ;RESTORE COMMAND OUT FDCMD,AL ;ISSUE COMMAND RD2071: IF NOT WAIT IN AL,FDAS ;WAIT FOR DRQ OR IRQ TEST AL,ASDRQ+ASIRQ JZ RD2071 ENDIF IN AL,FDDAT ;GET DATA STOSB ;STORE IN BUFFER LOOP RD2071 ;LOOP AND READ POPF ;RESTORE INTERRUPT STATUS CALL EXDSES ;RESTORE DS: AND ES: CALL WAIT2071 ;WAIT FOR COMMAND COMPLETION IF WAIT MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;DISABLE WAIT STATE I/O OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS ENDIF RET ;* RDA207 - READ ADDRESS ; ; ENTRY: (DI)=BUFFER ADDRESS ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX,DI ; RDA207: OR DSKOP,DSKOPRA ;SHOW READ ADDR OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER RDA2071: MOV AL,PHYSID ;GET SIDE FLAG VALUE OR AL,FDCRDA ; OR IN COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,FDRAL ;COUNT MOV DI,HSTPTR ;GET BUFFER POINTER CALL RD207 ;USE LOW LEVEL READ ROUTINE AND DSKOP,NOT DSKOPRA ;INDICATE READ ADDRESS OP DONE RET ;* S1S - SET 1ST SECTOR ; ; ENTRY: NONE ; EXIT: (AX)=BUFFER DISPLACEMENT ; 'PHYSEC','SEC1ST'=1ST SECTOR # ; USES: AX,DI ; S1S207: LEA DI,RDABUF ;USE READ ADDRESS BUFFER CALL RDA207 ; TO DO READ ADDRESS OPERATION LEA DI,RDABUF ;GET ADDR OF READ ADDRESS INFO TEST AL,AL ;CHECK IF READ ADDRESS RETURN ERROR JZ S1S2071 ; BR IF NO ERROR MOV BYTE PTR FDRASEC[DI],0 ; OTHERWISE 0 S1S2071: MOV AL,FDRASEC[DI] ;GET SECTOR # CMP AL,SECCNT ;CHECK IF LAST SECTOR ON TRACK JB S1S2072 ; BR IF NOT XOR AL,AL ; OTHERWISE 0 S1S2072: MOV SEC1ST,AL ;SAVE AS 1ST SECTOR # CBW ;SET 'PHYSEC' MOV PHYSEC,AX MUL COUNT ;COMPUTE DISPLACEMENT RET ;* WRS207 - WRITE SECTOR ; ; ENTRY: 'PHYSEC'=SECTOR # ; (SI)=BUFFER POINTER ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX,DX ; WRS207: OR DSKOP,DSKOPW ;INDICATE WRITE OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER MOV HSTPTR,SI ;SAVE BUFFER POINTER MOV AL,BYTE PTR PHYSEC ;GET SECTOR # INC AL ;PUT INTO RANGE 1 TO SPT OUT FDSEC,AL ;TELL CONTROLLER WRS2071: MOV AL,PHYSID ;GET SIDE SELECT VALUE OR AL,FDCWRS+FDFSLF ;FORM COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,COUNT ;GET COUNT MOV SI,HSTPTR ;GET BUFFER POINTER MOV DX,DS ;DATA SEGMENT CALL WR207 ;USE LOW LEVEL WRITE ROUTINE TEST AL,AL ;CHECK FOR ERROR JZ WRS2073 ; BR IF NO ERROR CALL WBS207 ;WAIT FOR WRITE GATE TURN OFF CALL ERR207 ;CHECK IF I SHOULD DO RETRY JNC WRS2071 ; BR IF YES CALL ABTIGN ;ASK ABOUT ABORTING MOV AL,ERRTYP ;RESTORE ERROR CODE WRS2073: MOV SI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPW ;INDICATE WRITE OP DONE RET ;* WR207 - LOW LEVEL WRITE ROUTINE ; ; ENTRY: (AL)=COMMAND ; (SI)=BUFFER POINTER ; (CX)=COUNT ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX,CX,SI ; WR207: MOV AH,AL ;SAVE COMMAND MOV AL,FDSWPV ;ASSUME WRITE PROTECT VIOLATION TEST DPEFLAG[BP],DPE48RO ;CHECK FOR 48 TPI R/O DISK JNZ WR2072 ; BR IF IT IS IN AL,FDDAT ;CLEAR ANY PENDING DRQ IF WAIT MOV AL,DEVCTL ;ENABLE WAIT STATE I/O OR AL,CONWE OUT FDCON,AL ENDIF PUSHF ;DISABLE INTERRUPTS CLI CLD ;FORWARD DIRECTION PUSH DS ;GET DATA SEGMENT MOV DS,DX MOV AL,AH OUT FDCMD,AL ;ISSUE COMMAND WR2071: IF NOT WAIT IN AL,FDAS ;WAIT FOR DRQ OR IRQ TEST AL,ASDRQ+ASIRQ JZ WR2071 ENDIF LODSB ;GET DATA OUT FDDAT,AL ;SEND TO DISK LOOP WR2071 ;LOAD AND WRITE POP DS ;RESTORE DATA SEGMENT POPF ;RESTORE INTERRUPT STATUS CALL WAIT2071 ;WAIT FOR COMMAND COMPLETION IF WAIT MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;DISABLE WAIT STATE I/O OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS ENDIF WR2072: RET ;* DONE WITH 207 ; ; ENTRY: NONE ; EXIT: NONE ; USES: AL ; DONE207: MOV AL,PHYSID ;SAVE SIDE SELECT VALUE CMP BUFERR[BX],0 ;Q. DID ERROR OCCUR JZ DONE2071 ; BR IF NOT MOV AL,FDFSS1 DONE2071: MOV SIDE207,AL XOR AL,AL ;DESELECT DRIVE OUT FDCON,AL MOV DEVCTL,AL TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELONOID JZ DONE2072 ; BR IF NOT PUSH AX MOV AX,35*250 ;WAIT DRIVE DESELECT TIME CALL WDLY POP AX DONE2072: RET ;* SET UP DEVICE ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: (BP)=ADDRESS OF DPE ; 'PHYTRK'=PHYSICAL TRACK # ; 'PHYSID'=PHYSICAL SIDE # ; 'SECCNT'=# SECTORS PER TRACK ; 'COUNT'=# BYTES PER SECTOR ; DRIVE IS SELECTED ; USES: AX,BP,SI ; SET207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE ; COMPUTE PHYSICAL TRACK AND SIDE VALUES MOV AL,BYTE PTR BUFTRK[BX] ;GET CP/M TRACK # MOV PHYSID,0 ;ASSUME SIDE 0 MOV PHYSIDN,0 TEST DPEFLAG[BP],DPE2S JZ SET2071A ;BR IF NOT DOUBLE SIDED MEDIA SHR AL,1 ;DIVIDE TRACK # BY 2 JNC SET2071A ;EVEN TRACKS ON SIDE 0 MOV PHYSID,FDFSS1 ; ODD TRACKS ON SIDE 1 MOV PHYSIDN,1 SET2071A: MOV PHYTRK,0 ;INSURE HIGH ORDER BYTE IS 0 MOV BYTE PTR PHYTRK,AL ;SAVE PHYSICAL TRACK # ; CHECK FOR SPECIAL CASE OF 8" DRIVE, TRACK 0, SIDE 0 CMP BYTE PTR PHYTRK,0 ;CHECK IF TRACK 0 JNE SET2072 ; BR IF NOT CMP PHYSID,0 ;CHECK IF SIDE 0 JNE SET2072 ; BR IF NOT TEST DPEFLAG[BP],DPET0SD ;CHECK IF TRACK 0 SINGLE DENSITY JZ SET2072 ; BR IF NOT MOV SECCNT,26 ;26 PHYSICAL SECTORS PER TRACK MOV COUNT,128 ;128 BYTES PER PHYSICAL SECTOR JMPS SET2073 ; COMPUTE NUMBER OF SECTORS PER TRACK SET2072: MOV SI,DPEDPB[BP] MOV AX,DPBSPT[SI] DIV DPERPS[BP] MOV SECCNT,AL ; COMPUTE NUMBER OF BYTES PER SECTOR MOV AL,128 MUL DPERPS[BP] MOV COUNT,AX ; SET2073: CALL DS207 ;SELECT DRIVE ; SET TRACK REGISTER IN CONTROLLER MOV AL,DPETRK[BP] ;GET TRACK POSITION OUT FDTRK,AL ;SET TRACK REGISTER TEST AL,DPEUNK ;CHECK IF UNKNOWN JZ SET2074 ; BR IF KNOWN CALL RST207 ;RESTORE HEAD ; SET2074: RET ;* SET I/O RETRY COUNTER ; ; ENTRY: NONE ; EXIT: 'RETRIES' SET ; USES: NONE ; SRC207: MOV RETRIES,12 ;ASSUME 12 TEST DSKOP,DSKOPRA+DSKOPS ;CHECK IF SPECIAL CASE JZ SRC2071 ; BR IF NOT MOV RETRIES,4 ;ALLOW ONLY 4 RETRIES SRC2071: RET ;* DRIVE SELECT ; ; ENTRY: NONE ; EXIT: DRIVE SELECTED AND UP TO SPEED ; USES: AX,CX ; DS207: MOV HLDDLYF,0 ;ASSUME ZERO DELAY ; FORM CONTROL WORD MOV AL,DPEUNIT[BP] ;GET UNIT SELECT FROM DPE OR AL,CONDSEN ;DRIVE SELECT ENABLE TEST DPEFLAG[BP],DPEDD ;Q. DOUBLE DENSITY JZ DS2070 ; BR IF NOT CMP BYTE PTR PHYTRK,0 ;CHECK FOR SPECIAL CASE JNE DS2071 ; WHERE TRACK 0 SIDE 0 CMP PHYSID,0 ; SINGLE DENSITY WHILE THE JNE DS2071 ; REST IS DOUBLE DENSITY TEST DPEFLAG[BP],DPET0SD JZ DS2071 ;BR IF NOT SPECIAL CASE DS2070: OR AL,CONSD ;SET FOR SINGLE DENSITY ; DS2071: MOV AH,AL ;(AH)=NEW CONTROL WORD TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELONOID JZ DS2071A ; BR IF NOT AND AL,CONDSEN+CONDS8+CONDS ;ISOLATE DRIVE SELECT BITS IN NEW MOV CL,DEVCTL ;ISOLATE DRIVE SELECT AND CL,CONDSEN+CONDS8+CONDS ; BITS IN OLD CONTROL WORD CMP AL,CL ;Q. SAME DRIVE STILL SELECTED JE DS2071A ; BR IF YES IN AL,FDTRK ;NEW DRIVE SELECTED - CAUSE 1797 OUT FDDAT,AL ; TO RESET HEAD LOAD DELAY TIMER MOV AL,FDCSEK ; BY DOING ZERO LENGTH SEEK WITH CALL WAIT207 ; HEAD UNLOADED MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O DS2071A: TEST AH,CONDS8 ;CHECK IF SELECTING 8" DRIVE JNZ DS2075 ; BR IF 8" ; SELECT 5 1/4" DRIVE AND AH,NOT CONPC ;ASSUME PRE-COMP TEST DPEFLAG[BP],DPE96T ;Q. 96 TPI DRIVE JNZ DS2072 ; BR IF YES CMP BYTE PTR PHYTRK,23 ;Q. TRACK >= 23 ON 48 TPI DRIVE JAE DS2072 ; BR IF YES OR AH,CONPC ;DON'T USE PRE-COMP DS2072: MOV AL,AH ;SELECT DRIVE OUT FDCON,AL ; HANDLE MOTOR START UP DELAY FOR 5 1/4" DRIVE TEST DSKOP,DSKOPWP+DSKOPI ;Q. WAIT FOR MOTOR UP TO SPEED ; JNZ DS2079 ; BR IF NO JZ $+5 JMP DS2079 MOV AL,DEVCTL ;CHECK IF A 5 1/4" DRIVE AND AL,CONDSEN+CONDS8 ; IS ALREADY SELECTED CMP AL,CONDSEN ; JE DS2079 ; BR IF YES JNE $+5 JMP DS2079 IN AL,FDAS ;SEE IF MOTOR STILL RUNNING TEST AL,ASMO ; JNZ DS2079 ; BR IF IT IS JZ $+5 JMP DS2079 MOV CX,250/TINTRVL+1 ;WAIT FOR 250 mS TEST DPESEK[BP],DPEMO ;CHECK IF FAST MOTOR UP TO SPEED JNZ DS2073 ; BR IF YES MOV CX,1000/TINTRVL+1 ;WAIT FOR 1 SEC DS2073: ADD CX,TICCNT DS2073A: CMP CX,TICCNT JNE DS2073A JMPS DS2079 ; SELECT 8" DRIVE ; ; SINCE THE 1797 CHECKS THE DRIVE READY STATUS LINE BEFORE PLACING ; THE VALUE OF THE SIDE SELECT ON ITS OUTPUT PIN, IT MAY BE NECESSARY ; TO FORCE THE 1797 TO PLACE A SIDE SELECT VALUE ACCEPTABLE TO THE ; DRIVE BEFORE PRECEDING. THIS SITUATION ARISES WHEN ; 1. A PREVIOUS 1797 COMMAND SELECTED SIDE 1 ; 2. THE MEDIA IS NOT DOUBLE SIDED ; WHAT HAPPENS IS SOME DRIVES INDICATE DRIVE READY AS ; 1. MEDIA INSERTED ; 2. DOOR CLOSED ; 3. SIDE SELECTED IS AVAILABLE DS2075: MOV AL,AH ;SELECT DRIVE OUT FDCON,AL TEST DSKOP,DSKOPWP+DSKOPI+DSKOPRD ;Q. SKIP JNZ DS2079 ; BR IF YES CMP PHYSID,FDFSS1 ;Q. WISH TO USE SIDE 1 JE DS2078 IN AL,FDAS ;CHECK IF DOUBLE SIDED MEDIA TEST AL,AS2S JNZ DS2078 ; BR IF DOUBLE SIDED MEDIA CMP SIDE207,FDFSS1 ;CHECK IF SIDE 1 SELECTED PREVIOUSLY JNE DS2078 ; BR IF NOT XOR AL,AL ;DESELECT DRIVE OUT FDCON,AL PUSH AX MOV AL,FDCRDA+FDFDLF ;USE READ ADDRESS COMMAND OUT FDCMD,AL ; TO FORCE SIDE 0 SELECT MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2076: IN AL,FDSTA ;WAIT UNTIL 1797 GOES BUSY TEST AL,FDSBSY JZ DS2076 MOV AL,FDCFI+FDFINI ;TERMINATE COMMAND OUT FDCMD,AL MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2077: IN AL,FDSTA ;WAIT UNTIL 1797 GOES NOT BUSY TEST AL,FDSBSY JNZ DS2077 IN AL,FDDAT ;FLUSH ANY DATA IN 1797 POP AX MOV AL,AH ;RESELECT DRIVE OUT FDCON,AL ; WAIT FOR MOTOR UP TO SPEED. DRIVE WILL INDICATE READY WHEN ; UP TO SPEED. THIS IS DONE TO ACCOMODATE DRIVES WITH DC MOTORS. DS2078: PUSH AX MOV AL,FDCFI+FDFINI ;FORCE TYPE 1 STATUS OUT FDCMD,AL MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2078A: IN AL,FDSTA ;WAIT UNITL 1797 GOES NOT BUSY TEST AL,FDSBSY JNZ DS2078A MOV CX,1000/TINTRVL+1 ;WAIT 1 SEC MAX ADD CX,TICCNT DS2078B: CMP CX,TICCNT ;Q. TIME UP JE DS2078C ; BR IF YES IN AL,FDSTA TEST AL,FDSNRD ;Q. DRIVE READY JNZ DS2078B ; BR IF NOT DS2078C: POP AX ; DS2079: MOV DEVCTL,AH ;SAVE CONTROL REGISTER IMAGE RET ;* ISSUE COMMAND AND WAIT FOR I/O COMPLETION ; ; ENTRY: (AL)=COMMAND ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL ; WAIT207: OUT FDCMD,AL ;ISSUE COMMAND PUSH AX ;WAIT AT LEAST 60uS MOV AX,(60+3)/4 ; BEFORE CHECKING STATUS CALL WDLY POP AX WAIT2071: IN AL,FDAS ;WAIT FOR IRQ TEST AL,ASIRQ JZ WAIT2071 WAIT2073: IN AL,FDSTA ;GET CONTROLLER STATUS TEST AL,FDSBSY ;WAIT FOR NOT BUSY JNZ WAIT2073 RET ;* CHECK IF TO DO RETRIES ; ; ENTRY: (AL)=CONTROLLER STATUS ; 'RETRIES'=RETRY COUNTER ; EXIT: PSW/C=RETRY STATUS (0=RETRY , 1=NO RETRY) ; USES: AL,DI ; ; I/O RECOVERY PROCEDURE: ; 1) RETRY I/O OPERATION ; 2) STEP HEAD IN/OUT 1 TRACK, THEN RETRY I/O OPERATION ; 3) RETRY I/O OPERATION ; 4) STEP HEAD OUT/IN 1 TRACK, THEN RETRY I/O OPERATION ; 5) RETRY I/O OPERATION ; 6) RESTORE HEAD/RE-SEEK, THEN RETRY I/O OPERATION ; 7) RETRY I/O OPERATION ; 8) STEP HEAD IN/OUT 1 TRACK, THEN RETRY I/O OPERATION ; 9) RETRY I/O OPERATION ; 10) STEP HEAD OUT/IN 1 TRACK, THEN RETRY I/O OPERATION ; 11) RETRY I/O OPERATION ; 12) FLAG AS HARD ERROR ; ERR207: MOV ERRTYP,AL ;SAVE CONTROLLER STATUS AS ERROR TYPE TEST AL,FDSNRD+FDSWPV ;CHECK FOR NOT READY OR WRITE PROTECT JNZ ERR2079 ; BR IF YES - NO RETRIES TEST DSKOP,DSKOPS ;IF NOT DOING A SELECT OPERATION JNZ ERR2071 MOV DI,BBIOS ; BUMP SOFT ERROR COUNTER INC SECNT[DI] ERR2071: DEC RETRIES ;UPDATE RETRY COUNTER JZ ERR2079 ; BR IF EXHAUSTED RETRIES MOV AL,RETRIES CMP AL,6 JA ERR2072 SUB AL,6 ERR2072: JNZ ERR2073 ;BR IF NOT TIME TO DO RESTORE HEAD CALL RST207 ;RESTORE HEAD BEFORE TRYING AGAIN JMPS ERR2077 ERR2073: CMP AL,4 ;CHECK IF TIME TO STEP OUT JNE ERR2074 ; BR IF NOT DEC BYTE PTR PHYTRK ;DECREMENT TO NEXT TRACK JS ERR2073A ; BR IF BEFORE TRACK 0 CALL SDT207 ; OTHERWISE STEP OUT ERR2073A: INC BYTE PTR PHYTRK ;RESTORE DESIRED TRACK JMPS ERR2077 ERR2074: CMP AL,2 ;CHECK IF TIME TO STEP IN JNE ERR2078 ; BR IF NOT MOV AL,NTRK837-1 ;GET MAXIMUM TRACK # TEST DPEUNIT[BP],CONDS8 JNZ ERR2074A MOV AL,NTRKD37-1 TEST DPEFLAG[BP],DPE96T JNZ ERR2074A MOV AL,NTRKS37-1 ERR2074A: INC BYTE PTR PHYTRK ;INCREMENT TO NEXT TRACK CMP AL,BYTE PTR PHYTRK ;CHECK IF MAX TRACK # >= NEXT TRACK JB ERR2074B ; BR IF IT IS CALL SDT207 ; OTHERWISE STEP IN ERR2074B: DEC BYTE PTR PHYTRK ;RESTORE DESIRED TRACK ERR2077: CALL SDT207 ;SEEK DESIRED TRACK ERR2078: CLC ;INDICATE TRY AGAIN RET ERR2079: MOV BUFERR[BX],1 ;SET ERROR FLAG MOV AL,ERRTYP ;RECOVER CONTROLLER STATUS TEST DSKOP,DSKOPR+DSKOPW ;IF DOING READ OR WRITE OPERATION JZ ERR2079B MOV DI,BUFERRF[BX] ; PLACE IN ERROR ARRAY ADD DI,PHYSEC MOV [DI],AL JMPS ERR2079D ERR2079B: TEST DSKOP,DSKOPF ;Q. FORMAT OPERATION JZ ERR2079C ; BR IF NO TEST DEVCTL,CONDS8 ;Q. 8" DRIVE JZ ERR2079C ; BR IF NOT CMP PHYTRK,0 ;Q. TRACK 0 JNE ERR2079C ; BR IF NOT CMP PHYSID,FDFSS1 ;Q. SIDE 1 JNE ERR2079C ; BR IF NOT CMP ERRTYP,FDSNRD ;Q. NOT READY ERROR JE ERR2079E ; BR IF YES ERR2079C: CALL ERRRPT ; OTHERWISE REPORT ERROR IMMEDIATELY ERR2079D: TEST DSKOP,DSKOPS ;IF NOT DOING A SELECT OPERATION JNZ ERR2079E MOV DI,BBIOS ; COUNT HARD ERROR INC HECNT[DI] ERR2079E: STC ;INDICATE DON'T TRY AGAIN RET ;* RESTORE HEAD ; ; ENTRY: NONE ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX ; RST207: MOV DPETRK[BP],0 ;INDICATE TRACK # 0 TEST DPESEK[BP],DPEFS ;Q. CAN DRIVE FAST STEP JZ RST2071 ; BR IF NOT MOV AL,DEVCTL ;SET UP FAST STEP OR AL,CON5FS OUT FDCON,AL RST2071: MOV AL,DPESEK[BP] ;GET STEP RATE AND AL,FDFSRM OR AL,FDCRST ;RESTORE HEAD COMMAND CALL WAIT207 ;DO RESTORE PUSH AX ;WAIT FOR MECHANICAL DELAY MOV AX,15*250 CALL WDLY POP AX TEST DSKOP,DSKOPI ;Q. INIT OPERATION JZ RST2072 ; BR IF NOT TEST AL,FDSTK0 ;Q. AT TRACK 0 JZ RST2073 ; BR IF NOT RST2072: MOV AL,10 ;STEP IN 10 TRACKS CALL SDT2077 MOV AL,FDCRST+FDFHLB+FDFS30 ;RESTORE HEAD COMMAND CALL WAIT207 ;DO RESTORE PUSH AX ;WAIT FOR MECHANICAL DELAY MOV AX,15*250 CALL WDLY POP AX RST2073: MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;TURN OFF FAST STEP OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O RET ;* SEEK DESIRED TRACK ; ; ENTRY: 'PHYTRK'=TRACK # ; EXIT: NONE ; USES: AL ; SDT207: MOV AL,DPETRK[BP] ;GET CURRENT TRACK CMP AL,BYTE PTR PHYTRK ;CHECK AGAINST DESIRED TRACK JE SDT2072 ;ALREADY AT DESIRED TRACK TEST DPESEK[BP],DPEFS ;CHECK FOR FAST STEP JZ SDT2070 ; BR IF NOT MOV AL,DEVCTL ;ENABLE FAST STEP OR AL,CON5FS OUT FDCON,AL SDT2070: CALL SDT2076 ;DO SEEK TEST DPEFLAG[BP],DPE48RO ;CHECK IF 48TPI R/O MEDIA JZ SDT2071 ; BR IF NOT -- NO NEED TO DOUBLE STEP MOV AL,DPETRK[BP] ;GO THROUGH SEEK PROCEDURE AGAIN A SECOND TIME OUT FDTRK,AL ;RESET CONTROLLER'S TRACK REG CALL SDT2076 ;DO 2ND SEEK SDT2071: MOV AL,BYTE PTR PHYTRK ;OUTPUT DESIRED TRACK TO TRACK REG OUT FDTRK,AL ; THIS IS DONE IN CASE SEEK ABORTED ; WHEN IT TRIED TO STEP TO NEGATIVE ; TRACK LEAVING TRACK REGISTER ; CONTAINING 0 MOV DPETRK[BP],AL ;UPDATE IN MEMORY TRACK VALUE MOV AL,DEVCTL ;RESTORE CONTROL REGISTER OUT FDCON,AL ; INCASE I WAS FAST STEPPING SDT2072: MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O RET ; DO SEEK SDT2076: MOV AL,BYTE PTR PHYTRK ;TELL CONTROLLER DESIRED TRACK SDT2077: OUT FDDAT,AL MOV AL,DPESEK[BP] ;GET STEP RATE AND AL,FDFSRM OR AL,FDCSEK+FDFHLB ; OR IN COMMAND CALL WAIT207 ;DO I/O PUSH AX ;WAIT FOR MECHANICAL DELAY MOV AX,15*250 CALL WDLY POP AX RET ;* WAIT ~1.5 mS BEFORE STEPPING ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; WBS207: PUSH AX MOV AX,250*3/2+1 CALL WDLY POP AX RET  ;** 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 ;*** Z217 DEVICE DRIVER ; ; * * * N O T E * * * ; ; THIS DRIVE ASSUMES A CELL SIZE OF 512 BYTES WITH 18 SECTORS PER TRACK. ; ; ONLY UNIT 0 IS HANDLED. ; ; ALTHOUGH THE CONTROLLER PROVIDES FOR 21 BIT LOGICAL SECTOR NUMBERS, ; THIS DRIVER ONLY HANDLES 16 BIT LOGICAL SECTOR NUMBERS. THEREFORE, ; THE MAXIMUM SIZE OF DISK IS 65536 SECTORS (0-FFFFH). ; ;** DRIVER ENTRY JUMP VECTORS ; DRVR217: JMP SEL217 ;SELECT JMP RDT217 ;READ TRACK JMP WRT217 ;WRITE TRACK JMP MNT217 ;MOUNT JMP FMT217 ;FORMAT JMP WPC217 ;WRITE PROTECT CHECK ;** INITIALIZE DRIVE TABLES ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; IN217: ; FILL IN COMMAND BLOCK LEA DI,Z217BLK ;ADDRESS OF NEXT COMMAND CALL TMA217 MOV AL,Z217BLK+OFFSET WI01HT MOV Z217BLK+OFFSET WI01HN,AL MOV AL,Z217BLK+OFFSET WI01MT MOV Z217BLK+OFFSET WI01MN,AL MOV AL,Z217BLK+OFFSET WI01LT MOV Z217BLK+OFFSET WI01LN,AL ; CHECK IF CONTROLLER IS PRESENT LEA DI,Z217BLK ;ATTEMPT TO ISSUE SETUP COMMAND CALL SUP217 JC IN2174 ; BR IF ERROR ; READ SBC AND SET DRIVE PARAMETERS LEA DI,BUFFER ;GET BUFFER ADDRESS CALL TMA217 CALL WAIT2171 ;EXECUTE READ COMMAND TEST AL,WISERR ;Q. ERROR JNZ IN2174 ; BR IF ERROR LEA DI,BUFFER+OFFSET SBCSDP ;ADDRESS OF SET DRIVE CALL SUP217 ; PARAMETERS COMMAND JC IN2174 ; BR IF ERROR CALL WAIT2171 ;EXECUTE COMMAND TEST AL,WISERR ;Q. ERROR JNZ IN2174 ; BR IF ERROR LEA DI,Z217BLK ;ADDRESS FOR REST OF DRIVER CALL SUP217 JNC IN2175 ; BR IF NO ERROR ; MARK DRIVE AS IMAGINARY IN2174: MOV CX,2 ;# OF Z217 DRIVES LEA BP,DPEBASE+DPEL*4 ;START ADDRESS OF Z217 DPE'S ADD BP,BBIOS IN21741: OR DPEFLG2[BP],DPEIMG ;FLAG DRIVE AS IMAGINARY ADD BP,DPEL ;BUMP POINTER LOOP IN21741 ;LOOP AND MARK ALL DRIVES ; FILL IN DPE TABLES / DISK MAP TABLE IN2175: MOV CH,2 ;# DRIVES MOV CL,0 ;STARTING UNIT # MOV DH,4 ;STARTING DRIVE MAP # CALL CBTFIL ;DO FILL ; ASSIGN PARTITION IF BOOT UNIT PUSH ES MOV ES,.MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA CMP ES: MTRBI,2 ;Q. Z217 BOOTED POP ES JNE IN2176 ; BR IF NOT LEA BP,DPEBASE+4*DPEL ;GET ADDRESS OF 1ST DPE FOR Z217 ADD BP,BBIOS OR DPEFLAG[BP],DPEASGN ;SHOW PARTITION ASSIGNED MOV AX,BBIOS-4 MOV WORD PTR DPETRK[BP],AX ;SET BEGINNING SECTOR OF PARTITION MOV AX,BBIOS-6 MOV WORD PTR DPEUPB[BP],AX ;SET LAST SECTOR # OF PARTITION IN2176: RET ;** SELECT DRIVE FOR 1ST LOGIN ; ; ENTRY: 'PHYDPE'=ADDRESS OF DPE FOR DRIVE ; (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'PHYDPE'=STATUS ; 0=ERROR , OTHERWISE SAME AS ON ENTRY ; USES: NONE ; SEL217: OR DSKOP,DSKOPS ;INDICATE SELECT OP IN PROGRESS MOV BUFTRK[BX],0 ;READ LABEL CALL SET217 MOV DI,BUFBUF[BX] CALL RDS217 CMP BUFERR[BX],0 ;Q. ERROR JNZ SET2179 ; BR IF YES MOV SI,BUFBUF[BX] ;CHECK CHECKSUM OF LABEL ADD SI,LABEL CALL CHKLAB JNZ SET2179 ; BR IF ERROR MOV SI,BUFBUF[BX] ;CHECK IF LABEL'S BEGINNING OF MOV DI,WORD PTR LABHTH+(OFFSET DPETRK)-(OFFSET DPEHTH) [SI] CMP DI,WORD PTR DPETRK[BP] ;PARTITION SECTOR # MATCHES DRIVE TABLE JNE SET2179 ; BR IF NOT MOV DI,WORD PTR LABHTH+(OFFSET DPEUPB)-(OFFSET DPEHTH) [SI] CMP DI,WORD PTR DPEUPB[BP] ;CHECK IF LABEL'S LAST SECTOR # OF ; PARTITION MATCHES DRIVE TABLE JNE SET2179 ; BR IF NOT MOV AL,LABHTH+(OFFSET DPERPAB)-(OFFSET DPEHTH) [SI] MOV DPERPAB[BP],AL ;CP/M RECORDS PER ALLOCATION BLOCK ADD SI,OFFSET LABDPB ;UPDATE DISK PARAMETER BLOCK VALUES MOV DI,DPEDPB[BP] MOV CX,DPBL CLD REP MOVSB SET2178: AND DSKOP,NOT DSKOPS ;INDICATE SELECT OP COMPLETE RET SET2179: MOV PHYDPE,0 ;INDICATE ERROR JMPS SET2178 ;** READ TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]=STATUS ; 0=NO ERROR , 1=ERROR ; USES: DI ; RDT217: CALL SET217 ;SETUP MOV DI,BUFBUF[BX] ;BUFFER ADDRESS RDT2171: CMP PREREAD,0 ;Q. DOING PREREAD JNE RDT2172 ; BR IF YES CMP BUFERR[BX],0 ;Q. ABORT JNE RDT2173 ; BR IF YES RDT2172: CALL RDS217 ;READ NEXT SECTOR RDT2173: ADD DI,WICSZ ;BUMP BUFFER POINTER INC PHYSEC ;BUMP 'PHYSEC' CMP PHYSEC,WINSPT ;Q. ALL SECTORS READ JNE RDT2171 ; BR IF NOT RET ;** WRITE TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,SI,DI ; WRT217: CALL SET217 ;SETUP MOV DI,BUFBUF[BX] ;BUFFER ADDRESS WRT2171: MOV SI,BUFSECF[BX] ;CHECK IF PHYSICAL SECTOR IS DIRTY ADD SI,PHYSEC TEST BYTE PTR [SI],1 JZ WRT2173 ; BR IF IT IS NOT MOV BYTE PTR [SI],0 ;CLEAR DIRTY SECTOR FLAG CMP BUFERR[BX],0 ;Q. ABORT JNE WRT2173 ; BR IF YES CALL WRS217 ;WRITE SECTOR WRT2173: ADD DI,WICSZ ;BUMP BUFFER POINTER TO NEXT SECTOR INC PHYSEC ;BUMP PHYSICAL SECTOR # CMP PHYSEC,WINSPT ;Q. ALL TRACK WRITTEN JNE WRT2171 ; BR IF NOT RET ;** MOUNT ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: NONE ; MNT217: RET ;** FORMAT TRACK ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; FMT217: RET ;** WRITE PROTECT CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=R/W , 1=R/O ; USES: NONE ; WPC217: MOV BUFERR[BX],0 ;ALWAYS R/W RET ;* READ SECTOR ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # ; 'SEC217'=STARTING LOGICAL SECTOR # OF TRACK ; (DI)=BUFFER POINTER ; EXIT: NONE ; USES: AL ; RDS217: OR DSKOP,DSKOPR ;INDICATE READ OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV Z217BLK+OFFSET WI01OP,WIRDL ;READ LOGICAL OP CODE CALL CLS217 ;CALCULATE LOGICAL SECTOR # JC RDS2172 ; BR IF ERROR CALL TMA217 ;CALCULATE DATA TMA ADDRESS CALL WAIT217 ;DO I/O TEST AL,WISERR ;Q. ERROR JZ RDS2173 ; BR IF NO ERROR RDS2172: CALL ERR217 ;REPORT ERROR CMP PREREAD,0 ;Q. IS THIS A PREREAD OPERATION JNE RDS2173 ; BR IF YES CALL ABTIGN ;HANDLE ABORT/IGNORE RDS2173: MOV DI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPR ;INDICATE READ OP DONE RET ;* WRITE SECTOR ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # ; 'SEC217'=STARTING LOGICAL SECTOR # OF TRACK ; (DI)=BUFFER POINTER ; EXIT: NONE ; USES: AL ; WRS217: OR DSKOP,DSKOPW ;INDICATE WRITE OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV Z217BLK+OFFSET WI01OP,WIWRL ;WRITE LOGICAL OP CODE CALL CLS217 ;CALCULATE LOGICAL SECTOR # JC WRS2172 ; BR IF ERROR CALL TMA217 ;CALCULATE DATA TMA ADDRESS CALL WAIT217 ;DO I/O TEST AL,WISERR ;Q. ERROR JZ WRS2173 ; BR IF NO ERROR WRS2172: CALL ERR217 ;REPORT ERROR CALL ABTIGN ;HANDLE ABORT/IGNORE WRS2173: MOV DI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPW ;INDICATE WRITE OP DONE RET ;* EXECUTE COMMAND AND WAIT FOR I/O COMPLETION ; ; ENTRY: 'Z217BLK'=COMMAND BLOCK ; EXIT: (AL)=CONTROLLER HARDWARE STATUS ; USES: AL ; WAIT217: TEST DPEFLAG[BP],DPEASGN ;Q. PARTITION ASSIGNED JNZ WAIT2171 ; BR IF YES TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ WAIT2171 ; BR IF YES MOV AL,WISERR ;INDICATE ERROR MOV Z217BLK+OFFSET WI01EEC,WIEPNA RET WAIT2171: MOV AL,WIEXEC ;ISSUE EXECUTE COMMAND OUT WIPCMD,AL WAIT2172: IN AL,WIPSTAT ;WAIT FOR CONTROLLER TO BE DONE TEST AL,WISDONE JZ WAIT2172 RET ;* CALCULATE LOGICAL SECTOR # AND PLACE IN COMMAND BLOCK ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # FOR TRACK ; 'PHYTRK'=LOGICAL SECTOR # OF 1ST SECTOR OF TRACK ; EXIT: 'Z217BLK'=COMMAND BLOCK CONTAINS LOGICAL SECTOR # ; 'C' = 0 NO ERROR , 1=ERROR ; USES: AX ; ; LOGICAL SECTOR # = 'PHYTRK' + 'PHYSEC' ; CLS217: MOV AX,PHYTRK ADD AX,PHYSEC TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ CLS2171 ; BR IF YES CMP AX,WORD PTR DPETRK[BP] ;Q. SECTOR # WITHIN PARTITION JB CLS2172 ; BR IF NOT CMP AX,WORD PTR DPEUPB[BP] JA CLS2172 ; BR IF NOT CLC CLS2171: MOV Z217BLK+OFFSET WI01LS,AL MOV Z217BLK+OFFSET WI01MS,AH RET CLS2172: STC ;INDICATE ERROR MOV Z217BLK+OFFSET WI01EEC,WIESNWP MOV Z217BLK+OFFSET WI01EMS,AH MOV Z217BLK+OFFSET WI01ELS,AL RET ;* CALCULATE DATA TMA ADDRESS ; ; ENTRY: (DS)=DATA SEGMENT ; (DI)=DATA OFFSET ; EXIT: 'Z217BLK'=COMMAND BLOCK CONTAINS DATA TMA ADDRESS ; USES: AX,DL ; ; DATA TMA ADDRESS = (DS)*16 + (DI) ; TMA217: MOV AX,DS XOR DL,DL SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 ADD AX,DI ADC DL,0 MOV Z217BLK+OFFSET WI01HT,DL MOV Z217BLK+OFFSET WI01MT,AH MOV Z217BLK+OFFSET WI01LT,AL RET ;* COMMON SETUP ROUTINE ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'PHYTRK'=LOGICAL SECTOR # OF 1ST SECTOR OF TRACK ; 'PHYSEC'=0 ; USES: AX,DX ; SET217: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE MOV AX,BUFTRK[BX] ;CALCULATE LOGICAL SECTOR # MOV DX,WINSPT ; OF 1ST SECTOR ON TRACK MUL DX TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ SET2171 ; BR IF YES ADD AX,WORD PTR DPETRK[BP] ;ADJUST FOR BEGINING OF PARTITION SET2171: MOV PHYTRK,AX MOV PHYSEC,0 RET ;* ISSUE SETUP COMMAND TO CONTROLLER ; ; ENTRY: (DI)=COMMAND BLOCK ADDRESS ; EXIT: PSW/C 0=OK , 1=ERROR ; USES: AX ; SUP217: CALL TMA217 ;CONVERT ADDRESS TO 24 BITS MOV AX,10*250 ;SET MAXIMUM TIME FOR ALL TO HAPPEN CALL NWDLY ; TO 10 mS MOV AL,WISETUP ;ISSUE SETUP COMMAND OUT WIPCMD,AL SUP2172: CMP TIMEFLG,0 ;Q. TIME UP JNE SUP2174 ; BR IF YES IN AL,WIPSTAT ;INPUT HARDWARE STATUS TEST AL,WISBUSY ;Q. CONTROLLER BUSY JZ SUP2172 ; BR IF NOT MOV AL,Z217BLK+OFFSET WI01HT ;SEND HIGH ADDRESS BYTE OUT WIPCMD,AL MOV AL,Z217BLK+OFFSET WI01MT ;SEND MIDDLE ADDRESS BYTE OUT WIPCMD,AL MOV AL,Z217BLK+OFFSET WI01LT ;SEND LOW ADDRESS BYTE OUT WIPCMD,AL SUP2173: CMP TIMEFLG,0 ;Q. TIME UP JNE SUP2174 ; BR IF YES IN AL,WIPSTAT ;INPUT HARDWARE STATUS TEST AL,WISBUSY ;Q. STILL BUSY JNZ SUP2173 ; BR IF YES TEST AL,WISDONE ;Q. I/O DONE JZ SUP2173 ; BR IF NOT DONE ; RET ; SUP2174: STC ;INDICATE ERROR RET ;* ERROR REPORTING ; ; ENTRY: 'Z217BLK' CONTAINS ERROR INFORMATION ; EXIT: NONE ; USES: AL,CX,SI,DI ; ERR217: MOV BUFERR[BX],1 ;INDICATE ERROR MOV AL,Z217BLK+OFFSET WI01EEC ;GET ERROR CODE TEST DSKOP,DSKOPR+DSKOPW ;IF DOING READ OR WRITE OPERATION JZ ERR2177 MOV DI,BUFERRF[BX] ; PLACE IN ERROR ARRAY ADD DI,PHYSEC MOV [DI],AL JMPS ERR2178 ERR2177: CALL ERRRPT ; OTHERWISE REPORT ERROR IMMEDIATELY ERR2178: TEST DSKOP,DSKOPS ;Q. DOING 1ST TIME SELECT JNZ ERR2179 ; BR IF YES MOV DI,BBIOS ;COUNT HARD ERROR INC HECNT[DI] ERR2179: RET ;* LOCAL DATA AREA FOR DRIVER WIX1 EQU OFFSET $ DSEG ORG WIX1 Z217BLK RB 0 ;COMMAND BLOCK DB WIRDL ; OP CODE DB 0 ; UNIT SELECT DB 0,0 ; LOGICAL SECTOR # DB 1 ; SECTOR COUNT DB 0,0,0 ; TMA ADDRESS DB 0,0,0 ; NEXT COMMAND ADDRESS DB 0 ; FLAGS DB 0,0,0,0 ; ERROR RETURN INFO IF (OFFSET $ - OFFSET Z217BLK) NE WI01BKL %: Z217BLK IS NOT CORRECT LENGTH ENDIF ; WIX2 EQU OFFSET $ CSEG ORG WIX2  ;** 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  ;** Z-100 GENERAL DATA PORT DEFINITIONS ; ; HARDWARE IS A 6821 ; ; PORT ASSIGNMENTS GDPDATA EQU ZGDP+PIADATA ;DATA PORT A GDPDDRA EQU ZGDP+PIADDRA ;DATA DIRECTION PORT A GDPCTLA EQU ZGDP+PIACTLA ;CONTROL PORT A GDPDATB EQU ZGDP+PIADATB ;DATA PORT B GDPDDRB EQU ZGDP+PIADDRB ;DATA DIRECTION PORT B GDPCTLB EQU ZGDP+PIACTLB ;CONTROL PORT B ; CONTROL PORT A ASSIGNMENTS GDPCAV EQU PIAC12+PIAC23+PIADDAC ;INITIALIZATION VALUE LPENSI EQU PIAIRQ1 ;CA1 = LIGHT PEN STROBE ; INTERRUPT ON 0->1 VSYNCI EQU PIAIRQ2 ;CA2 = VERTICAL SYNC ; INTERRUPT ON 0->1 ; DATA DIRECTION PORT A ASSIGNMENTS GDPDDAV EQU 10101111B ; DATA PORT A ASSIGNMENTS PPRTM10 EQU 00000011B ;PRINTER D1-D0 MASK PPRTSTB EQU 00000100B ;PRINTER STROBE (OUTPUT ACTIVE LOW) PPRTPRM EQU 00001000B ;PRINTER PRIME (OUTPUT ACTIVE LOW) VSYNC EQU 00010000B ;VERTICAL SYNC (INPUT ACTIVE HIGH) VSYNCE EQU 00100000B ;VERT SYNC TO CA2 (0=DISABLE, 1=ENABLE) LPEN EQU 01000000B ;LIGHT PEN SWITCH (INPUT ACTIVE HIGH) LPENSE EQU 10000000B ;LIGHT PEN STROBE TO CA1 (0=DISABLE, 1=ENABLE) ; CONTROL PORT B ASSIGNMENTS GDPCBV EQU PIAC12+PIAC20+PIADDAC ;INITIALIZATION VALUE PRTACKI EQU PIAIRQ1 ;CB1 = PRINTER ACKNOWLEDGE ; NO INTERRUPT ON 0->1 PRTBSYI EQU PIAIRQ2 ;CB2 = PRINTER BUSY ; NO INTERRUPT ON 1->0 ; DATA DIRECTION PORT B ASSIGNMENTS GDPBDDV EQU 11111100B ; DATA PORT B ASSIGNMENTS PPRTBSY EQU 00000001B ;PRINTER BUSY (INPUT ACTIVE HIGH) PPRTFLT EQU 00000010B ;PRINTER FAULT (INPUT ACTIVE LOW) PPRTM72 EQU 11111100B ;PRINTER D7-D2 MASK  ;** Z-MACHINE 8259A INTERRUPT ASSIGNMENTS ; ; MASTER 8259A ZINTMT EQU 0C0H ;BASE TRAP VECTOR # ZINTEI EQU 0 ;ERROR INTERRUPT ZINTPS EQU 1 ;PROCESSOR SWAP ZINTTIM EQU 2 ;TIMER ZINTSLV EQU 3 ;SLAVE 8259A ZINTSA EQU 4 ;SERIAL A ZINTSB EQU 5 ;SERIAL B ZINTKD EQU 6 ;KEYBOARD OR DISPLAY ZINTPP EQU 7 ;PARALLEL PRINTER ; SLAVE 8259A ZINTST EQU ZINTMT+8 ;BASE TRAP VECTOR #  ;** Z-MACHINE KEYBOARD DEFINITIONS ; ; PORT ASSIGNMENTS ZKEYBDD EQU ZKEYBD+0 ;DATA ZKEYBDC EQU ZKEYBD+1 ;COMMAND ZKEYBDS EQU ZKEYBD+1 ;STATUS ; STATUS REGISTER ZKEYOBF EQU 00000001B ;OUTPUT BUFFER FULL ZKEYIBF EQU 00000010B ;INPUT BUFFER FULL ; COMMANDS ZKEYRES EQU 000H ;RESET ZKEYARO EQU 001H ;AUTOREPEAT ON ZKEYARF EQU 002H ;AUTOREPEAT OFF ZKEYKCO EQU 003H ;KEY CLICK ON ZKEYKCF EQU 004H ;KEY CLICK OFF ZKEYCF EQU 005H ;CLEAR FIFO ZKEYCLK EQU 006H ;CLICK ZKEYBEP EQU 007H ;BEEP ZKEYEK EQU 008H ;ENABLE KEYBOARD ZKEYDK EQU 009H ;DISABLE KEYBOARD ZKEYUDM EQU 00AH ;KEY UP/DOWN MODE ZKEYNSM EQU 00BH ;NORMAL SCAN MODE ZKEYEI EQU 00CH ;ENABLE INTERRUPTS ZKEYDI EQU 00DH ;DISABLE INTERRUPTS ; SPECIAL KEYS ZKEYBRK EQU 0AAH ;BREAK KEY  ;** Z-MACHINE MEMORY MAP UTILIZATION EQUATES ; BOOTORG EQU 0400H ;BOOT CODE LOAD ADDRESS BCODEL EQU 256+32 ;MAXIMUM BOOT CODE LENGTH BLDR88 EQU BOOTORG+BCODEL ;BIOS LOADER (8088 PORTION) BLDR88L EQU 64 ;MAXIMUM BIOS LOADER (8088) LENGTH B88STK EQU 2*1024 ;8088 STACK AREA B88DAT EQU B88STK ;MONITOR ROM DATA AREA START ADDR BIOS88 EQU 4*1024 ;WHERE 8088 CODE OF BIOS WILL RESIDE BLDRP0 EQU 16*1024 ;BIOS LOADER PAGE ZERO BIAS VALUE IF REL0 BLOADER EQU 0000H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF IF NOT REL0 BLOADER EQU 0100H ;WHERE BOOT CODE LOADS BIOS LOADER ENDIF BLDR85L EQU 8*128-BCODEL-BLDR88L ;MAXIMUM BIOS LOADER (8085) LENGTH BOOT85 EQU 0000H ;WHERE 8085 STARTS AFTER PROCESSOR SWAP SWISWAP EQU 0FEH ;SWI FOR SWAPPING PROCESSORS SWAPVEC EQU SWISWAP*4 ; VECTOR ADDRESS  ;** Z-MACHINE MONITOR ROM MTR-100 EQUATES ; ;* MONITOR ENTRY POINTS ; ; THESE VECTORS ARE PROVIDED AS ALTERNATE ENTRY POINTS ; INTO THE MONITOR ROUTINES. ; MTRSEG EQU 0FE01H ;SEGMENT VALUE ; OFFSET VALUES MTRRES EQU 00000H ;RESET THE MONITOR MTRMON EQU 00005H ;MONITOR ENTRY MTRSWIM EQU 0000AH ;SOFTWARE INTERRUPT MTRDCRT EQU 0000FH ;DUMB CRT PROCESSOR MTRDKBD EQU 00014H ;DUMP KEYBOARD PROCESSOR MTRSCRT EQU 00019H ;SMART CRT PROCESSOR MTRSKBD EQU 0001EH ;SMART KEYBOARD PROCESSOR MTRTINT EQU 00023H ;TERMINAL INTERRUPT HANDLER (VERTICAL SYNC) MTRIRET EQU 00028H ;INTERRUPT RETURN ;* MONITOR DATA AREA MTRDSEG EQU 03FEH ;OFFSET IN PAGE ZERO OF POINTER TO BE USED ; AS THE DATA SEGMENT VALUE ; DATA AREA DEFINITIONS DSEG ORG 0 RB 5 ;WILD INTERRUPT JMPF INSTRUCTION MTRVER RB 1 ;VERSION MTRDSZ RW 1 ;DATA AREA SIZE IN BYTES ; BOOT PARAMETERS MTRBI RB 1 ;BOOT DEVICE INDEX MTRBP RB 1 ;BOOT DEVICE BASE PORT MTRBS RB 80 ;BOOT STRING MTRBU RB 1 ;BOOT UNIT ; RAM VECTORS FOR PARAMETERIZED ROUTINES MTRDCI RW 2 ;DISPLAY CHARACTER INITIALIZATION MTRDFC RW 2 ;DISPLAY FONT CHARACTER MTRDXMTC RW 2 ;DUMB KEYBOARD TRANSMIT CHARACTER MTREDC RW 2 ;ERASE DISPLAY CHARACTER MTREMEC RW 2 ;EXTENDED-MODE ESCAPE CHARACTER MTRFONT RW 2 ;CHARACTER FONT ADDRESS MTRMDC RW 2 ;MOVE DISPLAY CHARACTER MTRMDL RW 2 ;MOVE DISPLAY LINE MTRP RW 2 ;DISPLAY MONITOR PROMPT MTRRDC RW 2 ;READ DISPLAYED CHARACTER MTRSXMTC RW 2 ;SMART KEYBOARD TRANSMIT CHARACTER MTRUIES RW 2 ;UNIMPLEMENTED ESCAPE SEQUENCE MTRXCA RW 2 ;TRANSMIT CHARACTER ATTRIBUTES ; CHARACTER FONT VALUES MTRFNTL RW 1 ;CHARACTER FONT TABLE LENGTH IN BYTES MTRKMAP RB 256 ;KEYBOARD MAP MTRDMAP RB 256 ;DISPLAY MAP  ;** Z-MACHINE PORT ASSIGNMENTS ; ZVIDEO EQU 0D8H ;VIDEO 68A21 ZCRTC EQU 0DCH ;VIDEO 6845 CRTC ZLPEN EQU 0DEH ;LIGHT PEN COUNTER ZGDP EQU 0E0H ;GENERAL DATA PORT (68A21) ZTIMER EQU 0E4H ;8253 TIMER ZSERA EQU 0E8H ;SERIAL A ZSERB EQU 0ECH ;SERIAL B Z8259AS EQU 0F0H ;8259A SLAVE Z8259AM EQU 0F2H ;8259A MASTER ZKEYBD EQU 0F4H ;KEYBOARD ZTSTAT EQU 0FBH ;TIMER STATUS ZMCL EQU 0FCH ;MEMORY CONTROL LATCH ZHAL EQU 0FDH ;HI-ADDRESS LATCH ZPSP EQU 0FEH ;PROCESSOR SWAP PORT ZDIPSW EQU 0FFH ;DIP SWITCHES ; MEMORY CONTROL LATCH ZMCLMS EQU 00000011B ;MAP SELECT MASK ZMS0 EQU 000H ; MAP SELECT 0 ZMS1 EQU 001H ; MAP SELECT 1 ZMS2 EQU 002H ; MAP SELECT 2 ZMS3 EQU 003H ; MAP SELECT 3 ZMCLRM EQU 00001100B ;MONITOR ROM MAPPING ZRM0 EQU 000H ; POWER UP MODE - ROM EVERYWHERE ON READS ZRM1 EQU 004H ; ROM AT THE TOP 8K OF EVERY 64K ZRM2 EQU 008H ; ROM AT THE TOP 8K OF THE 8088'S ADDR SPACE ZRM3 EQU 00CH ; DISABLE ROM ZMCLP EQU 00110000B ;PARITY HANDLING ZMCLPZ EQU 00010000B ; 0=SET PARITY TO THE ZERO STATE ZMCLPK EQU 00100000B ; 0=DISABLE PARITY CHECKING CIRCUITRY ; HI-ADDRESS LATCH ZHAL85 EQU 11111111B ;8085 MASK ZHAL88 EQU 00001111B ;8088 MASK ; PROCESSOR SWAP PORT ZPSPPS EQU 10000000B ;PROCESSOR SELECT (0=8085 , 1=8088) ZPSPPS5 EQU 000H ; SELECT 8085 ZPSPPS8 EQU 080H ; SELECT 8088 ZPSPGIS EQU 00000010B ;GENERATE INTERRUPT ON SWAPPING ZPSPI88 EQU 00000001B ;8088 PROCESSES ALL INTERRUPTS