;******************************************************** ;* * ;* DISK I/O SUBROUTINES FOR CP/M CBIOS * ;* * ;******************************************************** ; ; ; SUBROUTINES FOR RESTORE, SET-TRACK, SET-SECTOR AND ; SET-DMA BIOS ENTRY POINTS. THESE ONLY STORE THEIR ; RESPECTIVE PARAMETERS AND THEN EXIT WITHOUT DOING ; ANY ACTUAL DISK I/O OPERATIONS. ; ; HOME: LD BC,0 SETTRACK: LD (TRACK),BC RET ; ; ; ; SETSECT: LD HL,SECTOR LD (HL),C RET ; ; ; ; SETDMA: LD (POINTR),BC RET ; ; ; ; SECTRAN: LD H,B LD L,C ;GET LOGICAL SECTOR# INTO HL FROM BC LD A,D OR E ;CHECK FOR XLT POINTER IN DE=0 JR Z,STRAN2 ;JUMP IF NO TRANSLATE TABLE USED ADD HL,DE ;ELSE INDEX INTO TABLE BY SECTOR# LD L,(HL) LD H,0 RET ;RETURN PHYSICAL SECTOR# FROM TABLE ; STRAN2: INC HL ;MAKE SECTOR NUMBERS START AT 1 RET PAGE ; ;**************************************************************** ; * ; MAGIC SELDISK ROUTINE WITH AUTO DISK PARAMETER SELECT * ; * ;**************************************************************** ; PORT0 EQU 0C8H ;DISK CONTROL BIT LATCH PORT1 EQU 0D9H ;DISK TYPE BIT LATCH SEL5 EQU 0 ;51/4 SELECT BIT SIDSEL EQU 1 ;BIT# OF SIDE SELECT BIT SMC1 EQU 2 SMC2 EQU 3 DDEN EQU 4 ; ON EQU 1000B OFF EQU 0000B ; ; SELDISK: LD HL,0 ;PREP TO CHECK FOR MAX DISK# LD A,C CP NFLOPPY+WINCH RET NC ;ERROR (HL=0) IF DISK# TOO BIG LD (DISK),A INC A LD BC,DPHSIZ LD HL,DPHTAB-DPHSIZ SDSK2: ADD HL,BC DEC A JR NZ,SDSK2 LD (DPHPTR),HL ;STORE POINTER TO DISK'S DPH ENTRY BIT 0,E ;TEST LOG-ON VECTOR BIT FOR DRIVE IF MIXED JR Z,SDK2A ;EXIT IF DRIVE IS LOGGED-ON SDK2C: CALL CKTYPE JP C,D8SEL ;RESET SELECTION TO 8 INCH JP D5SEL ;MUST BE 5 INCH SDK2A: ELSE RET NZ ENDIF PUSH HL POP IX BIT 0,(IX+FLAGS) ;TEST DRIVE PRE-SELECTED FLAG IF MIXED JR NZ,SDK2C ;EXIT IF DRIVE FORMAT ALREADY KNOWN ELSE RET NZ ;EXIT IF DRIVE FORMAT ALREADY KNOWN ENDIF CALL FLUSH ;FINISH ANY DEFERRED DISK OPERATIONS IF MIXED CALL CKTYPE ;CHECK FOR DRIVE TYPE LD A,R5ESERV ;PRESELECT 5 INCH JR NC,SDSK3 LD A,R8ESERV ;SELECT 8 INCH SDSK3: ELSE LD A,RESERV ENDIF LD (TRACK),A ;SEEK DIRECTORY TRACK FOR FORMAT CHECK ; ; PARAMS: IF WINCH LD HL,WINSTUFF LD (PRMPTR),HL ;SELECT WINCHESTER DISK PARAMS LD A,(DISK) CP NFLOPPY JP Z,PARM10 ;SKIP FLOPPY FORMAT CHECK ON HARD DISK ENDIF XOR A ;SET SECTOR# TO ZERO TO INDICATE LD (HSTSEC),A ; EXPLORATORY READ OPERATION PARM1: LD A,SIDSEL+OFF OUT (PORT0),A ;MAKE SURE SIDE #0 OF DISK IS SELECTED LD A,(DISK) LD (HSTDSK),A ;STORE UNIT# IN CASE OF ERROR LD C,A IF MIXED CALL CKTYPE CALL C,D8SEL CALL NC,D5SEL ENDIF CALL MONITR+27 ;SELECT NEW DISK DRIVE JR NZ,PARM2 LD A,(TRACK) LD (HSTTRK),A ;STORE TRACK# IN CASE OF ERROR LD C,A CALL MONITR+33 ;SEEK SPECIFIED TEST TRACK JR NZ,PARM2 LD HL,IDBUFF CALL MONITR+42 ;READ AN ID MARK FROM TEST TRACK JR Z,PARM3 PARM2: CALL REPORT ;DISPLAY ERROR AND ALLOW RECOVERY JR Z,PARM1 ;TRY AGAIN IF NOT ABORTED LD HL,0 RET ;ELSE RETURN PERM SELECT ERROR ; ; ARRIVE HERE AFTER SUCCESSFULLY READING AN ID RECORD ; PARM3: IF MIXED CALL CKTYPE LD HL,S5DSTUFF ;PRESELECT 5 INCH JR NC,PARM3B LD HL,S8DSTUFF ;SELECT 8 INCH PARM3B: ELSE LD HL,SDSTUFF ENDIF LD (PRMPTR),HL ;FIRST SELECT SINGLE DENSITY PARAMETERS LD A,(IDBUFF+6) BIT 0,A ;TEST DENSITY BYTE RETURNED BY READID JP Z,PARM10 ;JUMP IF SINGLE DENSITY IF MIXED CALL CKTYPE LD HL,D5DSTUFF ;PRESELECT 5 INCH JR NC,PARM3C LD HL,D8DSTUFF ;SELECT 8 INCH PARM3C: ELSE LD HL,DDSTUFF ENDIF LD (PRMPTR),HL ;USE DUAL DENSITY DISK PARAMETERS IF MIXED CALL CKTYPE LD HL,N5TRAKS-R5ESERV ;PRESELECT 5 INCH JR NC,PARM3D LD HL,N8TRAKS-R8ESERV PARM3D: ELSE LD HL,NTRAKS-RESERV ENDIF PUSH HL ;PUT TRACKS-PER-DISK PARAM ONTO STACK IF DOUBLE LD A,SIDSEL+ON OUT (PORT0),A ;SELECT TOP SIDE OF DISK LD HL,IDTOP CALL MONITR+42 ;ELSE READ AN ID MARK FROM TOP SIDE JR NZ,PARM3A ;JUMP IF NOT FORMATTED ON SECOND SIDE LD HL,IDBUFF LD DE,IDTOP ;ELSE COMPARE ID FIELDS TO EACH OTHER CALL EXOR1 JR NZ,PARM3A ;JUMP IF TRACK NUMBERS NOT IDENTICAL CALL EXOR1 CP 1 JR NZ,PARM3A ;JUMP IF SIDE NUMBERS NOT COMPLIMENTARY CALL EXOR2 JR NZ,PARM3A ;JUMP IF SECTOR LENGTHS NOT IDENTICAL CALL EXOR3 JR NZ,PARM3A ;JUMP IF DENSITIES NOT IDENTICAL IF MIXED CALL CKTYPE LD HL,2*N5TRAKS-R5ESERV JR NC,PARM3E LD HL,2*N8TRAKS-R8ESERV PARM3E: ELSE LD HL,2*NTRAKS-RESERV ENDIF EX (SP),HL ;REPLACE DOUBLE SIDED #TRACKS ON STACK PARM3A: LD A,SIDSEL+OFF OUT (PORT0),A ;SWITCH BACK TO REGULAR SIDE OF DISK ENDIF LD A,(IDBUFF+3) ;GET SECTOR LENGTH BYTE FROM ID RECORD AND 00000011B IF MIXED LD H,A ;SAVE 'A' CALL CKTYPE LD A,H JR NC,PARM3F LD (D8DSTUFF+17),A ;STORE AS DEBLOCK MASK IN 'DDSTUFF' JR PARM3G PARM3F: LD (D5DSTUFF+17),A PARM3G: ELSE LD (DDSTUFF+17),A ;STORE AS DEBLOCK MASK IN 'DDSTUFF' ENDIF LD H,0 LD L,A ADD HL,HL ADD HL,HL ;MULTIPLY LENGTH CODE BY 4 FOR INDEXING IF MIXED PUSH AF CALL CKTYPE LD BC,F5RMTAB LD DE,D5DSTUFF+18 JR NC,PARM3H LD BC,F8RMTAB LD DE,D8DSTUFF+18 PARM3H: POP AF ELSE LD BC,FRMTAB LD DE,DDSTUFF+18 ENDIF ADD HL,BC ;ADD BASE ADDRESS OF FORMAT POOP TABLE LD BC,3 LDIR ;STORE FORMAT PARAMS IN 'DDSTUFF' INC A LD B,A ;B=SECTOR LENGTH CODE+1 (RANGE 1..4) LD A,(IDBUFF+1) ;GET SIDE# BYTE FROM ID RECORD SRL A ;SHIFT OUT SIDE# BIT IN LSB JR NZ,PARM5 ;JUMP IF UPPER 7 BITS ARE NON-ZERO LD A,(HL) ;ELSE USE STANDARD VALUE FOR 'SPT' JR PARM6 ; FOUND IN PARAMETER TABLE ; PARM4: ADD A,A ;MULTIPLY PHYSICAL SPT BY 2,4 OR 8 TO PARM5: DJNZ PARM4 ; TO GET EQUIVALENT 128 BYTE SECTORS PARM6: IF MIXED LD H,A ;SAVE 'A' CALL CKTYPE LD A,H JR NC,PARM6A LD (D8DSTUFF+2),A ;STORE LOGICAL SPT CONST IN 'DDSTUFF' PARM6A: LD (D5DSTUFF+2),A ELSE LD (DDSTUFF+2),A ;STORE LOGICAL SPT CONST IN 'DDSTUFF' ENDIF POP DE ;POP TRACKS-PER-DISK PARAM OFF STACK LD HL,0 LD B,A ;PREPARE TO COMPUTE 'DRM' VALUE FOR DPB PARM7: ADD HL,DE DJNZ PARM7 ;GET PRODUCT OF SPT*(NTRAKS-RESERV) IF MIXED CALL CKTYPE LD A,(D5DSTUFF+4) JR NC,PARM7A LD A,(D8DSTUFF+4) PARM7A: ELSE LD A,(DDSTUFF+4) ENDIF LD B,A PARM8: SRL H ;DIVIDE TOTAL SECTORS BY 'BSH' TO GET RR L ; NUMBER OF BLOCKS ON DISK DJNZ PARM8 DEC HL ;RESULT LESS 1 IS 'DSM' VALUE FOR DPB IF MIXED CALL CKTYPE JR NC,PARM8A LD (D8DSTUFF+7),HL LD A,(D8DSTUFF+5) ;GET BLOCK MASK FROM DPB JR PARM8B PARM8A: LD (D5DSTUFF+7),HL LD A,(D5DSTUFF+5) PARM8B: ELSE LD (DDSTUFF+7),HL LD A,(DDSTUFF+5) ;GET BLOCK MASK FROM DPB ENDIF SRL A SRL A SRL A ;SHIFT RIGHT 3 TIMES GIVES EXTENT MASK INC H DEC H ;TEST IF 'DSM' IS > 255 JR Z,PARM9 SRL A PARM9: IF MIXED LD H,A CALL CKTYPE LD A,H JR NC,PARM9A LD (D8DSTUFF+6),A ;STORE VALUE FOR 'EXM' JR PARM9B PARM9A: LD (D5DSTUFF+6),A PARM9B: ELSE LD (DDSTUFF+6),A ;STORE VALUE FOR 'EXM' ENDIF PARM10: LD HL,(PRMPTR) LD DE,(DPHPTR) PUSH DE PUSH DE PUSH DE ;SAVE 3 COPIES OF POINTER TO DISK POOP LD BC,2 LDIR ;COPY 'XLT' ADDRESS TO START OF DPH EX DE,HL LD BC,14 ADD HL,BC ;POINT TO REST OF DPB STUFF NOW EX DE,HL LD BC,15+4 LDIR ;COPY DPB AND DEBLOCK PARAMETERS POP IX ;POINT IX TO BASE OF DISK STORAGE AREAS LD HL,DIRBUF ;GET ADDRESS OF DIRECTORY BUFFER LD (IX+8),L LD (IX+9),H ;STORE IN 'DIR' POINTER SLOT POP HL LD DE,16 ADD HL,DE ;COMPUTE ADDRESS OF DISK PARM BLOCK LD (IX+10),L LD (IX+11),H ;STORE IN 'DPB' POINTER SLOT LD DE,15+4+1 ADD HL,DE ;COMPUTE ADDRESS OF CHECK VECTOR LD (IX+12),L LD (IX+13),H ;STORE IN 'CKV' POINTER SLOT LD E,(IX+16+11) LD D,(IX+16+12) ;LOAD DE WITH CHECK VECTOR LENGTH ADD HL,DE ;COMPUTE ADDRESS OF ALLOCATION VECTOR LD (IX+14),L LD (IX+15),H ;STORE IN 'ALV' POINTER SLOT POP HL XOR A ;A=0 TO INDICATE PARAMS FOUND OK RET ;RETURN WITH DPH POINTER IN HL ; ; ; EXOR3: INC HL INC DE EXOR2: INC HL INC DE EXOR1: LD A,(DE) XOR (HL) ;COMPARE ID FIELD BYTES @HL AND @DE INC HL INC DE RET IF MIXED ; SETDENS: PUSH HL PUSH BC ;SAVE 'BC' LD A,(DSKTYP) AND 00000011B LD B,0 LD C,A LD HL,SMCTAB ADD HL,BC ;INDEX INTO SMC DATA SEPARATOR CONTROL ADD HL,BC ; BYTE TABLE FOR NEW DENSITY SETTING ADD HL,BC LD B,3 LD C,PORT0 OTIR ;OUTPUT 3 BYTES TO SET DISK DENSITY POP BC POP HL RET SMCTAB: DEFB SMC1+ON ;8 INCH SINGLE DENSITY DEFB SMC2+OFF DEFB DDEN+ON DEFB SMC1+OFF ;8 INCH DOUBLE DENSITY DEFB SMC2+OFF DEFB DDEN+OFF DEFB SMC1+OFF ;5 INCH SINGLE DENSITY DEFB SMC2+ON DEFB DDEN+ON DEFB SMC1+ON ;5 INCH DOUBLE DENSITY DEFB SMC2+OFF DEFB DDEN+OFF ; ; D8SEL: PUSH AF ;SAVE FLAGS LD A,(DSKTYP) RES 1,A ;SET TYPE TO 8 INCH LD (DSKTYP),A LD A,(SPEED8) ;8 INCH DRIVE SPEED LD (SPEED),A LD A,1 LD (NREVS),A ;1 REVS BEFORE READY LD A,6*20 ;20 SEC STOP DELAY LD (NSTOP),A LD A,SEL5+OFF ;SELECT 8 INCH D8SELA: OUT (PORT1),A LD A,SIDSEL+OFF ;PRESELECT SIDE 0 OUT (PORT0),A CALL SETDENS ;SET SMC DATA SEPARATOR POP AF RET D5SEL: PUSH AF LD A,(DSKTYP) SET 1,A ;SET TYPE TO 51/4 INCH LD (DSKTYP),A LD A,(SPEED5) ;5 1/4 INCH DRIVE SPEED LD (SPEED),A LD A,3 LD (NREVS),A ;3 REVS BEFORE READY LD A,5*20 ;20 SEC STOP DELAY LD (NSTOP),A LD A,SEL5+ON ;SELECT 5 1/4 INCH JR D8SELA ; ENDIF PAGE ; IF EIGHT ; ; DISK PARAMS FOR STANDARD SINGLE DENSITY FORMAT ; 26 SECTORS / 128 BYTES ; SDSTUFF: DEFW XLTAB ;1-IN-6 SECTOR SKEW TABLE DEFW NSECTS ;SECTORS PER TRACK DEFB 3 ;BLOCK SHIFT DEFB 00000111B ;BLOCK MASK DEFB 00000000B ;EXTENT MASK DEFW 242 ;MAX BLOCK# DEFW 63 ;MAX DIRECTORY ENTRY# DEFB 11000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 16 ;CHECK SIZE DEFW RESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;BYTES PER SECTOR ; ; ; 8 INCH STANDARD SECTOR TRANSLATE TABLE ; XLTAB: DEFB 01,07,13,19,25 DEFB 05,11,17,23 DEFB 03,09,15,21 DEFB 02,08,14,20,26 DEFB 06,12,18,24 DEFB 04,10,16,22 ; ; ; SECTOR DEBLOCK PARAMS FOR 8 INCH DOUBLE DENSITY DISKS ; FRMTAB: DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;PHYSICAL SECTOR LENGTH DEFB 52 ;LOGICAL SECTORS PER TRACK DEFB 00000001B DEFW 256 DEFB 26*2 DEFB 00000011B DEFW 512 DEFB 15*4 DEFB 00000111B DEFW 1024 DEFB 8*8 ENDIF ; ; IF FIVE ; ; DISK PARAMS FOR STANDARD SINGLE DENSITY FORMAT ; 18 SECTORS / 128 BYTES ; SDSTUFF: DEFW XLTAB ;1-IN-5 SECTOR SKEW TABLE DEFW NSECTS ;SECTORS PER TRACK DEFB 3 ;BLOCK SHIFT DEFB 00000111B ;BLOCK MASK DEFB 00000000B ;EXTENT MASK DEFW MBLK ;MAX BLOCK# DEFW 63 ;MAX DIRECTORY ENTRY# DEFB 11000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 16 ;CHECK SIZE DEFW RESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;BYTES PER SECTOR ; ; ; 5 INCH SECTOR TRANSLATE TABLE (SAME AS XEROX/CROMEMCO/OSBORNE) ; XLTAB: DEFB 01,06,11,16 DEFB 03,08,13,18 DEFB 05,10,15 DEFB 02,07,12,17 DEFB 04,09,14 ; ; ; SECTOR DEBLOCK PARAMS FOR 5 INCH DOUBLE DENSITY DISKS ; FRMTAB: DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;PHYSICAL SECTOR LENGTH DEFB 28 ;LOGICAL SECTORS PER TRACK DEFB 00000001B DEFW 256 DEFB 18*2 DEFB 00000011B DEFW 512 DEFB 9*4 DEFB 00000111B DEFW 1024 DEFB 5*8 ENDIF ; IFE MIXED; ; BASIC DISK PARAMS FOR DOUBLE DENSITY FORMATS ; DPBGEN BLS,DIRSIZ ;GENERATE BSH/BLM/DIRMSK CONSTS ; DDSTUFF: DEFW 0 ;NO SECTOR SKEW TABLE DEFW 0 ;SECTORS PER TRACK (DUMMY) DEFB BSHFT ;BLOCK SHIFT DEFB BMASK ;BLOCK MASK DEFB 0 ;EXTENT MASK (DUMMY) DEFW 0 ;MAX BLOCK# (DUMMY) DEFW DIRSIZ-1 ;MAX DIRECTORY ENTRY# DEFB HIGH DIRMSK ;ALLOCATION MASK MSB DEFB LOW DIRMSK ;ALLOCATION MASK LSB DEFW DIRSIZ/4 ;CHECK VECTOR SIZE DEFW RESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT (DUMMY) DEFB 0 ;DEBLOCK MASK (DUMMY) DEFW 0 ;BYTES PER SECTOR (DUMMY) ENDIF PAGE IF MIXED ; ; DISK PARAMS FOR STANDARD SINGLE DENSITY FORMAT ; 26 SECTORS / 128 BYTES ; S8DSTUFF: DEFW X8LTAB ;1-IN-6 SECTOR SKEW TABLE DEFW N8SECTS ;SECTORS PER TRACK DEFB 3 ;BLOCK SHIFT DEFB 00000111B ;BLOCK MASK DEFB 00000000B ;EXTENT MASK DEFW 242 ;MAX BLOCK# DEFW 63 ;MAX DIRECTORY ENTRY# DEFB 11000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 16 ;CHECK SIZE DEFW R8ESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;BYTES PER SECTOR ; ; ; 8 INCH STANDARD SECTOR TRANSLATE TABLE ; X8LTAB: DEFB 01,07,13,19,25 DEFB 05,11,17,23 DEFB 03,09,15,21 DEFB 02,08,14,20,26 DEFB 06,12,18,24 DEFB 04,10,16,22 ; ; ; SECTOR DEBLOCK PARAMS FOR 8 INCH DOUBLE DENSITY DISKS ; F8RMTAB: DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;PHYSICAL SECTOR LENGTH DEFB 52 ;LOGICAL SECTORS PER TRACK DEFB 00000001B DEFW 256 DEFB 26*2 DEFB 00000011B DEFW 512 DEFB 15*4 DEFB 00000111B DEFW 1024 DEFB 8*8 ; ; DISK PARAMS FOR STANDARD SINGLE DENSITY FORMAT ; 18 SECTORS / 128 BYTES ; S5DSTUFF: DEFW X5LTAB ;1-IN-5 SECTOR SKEW TABLE DEFW N5SECTS ;SECTORS PER TRACK DEFB 3 ;BLOCK SHIFT DEFB 00000111B ;BLOCK MASK DEFB 00000000B ;EXTENT MASK DEFW M5BLK ;MAX BLOCK# DEFW 63 ;MAX DIRECTORY ENTRY# DEFB 11000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 16 ;CHECK SIZE DEFW R5ESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;BYTES PER SECTOR ; ; ; 5 INCH SECTOR TRANSLATE TABLE (SAME AS XEROX/CROMEMCO/OSBORNE) ; X5LTAB: DEFB 01,06,11,16 DEFB 03,08,13,18 DEFB 05,10,15 DEFB 02,07,12,17 DEFB 04,09,14 ; ; ; SECTOR DEBLOCK PARAMS FOR 5 INCH DOUBLE DENSITY DISKS ; F5RMTAB: DEFB 00000000B ;DEBLOCK MASK DEFW 128 ;PHYSICAL SECTOR LENGTH DEFB 28 ;LOGICAL SECTORS PER TRACK DEFB 00000001B DEFW 256 DEFB 18*2 DEFB 00000011B DEFW 512 DEFB 9*4 DEFB 00000111B DEFW 1024 DEFB 5*8 ; ; ; BASIC DISK PARAMS FOR DOUBLE DENSITY FORMATS ; DPBGEN B8LS,D8IRSIZ ;GENERATE BSH/BLM/DIRMSK CONSTS ; D8DSTUFF: DEFW 0 ;NO SECTOR SKEW TABLE DEFW 0 ;SECTORS PER TRACK (DUMMY) DEFB BSHFT ;BLOCK SHIFT DEFB BMASK ;BLOCK MASK DEFB 0 ;EXTENT MASK (DUMMY) DEFW 0 ;MAX BLOCK# (DUMMY) DEFW D8IRSIZ-1 ;MAX DIRECTORY ENTRY# DEFB HIGH DIRMSK ;ALLOCATION MASK MSB DEFB LOW DIRMSK ;ALLOCATION MASK LSB DEFW D8IRSIZ/4 ;CHECK VECTOR SIZE DEFW R8ESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT (DUMMY) DEFB 0 ;DEBLOCK MASK (DUMMY) DEFW 0 ;BYTES PER SECTOR (DUMMY) DPBGEN B5LS,D5IRSIZ D5DSTUFF: DEFW 0 ;NO SECTOR SKEW TABLE DEFW 0 ;SECTORS PER TRACK (DUMMY) DEFB BSHFT ;BLOCK SHIFT DEFB BMASK ;BLOCK MASK DEFB 0 ;EXTENT MASK (DUMMY) DEFW 0 ;MAX BLOCK# (DUMMY) DEFW D5IRSIZ-1 ;MAX DIRECTORY ENTRY# DEFB HIGH DIRMSK ;ALLOCATION MASK MSB DEFB LOW DIRMSK ;ALLOCATION MASK LSB DEFW D5IRSIZ/4 ;CHECK VECTOR SIZE DEFW R5ESERV ;RESERVED TRACKS DEFB 0 ;DEBLOCK SHIFT COUNT (DUMMY) DEFB 0 ;DEBLOCK MASK (DUMMY) DEFW 0 ;BYTES PER SECTOR (DUMMY) ENDIF PAGE ;******************************************************** ;* * ;* LOGICAL SECTOR DEBLOCKING ROUTINES FOR * ;* CBIOS DISK READ/WRITE FUNCTIONS * ;* * ;******************************************************** ; ; WRALL EQU 0 ;WRITE TO ALLOCATED WRDIR EQU 1 ;WRITE TO DIRECTORY WRUAL EQU 2 ;WRITE TO UNALLOCATED ; ; INDEX OFFSETS TO ACCESS DEBLOCK PARAMETERS RELATIVE ; TO BASE ADDRESS OF DPH ENTRY FOR SPECIFIED DRIVE ; SPT EQU 16 BLM EQU 19 SHFCNT EQU 31 SECMSK EQU 32 SECLEN EQU 33 FLAGS EQU 35 ; ; ; ; READDB: LD IX,(DPHPTR) ;GET POINTER TO THIS DRIVE'S PARAMETERS LD A,1 LD (DIR),A ;SET DIRECTION FOR READ LD A,(IX+SHFCNT) OR A JR NZ,READ1 ;DO DEBLOCKING IF SECTOR LENGTH > 128 CALL FLUSH ;ELSE CLEAR ANY DEFERRED WRITES LD A,1 CALL RW128 ;READ 128 BYTE SECTOR DIRECTLY RET ; READ1: CALL PHYSECT ;TRANSLATE SECTOR# TO HOST EQUIV LD A,(WRTACT) OR A JR Z,READ2 ;JUMP IF WRITE BUFFER ACTIVE CALL FLUSH ;ELSE CLEAR OUT DEFERRED WRITE JR READ3 ; AND THEN READ NEW BUFFER FULL ; READ2: LD A,(RDACT) OR A JR Z,READ3 ;READ INTO BUFFER IF DEBLOCK INACTIVE CALL HOSTCMP ;CHECK IF STILL USING SAME HOST SECTOR JR Z,READ4 ;GET RECORD FROM BUFFER IF STILL THERE READ3: LD A,(SECTMP) ;ELSE COPY NEW DISK/TRACK/SECTOR LD (HSTSEC),A ; TO HOST DISK PARAMETERS LD HL,(TRACK) LD (HSTTRK),HL LD A,(DISK) LD (HSTDSK),A CALL READHST ;READ HOST SECTOR INTO DEBLOCK BUFFER RET NZ ;EXIT IF DISK ERROR READ4: CALL DEBLOCK ;MOVE 128 BYTES FROM BUFFER XOR A RET ;RETURN WITH A=0 (NO ERRORS) ; ; ; ; ; WRITEDB: LD IX,(DPHPTR) ;GET POINTER TO THIS DRIVE'S PARAMETERS XOR A LD (DIR),A ;FLAG AS WRITE OPERATION LD A,(IX+SHFCNT) OR A JR NZ,WRITE1 ;DO DEBLOCKING FOR SECTORS > 128 BYTES CALL FLUSH ;ELSE END ANY DEFERRED WRITES XOR A CALL RW128 ;WRITE 128 BYTE SECTOR DIRECTLY RET ; WRITE1: CALL PHYSECT ;TRANSLATE HOST EQUIV OF SECTOR# XOR A LD (RDACT),A ;RESET READ BUFFER ACTIVE FLAG LD A,C ;WRITE TYPE IN C CP WRUAL JR Z,UNALOC ;JUMP IF NEW UNALLOCATED BLOCK CP WRDIR JR Z,ALLOC ;JUMP IF DIRECTORY WRITE ; ; CHECK FOR CONTINUED WRITE TO UNALLOCATED BLOCK ; LD A,(SECTOR) LD HL,NXTSEC CP (HL) JR NZ,ALLOC LD HL,(TRACK) LD DE,(NXTTRK) OR A ;COMPARE NEW SECTOR/TRACK TO PREVIOUSLY SBC HL,DE ; ANTICIPATED NUMBERS FOR NEXT RECORD JR NZ,ALLOC ;JUMP IF NOT IN CURRENT BLOCK LD HL,RCOUNT ;CHECK IF RCOUNT HAS REACHED ZERO LD A,(HL) OR A JR NZ,UNAL2 ;JUMP IF CONTINUED WRITE ALLOC: CALL FLUSH ;FINISH OLD WRITE BUSINESS CALL READ3 ;READ NEW BUFFER RET NZ CALL WRITEHST RET ; ; START WRITING UNALLOCATED BLOCK BY SETTING PARAMETERS ; UNALOC: CALL FLUSH ;FINISH ANY PREVIOUS DEBLOCKED WRITES LD A,(IX+BLM) LD (RCOUNT),A ;RCOUNT=SECTORS-PER-BLOCK MINUS 1 LD A,(SECTOR) LD (NXTSEC),A LD HL,(TRACK) ;STORE PARAMS FOR COMPUTATION OF LD (NXTTRK),HL ; SUCCESSIVE SECTOR NUMBERS IN BLOCK JR UNAL3 ; ; ARRIVE HERE ON SUCCESSIVE WRITES TO UNALLOCATED BLOCK ; UNAL2: DEC (HL) ;RCOUNT = RCOUNT-1 CALL HOSTCMP ;TEST IF STILL IN SAME HOST SECTOR JR Z,UNAL4 ;PUT RECORD INTO BUFFER IF NOT FULL CALL WRITEHST ;WRITE HOST SECTOR FROM BUFFER RET NZ ;EXIT IF DISK ERROR UNAL3: LD A,(SECTMP) ;ELSE COPY NEW DISK/TRACK/SECTOR LD (HSTSEC),A ; TO HOST DISK PARAMETERS LD HL,(TRACK) LD (HSTTRK),HL LD A,(DISK) LD (HSTDSK),A LD (HSTDPH),IX ;STORE DPH POINTER FOR CALLS TO 'FLUSH' UNAL4: CALL DEBLOCK ;MOVE 128 BYTES INTO BUFFER LD HL,NXTSEC INC (HL) ;ADD 1 TO CURRENT DISK ADDRESS TO LD A,(HL) ; GET NEXT SECTOR/TRACK NUMBER IN BLOCK CP (IX+SPT) JR C,UNAL5 JR Z,UNAL5 LD (HL),1 ;RESET TO SECTOR# 1 AND BUMP TRACK# LD HL,(NXTTRK) INC HL LD (NXTTRK),HL UNAL5: XOR A RET ;RETURN WITH A=0 (NO ERRORS) ; ; ; TRANSLATE SECTOR# TO HOST DISK EQUIVALENT ; PHYSECT: LD B,A ;LOAD B WITH SHIFT COUNT (RANGE 1..3) LD A,(SECTOR) DEC A ;REMOVE +1 BIAS FROM SECTOR NUMBERS PHSEC2: SRL A DJNZ PHSEC2 INC A ;REINSTATE +1 BIAS TO SECTOR# LD (SECTMP),A ;SAVE FOR BUFFER RANGE TEST RET ; ; ; DEBLOCK: LD A,(SECTOR) DEC A ;REMOVE SECTOR NUMBER +1 BIAS AND (IX+SECMSK) ;MASK SECTOR# OFF TO GET BUFFER INDEX LD H,0 LD L,A ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD BC,BIGBUF ADD HL,BC ;HL = HOST BUFFER ADDRESS LD DE,(POINTR) ;DE = DMA ADDRESS FROM BDOS LD A,(DIR) OR A JR NZ,DEBLK2 ;SKIP IF READ LD A,1 LD (WRTACT),A ;INDICATE BUFFERED WRITE IS ACTIVE EX DE,HL ;SOURCE/DEST SWAP DEBLK2: LD BC,128 LDIR RET ; ; PAGE ; ; HOSTCMP: LD A,(SECTMP) LD HL,HSTSEC CP (HL) RET NZ LD HL,(TRACK) LD DE,(HSTTRK) OR A SBC HL,DE RET NZ LD A,(DISK) LD HL,HSTDSK CP (HL) RET ; ; ; ; FLUSH: XOR A LD (RDACT),A ;FLAG BUFFERED READ AS INACTIVE LD (RCOUNT),A ;TERMINATE ANY WRITE TO UNALLOCATED LD A,(WRTACT) OR A RET Z PUSH IX ;SAVE CURRENT DPH POINTER IN IX LD IX,(HSTDPH) ;LOAD RIGHT POINTER FOR STUFF IN BUFFER CALL WRITEHST ;WRITE BUFFER ONTO HOST DISK POP IX ;RESTORE DPH POINTER BEFORE GOING BACK RET IF MIXED ;CHECK TYPE OF DISK TO SELECT, 5 1/4 OR 8 INCH. CKTYPE: PUSH BC LD A,(DISK) INC A ;RANGE 1-4 LD B,A LD A,(TYPEFLAG) ;GET TYPE FROM MONITOR RAM SKTLP: SRL A ;PUT DISK FLAG IN CARRY DJNZ SKTLP POP BC RET ENDIF PAGE ;******************************************************** ;* * ;* HOST DISK SELECT/SEEK/READ/WRITE ROUTINE * ;* * ;******************************************************** ; ; ; ; ; READHST: LD HL,BIGBUF LD (HSTPTR),HL LD A,1 LD (RDACT),A CALL DOIT ;READ SECTOR FROM DISK RET Z LD HL,RDACT LD (HL),0 ;CLEAR FLAG IF DISK READ ERROR RET ; ; ; WRITEHST: LD HL,BIGBUF LD (HSTPTR),HL XOR A LD (WRTACT),A CALL DOIT ;WRITE SECTOR TO DISK RET ; ; ; RW128: LD HL,NEW LD DE,HOST LD BC,6 LDIR ;FALL THROUGH INTO 'DOIT' ; ; ... MASTER DISK READ/WRITE ROUTINE ... ; ; CALL WITH IX POINTING TO DISK PARAMETER TABLES ; AND ACC CONTAINING R/W OPERATION INDICATOR. ; ; DOIT: LD (RWFLAG),A ;STORE RWFLAG 1=READ 0=WRITE IF WINCH LD A,(HSTDSK) CP NFLOPPY JP NC,DOWINCH ;DO SASI DISK ROUTINE IF ON HARD DISK ENDIF DOFLOP: LD A,(HSTDSK) LD C,A CALL MONITR+27 ;SELECT SPECIFIED DRIVE JR Z,DOFLP2 CALL REPORT ;REPORT SELECT ERROR TO CONSOLE JR Z,DOFLOP RET ;RETURN PERMANENT ERROR IF NOT ZERO ; DOFLP2: LD B,SIDSEL+OFF ;DEFAULT TO SELECT DISK SIDE ZERO LD A,(HSTTRK) IF MIXED LD C,A CALL CKTYPE LD A,C JR NC,DFLP2A CP N8TRAKS JR DFLP2B DFLP2A: CP N5TRAKS DFLP2B: ELSE CP NTRAKS ;TEST IF TRACK# IS ON OTHER SIDE ENDIF JR C,DOFLP3 LD B,SIDSEL+ON ;SELECT OPPOSITE SIDE IF MIXED LD C,A CALL CKTYPE LD A,C JR NC,DFLP2C SUB N8TRAKS JR DFLP2D DFLP2C: SUB N5TRAKS DFLP2D: ELSE SUB NTRAKS ;CONVERT TRACK# TO REAL VALUE ENDIF DOFLP3: LD C,A LD A,B OUT (PORT0),A ;OUTPUT SIDE SELECT BIT CALL MONITR+33 ;SEEK SELECTED TRACK JR Z,DOFLP4 CALL REPORT ;REPORT SEEK ERROR TO CONSOLE JR Z,DOFLP2 RET ;RETURN PERMANENT ERROR IF INDICATED ; DOFLP4: LD HL,(HSTPTR) LD A,(HSTSEC) LD C,A LD A,(RWFLAG) OR A ;TEST DIRECTION 1=READ 0=WRITE JR Z,DOFLP5 CALL MONITR+36 JR DOFLP6 ; DOFLP5: CALL MONITR+39 DOFLP6: RET Z ;RETURN IF READ/WRITE SUCCESSFUL CALL REPORT JR Z,DOFLP4 ;TRY AGAIN IF INDICATED RET ; ; ; ; REPORT: LD E,A ;SAVE PERTINENT ERROR BITS IN E LD A,(HSTDSK) ADD A,'A' LD (DSKMSG+16),A LD HL,DSKMSG CALL PMSG ;PRINT OUT START OF MESSAGE LD BC,08FFH ;B=LOOPCOUNT C=255 FOR CPIR SCAN LD A,E REP2: RLA JR C,REP3 PUSH AF XOR A CPIR ;SCAN MEMORY LOOKING FOR NULL POP AF DJNZ REP2 REP3: CALL PMSG ;PRINT ERROR TYPE STRING LD A,E AND 11000000B ;MASK TO NOT-READY AND WRITE-PROTECT JR NZ,REP5 LD HL,TSMSG CALL PMSG LD A,(HSTTRK) CALL PUTDEC CALL PMSG LD A,(HSTSEC) CALL PUTDEC LD A,1 OR A RET ; REP5: LD HL,PROMPT CALL PMSG CALL IVEC ;LOOP FOR CONSOLE INPUT CP 'C'-64 JR Z,REP6 XOR A RET ; REP6: XOR A LD (IOBYTE+1),A ;CLEAR AUTO-LOG BYTE IF CTL-C ABORT INC A RET ;RETURN PERMANENT BIOS ERROR ; ; ; ; CHARACTER STRING OUTPUT ROUTINE. PRINTS ASCII DATA ; POINTED TO BY HL UNTIL A DOLLAR SIGN IS ENCOUNTERED ; PMSG: LD A,(HL) ;HL POINTS TO ASCII STRING INC HL OR A ;TEST FOR BYTE EQUAL ZERO RET Z LD C,A ;PRINT CHARACTER IF NOT DOLLAR SIGN CALL OVEC JR PMSG ; ; ; ; PRINT CONTENTS OF A IN DECIMAL (RANGE 0..255) ; PUTDEC: LD B,100 CALL PDIGIT ;PRINT HUNDREDS DIGIT LD B,10 CALL PDIGIT ;PRINT TENS DIGIT PNUM: OR '0' LD C,A CALL OVEC RET ; ; PDIGIT: LD C,-1 PDIG1: INC C SUB B JR NC,PDIG1 ADD A,B PUSH AF LD A,C OR A CALL NZ,PNUM ;PRINT NUMERIC CHARACTER IF NON-ZERO POP AF RET ; ; ; ; ; ; NULL EQU 00H ;NULL (END-OF-STRING INDICATOR) LF EQU 0AH ;LINE FEED CR EQU 0DH ;CARRIAGE RETURN DSKMSG: DEFB CR,LF DEFB 'BIOS error on A: ',NULL DEFB 'not ready',NULL DEFB 'wrt protect',NULL DEFB 'wrt fault',NULL DEFB 'not found',NULL DEFB 'bad crc',NULL DEFB 'overrun',NULL DEFB 'drq',NULL DEFB 'busy',NULL DEFB NULL TSMSG: DEFB ' track ',NULL DEFB ' sector ',NULL PROMPT: DEFB ' ?','H'-64,NULL ; ; ; ; ;