; DJDISKIO.ASM FOR MORROW DISK JOCKEY ;TITLE 'WD1791 MORROW DISK JOCKY DISKETTE HANDLER' ; CP/M-80 VERSION 3 -- MODULAR BIOS ; DISK I/O MODULE FOR WD1791 BASED DISKETTE SYSTEMS ; INITIAL VERSION 1.00, DSEG ; DISK DRIVE DISPATCHING TABLES FOR LINKED BIOS PUBLIC DRIVEA,DRIVEB ; VARIABLES CONTAINING PARAMETERS PASSED BY BDOS EXTRN @ADRV,@RDRV EXTRN @DMA,@TRK,@SECT EXTRN @DBNK ; SYSTEM CONTROL BLOCK VARIABLES EXTRN @ERMDE ; BDOS ERROR MODE ; UTILITY ROUTINES IN STANDARD BIOS EXTRN ?WBOOT ; WARM BOOT VECTOR EXTRN ?PMSG ; PRINT MESSAGE @ UP TO 00, SAVES & EXTRN ?PDEC ; PRINT BINARY NUMBER IN FROM 0 TO 99. EXTRN ?PDERR ; PRINT BIOS DISK ERROR HEADER EXTRN ?CONIN,?CONO ; CON IN AND OUT EXTRN ?CONST ; GET CONSOLE STATUS EXTRN ?STDMA ; SET DMA EXTRN ?STSEC ; SET SECTOR EXTRN ?STTRK ; SET TRACK ; DISK JOCKY FIRMWARE EQUATES CSEG ; PORT ADDRESS EQUATES MACLIB PORTS ; CP/M 3 DISK DEFINITION MACROS MACLIB CPM3 ; Z80 MACRO LIBRARY INSTRUCTION DEFINITIONS MACLIB Z80 ; DJ ROM EQUATES RAM EQU E400H IO EQU E3F8H UDATA EQU IO DREG EQU IO+1 USTAT EQU IO+1 DCMD EQU IO+2 DSTAT EQU IO+2 CSTALL EQU IO+3 CMDREG EQU IO+4 CSTAT EQU IO+4 TRKREG EQU IO+5 SECREG EQU IO+6 DATREG EQU IO+7 LIGHT EQU 1 HEAD EQU 1 DENSITY EQU 1 INTRQ EQU 4 ISTAT EQU 4 TZERO EQU 4 LOAD EQU 4 ULOAD EQU 6 OSTAT EQU 8H DSIDE EQU 8H NOLITE EQU 9H DCRINT EQU 9H HCMD EQU 9H INDEX EQU 10H WINDXD EQU 12H SKCMD EQU 18H RINDXD EQU 1AH SVCMD EQU 1DH WPROT EQU 40H ACCESS EQU 40H RSTBIT EQU 80H READY EQU 80H RDCMD EQU 80H WRCMD EQU 0A0H STBITS EQU 0C0H RACMD EQU 0C4H CLRCMD EQU 0D0H ; DJ BIOS EQUATES CDISK EQU 4 ;ADDRESS OF LAST LOGGED DISK BUFF EQU 80H ;DEFAULT BUFFER ADDRESS TPA EQU 100H ;TRANSIENT MEMORY WBOT EQU 0 ;WARM BOOT JUMP ADDRESS ENTRY EQU 5 ;BDOS ENTRY JUMP ADDRESS RETRIES EQU 10 ;MAX RETRIES ON DISK I/O BEFORE ERROR MAXDISK EQU 4 ;MAXIMUM # OF DISK DRIVES DBLSID EQU 8 ;SIDE BIT FROM CONTROLLER PUBLIC @DTBL CSEG @DTBL DW DRIVEA ;DRIVE A DW DRIVEB ;DRIVE B DW 0 ;DRIVE C NON EXISTANT DW 0 ;DRIVE D DW 0 ;DRIVE E DW 0 ;DRIVE F DW 0 ;DRIVE G DW 0 ;DRIVE H DW 0 ;DRIVE I DW 0 ;DRIVE J DW 0 ;DRIVE K DW 0 ;DRIVE L DW 0 ;DRIVE M DW 0 ;DRIVE N DW 0 ;DRIVE O DW 0 ;DRIVE P END ; EXTENDED DISK PARAMETER HEADERS (XPDHS) DSEG DW FD$WRITE DW FD$READ DW FD$LOGIN DW FD$INIT0 DB 0,0 ; RELATIVE DRIVE ZERO DRIVEA DPH TRANS,DPBSD,16,31 DW FD$WRITE DW FD$READ DW FD$LOGIN DW FD$INIT1 DB 1,0 ; RELATIVE DRIVE ONE DRIVEB DPH TRANS,DPBSD,16,31 ***************************************************************** * * * CP/M EXTENDED DISK PARAMETER HEADERS, UNITIALIZED. * * * ***************************************************************** DPZERO DW 0 ;ADDRESS OF TRANSLATION TABLE (FILLED ; IN BY SETDRV) DW 0,0,0 ;USED BY BDOS DW DIRBUF ;ADDRESS OF DIRECTORY BUFFER DW 0 ;ADDRESS OF DPB (FILLED IN BY SETDRV) DW CSV0 ;DIRECTORY CHECK VECTOR DW ALV0 ;ALLOCATION VECTOR DPONE DW 0 DW 0,0,0 DW DIRBUF DW 0 DW CSV1 DW ALV1 DPTWO DW 0 DW 0,0,0 DW DIRBUF DW 0 DW CSV2 DW ALV2 DPTHRE DW 0 DW 0,0,0 DW DIRBUF DW 0 DW CSV3 DW ALV3 DSEG ; REST IS BANKED TRANS SKEW 26,6,1 ; DISK I/O ROUTINES FOR STANDARDIZED BIOS INTERFACE ; INITIALIZATION ENTRY POINT. ; CALLED FOR FIRST TIME INITIALIZATION. FD$INIT0: RET FD$INIT1: ; ALL INITIALIZATION DONE BY DRIVE 0 RET FD$INIT2: ; ALL INITIALIZATION DONE BY DRIVE 0 RET FD$LOGIN: ; THIS ENTRY IS CALLED WHEN A LOGICAL DRIVE IS ABOUT TO ; BE LOGGED INTO FOR THE PURPOSE OF DENSITY DETERMINATION. ; IT MAY ADJUST THE PARAMETERS CONTAINED IN THE DISK ; PARAMETER HEADER POINTED AT BY RET ; WE HAVE NOTHING TO DO IN ; SIMPLE SINGLE DENSITY ONLY ENVIRONMENT. ; DISK READ AND WRITE ENTRY POINTS. ; THESE ENTRIES ARE CALLED WITH THE FOLLOWING ARGUMENTS: ; RELATIVE DRIVE NUMBER IN @RDRV (8 BITS) ; ABSOLUTE DRIVE NUMBER IN @ADRV (8 BITS) ; DISK TRANSFER ADDRESS IN @DMA (16 BITS) ; DISK TRANSFER BANK IN @DBNK (8 BITS) ; DISK TRACK ADDRESS IN @TRK (16 BITS) ; DISK SECTOR ADDRESS IN @SECT (16 BITS) ; POINTER TO XDPH IN ; THEY TRANSFER THE APPROPRIATE DATA, PERFORM RETRIES ; IF NECESSARY, THEN RETURN AN ERROR CODE IN FD$READ: LXI H,READ$MSG ; POINT AT " READ " MVI A,88H MVI B,01H ; 1797 READ + Z80DMA DIRECTION JMP RW$COMMON FD$WRITE: LXI H,WRITE$MSG ; POINT AT " WRITE " MVI A,0A8H MVI B,05H ; 1797 WRITE + Z80DMA DIRECTION ; JMP WR$COMMON RW$COMMON: ; SEEK TO CORRECT TRACK (IF NECESSARY), ; INITIALIZE DMA CONTROLLER, ; AND ISSUE 1797 COMMAND. JMP SETDRV ;SELECT DISK JMP READ ;READ THE DISK JMP WRITE ;WRITE THE DISK JMP SECTRAN ;SECTOR TRANSLATION XRA A ;A <- 0 STA BUFSEC ;DISK JOCKEY BUFFER EMPTY STA BUFWRTN ;SET BUFFER NOT DIRTY FLAG MVI C,0 ;SELECT SINGLE DENSITY MOV A,C ;trim the ANI 1 ; excess bits CMA ;compliment and MOV B,A ; save in B LXI H,DISK ;new disk ptr MOV E,M ;get disk no. MVI D,0 ;offset addr INX H ;current disk ptr MOV A,M ;move to ACC XRA E ;cmpr old w/new PUSH PSW ;save status INX H ;disk table INX H ; address DAD D ;add the DAD D ; offset MOV A,M ;get parameters ORI 1 ;mask off density ANA B ;set new density MOV M,A ;update parameters POP PSW ;test new=old? RNZ MOV A,M ;updata CDISK STA DCREG ; also MVI C,0 ;SELECT SIDE 0 CALL DJSIDE ***************************************************************** * ~~~ IN CBIOS ROOT ~~~ * * SETSEC JUST SAVES THE DESIRED SECTOR TO SEEK TO UNTIL AN * * ACTUAL READ OR WRITE IS ATTEMPTED. * *-------CPM3 USES 2 BYTES, SECTOR IS IN L -------------------- * ***************************************************************** ***************************************************************** * ~~~ IN CBIOS ROOT ~~~ * * SETTRK SAVES THE TRACK # TO SEEK TO. NOTHING IS DONE AT THIS * * POINT, EVERYTHING IS DEFFERED UNTIL A READ OR WRITE. * * --- CPM3 USES 2 BYTES, TRACK IS IN H --- * ***************************************************************** ***************************************************************** * * * SECTRAN TRANSLATES A LOGICAL SECTOR # INTO A PHYSICAL SECTOR * * #. * * * ***************************************************************** SECTRAN INX B PUSH D ;SAVE TABLE ADDRESS PUSH B ;SAVE SECTOR # CALL GETDPB ;GET DPB ADDRESS INTO HL MOV A,M ;GET # OF CP/M SECTORS/TRACK ORA A ;CLEAR CARY RAR ;DIVIDE BY TWO SUB C PUSH PSW ;SAVE ADJUSTED SECTOR JM SIDETWO SIDEA POP PSW ;DISCARD ADJUSTED SECTOR POP B ;RESTORE SECTOR REQUESTED POP D ;RESTOR ADDRESS OF XLT TABLE SIDEONE XCHG ;HL <- &(TRANSLATION TABLE) DAD B ;BC = OFFSET INTO TABLE MOV L,M ;HL <- PHYSICAL SECTOR MVI H,0 RET SIDETWO LXI B,15 ;OFFSET TO SIDE BIT DAD B MOV A,M ANI 8 ;TEST FOR DOUBLE SIDED JZ SIDEA ;MEDIA IS ONLY SINGLE SIDED POP PSW ;RETRIEVE ADJUSTED SECTOR POP B CMA ;MAKE SECTOR REQUEST POSITIVE INR A MOV C,A ;MAKE NEW SECTOR THE REQUESTED SECTOR POP D CALL SIDEONE MVI A,80H ;SIDE TWO BIT ORA L ; AND SECTOR MOV L,A RET ***************************************************************** * * * SETDRV SELECTS THE NEXT DRIVE TO BE USED IN READ/WRITE * * OPERATIONS. IF THE DRIVE HAS NEVER BEEN SELECTED BEFORE, A * * PARAMETER TABLE IS CREATED WHICH CORRECTLY DESCRIBES THE * * DISKETTE CURRENTLY IN THE DRIVE. DISKETTES CAN BE OF FOUR * * DIFFERENT SECTOR SIZES: * * 1) 128 BYTES SINGLE DENSITY. * * 2) 256 BYTES DOUBLE DENSITY. * * 3) 512 BYTES DOUBLE DENSITY. * * 4) 1024 BYTES DOUBLE DENSITY. * * * ***************************************************************** SETDRV MOV A,C ;SAVE THE DRIVE # STA CPMDRV CPI MAXDISK ;CHECK FOR A VALID DRIVE # JNC ZRET ;ILLEGAL DRIVE # MOV A,E ;TEST IF DRIVE EVER LOGGED IN BEFORE ANI 1 JNZ SETDRV1 ;BIT 0 OF E = 0 -> NEVER SELECTED BEFORE MVI A,1 ;SELECT SECTOR 1 OF TRACK 1 STA TRUESEC STA @TRK CALL FILL ;FLUSH BUFFER AND REFILL JC ZRET ;TEST FOR ERROR RETURN CALL DJSTAT ;GET STATUS ON CURRENT DRIVE ANI 0CH ;STRIP OFF UNWANTED BITS PUSH PSW ;USED TO SELECT A DPB RAR LXI H,XLTS ;TABLE OF XLT ADDRESSES MOV E,A MVI D,0 DAD D PUSH H ;SAVE POINTER TO PROPER XLT CALL GETDPB ;GET DPH POINTER INTO DE XCHG ; POP D MVI B,2 ;NUMBER OF BYTES TO MOVE CALL MOVLOP ;MOVE THE ADDRESS OF XLT LXI D,8 ;OFFSET TO DPB POINTER DAD D ;HL <- &DPH.DPB PUSH H LHLD ORIGIN+7 ;GET ADDRESS OF DJ TERMINAL OUT ROUTINE INX H ;BUMP TO LOOK AT ADDRESS OF ; UART STATUS LOCATION MOV A,M XRI 3 ;ADJUST FOR PROPER REV DJ MOV L,A MVI H,(ORIGIN+300H)/100H MOV A,M ANI DBLSID ;CHECK DOUBLE SIDED BIT LXI D,DPB128S ;BASE FOR SINGLE SIDED DPB'S JNZ SIDEOK LXI D,DPB128D ;BASE OF DOUBLE SIDED DPB'S SIDEOK XCHG ;HL <- DBP BASE, DE <- &DPH.DPB POP D ;RESTORE DE (POINTER INTO DPH) POP PSW ;OFFSET TO CORRECT DPB RAL RAL MOV C,A MVI B,0 DAD B XCHG ;PUT DPB ADDRESS IN DPH MOV M,E INX H MOV M,D SETDRV1 CALL GETDPB ;GET ADDRESS OF DPB IN HL LXI B,15 ;OFFSET TO SECTOR SIZE DAD B MOV A,M ;GET SECTOR SIZE ANI 7H STA SECSIZ MOV A,M RAR RAR RAR RAR ANI 0FH STA SECPSEC XCHG ;HL <- DPH RET ZRET LXI H,0 ;SELDRV ERROR EXIT RET ***************************************************************** * * * GETDPB RETURNS HL POINTING TO THE DPB OF THE CURRENTLY * * SELECTED DRIVE, DE POINTING TO DPH. * * * ***************************************************************** GETDPB LDA CPMDRV ;GET DRIVE # MOV L,A ;FORM OFFSET MVI H,0 DAD H DAD H DAD H DAD H LXI D,DPZERO ;BASE OF DPH'S DAD D PUSH H ;SAVE ADDRESS OF DPH LXI D,10 ;OFFSET TO DPB DAD D MOV A,M ;GET LOW BYTE OF DPB ADDRESS INX H MOV H,M ;GET LOW BYTE OF DPB MOV L,A POP D RET ***************************************************************** * * * XLTS IS A TABLE OF ADDRESS THAT POINT TO EACH OF THE XLT * * TABLES FOR EACH SECTOR SIZE. * * * ***************************************************************** XLTS DW XLT128 ;XLT FOR 128 BYTE SECTORS DW XLT256 ;XLT FOR 256 BYTE SECTORS DW XLT512 ;XLT FOR 512 BYTE SECTORS DW XLT124 ;XLT FOR 1024 BYTE SECTORS ***************************************************************** * * * WRITE ROUTINE MOVES DATA FROM MEMORY INTO THE BUFFER. IF THE * * DESIRED CP/M SECTOR IS NOT CONTAINED IN THE DISK BUFFER, THE * * BUFFER IS FIRST FLUSHED TO THE DISK IF IT HAS EVER BEEN * * WRITTEN INTO, THEN A READ IS PERFORMED INTO THE BUFFER TO GET * * THE DESIRED SECTOR. ONCE THE CORRECT SECTOR IS IN MEMORY, THE * * BUFFER WRITTEN INDICATOR IS SET, SO THE BUFFER WILL BE * * FLUSHED, THEN THE DATA IS TRANSFERRED INTO THE BUFFER. * * * ***************************************************************** WRITE MOV A,C ;SAVE WRITE COMMAND TYPE STA WRITTYP MVI A,1 ;SET WRITE COMMAND DB (MVI) OR (B*8) ;THIS "MVI B" INSTRUCTION CAUSES ; THE FOLLOWING "XRA A" TO ; BE SKIPPED OVER. ***************************************************************** * * * READ ROUTINE TO BUFFER DATA FROM THE DISK. IF THE SECTOR * * REQUESTED FROM CP/M IS IN THE BUFFER, THEN THE DATA IS SIMPLY * * TRANSFERREd FROm THe BUFFEr To THe DESIREd DMA ADDRESS. IF * * THE BUFFER DOES NOT CONTAIN THE DESIRED SECTOR, THE BUFFER IS * * FLUSHED TO THE DISK IF IT HAS EVER BEEN WRITTEN INTO, THEN * * FILLED WITH THE SECTOR FROM THE DISK THAT CONTAINS THE * * DESIRED CP/M SECTOR. * * * ***************************************************************** READ XRA A ;SET THE COMMAND TYPE TO READ STA RDWR ;SAVE COMMAND TYPE ***************************************************************** * * * REDWRT CALCULATES THE PHYSICAL SECTOR ON THE DISK THAT * * CONTAINS THE DESIRED CP/M SECTOR, THEN CHECKS IF IT IS THE * * SECTOR CURRENTLY IN THE BUFFER. IF NO MATCH IS MADE, THE * * BUFFER IS FLUSHED IF NECESSARY AND THE CORRECT SECTOR READ * * FROM THE DISK. * * * ***************************************************************** REDWRT MVI B,0 ;THE 0 IS MODIFIED TO CONTAIN THE LOG2 SECSIZ EQU $-1 ; OF THE PHYSICAL SECTOR SIZE/128 ; ON THE CURRENTLY SELECTED DISK. LDA @SECT ;GET THE DESIRED CP/M SECTOR # PUSH PSW ;TEMPORARY SAVE ANI 80H ;SAVE ONLY THE SIDE BIT MOV C,A ;REMEMBER THE SIDE POP PSW ;GET THE SECTOR BACK ANI 7FH ;FORGET THE SIDE BIT DCR A ;TEMPORARY ADJUSTMENT DIVLOOP DCR B ;UPDATE REPEAT COUNT JZ DIVDONE ORA A ;CLEAR THE CARY FLAG RAR ;DIVIDE THE CP/M SECTOR # BY THE SIZE ; OF THE PHYSICAL SECTORS JMP DIVLOOP ; DIVDONE INR A ORA C ;RESTORE THE SIDE BIT STA TRUESEC ;SAVE THE PHYSICAL SECTOR NUMBER LXI H,CPMDRV ;POINTER TO DESIRED DRIVE,TRACK, AND SECTOR LXI D,BUFDRV ;POINTER TO BUFFER DRIVE,TRACK, AND SECTOR MVI B,4 ;COUNT LOOP DTSLOP DCR B ;TEST IF DONE WITH COMPARE JZ MOVE ;YES, MATCH. GO MOVE THE DATA LDAX D ;GET A BYTE TO COMPARE CMP M ;TEST FOR MATCH INX H ;BUMP POINTERS TO NEXT DATA ITEM INX D JZ DTSLOP ;MATCH, CONTINUE TESTING ***************************************************************** * * * DRIVE, TRACK, AND SECTOR DON'T MATCH, FLUSH THE BUFFER IF * * NECESSARY AND THEN REFILL. * * * ***************************************************************** CALL FILL ;FILL THE BUFFER WITH CORRECT PHYSICAL SECTOR RC ;NO GOOD, RETURN WITH ERROR INDICATION ***************************************************************** * * * MOVE HAS BEEN MODIFIED TO CAUSE EITHER A TRANSFER INTO OR OUT * * THE BUFFER. * * * ***************************************************************** MOVE LDA @SECT ;GET THE CP/M SECTOR TO TRANSFER DCR A ;ADJUST TO PROPER SECTOR IN BUFFER ANI 0 ;STRIP OFF HIGH ORDERED BITS SECPSEC EQU $-1 ;THE 0 IS MODIFIED TO REPRESENT THE # OF ; CP/M SECTORS PER PHYSICAL SECTORS MOV L,A ;PUT INTO HL MVI H,0 DAD H ;FORM OFFSET INTO BUFFER DAD H DAD H DAD H DAD H DAD H DAD H LXI D,BUFFER ;BEGINNING ADDRESS OF BUFFER DAD D ;FORM BEGINNING ADDRESS OF SECTOR TO TRANSFER XCHG ;DE = ADDRESS IN BUFFER LXI H,@DMA ;GET DMA ADDRESS MVI A,0 ;THE ZERO GETS MODIFIED TO CONTAIN ; A ZERO IF A READ, OR A 1 IF WRITE RDWR EQU $-1 ANA A ;TEST WHICH KIND OF OPERATION JNZ INTO ;TRANSFER DATA INTO THE BUFFER OUTOF CALL MOVER XRA A RET INTO XCHG ; CALL MOVER ;MOVE THE DATA, HL = DESTINATION ; DE = SOURCE MVI A,1 STA BUFWRTN ;SET BUFFER WRITTEN INTO FLAG MVI A,0 ;CHECK FOR DIRECTORY WRITE WRITTYP EQU $-1 DCR A MVI A,0 STA WRITTYP ;SET NO DIRECTORY WRITE RNZ ;NO ERROR EXIT ***************************************************************** * * * FLUSH WRITES THE CONTENTS OF THE BUFFER OUT TO THE DISK IF * * IT HAS EVER BEEN WRITTEN INTO. * * * ***************************************************************** FLUSH MVI A,0 ;THE 0 IS MODIFIED TO REFLECT IF ; THE BUFFER HAS BEEN WRITTEN INTO BUFWRTN EQU $-1 ANA A ;TEST IF WRITTEN INTO RZ ;NOT WRITTEN, ALL DONE LXI H,DJWRITE ;WRITE OPERATION ***************************************************************** * * * PREP PREPARES TO READ/WRITE THE DISK. RETRIES ARE ATTEMPTED. * * UPON ENTRY, H&L MUST CONTAIN THE READ OR WRITE OPERATION * * ADDRESS. * * * ***************************************************************** PREP XRA A ;RESET BUFFER WRITTEN FLAG STA BUFWRTN SHLD RETRYOP ;SET UP THE READ/WRITE OPERATION MVI B,RETRIES ;MAXIMUM NUMBER OF RETRIES TO ATTEMPT RETRYLP PUSH B ;SAVE THE RETRY COUNT LDA BUFDRV ;GET DRIVE NUMBER INVOLVED IN THE OPERATION MOV C,A CALL DJSEL ;SELECT THE DRIVE LDA BUFTRK ANA A ;TEST FOR TRACK ZERO MOV C,A PUSH B CZ DJHOME ;HOME THE DRIVE IF TRACK 0 POP B ;RESTORE TRACK # CALL ?STTRK ;SEEK TO PROPER TRACK LDA BUFSEC ;GET SECTOR INVOLVED IN OPERATION PUSH PSW ;SAVE THE SECTOR # RLC ;BIT 0 OF A EQUALS SIDE # ANI 1 ;STRIP OFF UNNECESSARY BITS MOV C,A ;C <- SIDE # CALL DJSIDE ;SELECT THE SIDE POP PSW ;A <- SECTOR # ANI 7FH ;STRIP OFF SIDE BIT MOV C,A ;C <- SECTOR # CALL ?STSEC ;SET THE SECTOR TO TRANSFER LXI B,BUFFER ;SET THE DMA ADDRESS CALL ?STDMA CALL DJREAD ;THE READ OPERATION IS MODIFIED TO WRITE RETRYOP EQU $-2 POP B ;RESTORE THE RETRY COUNTER MVI A,0 ;NO ERROR EXIT STATUS RNC ;RETURN NO ERROR DCR B ;UPDATE THE RETRY COUNTER STC ;ASSUME RETRY COUNT EXPIRED MVI A,0FFH ;ERROR RETURN RZ JMP RETRYLP ;TRY AGAIN ***************************************************************** * * * FILL FILLS THE BUFFER WITH A NEW SECTOR FROM THE DISK. * * * ***************************************************************** FILL CALL FLUSH ;FLUSH BUFFER FIRST RC ;CHECK FOR ERROR LXI D,CPMDRV ;UPDATE THE DRIVE, TRACK, AND SECTOR LXI H,BUFDRV MVI B,3 ;NUMBER OF BYTES TO MOVE CALL MOVLOP ;COPY THE DATA LXI H,DJREAD JMP PREP ;SELECT DRIVE, TRACK, AND SECTOR. ; THEN READ THE BUFFER ***************************************************************** * * * MOVER MOVES 128 BYTES OF DATA. SOURCE POINTER IN DE, DEST * * POINTER IN HL. * * * ***************************************************************** MOVER MVI B,128 ;LENGTH OF TRANSFER MOVLOP LDAX D ;GET A BTE OF SOURCE MOV M,A ;MOVE IT INX D ;BUMP POINTERS INX H DCR B ;UPDATE COUNTER JNZ MOVLOP ;CONTINUE MOVING UNTIL DONE RET ***************************************************************** * * * XLT TABLES (SECTOR SKEW TABLES) FOR CP/M 2.0. THESE TABLES * * DEFINE THE SECTOR TRANSLATION THAT OCCURS WHEN MAPPING CP/M * * SECTORS TO PHYSICAL SECTORS ON THE DISK. THERE IS ONE SKEW * * TABLE FOR EACH OF THE POSSIBLE SECTOR SIZES. CURRENTLY THE * * TABLES ARE LOCATED ON TRACK 0 SECTORS 6 AND 8. THEY ARE * * LOADED INTO MEMORY IN THE CBIOS RAM BY THE COLD BOOT ROUTINE. * * * ***************************************************************** XLT128 DB 0 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 XLT256 DB 0 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 XLT512 DB 0 DB 1,2,3,4,17,18,19,20 DB 33,34,35,36,49,50,51,52 DB 5,6,7,8,21,22,23,24 DB 37,38,39,40,53,54,55,56 DB 9,10,11,12,25,26,27,28 DB 41,42,43,44,57,58,59,60 DB 13,14,15,16,29,30,31,32 DB 45,46,47,48 XLT124 DB 0 DB 1,2,3,4,5,6,7,8 DB 25,26,27,28,29,30,31,32 DB 49,50,51,52,53,54,55,56 DB 9,10,11,12,13,14,15,16 DB 33,34,35,36,37,38,39,40 DB 57,58,59,60,61,62,63,64 DB 17,18,19,20,21,22,23,24 DB 41,42,43,44,45,46,47,48 ***************************************************************** * * * EACH OF THE FOLLOWING TABLES DESCRIBES A DISKETTE WITH THE * * SPECIFIED CHARACTERISTICS. THE TABLES ARE CURRENTLY STORED * * ON TRACK 0 SECTOR 13. THEY ARE READ INTO MEMORY BY THE GOCPM * * ROUTINE IN THE CBIOS FOR CP/M VER 2.0. * * * ***************************************************************** ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE FOR 128 BYTE SECTORS, * * SINGLE DENSITY, AND SINGLE SIDED. * * * ***************************************************************** DPB128S DW 26 ;CP/M SECTORS/TRACK DB 3 ;BSH DB 7 ;BLM DB 0 ;EXM DW 242 ;DSM DW 63 ;DRM DB 0C0H ;AL0 DB 0 ;AL1 DW 16 ;CKS DW 2 ;OFF DB 1H ;16*((#CPM SECTORS/PHYSICAL SECTOR) -1) + ;LOG2(#BYTES PER SECTOR/128) + 1 + ;8 IF DOUBLE SIDED. ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE FOR 256 BYTE SECTORS, * * DOUBLE DENSITY, AND SINGLE SIDED. * * * ***************************************************************** DPB256S DW 52 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 242 ;DSM DW 127 ;DRM DB 0C0H ;AL0 DB 0 ;AL1 DW 32 ;CKS DW 2 ;OFF DB 12H ;16*((#CPM SECTORS/PHYSICAL SECTOR) -1) + ;LOG2(#BYTES PER SECTOR/128) + 1 + ;8 IF DOUBLE SIDED. ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE AS 512 BYTE SECTORS, * * DOUBLE DENSITY, AND SINGLE SIDED. * * * ***************************************************************** DPB512S DW 60 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 280 ;DSM DW 127 ;DRM DB 0C0H ;AL0 DB 0 ;AL1 DW 32 ;CKS DW 2 ;OFF DB 33H ;16*((#CPM SECTORS/PHYSICAL SECTOR) -1) + ;LOG2(#BYTES PER SECTOR/128) + 1 + ;8 IF DOUBLE SIDED. ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE AS 1024 BYTE SECTORS, * * DOUBLE DENSITY, AND SINGLE SIDED. * * * ***************************************************************** DP1024S DW 64 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 299 ;DSM DW 127 ;DRM DB 0C0H ;AL0 DB 0 ;AL1 DW 32 ;CKS DW 2 ;OFF DB 74H ;16*((#CPM SECTORS/PHYSICAL SECTOR) -1) + ;LOG2(#BYTES PER SECTOR/128) + 1 + ;8 IF DOUBLE SIDED. ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE FOR 128 BYTE SECTORS, * * SINGLE DENSITY, AND DOUBLE SIDED. * * * ***************************************************************** DPB128D DW 52 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 1 ;EXM DW 242 ;DSM DW 127 ;DRM DB 0C0H ;AL0 DB 0 ;AL1 DW 32 ;CKS DW 2 ;OFF DB 9H ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE AS 256 BYTE SECTORS, * * DOUBLE DENSITY, AND DOUBLE SIDED. * * * ***************************************************************** DPB256D DW 104 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 486 ;DSM DW 255 ;DRM DB 0F0H ;AL0 DB 0 ;AL1 DW 64 ;CKS DW 2 ;OFF DB 1AH ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE AS 512 BYTE SECTORS, * * DOUBLE DENSITY, AND DOUBLE SIDED. * * * ***************************************************************** DPB512D DW 120 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 561 ;DSM DW 255 ;DRM DB 0F0H ;AL0 DB 0 ;AL1 DW 64 ;CKS DW 2 ;OFF DB 3BH ***************************************************************** * * * THE FOLLOWING DPB DEFINES A DISKETTE AS 1024 BYTE SECTORS, * * DOUBLE DENSITY, AND DOUBLE SIDED. * * * ***************************************************************** DP1024D DW 128 ;CP/M SECTORS/TRACK DB 4 ;BSH DB 15 ;BLM DB 0 ;EXM DW 599 ;DSM DW 255 ;DRM DB 0F0H ;AL0 DB 0 ;AL1 DW 64 ;CKS DW 2 ;OFF DB 7CH ; SUPPRESS ERROR MESSAGE IF BDOS IS RETURNING ERRORS TO APPLICATION... LDA @ERMDE CPI 0FFH JZ HARD$ERROR ; HAD PERMANENT ERROR, PRINT MESSAGE LIKE: ; BIOS ERR ON D: T-NN, S-MM, , RETRY ? CALL ?PDERR ; PRINT MESSAGE HEADER LHLD OPERATION$NAME CALL ?PMSG ; LAST FUNCTION ; THEN, MESSAGES FOR ALL INDICATED ERROR BITS LDA DISK$STATUS ; GET STATUS BYTE FROM LAST ERROR LXI H,ERROR$TABLE ; POINT AT TABLE OF MESSAGE ADDRESSES ERRM1: MOV E,M INX H MOV D,M INX H ; GET NEXT MESSAGE ADDRESS ADD A PUSH PSW ; SHIFT LEFT AND PUSH RESIDUAL BITS WITH STATUS XCHG CC ?PMSG XCHG ; PRINT MESSAGE, SAVING TABLE POINTER POP PSW JNZ ERRM1 ; IF ANY MORE BITS LEFT, CONTINUE LXI H,ERROR$MSG CALL ?PMSG ; PRINT ", RETRY (Y/N) ? " CALL U$CONIN$ECHO ; GET OPERATOR RESPONSE CPI 'Y' JZ MORE$RETRIES ; YES, THEN RETRY 10 MORE TIMES HARD$ERROR: ; OTHERWISE, MVI A,1 RET ; RETURN HARD ERROR TO BDOS CANCEL: ; HERE TO ABORT JOB JMP ?WBOOT ; LEAP DIRECTLY TO WARMSTART VECTOR U$CONIN$ECHO: ; GET CONSOLE INPUT, ECHO IT, AND SHIFT TO UPPER CASE CALL ?CONST ORA A JZ U$C1 ; SEE IF ANY CHAR ALREADY STRUCK CALL ?CONIN JMP U$CONIN$ECHO ; YES, EAT IT AND TRY AGAIN U$C1: CALL ?CONIN PUSH PSW MOV C,A CALL ?CONO POP PSW CPI 'A' RC SUI 'A'-'A' ; MAKE UPPER CASE RET DISK$COMMAND DS 1 ; CURRENT WD1797 COMMAND SELECT$MASK DS 1 ; CURRENT DRIVE SELECT CODE OLD$SELECT DS 1 ; LAST DRIVE SELECTED OLD$TRACK DS 1 ; LAST TRACK SEEKED TO DISK$STATUS DS 1 ; LAST ERROR STATUS CODE FOR MESSAGES SELECT$TABLE DB 0001$0000B,0010$0000B ; FOR NOW USE DRIVES C AND D ; ERROR MESSAGE COMPONENTS READ$MSG DB ', READ',0 WRITE$MSG DB ', WRITE',0 OPERATION$NAME DW READ$MSG ; TABLE OF POINTERS TO ERROR MESSAGE STRINGS ; FIRST ENTRY IS FOR BIT 7 OF 1797 STATUS BYTE ERROR$TABLE DW B7$MSG DW B6$MSG DW B5$MSG DW B4$MSG DW B3$MSG DW B2$MSG DW B1$MSG DW B0$MSG B7$MSG DB ' NOT READY,',0 B6$MSG DB ' PROTECT,',0 B5$MSG DB ' FAULT,',0 B4$MSG DB ' RECORD NOT FOUND,',0 B3$MSG DB ' CRC,',0 B2$MSG DB ' LOST DATA,',0 B1$MSG DB ' DREQ,',0 B0$MSG DB ' BUSY,',0 ERROR$MSG DB ' RETRY (Y/N) ? ',0 CSEG ; EASIER TO PUT ID BUFFER IN COMMON ID$BUFFER DS 6 ; BUFFER TO HOLD ID FIELD ; TRACK ; SIDE ; SECTOR ; LENGTH ; CRC 1 ; CRC 2 LXI H,1 PUSH H ;track 0, sector 1 MVI L,DCRINT ;set up the PUSH H ; side select MVI H,0FFH ; and initial PUSH H ; drive PUSH H ; parameters PUSH H PUSH H LXI H,8H ;initialize PUSH H ; tzflag & cdisk MVI L,7EH ;initialize PUSH H ; disk & drvsel MVI L,8H ;initialize PUSH H ; hdflag & dsflag MVI H,18H ;initialize PUSH H ; timer constant MVI A,7FH ;start 1791 STA DREG MVI A,CLRCMD ;1791 reset STA CMDREG LDHEAD XRA A ;load the head CALL HDCHK ; and test for JNC DOOROK ; drive ready MVI A,LIGHT ;turn on the STA DCREG ; error LED CALL TIMOUT ;timeout to JMP LDHEAD ; close drive door DOOROK MVI A,NOLITE ;turn off the STA DCREG ; error LED CALL MEASUR ;head load time POP B ;adjust the stack LXI B,RAM+300H ;DMA addr PUSH B ;initialize PUSH D ; dmaadr & timer LXI H,0 ;initialize PUSH H ; intrfg & ramins NOP ;debug instruction PUSH B ;boot address MVI B,12 ;number of retrys LDLOOP PUSH B ;save the retry no. CALL DJREAD ;read boot sector POP B ;restor retry no. RNC ;successful read? DCR B ;no - count down JNZ LDLOOP ; and try again DJSTAT LXI H,TRKREG ;most recent MOV C,M ; track to C INX H ;most recent MOV B,M ; sector to B LDA DCREG ;get current CMA ; density in ANI 1 ; the msb RRC ; position MOV D,A ;save in D LDA SIDE ;put the RLC ; most recent RLC ; side select RLC ; in bit positin ORA D ; 6 and merge MOV D,A ;save in D LDA DSFLAG ;get the XRI DSIDE ; most recent RAL ; double sided RAL ; status and place ADD D ; in bit position MOV D,A ; 5 and merge LDA SECLEN ;get the RAL ; sector length RAL ; code bits in ORA D ; positions 2 & 3 MOV D,A ; and merge LDA CDISK ;get the current ADD D ; disk no. in bit RET ; positions 0 & 1 DJSEL MOV A,C ;drive select ANI 3 ; values must be STA DISK ; between zero RET ; and three DJHOME CALL HDLOAD ;load the head RC ;not ready error CALL HENTRY ;move the head PUSH PSW ;save status SBB A ;update the STA @TRK ; track STA TRKREG ; registers XRA A ;set the not STA TZFLAG ; verified flag JMP LEAVE+1 ;unload the head HENTRY XRA A ;set the force STA HDFLAG ; verify flag LXI H,0 ;timeout constant MVI A,HCMD ;move the head CALL CENTRY ;to track 0 ANI TZERO ;track zero bit RNZ STC ;error flag RET ISSUE STA ECOUNT+1 ;update count CALL MEASUR ;find index MVI C,1 ;Start with sector 1 ISLOOP MOV A,C ;Initilize the STA SECREG ; sector register LDA @SECT ;Test for CMP C ; target sector RZ MVI A,RDCMD ;do a fake CALL COMAND ; read command JC PLEAVE ;Abort on error INR C ;Increment sector number JMP ISLOOP COMNDP STA CMDREG ;Start operation MOV C,B ;Initilize block count LXI D,DATREG ;Data register LHLD @DMA ;transfer address RET DJWRITE CALL PREP ;prepare for write JC LEAVE ;abort operation WRENTRY MVI A,WRCMD ;write sector cmd CALL COMNDP WRLOOP MOV A,M ;load 1st byte of data INX H STAX D ;write 1st byte of data MOV A,M ;load 2nd byte of data INX H STAX D ;write 2nd byte of data MOV A,M ;load 3rd byte of data INX H STAX D ;write 3rd byte of data DCR c ;reduce block count MOV A,M INX H STAX D JNZ WRLOOP ;write next 4 bytes LXI H,WRENTRY JMP CBUSY DJREAD CALL PREP ;prepare for read JC LEAVE ;abort operation RDENTRY MVI a,RDCMD CALL COMNDP RDLOOP LDAX D ;read 1st byte MOV M,A ;store 1st byte INX H LDAX D ;read 2nd byte MOV M,A ;store 2nd byte INX H LDAX D ;read 3rd byte MOV M,A ;store 3rd byte INX H DCR c ;reduce block count LDAX D ;read 4th byte MOV M,A ;store 4th byte INX H JNZ RDLOOP ;read next 4 bytes LXI H,RDENTRY CBUSY PUSH H ;Save return LXI H,CSTAT ;Wait for 1791 CALL BUSY ; to finish command ANI 5FH ;Error mask JZ LEAVE-1 ;No error CPI 10H ;Premature interupt JNZ PLEAVE ;Other type of error LDA ECOUNT ;decrement error count DCR A ; by one JM STEST ;Hard interupt error STA ECOUNT ;Update count RET STEST LDA ECOUNT+1 ;Decrement error DCR A JP ISSUE MVI A,10H PLEAVE STC ;error flag POP H LEAVE PUSH PSW ;save the status LDA DCREG ;control bits XRI LOAD ;toggle the STA DCMD ; head load bit LDA DRVSEL ;enable access to STA DREG ; the data register POP PSW ;recover the status RET PREP CALL HDLOAD ;load the head RC ;test for drive ready LDA TRKREG ;get old track INR A ;test for head CZ HENTRY ; not calibrated RC ;seek error? LXI H,TRKREG ;old track LDA @TRK ;new track CMP M ;test for head motion INX H ;advance to the INX H ; data register MOV M,A ;save new track MOV A,C ;turn off data reg STA DREG ; access control bit JZ TVERFY ;test for seek XRA A ;force a read STA HDFLAG ; header operation LDA DSTAT ;get the double ANI DSIDE ; sided flag STA DSFLAG ;save for status RAR ;shift for RAR ; 3/6 ms step RAR ; rate constant ADI SKCMD ;do a LXI H,0 ; seek CALL CENTRY ; operation JC SERROR ;seek error? TVERFY LDA HDFLAG ;get the force ORA A ; verify hdr flag JNZ CHKSEC ;no seek & head OK MVI B,2 ;verify retry count SLOOP MVI A,SVCMD ;do a verify CALL COMAND ; command ANI 99H ;error bit mask MOV D,A ;save JZ RDHDR ;no error LDA DCREG ;denisty control XRI DENSITY ;flip the density STA DCREG ;update and STA DCMD ; change density DCR B ;decrement retry JNZ SLOOP ; count & test MOV A,D SERROR STC PUSH PSW CALL HENTRY POP PSW RET RDHDR MVI B,0AH ;number of retrys RHLOOP LXI D,DATREG ;Data register LXI H,@TRK+1 ;Data pointer MVI A,RACMD ;Start read header command STA CMDREG RHL1 LDAX D ;get disk data 0 MOV M,A ;store in mem INR L ;advance pointer JNZ RHL1 ;test end of page LXI H,CSTAT ;wait for 1791 CALL BUSY ; to finish cmd ORA A ;test for errors JZ CHKSEC ;transfer OK? DCR B ;no - test for JNZ RHLOOP ; hard error JMP SERROR ;recalibrate CHKSEC LDA SECLEN ;get the sector MOV C,A ; size and setup MVI B,0 ; the table offset LXI H,STABLE ;sector table DAD B ;sector size pntr LDA @SECT ;get the sector MOV B,A ; and save in B ADD M ;compare w/table MVI A,10H ;error flag RC ;error return MOV A,B ;initialize 1791 STA SECREG ; sector register MVI A,20H ;128 byte sector LXI H,505H SHLD ECOUNT SZLOOP DCR C ;reduce size count MOV B,A ;sector size to B RM ;return on minus RAL ;double the count ORA A ;clear the carry JMP SZLOOP STABLE DB 0E5H ;26 sector diskettes DB 0E5H ;26 sector diskettes DB 0F0H ;15 sector diskettes DB 0F7H ;8 sector diskettes HDLOAD LXI H,DISK ;new drv ptr MOV C,M ;save new drv in C INX H ;current drv ptr MOV E,M ;save old drv in E MOV M,C ;update current drv INX H ;home cmd flag MOV A,E ;test for CMP C ; drive change MOV A,M ;head load mask MVI M,HEAD ;update the mask JZ HDCHK ;no drive change? INX H ;addr of drive table PUSH H ;save table addr MVI D,0 ;set up the MOV B,D ; offset address DAD D ;calculate the DAD D ; parameter addr LDA DCREG ;save the MOV M,A ;density status INX H ;track pointer LXI D,TRKREG ;1791 trk reg LDAX D ;get current track MOV M,A ;save in the table POP H ;beginning of table DAD B ;new drive DAD B ; table pointer MOV A,M ;get density status STA DCREG ;update DCREG INX H ;get the old MOV A,M ; track number STAX D ; and update 1791 MVI A,7FH ;drive select bits DSROT RLC ;rotate to DCR C ; select the JP DSROT ; proper drive ANI 7FH ;set the run bit STA DRVSEL ;save in drv reg XRA A ;force a head load HDCHK LXI H,DSTAT ;test for ANA M ; head loaded STA HDFLAG ;save the head PUSH PSW ; loaded status LDA DRVSEL ;get current drive MOV C,A ;save LDA SIDE ;get current side CMA ; and merge ANA C ; with drive select STA DREG ;select drive & side XRI ACCESS ;toggle access bit MOV C,A ;save for PREP routine LDA DCREG ;den & head cntl bits MOV B,A ;save LDA @TRK ;get the new track SUI 1 ;force single SBB A ; density DCR A ; if track = 0 CMA ;compliment ORA B ;merge w/control bits MOV M,A ;load head & set density POP PSW ;head load status JNZ RDYCHK ;conditionally PUSH H ; wait for head LHLD TIMER ; load time out TLOOP DCX H ;count down MOV A,H ; 40 ms for ORA L ; head load JNZ TLOOP ; time out POP H RDYCHK MOV A,M ;test for ANI READY ; drive ready RNZ UNLOAD LDA DCREG ;force a ORI ULOAD ; head MOV M,A ; unload MVI A,READY ;set drive STC ; not ready RET ; error flag COMAND LHLD TIMER ;get index count DAD H ; and multiply DAD H ; by four CENTRY XCHG ;save in D-E pair LXI H,CSTAT ;issue command MOV M,A ; to the 1791 NBUSY MOV A,M ;wait RAR ; for the JNC NBUSY ; busy flag BUSY MOV A,M ;test for RAR ; device busy MOV A,M ;restore status RNC ;return if not busy JMP PATCH+3 ;jump around patch PATCH JMP HDLOAD ;patch for old ATE DCX D ;test for MOV A,D ; two disk ORA E ; revolutions JNZ BUSY ;47 machine cycles MOV E,M ;get error code PUSH H ;save cmd address INX H ;track register MOV D,M ;save present track LDA DRVSEL ;control bits XRI RSTBIT ;reset the 1791 STA DREG ; controller to XRI STBITS ; clear the XTHL ; command busy STA DREG ; fault condition MVI M,CLRCMD ;force interrupt XTHL ;restore the MOV M,D ; the track reg POP H ;restore the stack MOV A,E ;error code to A STC ; error flag RET MEASUR LXI D,0 ;initialize count LXI H,DSTAT ;status port MVI C,INDEX ;index bit flag INDXLO MOV A,M ;wait for ANA C ; index JZ INDXLO ; pulse high INDXHI MOV A,M ;wait for ANA C ; index JNZ INDXHI ; pulse low INDXCT INX D ;advance count XTHL ;four dummy XTHL ; instructions XTHL ; to lengthen XTHL ; the delay MOV A,M ;wait for ANA C ; the index JZ INDXCT ; to go high RET ;98 machine cycles TIMOUT LXI H,0 ;time-out delay TILOOP DCX H ;decrement count MOV A,H ;test for delay ORA L ; count equal zero XTHL ;long NOP XTHL ; instruction JNZ TILOOP RET SBEGIN PUSH H LXI H,DSTALL DSTALL PCHL POP H RET DJSIDE MOV A,C ;get the side bit ANI 1 ;trim the excess RAL ;move the bit RAL ; to the side RAL ; select bit RAL ; position STA SIDE ;save side bit RET PWRJMP NOP ;power-on NOP ; jump NOP ; sequence NOP ; with NOP NOP ; padding JMP DBOOT ECOUNT DW 0 TIMER DW 1800H ;head load time out DSFLAG DB 8H HDFLAG DB 0 ;read header flag DRVSEL DB 7EH ;drive select constant DISK DB 0 ;new drive CDISK DB 8H ;current disk TZFLAG DB 0 ;home cmd indicator DOPRAM DB 9H ;drive 0 parameters DOTRK DB 0FFH ;drive 0 track no D1PRAM DB 9H ;drive 1 parameters D1TRK DB 0FFH ;drive 1 track no D2PRAM DB 9H ;drive 2 parameters D2TRK DB 0FFH ;drive 2 track no D3PRAM DB 9H ;drive 3 parameters D3TRK DB 0FFH ;drive 3 track no DCREG DB 9H ;current parameters SIDE DB 0 ;new side TRKNO DB 0 ;disk SIDENO DB 0 ; sector SECTNO DB 0 ; header SECLEN DB 0 ; data CRCLO DB 0 ; buffer CRCHI DB 0 ***************************************************************** * * * CBIOS RAM LOCATIONS THAT DON'T NEED INITIALIZATION. * * * ***************************************************************** CPMDRV DB 0 ;CP/M DRIVE # TRUESEC DB 0 ;DISK JOCKEY SECTOR THAT CONTAINS CP/M SECTOR BUFDRV DB 0 ;DRIVE THAT BUFFER BELONGS TO BUFTRK DB 0 ;TRACK THAT BUFFER BELONGS TO BUFSEC DB 0 ;SECTOR THAT BUFFER BELONGS TO BUFFER DS 1024 ;MAXIMUM SIZE BUFFER FOR 1K SECTORS ALV0 DS 75 ;ALLOCATION VECTOR FOR DRIVE A ALV1 DS 75 ;ALLOCATION VECTOR FOR DRIVE B ALV2 DS 75 ;ALLOCATION VECTOR FOR DRIVE C ALV3 DS 75 ;ALLOCATION VECTOR FOR DRIVE D CSV0 DS 64 ;DIRECTORY CHECK VECTOR FOR DRIVE A CSV1 DS 64 ;DIRECTORY CHECK VECTOR FOR DRIVE B CSV2 DS 64 ;DIRECTORY CHECK VECTOR FOR DRIVE C CSV3 DS 64 ;DIRECTORY CHECK VECTOR FOR DRIVE D DIRBUF DS 128 ;DIRECTORY BUFFER