;******************************************************** ;* * ;* 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 SIDSEL EQU 1 ;BIT# OF SIDE SELECT BIT 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 RET NZ ;EXIT IF DRIVE IS LOGGED-ON PUSH HL POP IX BIT 0,(IX+FLAGS) ;TEST DRIVE PRE-SELECTED FLAG RET NZ ;EXIT IF DRIVE FORMAT ALREADY KNOWN CALL FLUSH ;FINISH ANY DEFERRED DISK OPERATIONS LD A,RESERV 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 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: LD HL,SDSTUFF 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 LD HL,DDSTUFF LD (PRMPTR),HL ;USE DUAL DENSITY DISK PARAMETERS LD HL,NTRAKS-RESERV 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 LD HL,2*NTRAKS-RESERV 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 LD (DDSTUFF+17),A ;STORE AS DEBLOCK MASK IN 'DDSTUFF' LD H,0 LD L,A ADD HL,HL ADD HL,HL ;MULTIPLY LENGTH CODE BY 4 FOR INDEXING LD BC,FRMTAB ADD HL,BC ;ADD BASE ADDRESS OF FORMAT POOP TABLE LD DE,DDSTUFF+18 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: LD (DDSTUFF+2),A ;STORE LOGICAL SPT CONST IN 'DDSTUFF' 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) LD A,(DDSTUFF+4) 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 LD (DDSTUFF+7),HL LD A,(DDSTUFF+5) ;GET BLOCK MASK FROM DPB 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: LD (DDSTUFF+6),A ;STORE VALUE FOR 'EXM' 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 ; 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 81 ;MAX BLOCK# DEFW 31 ;MAX DIRECTORY ENTRY# DEFB 10000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 8 ;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 ; ; ; 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) 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 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) CP NTRAKS ;TEST IF TRACK# IS ON OTHER SIDE JR C,DOFLP3 LD B,SIDSEL+ON ;SELECT OPPOSITE SIDE SUB NTRAKS ;CONVERT TRACK# TO REAL VALUE 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 ; ; ; ; ;