PAGE ;******************************************************** ;* * ;* 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 C,0 SETTRACK: LD HL,TRACK LD (HL),C 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 RET ;INCR SO SECTOR NUMBERS START AT 1 PAGE ; ; ; MAGIC SELDISK ROUTINE WITH AUTO DISK PARAMETER SELECT ; ; SELDISK: LD A,C CP 4 JR NC,SDSK3A ;ERROR IF DRIVE# TOO BIG LD (DRIVE),A INC A ;GET A IN RANGE 1..4 LD BC,DPHLEN LD HL,DPHTAB-DPHLEN SDSK2: ADD HL,BC DEC A JR NZ,SDSK2 LD (DPHPTR),HL ;STORE POINTER TO DISK'S DPH ENTRY PUSH HL POP IX ;GET POINTER INTO IX ALSO INC D JP Z,SETNFMT ;SPECIAL FOR 'DDINIT' TO SET NTRACKS BIT 0,E ;TEST FOR INITIAL DRIVE SELECT RET NZ ;EXIT IF NOT AN INITIAL DISK SELECT BIT 0,(IX+FLAGS) ;TEST DRIVE PRE-SELECTED FLAG RET NZ ;EXIT IF DRIVE FORMAT ALREADY KNOWN CALL FLUSH ;FINISH ANY DEFERRED DISK OPERATIONS SDSK3: LD A,(DRIVE) LD (HSTDSK),A LD A,2 LD (HSTTRK),A XOR A LD (HSTSEC),A ;SET SECTOR=0 IN CASE 'REPORT' CALLED LD HL,IDBUFF LD (HSTPTR),HL LD A,GETID CALL DISKOP ;READ AN ID MARK OFF FIRST USER TRACK JR Z,SDSK3B ;JUMP IF SUCCESSFUL SDSK3A: LD HL,0 RET ;ELSE RETURN PERM SELECT ERROR ; ; SDSK3B: LD A,(IOCB+DSKAUX) RLCA RLCA AND 00000011B LD DE,17 CALL MULT ;MULTIPLY DRIVE TYPE CODE BY DPB SIZE LD DE,PARMTAB ADD HL,DE ;INDEX TO START OF CORRECT DPB STUFF LD DE,(DPHPTR) 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 LDIR ;COPY DISK PARAMETER BLOCK LD IX,(DPHPTR) LD HL,DIRBUF ;GET ADDRESS OF DIRECTORY BUFFER LD (IX+DIRBF),L LD (IX+DIRBF+1),H ;STORE IN 'DIRBUF' POINTER SLOT LD HL,(DPHPTR) LD DE,16 ADD HL,DE ;COMPUTE ADDRESS OF DISK PARM BLOCK LD (IX+DPB),L LD (IX+DPB+1),H ;STORE IN 'DPB' POINTER SLOT LD C,(IX+CKS) LD B,(IX+CKS+1) LD DE,CSV CALL ALLOCAT ;ALLOCATE SPACE FOR CHECK VECTOR LD DE,SECTAB LD BC,77 OR (44 SHL 8) LD A,(IOCB+DSKAUX) BIT 6,A ;TEST IF EIGHT INCH OR FIVE INCH DISK JR Z,SDSK4 LD DE,SECTAB+4 LD BC,40 OR (25 SHL 8) SDSK4: PUSH BC LD HL,128 ;PREPARE TO DERRIVE DEBLOCK PARAMS LD B,H LD A,(IDBUFF+3) ;GET SECTOR LENGTH BYTE FROM ID RECORD AND 00000011B LD (IX+SHFCNT),A ;STORE AS DEBLOCK SHIFT IN DPB JR Z,SDSK4B ;JUMP IF 128 BYTE SECTORS SDSK4A: ADD HL,HL INC DE SCF RL B DEC A ;MULTIPLY SECTOR LENGTH AND MASK BYTE JR NZ,SDSK4A SDSK4B: LD A,(DE) LD (IX+SPT),A LD (IX+SECMSK),B LD (IX+SECLEN),L LD (IX+SECLEN+1),H ;STORE RESULTS FOR USE BY DEBLOCKER POP BC ;RECOVER #BLKS,#TRKS VALUES FROM STACK LD A,(IX+NTRACKS) OR A CALL Z,SNTRACKS ;GO SET 'NTRACKS' PARAM IF EQUAL ZERO BIT 7,(IX+FLAGS) JR Z,SDSK7 ADD A,A ;DOUBLE NUMBER OF TRACKS IF 2 SIDED SLA B ;ALSO DOUBLE NUMBER OF ALV BYTES SDSK7: LD C,B ;COPY #BLOCKS TO C FOR SAFEKEEPING SUB (IX+OFF) ;COMPUTE USER TRACKS MINUS RESERVED LD E,A LD D,0 LD A,(IX+SPT) CALL MULT ;GET PRODUCT OF SPT * (NTRACKS-RESERV) LD A,(IX+BSH) LD B,A SDSK8: SRL H ;DIVIDE TOTAL SECTORS BY 'BSH' TO GET RR L ; NUMBER OF BLOCKS ON DISK DJNZ SDSK8 DEC HL ;RESULT LESS 1 IS 'DSM' VALUE FOR DPB LD (IX+DSM),L LD (IX+DSM+1),H LD A,(IX+BLM) ;PREPARE TO DERRIVE EXTENT MASK SRL A SRL A SRL A INC H DEC H ;TEST IF 'DSM' IS > 255 JR Z,SDSK8A SRL A SDSK8A: LD (IX+EXM),A ;STORE VALUE FOR 'EXM' (A=0 IF H<>0) LD B,0 ;CLEAR MSB SO BC=#BLOCKS/8 FOR BITMAP LD DE,ALV CALL ALLOCAT ;ALLOCATE SPACE FOR BITMAP LD A,(FREPTR+1) CP HIGH (SCRATCH+2048-256) JP NC,SDSK3A ;SELECT ERROR IF NO ROOM FOR VECTORS LD HL,(DPHPTR) RET ;RETURN WITH DPH POINTER IN HL ; ; ; ALLOCAT: LD HL,(DPHPTR) ADD HL,DE ;INDEX INTO DPH TO ALV OR CSV LOCATION LD A,(HL) INC HL OR (HL) RET NZ ;EXIT IF ALREADY ALLOCATED (NON-ZERO) LD DE,(FREPTR) ;ELSE STORE CURRENT FREE MEMORY POINTER LD (HL),D DEC HL LD (HL),E EX DE,HL ADD HL,BC ;ADD LENGTH OF VECTOR TO FREE POINTER LD (FREPTR),HL ; AND STORE UPDATED VALUE RET ; ; FREPTR: DEFW FREEMEM ;MEMORY POINTER FOR CHECK/ALLOC VECTORS ; ; ; ; MULT: ;MULTIPLY DE BY A GIVING RESULT IN HL LD HL,0 LD B,8 MULT2: RRA JR NC,MULT3 ADD HL,DE MULT3: SLA E RL D DJNZ MULT2 RET ; ; ; SETNFMT: ;SPECIAL ENTRY FROM 'SELDISK' WITH D=FF LD C,0 ;FORCES PARAMS TO BE SET FROM TABLE ; ; ; SET NTRACKS SUBROUTINE. CALL WITH C=DEFAULT. RETURNS WITH ; (IX+NTRACKS) AND (IX+FLAGS) ALTERED AND A=NTRACKS. ; SNTRACKS: LD A,(DRIVE) LD DE,NTRKSA ADD A,E ;INDEX INTO DEFAULT DRIVE DEF TABLE LD E,A LD A,(DE) OR A JR Z,STRKS2 ;JUMP IF ENTRY=0 (IE. USE DEFAULTS) AND 10000000B OR (IX+FLAGS) ;MERGE MSB (DOUBLE SIDED DRIVE BIT) LD (IX+FLAGS),A ; WITH 'FLAGS' BYTE FROM PARAMS LD A,(DE) AND 01111111B ;LOWER 7 BITS ARE TRACKS-PER-DISK JR STRKS3 ; STRKS2: LD A,C STRKS3: LD (IX+NTRACKS),A ;STORE VAULE DERRIVED FOR NTRACKS RET NTRKSA: DEFB 0 ;DEFAULT TO 48 TPI, SINGLE SIDED NTRKSB: DEFB 0 NTRKSC: DEFB 0 NTRKSD: DEFB 0 ; ; ; PAGE ; ; ; ; ... DISK PARAMETER BLOCK DEFAULTS FOR 5/8 SD/DD DISKS ... ; PARMTAB EQU $ ; ; DPB FOR 8 INCH DOUBLE DENSITY ; DD8IN: DEFW 0 ;NO SECTOR SKEW TABLE DEFW 0 ;SECTORS PER TRACK (DUMMY) DEFB 4 ;BLOCK SHIFT DEFB 00001111B ;BLOCK MASK DEFB 0 ;EXTENT MASK (DUMMY) DEFW 0 ;MAX BLOCK# (DUMMY) DEFW 127 DEFB 11000000B DEFB 00000000B DEFW 32 ;CHECK SIZE DEFW 2 ;RESERVED TRACKS ; ; ; DPB FOR 5 INCH DOUBLE DENSITY ; DD5IN: DEFW 0 ;NO SECTOR SKEW TABLE DEFW 0 ;SECTORS PER TRACK (DUMMY) DEFB 3 ;BLOCK SHIFT DEFB 00000111B ;BLOCK MASK DEFB 00000000B ;EXTENT MASK (DUMMY) DEFW 0 ;MAX BLOCK# (DUMMY) DEFW 63 ;MAX DIRECTORY ENTRY# DEFB 11000000B ;ALLOCATION MASK MSB DEFB 00000000B ;' ' LSB DEFW 16 ;CHECK SIZE DEFW 2 ;RESERVED TRACKS ; ; ; DPB FOR 8 INCH SINGLE DENSITY ; SD8IN: DEFW SIXTAB ;1-IN-6 SECTOR SKEW TABLE DEFW 26 ;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 2 ;RESERVED TRACKS ; ; ; DPB FOR 5 INCH SINGLE DENSITY ; SD5IN: DEFW FIVTAB ;1-IN-5 SECTOR SKEW TABLE DEFW 18 ;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 3 ;RESERVED TRACKS ; ; ; ; ... TABLE OF STANDARD NUMBERS OF SECTORS/TRACK ... ; SECTAB: DEFB 26*1 ;SD 8 INCH 26*128 DEFB 26*2 ;DD 8 INCH 26*256 DEFB 16*4 ;DD 8 INCH 16*512 DEFB 9*8 ;DD 8 INCH 9*1024 DEFB 18*1 ;SD 5 INCH 18*128 DEFB 18*2 ;DD 5 INCH 18*256 DEFB 10*4 ;DD 5 INCH 10*512 DEFB 5*8 ;DD 5 INCH 5*1024 ; ; ; ; SIXTAB: 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 ; ; ; FIVTAB: DEFB 01,06,11,16 DEFB 03,08,13,18 DEFB 05,10,15 DEFB 02,07,12,17 DEFB 04,09,14 ; ; 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 ; XLT EQU 0 ;OFFSETS FOR POINTERS IN DPH DIRBF EQU 8 DPB EQU 10 CSV EQU 12 ALV EQU 14 SPT EQU 16 ;OFFSETS FOR ITEMS IN DPB BSH EQU 18 BLM EQU 19 EXM EQU 20 DSM EQU 21 DRM EQU 23 AL0 EQU 25 AL1 EQU 26 CKS EQU 27 OFF EQU 29 SHFCNT EQU 31 ;OFFSETS FOR EXTRA SWP PARAMS SECMSK EQU 32 SECLEN EQU 33 NTRACKS EQU 35 FLAGS EQU 36 ; ; ; ; 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 DO128 ;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 (HOST),A ; TO HOST DISK PARAMETERS LD HL,(NEW+1) LD (HOST+1),HL 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 DO128 ;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 hl,(next) ld de,(new) 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 hl,(new) ;store params for computation of ld (next),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 (HOST),A ; TO HOST DISK PARAMETERS LD HL,(NEW+1) LD (HOST+1),HL LD (HSTDPH),IX ;STORE DPH POINTER FOR CALLS TO 'FLUSH' UNAL4: CALL DEBLOCK ;MOVE 128 BYTES INTO BUFFER ld hl,next 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# inc hl inc (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 HL,HOST ;POINT TO HOST DISK/TRACK/SECTOR LD A,(SECTMP) CP (HL) ;COMPARE SECTOR# TO SECTOR @ HL RET NZ ;EXIT IF NOT THE SAME INC HL LD A,(TRACK) CP (HL) ;COMPARE TRACK# TO TRACK @ HL RET NZ ;EXIT IF NOT THE SAME INC HL LD A,(DRIVE) CP (HL) ;COMPARE DISK# TO DISK @ 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 ; ; ; DO128: LD HL,NEW LD DE,HOST LD BC,5 LDIR ;FALL THROUGH INTO 'DOIT' ; DOIT: OR A ;TEST DIRECTION 1=READ 0=WRITE JR Z,DOIT2 LD A,GETSEC JR DISKOP ; DOIT2: LD A,PUTSEC ; ; ... MASTER DISK READ/WRITE ROUTINE ... ; ; CALL WITH IX POINTING TO DISK PARAMETER TABLES ; DISKOP: LD (IOCB+DSKOP),A ;STORE COMMAND BYTE FOR DISKOP LD A,(ONEDSK) OR A ;TEST FOR SINGLE DRIVE SYSTEM JR Z,DISKO2 ;JUMP IF MULTIPLE DRIVES XOR A LD (IOCB+DSKDRV),A ;SELECT DRIVE ZERO ALWAYS LD A,(HSTDSK) LD HL,OLDDSK CP (HL) ;COMPARE LAST LOGICAL DRIVE# TO HSTDSK JR Z,DISKO3 ;JUMP IF STILL ACCESSING SAME ONE LD (HL),A ;ELSE STORE NEW LOGICAL DRIVE# ADD A,'A' LD (SWAP+9),A LD HL,SWAP CALL REP5B ;DISPLAY 'SWAP DISKS' MESSAGE JR DISKO3 ; DISKO2: LD A,(HSTDSK) ;SELECT DRIVE FROM 'HSTDSK' LD (IOCB+DSKDRV),A DISKO3: LD A,(HSTTRK) LD B,(IX+NTRACKS) INC B ;TEST IF 'NTRACKS' PARAM HAS BEEN SET DEC B JR Z,DISKO4 ;SKIP SIDE# TEST CODE IF B=0 CP B JR C,DISKO4 ;JUMP IF TRACK IS ON FIRST SIDE OF DISK SUB B LD HL,IOCB+DSKDRV SET 7,(HL) ;SELECT FLIP SIDE OF DISK DISKO4: LD (IOCB+DSKTRK),A ;STORE TRACK NUMBER LD A,(HSTSEC) BIT 1,(IX+FLAGS) JR Z,DISKO5 ;JUMP IF NO SECTOR# ZERO ON DRIVE DEC A ;ELSE MAKE PHYSICAL SECTOR# ONE LESS DISKO5: LD (IOCB+DSKSEC),A ;STORE SECTOR NUMBER LD HL,(HSTPTR) LD (IOCB+DSKPTR),HL ;STORE DISK I/O POINTER LD L,(IX+SECLEN) LD H,(IX+SECLEN+1) LD (IOCB+DSKAUX),HL ;STORE SECTOR LENGTH DISKO6: PUSH IX LD IX,IOCB CALL DISKDVR ;CALL PHYSICAL DISK I/O HANDLER POP IX LD A,(IOCB+DSKSTS) OR A RET Z ;EXIT IF OPERATION WAS SUCCESSFUL CALL REPORT JR Z,DISKO6 ;TRY AGAIN IF INDICATED RET ; ; ; ONEDSK: DEFB 0 ;ONE-DRIVE SYSTEM FLAG (0=MULTIPLE) ; ; ; REPORT: LD E,A LD A,(HSTDSK) ADD A,'A' LD (DSKMSG+17),A LD HL,DSKMSG CALL PMSG ;PRINT OUT START OF MESSAGE LD A,E AND 11000000B ;MASK TO NOT-READY AND WRITE-PROTECT JR NZ,REP5 LD A,E CALL PUTDEC ;PRINT ERROR CODE NUMBER CALL PMSG ;PRINT REST OF MESSAGE LD C,'t' CALL OUTCHR LD A,(HSTTRK) CALL PUTDEC ;PRINT TRACK# LD C,'s' CALL OUTCHR LD A,(HSTSEC) CALL PUTDEC ;PRINT SECTOR# LD A,1 OR A RET ; REP5: CALL PMSG ;PRINT REST OF MESSAGE BIT 7,E JR NZ,REP5A LD HL,WRTMSG REP5A: CALL PMSG LD HL,PROMPT REP5B: 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 OUTCHR JR PMSG ; ; ; ; NULL EQU 00H ;NULL (END-OF-STRING INDICATOR) BELL EQU 07H LF EQU 0AH CR EQU 0DH DSKMSG: DEFB CR,LF DEFB 'BIOS error ',NULL,'on A: ',NULL ; RDYMSG: DEFB 'not ready',NULL ; WRTMSG: DEFB 'write protect',NULL ; SWAP: DEFB CR,LF DEFB 'Select A:' PROMPT: DEFB ' ?',BELL,NULL ; ; ; ; ; PRINT CONTENTS OF A IN DECIMAL (RANGE 0..255) ; PUTDEC: LD D,0 ;SET UP LEADING ZERO SUPPRESSION LD B,100 CALL PDIGIT ;PRINT HUNDREDS DIGIT LD B,10 CALL PDIGIT ;PRINT TENS DIGIT CALL OUTNUM LD A,' '-'0' OUTNUM: ADD A,'0' LD C,A OUTCHR: PUSH HL PUSH DE CALL OVEC POP DE POP HL RET ; ; PDIGIT: LD C,-1 PDIG1: INC C SUB B JR NC,PDIG1 ADD A,B PUSH AF LD A,C OR A JR NZ,PDIG2 INC D DEC D JR Z,PDIG3 PDIG2: CALL OUTNUM INC D PDIG3: POP AF RET ; ; ; ; ;