TITLE 'CP/M-86 BIOS 23 SEP 83' ;*** ; ; THIS IS THE ZENITH DATA SYSTEMS' BIOS FOR CP/M-86. ; ; COPYRIGHT (C) 1983, ZENITH DATA SYSTEMS CORP. ; ; ; RESTRICTED RIGHTS LEGEND ; ------------------------ ; ; "Use, duplication, or disclosure by the ; government is subject to restrictions as set forth ; in paragraph (b) (3) (B) of the Rights in Technical ; Data and Computer Software clause in DAR ; 7-104.9(a). Contractor/manufacturer is Zenith ; Data Systems Corporation of Hilltop Road, St. ; Joseph, Michigan 49085. ; FALSE EQU 0 TRUE EQU NOT FALSE EXPER EQU FALSE ;EXPERIMENTAL R8085 EQU TRUE ;RUNNING 8085 PROCESSOR SUPPORTED ;*** EQUATES ; DSEG INCLUDE ZMEMMAP.LIB INCLUDE ASCII.LIB INCLUDE DEF6821.LIB INCLUDE DEF6845.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 INCLUDE ZVIDEO.LIB INCLUDE CPM86SYS.LIB INCLUDE CPM86SCB.LIB INCLUDE CIOTABLE.LIB INCLUDE ZDPEDEF.LIB INCLUDE LABDEF.LIB IF R8085 INCLUDE RUN8085.LIB ENDIF ;** MISCELLANEOUS EQUATES ; ORG 0DFH*4 ZPATVEC RW 2 ;SWI VECTOR FOR PATCHES TO CCP/BDOS ORG BDOSE*4 BDOSVEC RW 2 ;SWI VECTOR FOR BDOS ENTRY 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 ; BUFMCNT EQU 7 ;MAXIMUM # OF BUFFERS BUFMNS EQU 26 ;MAXIMUM NUMBER OF SECTORS BUFSIZ EQU 9*1024 ;BUFFER SIZE (MAX TRACK SIZE) ; 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 0 ;ADDRESS OF BUFFER AREA BUFBUFO RW 1 ; OFFSET BUFBUFS RW 1 ; SEGMENT BUFHDRL EQU OFFSET $ - OFFSET BUFHDR ;LENGTH OF BUFFER HEADER INFO EJECT ;*** SOME DEFINITIONS OF SLOTS WITHIN CCP ; CSEG ORG CPMCCP ;! CCP: ;COLD BOOT ENTRY ;! ORG CPMCCP+6 ;! CCPRET: ;WARM BOOT ENTRY ;! DSEG ORG CPMCCP+0009H ;! CCPCMD RB 0 ;COMMAND BUFFER ;! ORG CPMCCP+0939H ;! DFTDRV RB 0 ;DEFAULT DRIVE ;! ;*** SOME DEFINITIONS OF SLOTS WITHIN BDOS ; DSEG ORG CPMCCP+22E6H ;! KBCHAR RB 0 ;1 CHAR TYPE AHEAD BUFFER ;! EJECT ;*** BIOS ENTRY JUMP TABLE ; CSEG ORG CPMBIOS BIOSJMP: JMP CBOOTE ;COLD BOOT JMP WBOOTE ;WARM BOOT JMP CONSTE ;CONSOLE STATUS JMP CONINE ;CONSOLE INPUT JMP CONOUTE ;CONSOLE OUTPUT JMP LSTOUTE ;LIST OUTPUT JMP PUNOUTE ;PUNCH OUTPUT JMP RDRINE ;READER INPUT JMP HOMEE ;HOME HEAD JMP SETDSKE ;SET DISK DRIVE JMP SETTRKE ;SET TRACK JMP SETSECE ;SET SECTOR JMP SETDMAE ;SET DMA OFFSET JMP READE ;READ CP/M SECTOR JMP WRITEE ;WRITE CP/M SECTOR JMP LSTSTE ;LIST STATUS JMP SECTRNE ;SECTOR TRANLATE JMP SDMABE ;SET DMA SEGMENT JMP GETMRTE ;GET MEM DESCRIPTION TABLE OFFSET JMP GETIOBE ;GET I/O MAPPING BYTE JMP SETIOBE ;SET I/O MAPPING BYTE JMP FORMATE ;FORMAT JMP RDTRKE ;READ TRACK JMP WRTRKE ;WRITE TRACK JMP WPCE ;WRITE PROTECT CHECK JMP CLRBUFD ;CLEAR BUFFERS FOR DRIVE JMP GETBTE ;GET BIOS TABLES EJECT ;*** COLD BOOT ENTRY ; CBOOTE: CLI ;INSURE I'M NOT DISTURBED ; INITIALIZE REGISTERS MOV AX,CS MOV DS,AX MOV SS,AX LEA SP,STACK ADD NXTAVL,AX ;MEMORY TABLE (ADJUST FOR LOAD ADDRESS) MOV IFLAG,0 ;CLEAR BIOS INTERRUPT HANDLER FLAGS IF R8085 MOV R85MEM,0 ;INDICATE 8085 PROCESSOR NOT RUNNING MOV R85BCS,CS ;SAVE (CS) FOR RUNTIME PACKAGE ENDIF ; INITIALIZE PARITY GENERATION & SIZE MEMORY (IN 1K CHUNKS) PUSH DS 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 MOV DX,AX ;INIT TOP OF MEMORY PARAGRAPH CLD 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 JE MEMIA ; BR IF YES CMP DX,0 ;Q. 1ST SECTION OF CONTIGUOUS MEMORY JNE MEMIC ; BR IF ALREADY ESTABLISHED MOV DX,DS JMPS MEMIC MEMIA: MOV .0,BX ;RESTORE VALUE XOR SI,SI ;SET UP REGS FOR MOVE XOR DI,DI MOV CX,512 ;GET NUMBER OF WORDS TO MOVE REP MOVSW ;MOVE WORDS ONTO THEMSELVES MEMIC: MOV AX,DS ;POINT TO NEXT SEGMENT ADD AX,1024/16 JNZ MEMIL ; LOOP IF NO WRAP AROUND POP DS MOV TOPMEM,DX ;SAVE AS TOP OF MEMORY 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 ; INCASE BOOTING WAS DONE ON Z217, PICK UP PARTITION LIMITS ; FROM LOW MEMORY XOR AX,AX MOV ES,AX MOV AX,ES: .0 MOV Z217BP,AX MOV AX,ES: .2 MOV Z217EP,AX ; INITIALIZE ALL VECTORS (EXCEPT WHERE MONITOR DATA SEGMENT INFO ; IS) TO POINT TO WILD INTERRUPT HANDLER PUSH DS XOR AX,AX MOV DS,AX MOV ES,AX MOV WORD PTR .0,OFFSET INTWILD ;INIT VECTORS FOR WILD INT MOV .2,CS MOV SI,0 MOV DI,4 MOV CX,(256-2)*4/2 CLD REP MOVSW ; INITIALIZE SOFTWARE INTERRUPT VECTORS MOV WORD PTR .0,OFFSET INTDIV0 ;DIVIDE BY ZERO MOV .2,CS MOV BDOSVEC,CPMBDOS ;BDOS CALLS MOV BDOSVEC+2,CS MOV ZPATVEC,OFFSET ZPATCH ;PATCHES TO CCP/BDOS MOV ZPATVEC+2,CS POP DS ; INITIALIZE HARDWARE INTERRUPT VECTORS XOR AX,AX MOV ES,AX LEA SI,HINTVO MOV DI,ZINTMT*4 MOV CX,HINTVON 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 ; 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 MOV AX,0 ;INDICATE NO LIGHT PEN HIT MOV ES,AX MOV ES: LPENHF,0 ; MOVE ROM MONITOR DATA AREA TO BIOS XOR AX,AX ;GET MONITOR DATA AREA SEGMENT MOV ES,AX MOV ES,ES:.MTRDSEG MOV AX,ES:MTRDSZ ;GET FREE MEMORY CALL GETMEM JNC MVMDA ; BR IF AVAILABLE LEA SI,MTRMSG CALL PMSG JMP SYSHLT MVMDA: MOV CX,ES:MTRDSZ ;MOVE MONITOR DATA AREA MOV SI,0 MOV DI,0 PUSH DS MOV DX,ES MOV DS,DX MOV ES,AX CLD REP MOVSB POP DS XOR DX,DX ;UPDATE LOW MEMORY POINTER MOV ES,DX ; TO MONITOR DATA AREA MOV ES:.MTRDSEG,AX ; CALL INTIM ;INITIALIZE TIMER STI ;ALLOW INTERRUPTS NOW ; INITIALIZE HOST BUFFERING SCHEME CALL INBUF ; INITIALIZE LOGICAL DRIVE TO PHYSICAL DRIVE MAP XOR AX,AX MOV ES,AX MOV ES,ES: .MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA CMP ES: MTRBI,2 ;Q. Z217 BOOTED JNE CBINDRV1 ; BR IF NOT CALL IN217 CALL IN207 JMPS INITMT CBINDRV1: CALL IN207 CALL IN217 ; INIT MEMORY REGION DESCRIPTION TABLE INITMT: MOV AX,TOPMEM ;CALC # PARAGRAPHS SUB AX,NXTAVL MOV MEMAVL,AX ; GET ALTERNATE CHARACTER FONT INFO GALTCHR: CALL ALTCHR ; PRINT SIGNON MESSAGE MOV AL,DEFIOB ;SET DEFAULT I/O BYTE MOV IOBYTE,AL LEA SI,SIGNON CALL PMSG ; ENTER CP/M COMMAND PROCESSOR MOV AX,CS ;INIT (ES) MOV ES,AX CMP AUTOCBC,0 ;Q. AUTO COMMAND ON COLD BOOT JE CBOOTCCP ; BR IF NOT XOR CH,CH ;ZERO COMMAND BUFFER MOV CL,CCPCMD INC CX LEA DI,CCPCMD+1 CLD MOV AL,0 REP STOSB MOV CL,AUTOCBC ;MOVE IN AUTO COMMAND INC CX LEA SI,AUTOCBC LEA DI,CCPCMD+1 REP MOVSB CBOOTCCP: MOV AX,BIOSWJ ;RESET COLD BOOT JMP TO ADD AX,3 ; POINT TO WARM BOOT MOV BIOSCJ,AX MOV CL,0 ;DEFAULT DISK IS A: JMP CCP CBX1 EQU OFFSET $ DSEG ORG OFFSET BIOSJMP RB 1 BIOSCJ RW 1 RB 1 BIOSWJ RW 1 CSEG ORG CBX1 EJECT ;** WARM BOOT ENTRY ; WBOOTE: CALL CLRBUFA ;CLEAR ALL HOST BUFFERS IF R8085 ; TERMINATE 8085 PROCESS IF ONE IS RUNNING CMP R85MEM,0 ;Q. 8085 RUNNING JE WBOOTE1 ; BR IF NOT PUSHF ;I DON'T WANT TO BE DISTURBED CLI MOV ES,R85MEM ;INDICATE TO 8085 TERMINATE MOV ES:COMFLG,COMTERM MOV AL,ZPSPPS5+ZPSPI88 ;SWAP TO 8085 TEMPORARILY OUT ZPSP,AL MOV R85MEM,0 ;INDICATE NO 8085 PROCESS RUNNING POPF ;RE-ESTABLISH INTERRUPT STATUS ENDIF WBOOTE1: CMP AUTOWBC,0 ;Q. AUTO COMMAND ON WARM BOOT JE WBOOTE2 ; BR IF NOT XOR CH,CH ;ZERO COMMAND BUFFER MOV CL,CCPCMD INC CX LEA DI,CCPCMD+1 MOV AX,DS MOV ES,AX CLD MOV AL,0 REP STOSB MOV CL,AUTOWBC ;MOVE IN AUTO COMMAND INC CX LEA SI,AUTOWBC LEA DI,CCPCMD+1 REP MOVSB WBOOTE2: JMP CCPRET ;ENTER CP/M COMMAND PROCESSOR ;** CONSOLE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=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 RET ;** CONSOLE INPUT ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=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 RET ;** CONSOLE OUTPUT ENTRY ; ; ENTRY: (CL)=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; CONOUTE: 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 LSTOUTE ; BR IF YES JMP ODCIO ;RETURN VIA CIO HANDLER ;** LIST OUTPUT ENTRY ; ; ENTRY: (CL)=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; LSTOUTE: MOV AH,CL ;SAVE CHARACTER MOV AL,IOBYTE ;GET IOBYTE VALUE MOV CL,5 ;ADJUST VALUE SHR AL,CL MOV CL,AH ;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: (CL)=CHARACTER TO BE OUTPUT ; EXIT: NONE ; USES: ALL ; PUNOUTE: MOV AH,CL ;SAVE CHARACTER MOV AL,IOBYTE ;GET IOBYTE VALUE MOV CL,3 ;ADJUST VALUE SHR AL,CL MOV CL,AH ;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)=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 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 CX,0 ;SET REQUESTED TRACK # = 0 JMP SETTRKE ;JOIN SET TRACK CODE ;** SET DISK DRIVE ENTRY ; ; ENTRY: (CL)=REQUESTED DRIVE ; (DL)=LSB INDICATES 1ST TIME SINCE WARM BOOT SELECT ; 0=1ST TIME , 1=SUBSEQUENT TIMES ; EXIT: (BX)=RESULTS ; 0=ERROR , NOT 0=NO ERROR ; USES: ALL ; SETDSKE: PUSH ES MOV REQDRV,CL ;SAVE REQUESTED DRIVE CMP CL,NDISKS ;CHECK IF IN RANGE JAE SETDSKE5 ; BR IF NOT MOV AL,CL ;CONVERT LOGICAL DRIVE # TO CBW ; PHYSICAL DRVIE # MOV BX,AX MOV AL,BDMAP[BX] MOV PHYDRV,AL MOV BL,DPEL ;COMPUTE ADDRESS OF DPE MUL BL ADD AX,OFFSET DPEBASE MOV PHYDPE,AX ;SAVE IT TEST DL,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 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 BX,PHYDPE POP ES RET ; ERROR DURING SETUP SETDSKEA: CALL CLRBUFD ;GIVE BACK BUFFER JMPS SETDSKE5 ;** SET TRACK ENTRY ; ; ENTRY: (CX)=TRACK # ; EXIT: NONE ; USES: ALL ; SETTRKE: MOV REQTRK,CX ;SAVE AS REQUESTED CP/M TRACK # RET ;** SET SECTOR ENTRY ; ; ENTRY: (CX)=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 CL 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: DEC CL ;PUT INTO RANGE 0 TO SPT-1 XOR CH,CH ;ZERO HIGH ORDER BYTE MOV REQSEC,CX ;SAVE AS REQUESTED CP/M SECTOR # RET ;** SET DMA OFFSET ENTRY ; ; ENTRY: (CX)=DMA POINTER OFFSET ; EXIT: NONE ; USES: ALL ; SETDMAE: MOV DMAPTR,CX ;SAVE AS DMA POINTER OFFSET RET ;** READ CP/M SECTOR ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; READE: PUSH ES 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. PUSH DS LES DI,DWORD PTR DMAPTR ;GET DMA POINTER LDS SI,DWORD PTR BUFBUF[BX] ;COMPUTE START OF REQ CP/M SECTOR ADD SI,AX ; IN HOST BUFFER CLD REP MOVSW ;MOVE DATA FROM HOST TO USER BUFFER POP DS ; CALL CPSEC ;INDICATE ERROR STATUS OR DSKOP,DSKOPR CALL ABTIGN AND DSKOP,NOT DSKOPR READE1: MOV AL,BUFERR[BX] POP ES RET ;** WRITE CP/M SECTOR ENTRY ; ; ENTRY: (CL)=TYPE OF WRITE ; 0=NORMAL WRITE ; 1=WRITE TO A DIRECTORY SECTOR ; 2=1ST WRITE TO A SECTOR IN AN UNALLOCATED BLOCK ; EXIT: (AL)=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; WRITEE: PUSH ES MOV BWRFLG,CL ;SAVE TYPE OF WRITE 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. PUSH DS LES DI,DWORD PTR BUFBUF[BX] ;COMPUTE START OF REQ CP/M SECTOR ADD DI,AX ; IN HOST BUFFER LDS SI,DWORD PTR DMAPTR ;GET DMA POINTER CLD REP MOVSW ;MOVE DATA FROM USER TO HOST BUFFER POP DS ; 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. CMP BWRFLG,BWRDIR ;CHECK TYPE OF WRITE JNE WRITEE5 ; BR IF NOT DIRECTORY WRITE CALL FLUSHD ;FLUSH BUFFERS JMPS WRITEE6 ; WRITEE5: MOV AL,BUFERR[BX] ;INDICATE ERROR STATUS WRITEE6: POP ES RET ;** CHECK LIST DEVICE STATUS ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=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 RET ;** SECTOR TRANSLATE ENTRY ; ; ENTRY: (CX)=LOGICAL SECTOR NUMBER (IN RANGE 0 TO SPT-1) ; (DX)=ADDRESS OF SECTOR TABLE ; EXIT: (BX)=TRANSLATED CP/M SECTOR NUMBER (IN RANGE 1 TO SPT) ; USES: ALL ; SECTRNE: MOV BX,CX TEST DX,DX JZ SECTRNE1 ADD BX,DX MOV BL,[BX] XOR BH,BH JMPS SECTRNE2 SECTRNE1: INC BX SECTRNE2: RET ;** SET DMA SEGMENT ADDRESS ; ; ENTRY: (CX)=SEGMENT BASE FOR DMA READ OR WRITE OPERATIONS ; EXIT: NONE ; USES: NONE ; SDMABE: MOV DMASEG,CX ;SAVE FOR LATER RET ;** GET THE OFFSET OF THE MEMORY REGION TABLE ; ; ENTRY: NONE ; EXIT: (BX)=OFFSET OF THE MEMORY REGION TABLE ; USES: BX ; GETMRTE: LEA BX,MSEGTBL RET ;** GET THE I/O MAPPING BYTE ; ; ENTRY: NONE ; EXIT: (AL)=VALUE ; USES: AL ; GETIOBE: MOV AL,IOBYTE RET ;** SET THE I/O MAPPYING BYTE ; ; ENTRY: (CL)=VALUE ; EXIT: NONE ; USES: NONE ; SETIOBE: MOV IOBYTE,CL RET ;** FORMAT - FORMAT ENTRY ; ; ENTRY: (CL)=VERIFY FLAG (0=NO , 1=YES) ; EXIT: (AL)=STATUS BYTE ; USES: ALL ; FORMATE: PUSH ES MOV FVFLG,CL ;SAVE VERIFY FLAG 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,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: PUSH AX CALL CLRBUFD ;GIVE BACK BUFFER POP AX POP ES RET ;** READ TRACK ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; RDTRKE: PUSH ES 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 PUSH DS LES DI,DWORD PTR DMAPTR ;GET DMA POINTER LDS SI,DWORD PTR BUFBUF[BX] ;GET START OF HOST BUFFER CLD REP MOVSB ;MOVE DATA FROM HOST TO USER BUFFER POP DS ; RDTRKE1: MOV AL,BUFERR[BX] ;INDICATE ERROR STATUS POP ES RET ;** WRITE TRACK ENTRY ; ; ENTRY: NONE ; EXIT: (AL)=ERROR STATUS ; 0=NO ERROR , 1=ERROR ; USES: ALL ; WRTRKE: PUSH ES 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 PUSH DS LES DI,DWORD PTR BUFBUF[BX] ;GET START OF HOST BUFFER LDS SI,DWORD PTR DMAPTR ;GET DMA POINTER CLD REP MOVSB ;MOVE DATA FROM USER TO HOST BUFFER POP DS ; 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 POP ES RET ;** WRITE PROTECT CHECK ; ; ENTRY: NONE ; EXIT: (AL)=STATUS (0=R/W , 1=R/O) ; USES: ALL ; WPCE: PUSH ES 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 POP ES RET ;** GET BIOS TABLES ; ; ENTRY: NONE ; EXIT: (BX)=OFFSET ; USES: BX ; GETBTE: LEA BX,BIOSTBL 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 CLD 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 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 ; DETERMINE NUMBER OF BUFFERS TO PROVIDE BASED ON AMOUNT OF MEMORY MOV CX,1 ;1 BUFFER CMP TOPMEM,1000H ;Q. <= 64K JBE INBUF0 ; BR IF YES MOV CX,4 CMP TOPMEM,3000H ;Q. 64K < X <= 192K JBE INBUF0 ; BR IF YES MOV CX,BUFMCNT ;MAX # BUFFERS INBUF0: MOV BUFCNT,CX ;SAVE BUFFER COUNT ; ATTEMPT TO PROVIDE N 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 INBUF1: MOV AX,BUFSIZ ;GET MEMORY FOR BUFFER CALL GETMEM JC INBUF3 ; BR IF NOT AVAILABLE MOV BUFBUFO[BX],0 ;INIT OFFSET OF BUFFER MOV BUFBUFS[BX],AX ;INIT SEGMENT OF BUFFER MOV BUFSECF[BX],SI ;INIT ADDRESS OF DIRTY SECTOR FLAG AREA MOV BUFERRF[BX],DX ;INIT ADDRESS OF SECTOR ERROR FLAG AREA PUSH BX PUSH CX PUSH DX PUSH SI PUSH BX MOV DI,0 ;INSERT HEADER AT END CALL INSBUF POP BX CALL CLRBUF ;CLEAR BUFFER HEADER POP SI POP DX POP CX POP BX ADD BX,BUFHDRL ;BUMP POINTERS ADD SI,SECFLGL ADD DX,ERRFLGL LOOP INBUF1 ;LOOP FOR # OF BUFFERS INBUF2: SUB BUFCNT,CX ;UPDATE ACTUAL # BUFFERS PROVIDED RET ; OUT OF MEMORY FOR BUFFERS. ERROR IF AT LEAST 1 BUFFER COULD ; NOT BE PROVIDED. INBUF3: CMP CX,BUFCNT ;Q. COUNT = REQUEST JNE INBUF2 ; BR IF NOT -- ABLE TO GET AT LEAST 1 LEA SI,BUFMSG CALL PMSG JMP SYSHLT ;** 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: PUSH ES 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: POP ES 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 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 CL,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 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: TEST CIOF1[BX],CIOFO ;Q. FAST I/O JZ ODCIO0 ; BR IF NOT MOV AL,CL JMP CIOOD[BX] ;DO OUTPUT ODCIO0: CALL OSCIO ;WAIT UNTIL READY TEST AL,AL JZ ODCIO0 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: AX,BX ; INCRT: PUSHF ;INSURE INTERRUPTS ARE DISABLED CLI ; DURING INIT LEA BX,CRTTBL ;GET ADDRSS OF CIO TABLE ENTRY 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 XOR AX,AX ;INITIALIZE KEYBOARD HANDLER TO MOV ES,AX ; USE MY QUEUE MOV ES,ES: .MTRDSEG MOV ES:MTRDXMTC,MTRSKBD MOV ES:MTRDXMTC+2,MTRSEG MOV ES:MTRSXMTC,OFFSET PUTKEY MOV ES:MTRSXMTC+2,CS INCRT1: IN AL,ZKEYBDS ;INSURE KEYBOARD INTERRUPTS TEST AL,ZKEYIBF ; ARE ENABLED JNZ INCRT1 MOV AL,ZKEYEI OUT ZKEYBDC,AL 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 CALL FLCRT9 ;FLUSH TYPE AHEAD BUFFER 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 FLCRT9: MOV KEYCNT,0 ;INIT BUFFER HANDLING VALUES LEA BX,KEYBUF MOV KEYPUT,BX MOV KEYGET,BX 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: PUSH BX MOV MSAVSS,SS ;SET UP LOCAL STACK FOR MONITOR CALL MOV MSAVSP,SP MOV BX,DS MOV SS,BX LEA SP,MSTACK PUSHA CLD CALLFI MTRSCRT,MTRSEG ;CALL ROM MONITOR ROUTINE POPA MOV SS,MSAVSS MOV SP,MSAVSP ;RESTORE (SP) POP BX 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 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 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 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 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 MOV AX,CS MOV DS,AX LEA SI,DIV0MSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** INTPBE - PARITY OR BUSS ERROR HANDLER ; INTPBE: PUSHA MOV AX,CS MOV DS,AX LEA SI,PBEMSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** INTLVK - LIGHTPEN, VSYNC, & KEYBOARD HANDLER ; INTLVK: POP CS: ISAVPC ;SET UP INTERRUPT LOCAL STACK CALL ISETSTK 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 IN AL,GDPDATA ;CLEAR INTERRUPT AND GET DATA TEST AL,LPEN ;Q. LIGHT PEN HIT INTERRUPT JZ INTV ; BR IF NOT PUSH AX MOV AX,0 ;NEED ADDRESSABILITY TO PAGE 0 MOV ES,AX MOV AL,CRTLPH ;GET LIGHT PEN ADDRESS MSB OUT ZCRTC+CRTREG,AL IN AL,ZCRTC+CRTDAT MOV BH,AL MOV AL,CRTLPL ;GET LIGHT PEN ADDRESS LSB OUT ZCRTC+CRTREG,AL IN AL,ZCRTC+CRTDAT MOV BL,AL ; BX = RELATIVE ADDRESS OF HIT, NOW GET REAL ADDRESS MOV AL,CRTSAH ;GET START ADDRESS MSB OUT ZCRTC+CRTREG,AL IN AL,ZCRTC+CRTDAT MOV AH,AL MOV AL,CRTSAL ;GET START ADDRESS LSB OUT ZCRTC+CRTREG,AL IN AL,ZCRTC+CRTDAT SUB BX,AX ;(BX)=RELATIVE HIT ADDRESS SUB BX,ZLPENEV ; SUBTRACT ERROR VALUE ; MOV ES: LPENHF,1 ;INDICATE LIGHT PEN HIT MOV ES: LPENPOS,BX ;STORE LIGHT PEN POSITION IN AL,ZLPEN ;READ LIGHT PEN HIT REGISTER MOV ES: LPENHIT,AL ; STORE IT POP AX ;* 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 AL,ZKEYBRK ;Q. KEY -- FLUSH TYPE AHEAD BUFS JNE INTKEY0 ; BR IF NOT CALL FLCRT9 ; FLUSH BIOS BUFFER MOV AL,IOBYTE ; IF CRT IS CON:, THEN ALSO AND AL,3 ; FLUSH BDOS 1 CHARACTER BUFFER CMP AL,1 JNE INTKEY3 MOV KBCHAR,0 JMPS INTKEY3 INTKEY0: 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 ;** INTWILD - WILD INTERRUPT ; INTWILD: PUSHA MOV AX,CS MOV DS,AX LEA SI,WILDMSG ;PRINT MESSAGE AND DUMP CALL PMSG POPA JMP SYSDMP ;** SYSDMP - DUMP REGISTERS AT INTERRUPT ; SYSDMP: PUSH DS ;SAVE DS PUSH DI MOV DI,CS ;GET DS MOV DS,DI LEA DI,DMPAX ;AX CALL HEXW POP AX ;DI LEA DI,DMPDI CALL HEXW POP AX ;DS LEA DI,DMPDS 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,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 SYSHLT1: CLI ;INSURE MACHINE HALTS JMPS SYSHLT1 ;** 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: TEST CS: IFLAG,IBIOS ;Q. HANDLER IN BIOS JNZ INTX3A ; BR IF YES POP CS: ISAVPC ;RETRIEVE (PC) JMPS INTX3B INTX3A: MOV SS,CS: ISAVSS ;RESTORE STACK MOV SP,CS: ISAVSP INTX3B: IF R8085 POP CS: ISAVCS PUSH ES CMP CS:R85MEM,0 ;Q. 8085 PROCESS RUNNING JE INTX3C ; BR IF NOT MOV ES,CS:R85MEM TEST ES:COMWHO,ZPSPPS ;Q. 8088 IN CONTROL AT TIME OF INT JNZ INTX3C ; BR IF YES IF ZPSPPS8 NE ZPSPPS %: ZPSPPS8 NE ZPSPPS ENDIF MOV CS:ISAVCS,CS ;ALTER RETURN INFO TO PASS CONTROL MOV CS:ISAVPC,OFFSET SWAP851 ; TO 8085 SWAP ROUTINE INTX3C: POP ES PUSH CS: ISAVCS ENDIF PUSH CS: ISAVPC AND CS: IFLAG,NOT IBIOS IRET ;DO RETURN FROM INTERRUPT ;** SET UP LOCAL STACK FOR INTERRUPT HANDLER ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; ISETSTK: POP CS: ISAVRET ;SAVE RETURN ADDRESS MOV CS: ISAVSS,SS ;SAVE STACK POINTERS MOV CS: ISAVSP,SP MOV CS: ISAVAX,AX ;SET UP LOCAL STACK MOV AX,CS MOV SS,AX LEA SP,ISTACK MOV AX,CS: ISAVAX OR CS: IFLAG,IBIOS ;INDICATE HANDLER IN BIOS & STACK USED JMP CS: ISAVRET ;RETURN USING SAVED RETURN ADDRESS 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: NONE ; EXIT: NONE ; USES: ALL ; ALTCHR: MOV CL,FAM ;FREE ALL MEMORY TO INIT BDOS INT BDOSE ; MEMORY MANAGEMENT MOV CL,RDS ;RESET BDOS DISK SYSTEM INT BDOSE MOV CL,OPEN ;ATTEMPT TO OPEN FILE LEA DX,ALTCFCB ; 'ALTCHAR.SYS' INT BDOSE INC AL ; JZ ALTCHR9 ; BR IF NOT FOUND JNZ $+5 JMP ALTCHR9 MOV CL,CFSIZE ;COMPUTE FILE SIZE LEA DX,ALTCFCB INT BDOSE MOV AX,WORD PTR ALTCFCB+(OFFSET FCBRR) CMP AX,0 ;Q. NULL FILE ; JE ALTCHR8 ; BR IF YES JNE $+5 JMP ALTCHR8 CMP AX,512 ;Q. FILE SIZE > 64K ; JA ALTCHR8 ; BR IF YES JBE $+5 JMP ALTCHR8 MOV DX,128/16 ;COMPUTE # PARAGRAPHS IN FILE MUL DX MOV MCBLEN,AX ;ALLOCATE SPACE TO READ IN FILE MOV CL,GMREG LEA DX,MCB INT BDOSE INC AL ; JZ ALTCHR8 ; BR IF UNABLE TO ALLOCATE JNZ $+5 JMP ALTCHR8 MOV CL,SDMASB ;SET DMA SEGMENT BASE MOV DX,MCBBASE INT BDOSE XOR DX,DX ;INITIALZE DMA OFFSET ALTCHR0: MOV CL,SETDMA ;SET DMA OFFSET PUSH DX INT BDOSE MOV CL,READ ;READ NEXT CP/M RECORD LEA DX,ALTCFCB INT BDOSE POP DX ;BUMP DMA OFFSET ADD DX,128 CMP AL,0 ;Q. END OF FILE JZ ALTCHR0 ; BR IF NOT XOR AX,AX MOV ES,AX MOV ES,ES:.MTRDSEG ;ES=>MONITOR DATA AREA CMP ES:MTRFNTL,ALTFNTL ;Q. WILL ROM FONT TABLE FIT IN MY AREA JBE ALTCHR1 ; BR IF YES LEA SI,FNTMSG ;PRINT ERROR MESSAGE CALL PMSG JMP SYSHLT ; MOVE ROM FONT TABLE TO MY AREA ALTCHR1: CLD LEA DI,ALTFNT MOV CX,ES:MTRFNTL MOV SI,ES:MTRFONT MOV ES,ES:MTRFONT+2 CALL EXDSES ;DS=>ROM FONT TABLE , ES=>BIOS REP MOVSB CALL EXDSES ;DS=>BIOS , ES=>ROM FONT TABLE ; MAKE CHANGES TO KEYBOARD MAP XOR SI,SI PUSH DS MOV DS,MCBBASE ;DS=>ALTCHAR.SYS FILE DATA XOR AX,AX MOV ES,AX MOV ES,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: POP ES ;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: PUSH ES XOR AX,AX MOV ES,AX MOV ES,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: POP DS ;DS=>BIOS MOV ES: MTRFONT,OFFSET ALTFNT MOV ES: MTRFONT+2,DS ;UPDATE FONT TABLE VECTOR ALTCHR8: MOV CL,CLOSE ;CLOSE FILE LEA DX,ALTCFCB INT BDOSE MOV CL,FAM ;FREE ALLOCATED MEMORY INT BDOSE 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 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 DEC NDISKS ; NONEXISTANT DRIVE AND DECREMENT JMPS CBTF4 ; # CP/M DRIVES 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 MOV AX,DS MOV ES,AX CLD REP MOVSB 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 [BX],AL ;PLACE MAPPED DRIVE # THERE INC CBIC ;BUMP VALUE NEXT LOGICAL DRIVE # RET ;** CHKLAB - CHECK CHECKSUM OF LABEL ; ; ENTRY: (SI),(ES)=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,ES:[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 ;** 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 MOV AX,DS ;'READ' OR 'WRITE' ERROR 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 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' ;** GETMEM -- GET NEXT AVAILABLE PARAGRAPH VALUE & UPDATE ; MEMORY TABLE ; ; ENTRY: (NXTAVL)=NEXT AVAILABLE PARAGRAPH ; (AX)=LENGTH OF REQUEST ; EXIT: 'CY' 1=ERROR ; 0=OK , (AX)=PARAGRAPH VALUE ; USES: AX ; GETMEM: PUSH CX ;CALC # PARAGRAPHS REQUESTED PUSH DX MOV DX,0 ADD AX,15 ADC DX,0 MOV CX,16 DIV CX POP DX POP CX ADD AX,NXTAVL ;CALC NEW NEXT CMP AX,TOPMEM ;Q. PAST END OF MEMORY JAE GETMEM1 ; BR IF YES XCHG AX,NXTAVL ;GET RETURN VALUE CLC ;INDICATE NO ERROR RET GETMEM1: STC ;INDICATE ERROR RET ;** 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 CL,AL PUSH SI CALL CONOUTE POP SI 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 INCLUDE PATHNDLR.LIB EJECT IF R8085 INCLUDE R85PKG.LIB ENDIF EJECT ;*** BIOS TABLES ; X EQU OFFSET $ DSEG ORG X BIOSFLG EQU TRUE INCLUDE BIOSDEF.LIB ; DISK PARAMETER ENTRY TABLES DPE1A RB 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 OFFSET $ - OFFSET DPE1A NE DPEL %: DPE1A IS INCORRECT LENGTH ENDIF DPE1B RB 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 OFFSET $ - OFFSET DPE1B NE DPEL %: DPE1B IS INCORRECT LENGTH ENDIF DPE1C RB 0 ;PHYSICAL DRIVE 2 -- Z207 8" DW XLATE1,0,0,0 DW DIRBUF DW DPB1C DW CSV1C DW ALV1C DB DPEZ207+DPEDD DB CONPC+CONDS8+0 DB 0 DB 0 DB DPEUNK DB FDFS6 DB DPEHLS DB 0 IF OFFSET $ - OFFSET DPE1C NE DPEL %: DPE1C IS INCORRECT LENGTH ENDIF DPE1D RB 0 ;PHYSICAL DRIVE 3 -- Z207 8" DW XLATE2,0,0,0 DW DIRBUF DW DPB1D DW CSV1D DW ALV1D DB DPEZ207+DPEDD DB CONPC+CONDS8+1 DB 0 DB 0 DB DPEUNK DB FDFS6 DB DPEHLS DB 0 IF OFFSET $ - OFFSET DPE1D NE DPEL %: DPE1D IS INCORRECT LENGTH ENDIF DPE2A RB 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 OFFSET $ - OFFSET DPE2A NE DPEL %: DPE2A IS INCORRECT LENGTH ENDIF DPE2B RB 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 OFFSET $ - OFFSET DPE2B NE DPEL %: DPE2B IS INCORRECT LENGTH ENDIF EJECT ;*** DATA STORAGE ; FNTMSG RB 0 ;ROM FONT TABLE TOO LARGE DB CR,LF,'MONITOR ROM FONT TABLE IS LARGER THAN BIOS ' DB 'FONT TABLE AREA',CPMEOM SIGNON RB 0 ;SIGNON MESSAGE DB CR,LF,LF DB 'CP/M-86 1.1 Release ' IF (BREL/10) NE 0 DB BREL/10+'0' ENDIF DB (BREL MOD 10)+'0' IF EXPER DB 'x' ENDIF IF NOT EXPER DB '.' ENDIF DW BREVSNA 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 MTRMSG RB 0 DB BELL,CR,LF,'UNABLE TO MOVE MONITOR ROM DATA AREA',CR,LF,CPMEOM TIMERRM RB 0 ;TIMER BROKE MSG DB BELL,CR,LF,'THE TIMER IS BROKE',CR,LF,CPMEOM BUFMSG RB 0 DB BELL,CR,LF,'NOT ENOUGH MEMORY FOR DISK BUFFERS',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 DW OFFSET INTX3 ; SOFTWARE INTERRUPT EXIT ROUTINE HINTVON EQU (OFFSET $ - OFFSET HINTVO)/2 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 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 RB 0 ;SINGLE DENSITY / SINGLE SIDED / 128 DW XLATE1 DB 1,8 DW 26 DB 3,7,0 DW 242,63 DB 0C0H,0 DW 16,2 Z2072S RB 0 ;SINGLE DNESITY / DOUBLE SIDED / 128 DW XLATE1 DB 1,16 DW 26 DB 4,15,1 DW 246,127 DB 0C0H,0 DW 32,2 Z2071D1 RB 0 ;DOUBLE DENSITY / SINGLE SIDED / 256 DW XLATE2 DB 2,16 DW 52 DB 4,15,0 DW 242,127 DB 0C0H,0 DW 32,2 Z2071D2 RB 0 ;DOUBLE DENSITY / SINGLE SIDED /1024 DW 0 DB 8,16 DW 64 DB 4,15,0 DW 299,127 DB 0C0H,0 DW 32,2 Z2072D1 RB 0 ;DOUBLE DENSITY / DOUBLE SIDED / 256 DW XLATE2 DB 2,16 DW 52 DB 4,15,0 DW 493,255 DB 0F0H,0 DW 64,2 Z2072D2 RB 0 ;DOUBLE DENSITY / DOUBLE SIDED /1024 DW 0 DB 8,16 DW 64 DB 4,15,0 DW 607,255 DB 0F0H,0 DW 64,2 XLATE1 RB 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 RB 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 ; MEMORY REGION TABLE MSEGTBL RB 0 DB 1 NXTAVL DW (B86END+15)/16 MEMAVL DW 0 ; ALTCFCB RB 0 ;FCB FOR FILE 'ALTCHAR.SYS' DB 1,'ALTCHAR SYS',0,0,0,0 DW 0,0,0,0,0,0,0,0 DB 0,0,0,0 IF OFFSET $ - OFFSET ALTCFCB NE FCBLR %: 'ALTCHAR.SYS' FCB IS NOT CORRECT LENGTH ENDIF TODINT RB 0 ;INITIAL SCB DATE & TIME FIELDS DW 0 DB 0,0,0 DB '01/01/78,00:00:00' TODINTL EQU OFFSET $ - OFFSET TODINT TODDAYS RW 0 ;NUMBER OF DAYS IN EACH MONTH DW '31' ; JAN DW '28' ; FEB DW '31' ; MAR DW '30' ; APR DW '31' ; MAY DW '30' ; JUN DW '31' ; JUL DW '31' ; AUG DW '30' ; SEP DW '31' ; OCT DW '30' ; NOV DW '31' ; DEC IOBYTE DB 00000001B ;I/O MAPPING BYTE ; (VALUE AT COLD BOOT IS CON:=CRT:) ; PATCH RB 128 ;PATCH AREA ; 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 (OFFSET) DMASEG RW 1 ;DMA ADDRESS (SEGMENT) IF (OFFSET DMASEG) NE (OFFSET DMAPTR + 2) %: DMASEG DOES NOT IMMEDIATELY FOLLOW DMAPTR ENDIF BWRFLG RB 1 ;WRITE TYPE FLAG FVFLG RB 1 ;FORMAT VERIFY FLAG HSTPTR RW 2 ;HOST BUFFER POINTER (OFFSET,SEGMENT) 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) RDABUF RB FDRAL ;READ ADDRESS BUFFER RDABUF2 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 TICCNT RW 2 ;TIC COUNTER (32 BIT) TIMEFLG RB 1 ;TIMER 2 FLAG (1=TIMER FIRED) TODHSEC RW 1 ;TOD TIME HUNDREDTHS OF SECOND CPMSCB RW 1 ;CP/M-86 SYSTEM CONTROL BLOCK OFFSET TOPMEM RW 1 ;TOP OF MEMORY BDMAP RB 16 ;LOGICAL TO PHYSICAL DRIVE MAP DIRBUF RB 128 ;DIRECTORY SECTOR BUFFER DPB1A RB DPBL CSV1A RB 64 ALV1A RB 77 DPB1B RB DPBL CSV1B RB 64 ALV1B RB 77 DPB1C RB DPBL CSV1C RB 64 ALV1C RB 77 DPB1D RB DPBL CSV1D RB 64 ALV1D RB 77 DPB2A RB DPBL ALV2A RB 256 DPB2B RB DPBL ALV2B RB 256 ; MCB RB 0 ;MEMORY CONTROL BLOCK MCBBASE RW 1 MCBLEN RW 1 MCBEXT RB 1 ; 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 ; STACK FOR COLD BOOT RW 64 STACK RW 0 ; STACK FOR MONITOR CALLS RW 512 MSTACK RW 0 MSAVSS RW 1 MSAVSP RW 1 ; STACK FOR INTERRUPT HANDLERS RW 128 ISTACK RW 0 ISAVRET RW 1 ISAVAX RW 1 ISAVCS RW 1 ISAVPC RW 1 ISAVSS RW 1 ISAVSP RW 1 IFLAG RB 1 IBIOS EQU 00000001B ;INT HANDLER IN BIOS & INTERNAL STACK USED ; DISK BUFFER AND BUFFER HANDLING STORAGE BUFCNT RW 1 ;NUMBER OF BUFFERS FSTBUF RW 1 ;POINTER TO FIRST ELEMENT LSTBUF RW 1 ;POINTER TO LAST ELEMENT DMYHDR RB BUFHDRL ;DUMMY BUFFER HEADER HEADER RB BUFMCNT*BUFHDRL ;DISK BUFFER HEADER INFO STACK SECFLGL EQU BUFMNS DSECFLG RB SECFLGL ;DUMMY BUFFER SECTOR FLAGS SECFLG RB BUFMCNT*SECFLGL ;DIRTY SECTOR FLAGS (1=DIRTY) ERRFLGL EQU BUFMNS DERRFLG RB ERRFLGL ;DUMMY BUFFER SECTOR ERROR FLAGS ERRFLG RB BUFMCNT*ERRFLGL ;SECTOR ERROR FLAGS B86END EQU OFFSET $ END