TITLE 'CBIOS FOR CP/M 2.2' PAGE 60 ; CP/M BASIC INPUT/OUTPUT OPERATING SYSTEM (BIOS) ; TARBELL ELECTRONICS ; 2.2 VERSION OF 12-5-79 ; MODIFIED BY RICHARD B. KOLBLY ; 10-01-80 ; ; THIS BIOS MODULE IS THE CPM V2.2 ; CBIOS. THIS BIOS READS SINGLE DENSITY ; DISK.. TRACK 0 = SINGLE DENSITY (IBM COMPATABLE) ; TRACKS 1 - 76 SINGLE DENSITY 52 SECTORS. ; ; THIS SECTION DEFINES THE I/O PORTS AND ; STATUS BITS. BY SETTING THE PROPER VALUES ; FOR THE EQU STATEMENTS, THE I/O MAY BE ; AUTOMATICALLY RECONFIGURED TO FIT MOST ; SITUATIONS. THE TRUE AND FALSE ONES ; CONTROL CONDITIONAL ASSEMBLIES OF DIFFERENT ; SECTIONS OF I/O ROUTINES TO FIT DIFFERENT ; INTERFACE REQUIREMENTS. TRUE EQU 0FFFFH ;DEFINE VALUE OF TRUE. FALSE EQU NOT TRUE ;DEFINE VALUE OF FALSE. ;*************************************************** ;*** THIS BEGINS THE AREA WHICH REQUIRES CHANGES *** ;*** FOR DIFFERENT CONSOLE I/O SYSTEMS *** ;*************************************************** MSIZE EQU 56 ;MEMORY SIZE IN KBYTES. NDISK EQU 2 ;DEFINES THE NUMBER DRIVES IN SYSTEM. CDATA EQU 0 ;USED TO CLEAR CONSOLE STATUS. HLAB EQU 0 ;8 FOR HD LD AT BEG OF SEEK. STPRAT EQU 2 ;RATE 1=6MS, 2=10MS, 3=20MS. ;******************************************************* ;*** THIS IS THE END OF THE AREA WHICH NORMALLY NEED *** ;*** BE CHANGED FOR MOST CONSOLE I/O SYSTEMS *** ;******************************************************* RDYLO EQU TRUE ;STATUS READY WHEN LOW. RDYHI EQU NOT RDYLO DISK EQU 0F8H ;DISK BASE ADDRESS. DCOM EQU DISK ;DISK COMMAND PORT. DSTAT EQU DISK ;DISK STATUS PORT. TRACK EQU DISK+1 ;DISK TRACK PORT. SECTP EQU DISK+2 ;DISK SECTOR PORT. DDATA EQU DISK+3 ;DISK DATA PORT. WAIT EQU DISK+4 ;DISK WAIT PORT. RTCNT EQU 10 ;RETRY COUNT. IOBYTE EQU 3 ;ADDRESS OF I/O BYTE. FF EQU 0CH ;ASCII FORM FEED CHARACTER LF EQU 0AH ;ASCII LINE FEED CHARACTER ; ; VALUES OF I/O FUNCTIONS ; @CONIN EQU 0F803H ;GET CHARACTER FROM CONSOLE @READER EQU 0F806H ;GET CHARACTER FROM READER @CONOT EQU 0F809H ;WRITE TO CONSOLE DEVICE @PUNCH EQU 0F80CH ;WRITE TO PUNCH DEVICE @LIST EQU 0F80FH ;CHARACTER TO LIST DEVICE @CONST EQU 0F812H ;GET STATUS OF CONSOLE KEYBOARD @PRSTAT EQU 0F815H ;STATUS OF LIST DEVICE @PMSG EQU 0F818H ;PRINT MESSAGE IN (HL) TIL ZERO @ERROR EQU 0F81BH ;ERROR REPORTING ROUTINE ; CBASE EQU (MSIZE-20)*1024 ;BIAS FOR LARGER THAN 20K. CPMB EQU CBASE+3400H ;START OF CPM 2.2 BDOS EQU CPMB+806H ;START OF BDOS 2.2. BIOS EQU CPMB+1600H ;START OF CBIOS IO. CDISK EQU 4 ;LOCATION 4 IS CURRENT DISK. NSECTS EQU 17 ;NUMBER OF SECTORS IN IT. ORG CPMB+16 ; SMSG: DB 0DH,0AH,0DH,'SBMS/K6HIJ',0AH,0DH DB MSIZE/10+'0',MSIZE MOD 10+'0' DB 'K CP/M V2.2 of 06-06-80',0 ; ; BOOT ; THIS SECTION IS EXECUTED WHENEVER RESET AND RUN ; IS PUSHED, AFTER THE COLDSTART LOADER READS IN ; THE CPM SYSTEM. ; BOOT: LXI SP,80H ;SET STACK POINTER. JMP BOOTF ;FINISH BOOT. ORG BIOS-64 ;HIDE REST OF BOOT HERE. BOOTF: XRA A ;CLEAR SCRATCH AREA. STA CDISK ;SELECT DRIVE ZERO STA LATCH ;SET LATCH FOR DRIVE A. LXI H,IOBYTE ;POINT TO IOBYTE. MVI M,01H ;SET UP IOBYTE. MVI B,ENDZ-STARTZ ;GET LENGTH OF ZERO AREA. LXI H,STARTZ ;GET SCRATCH ADDRESS. BOOTL: MOV M,A ;PUT ZERO IN MEMORY. INX H ;INCREMENT POINTER. DCR B ;DECREMENT COUNTER. JNZ BOOTL ;LOOP TILL DONE. IN CDATA ;CLEAR CONSOLE STATUS. LXI H,SMSG ;POINT TO SIGN ON. PMSG1: MOV A,M ;GET A BYTE OF THE MESSAGE INX H ;BUMP MEMORY POINTER. ORA A ;IS IT A ZERO? JZ GOCPM ;YES, WE ARE DONE, JMP TO CPM. MOV C,A ;NOPE, PRINT MORE MESSAGE. CALL @CONOT ;USE THE CONOT ROUTINE. JMP PMSG1 ;AND LOOP TILL DONE. ORG BIOS ;START OF CBIOS STRUCTURE. ; ; I/O JUMP VECTOR ; THIS IS WHERE CPM CALLS WHENEVER IT NEEDS ; TO DO ANY INPUT/OUTPUT OPERATION. ; USER PROGRAMS MAY USE THESE ENTRY POINTS ; ALSO, BUT NOTE THAT THE LOCATION OF THIS ; VECTOR CHANGES WITH THE MEMORY SIZE. ; DMAENT: JMP BOOT ;FROM SBOOT LOADER,CHANGED FOR DMA. WBOOTE: JMP WBOOT ;FROM WARM BOOT. JMP @CONST ;CHECK CONSOLE KB STATUS. JMP @CONIN ;READ CONSOLE CHARACTER. JMP @CONOT ;WRITE CONSOLE CHARACTER. JMP LIST ;WRITE LISTING CHAR. JMP @PUNCH ;WRITE PUNCH CHAR. JMP @READER ;READ READER CHAR. JMP HOME ;MOVE DISK TO TRACK ZERO. JMP SELDSK ;SELECT DISK DRIVE. JMP SETTRK ;SEEK TO TRACK IN REG A. JMP SETSEC ;SET SECTOR NUMBER. JMP SETDMA ;SET DISK STARTING ADR. JMP READ ;READ SELECTED SECTOR. JMP WRITE ;WRITE SELECTED SECTOR. JMP @PRSTAT ;LIST STATUS CHECK. JMP SECTRAN ;SECTOR TRANSLATE ROUTINE. ; THIS SECTION DEFINES THE THE DISK PARAMETERS ; NOTE: ; IF YOU HAVE THE MACRO ASSEMBLER (MAC) FROM ; DIGITAL RESEARCH, YOU MAY ELIMINATE THIS SECTION ; STARTING AT **AA** TO **BB** AND USE THE MACRO ; FILE "DISKDEF" TO CUSTOM TAILOR YOUR SYSTEM TO ; ALLOW DIFFERENT TYPES OF DRIVES OR MORE THAN 4 ; DRIVES. ; ;**AA** ; DPBASE EQU $ ;BASE OF DISK PARAMETER BLOCK DPE0: DW XLT0,0000H ;TRANSLATE TABLE DW 0000H,0000H ;SCRATCH AREA DW DIRBUF,SDTAB+2 ;DIR BUFF, PARM BLOCK DW CSV0,ALV0 ;CHECK, ALLOC VECTORS ; DPE1: DW XLT1,0000H DW 0000H,0000H DW DIRBUF,DPB1 DW CSV1,ALV1 ; ;THE FOLLOWING DESCRIBES THE DISK PHYSICAL ;NATURE, SUCH AS SECTORS/TRACK,DIRECTORY SIZE. ;THE FOLLOWING TABLE DEFINES A SINGLE DENSITY DRIVE. ; SDTAB: EQU $ ;ONE OF 4 DISK PARM. BLOCKS DW XLT0 ;USE SINGLE DENSITY TRANSLATE TAB. DW 26 ;SECTORS/TRACK DB 3 ;BLOCK SHIFT DB 7 ;BLOCK MASK DB 0 ;EXTNT MASK DW 242 ;DISK SIZE - 1 DW 63 ;DIRECTORY MAX. DB 192 ;ALLOC0 DB 0 ;ALLOC1 DW 16 ;CHECK SIZE DW 2 ;NUMBER OF SYSTEM TRACKS ; ;SECTOR TRANSLATION TABLE ; XLT0 EQU $ ;START OF TRANS. TABLE DB 1,7,13,19,25 DB 5,11,17,23,3 DB 9,15,21,2,8 DB 14,20,26,6,12 DB 18,24,4,10,16,22 ; DPB1 EQU SDTAB+2 ;EQUIVALENT PARAMETERS XLT1 EQU XLT0 ;SAME TRANSLATE TABLE ; ;**BB** ; ; ; WARM-BOOT: READ ALL OF CPM BACK IN ; EXCEPT BIOS, THEN JUMP TO CCP. ; WBOOT: LXI SP,80H ;SET STACK POINTER. LDA CDISK ;SAVE DISK NUMBER. STA TEMP MVI C,0 ;SELECT DISK 0. CALL SELDSK CALL HOME ;MOVE TO TRACK ZERO. JNZ RDERR ;IF ERROR, PRINT MESSAGE. MVI D,NSECTS ;GET # SECTORS FOR CPM READ. LXI B,2 ;TRACK (B)=0, SECTOR (C)=2. LXI H,CPMB ;GET STARTING ADDRESS. RDBLK: MOV A,B ;GOTO TRACK IN B. CALL SEEK JNZ RDERR ;IF ERROR, PRINT MESSAGE. MOV A,C ;READ STARTING AT SECTOR IN C. CALL READ1 RBLK1: JNZ RDERR ;IF ERROR, PRINT MESSAGE. DCR D ;DECREMENT SECTOR COUNT. JZ ALDON ;ALL DONE WHEN ZERO. INR C ;INCREMENT SECTOR NUMBER. MOV A,C ;IF SECTOR NUMBER CPI 27 ; IS NOT 27, JC RBLK2 ; HOP OUT OF LOOP. MVI C,1 ;OTHERWISE, RESET SECTOR=1 INR B ; INCREMENT TRACK NUMBER, JMP RDBLK ; AND READ NEXT TRACK. ALDON: LDA TEMP ;RESTORE DISK NUMBER. STA CDISK JMP GOCPM ;GO BACK TO CPM. RBLK2: CALL READ2 ;READ ANOTHER TRACK. JMP RBLK1 RDERR: MVI C,'B' ;GET BOOT ERROR CODE. CALL @CONOT ;PRINT IT. CALL @CONIN ;READ A CHAR FROM CONSOLE. JMP WBOOT ;DO A WARM BOOT. GOCPM: ; ; SET UP JUMPS INTO CP/M IN LOWER MEMORY. ; MVI A,0C3H ;PUT JMP TO WBOOT STA 0 ;ADR AT ZERO. LXI H,WBOOTE SHLD 1 STA 5 LXI H,BDOS ;PUT JUMP TO BDOS SHLD 6 ;AT ADR 5,6,7. LXI H,80H ;SET DEFAULT DMA ADR. SHLD DMAADD LDA CDISK ;GET DISK NUMBER TO MOV C,A ;PASS TO CCP IN C. JMP CPMB ;JUMP TO CCP. ; ; LISTING ROUTINE - REQUIRED TO HANDLE FORMFEED CHARACTERS ; LIST: LDA IOBYTE ;GET STATUS ANI 40H ;SEE IF IT IS TTY JNZ @LIST ;IF NOT, NO SPECIAL HANDLING MOV A,C ;GET CHARACTER TO BE LISTED CPI FF ;IS IT A FORM FEED? JZ FFEED ;YES, DO A FORM FEED CPI LF ;IS IT LINE FEED? JNZ @LIST ;NO, SO LIST IT LIST1: LDA COUNT ;GET LINES COUNT INR A ;UP THE COUNT CPI 66 ;MAX LINES PER PAGE JNZ $+4 ;NOT MAX, CONTINUE XRA A ;ZERO COUNT STA COUNT ;SAVE FOR NEXT TIME JMP @LIST ;NOW SEND LF ; FFEED: LDA COUNT ;GET COUNT ORA A ;SET FLAGS RZ ;ZERO,MUST BE AT TOP OF FORM ALREADY MVI C,LF ;GET LINE FEED TO SEND CALL LIST1 ;SEND TO PRINTER JMP FFEED ;KEEP SENDING LF'S TIL TOP OF FORM ; ; SELECT DISK NUMBER ACCORDING TO REGISTER C. ; SELDSK: LXI H,0 ;SET UP FOR ERROR CODE MOV A,C ;GET NEW DRIVE. CPI NDISK ;CALLING UNDEFINED DRIVE ? RNC ;IF NO CY, H,L TELLS CPM YES. STA CDISK ;WE ARE OK, SAVE NEW DISK NUMB. LXI H,DISKNO ;GET OLD DRIVE NUMBER. SELMOR: MOV A,M ;GET OLD DISK NUMBER. MOV E,A ;PUT OLD DISK NO. IN D&E. MVI D,0 LXI H,TRTAB ;GET ADDRESS OF TRACK TABLE. PUSH H ;SAVE ADDRESS OF TRTAB. DAD D ;ADD DISK NO. TO ADDRESS. IN TRACK ;READ 1771 TRACK REGISTER. MOV M,A ;PUT INTO TABLE. MOV A,C ;GET NEW DISK NUMBER. MOV E,A ;PUT NEW DISK NO. IN D&E. POP H ;RESTORE ADDRESS OF TRTAB. DAD D ;ADD DISK NO. TO ADDRESS. MOV A,M ;GET NEW TRACK NUMBER. OUT TRACK ;PUT INTO 1771 TRACK REG. SELD1: MOV A,C ;UPDATE OLD DISK NUMBER. STA DISKNO CMA ADD A ;PUT BITS 1&2 AT 4&5. ADD A ADD A ADD A ORI 2 STA LATCH ;SAVE NEW LATCH CODE. ; ;SELECT DRIVE AS A FUNCTION OF H,L ; PARINDX:LHLD DISKNO ;LOAD DISK NUMBER AND ZERO BYTE LXI D,DPBASE ;POINT TO DISK PARM START. DAD H ;*2 DAD H ; *4 DAD H ; *8 DAD H ; *16 DAD D ;COMPUTE INDEX FOR THE DRIVE XRA A ;SET A = 0. RET ;RETURN FROM SELDSK. ; ; MOVE DISK TO TRACK ZERO. ; HOME: MVI C,0 ;SEEK TO TRACK ZERO. MVI A,0D0H ;RESTORE COMMAND OUT DCOM ;TELL CONTROLLER. ; ; SET TRACK NUMBER TO WHATEVER IS IN REGISTER C. ; ALSO PERFORM MOVE TO THE CORRECT TRACK (SEEK). ; SETTRK: PUSH H ;SAVE H&L. LHLD LATCH ;GET NEW & OLD LATCH. MOV A,L ;GET NEW LATCH. OUT WAIT ;SELECT DRIVE NOW. STA CLATCH ;REMEMBER CURRENT LATCH. CMP H ;IS NEW SAME AS OLD? MVI A,0FFH ;IF NOT, SET FLAG = FF. JNZ SFLAG CMA ;IF NEW = OLD, FLAG = 0. SFLAG: STA HLSF ;SET HEAD-LOAD/SELECT FLAG. POP H ;RESTORE H&L. MOV A,C ;GET NEW TRACK NUMBER. STA TRK ;UPDATE OLD WITH NEW. ; ; MOVE THE HEAD TO THE TRACK IN REGISTER A. ; SEEK: PUSH B ;SAVE B&C. MOV B,A ;SAVE DESTINATION TRACK. MVI A,RTCNT ;GET RETRY COUNT. SRETRY: STA SERCNT ;STORE IN ERROR COUNTER. IN TRACK ;READ PRESENT TRACK NO. CMP B ;SAME AS NEW TRACK NO.? JNZ NOTHR ;JUMP IF NOT THERE. THERE: POP B ;RESTORE B&C. RET ;RETURN FROM SEEK. NOTHR: ;DELAY LOOP TO ALLOW TUNNEL ;ERASE TO END DURING WRITE. ; PUSH PSW ;SAVE ACCUM AND FLAGS MVI A,0D0H ;COUNT = 208 BUSY1: DCR A ;LOOP JNZ BUSY1 ; TILL = ZER0 POP PSW ;RESTORE ACCUM. MOV A,B ;RESTORE A FROM B. OUT DDATA ;TRACK TO DATA REGISTER. BUSY: IN DSTAT ;READ DISK STATUS. RRC ;LOOK AT BIT 0. JC BUSY ;WAIT TILL NOT BUSY. MVI A,14H+STPRAT+HLAB ;GET STEP RATE, DO OUT DCOM ;SEEK WITH VERIFY. IN WAIT ;WAIT FOR INTRQ. IN DSTAT ;READ STATUS. ANI 91H ;LOOK AT BITS. JZ THERE ;OK IF ZERO. LDA SERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ SRETRY ;RETRY SEEK. POP B ;RESTORE B&C. CALL RECOV ;IF SEEK RETRY = 10 CHECK JMP SEEK ; FOR CNTL-C FOR ABORT. ; ; SET DISK SECTOR NUMBER. ; SETSEC: MOV A,C ;GET SECTOR NUMBER. STA SECT ;PUT AT SECT # ADDRESS. RET ;RETURN FROM SETSEC. ; ;TRANSLATE THE SECTOR GIVEN B,C ;USING THE TRANSLATE TABLE ;GIVEN BY D,E ; SECTRAN: MOV L,C ;GET PHYSICAL SECTOR NUMBER INR L ;BUMP IT BY ONE. MOV A,D ;ARE WE USING NO XLAT TABLE? ORA E ;IT WILL BE ZERO IF NOT. RZ ;RETURN IF IT IS ZERO. XCHG ;H,L = TRANS DAD B ;H,L = TRANS (SECTOR) MOV L,M ;L = TRANS (SECTOR) MVI H,0 ;CLEAR REG H RET ;H,L = TRANSLATED SECTOR ; ; SET DISK DMA ADDRESS. ; SETDMA: MOV H,B ;MOVE B&C TO H&L. MOV L,C SHLD DMAADD ;PUT AT DMA ADR ADDRESS. RET ;RETURN FROM SETDMA. ; ; HDLD - GET HEAD-LOAD BIT IF REQUIRED. ; HDLD: LDA HLSF ;GET HEAD-LOAD FLAG. ORA A ;IS A = ZERO? JZ HDLD1 ;HOP IF SO. CMA ;SET A = 0. STA HLSF ;SET FLAG = 0 IF NOT. ; ;IF CHANGING TO A NEW DRIVE, PERFORM A SEEK TO ;THE SAME TRACK TO UNLOAD THE HEAD ON NEW DRIVE. ; IN TRACK ;GET PRESENT TRACK OUT DDATA ;TELL CONTROLLER. MVI A,14H+STPRAT+HLAB OUT DCOM IN WAIT ;WAIT FOR INTRQ. HDLDY: MVI A,4 ;SET BIT TO LOAD HEAD. RET ;RETURN FROM HDLD. HDLD1: IN DSTAT ;READ 1771 STATUS. ANI 20H ;LOOK AT HL BIT. JZ HDLDY ;LOAD IF NOT LOADED. XRA A ;OTHERWISE, A=0. RET ;RETURN FROM HDLD. ; READ A SECTOR WITHOUT LOADING HEAD FIRST. ; READ2: OUT SECTP ;SET SECTOR NUMBER INTO 1771. MVI A,88H ;GET CODE FOR READ W/O HLD. JMP READE ;READ A SECTOR. ; ; READ THE SECTOR AT SECT, FROM THE PRESENT TRACK. ; USE STARTING ADDRESS AT DMAADD. ; READ: MVI A,RTCNT ;GET RETRY COUNT. RRETRY: STA ERCNT ;STOR IN ERROR CTR. LDA SECT ;GET SECTOR NUMBER. LHLD DMAADD ;GET STARTING ADR. READ1: OUT SECTP ;SET SECTOR INTO 1771. MVI A,8CH ;CODE FOR READ W/O HD LD. READE: OUT DCOM ;SEND COMMAND TO 1771. RLOOP: IN WAIT ;WAIT FOR DRQ OR INTRQ. ORA A ;SET FLAGS. JP RDDONE ;DONE IF INTRQ. IN DDATA ;READ A DATA BYTE FROM DISK. MOV M,A ;PUT BYTE INTO MEMORY. INX H ;INCREMENT MEMORY POINTER. JMP RLOOP ;KEEP READING. RDDONE: IN DSTAT ;READ DISK STATUS. ANI 9DH ;LOOK AT ERROR BITS. RZ ;RETURN IF NONE. CALL ERCHK ;CHECK FOR SEEK ERROR. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ RRETRY ;TRY TO READ AGAIN. CALL RECOV ;CHECK FOR ABORT OR CONTINUE JMP READ ;IF NOT CNTL-C, TRY TO READ AGAIN. ; ;RECOV ;THIS ROUTINE IS CALLED BY ANY READ,WRITE,SEEK ;ROUTINE IF THE RETRY COUNT GOES TO 10. IF IT ;DOES,THIS ROUTINE CALLS CONIN FOR A KEY TO BE ;PUSHED. IF THE KEY IS A CNTL-C, THEN A WARMBOOT ;IS EXECUTED. IF ANY OTHER KEY IS PUSHED, THEN ;A RETURN IS MADE BACK TO THE CALLER AND THAT ;ROUTINE IS RETRIED FOR 10 MORE TIMES. ; RECOV: MVI C,'e' ;ERROR CODE CALL @CONOT ;PRINT IT CALL @CONIN ;CHECK FOR PUSHED KEY. CPI 03H ;IS IT A CNTL-C ? RNZ ;RETURN TO CALLER IF NOT. JMP WBOOT ;YES, DO WARMBOOT. ; ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR. ; ERCHK: MOV D,A ;SAVE ERROR BITS ON STACK. ANI 10H ;IF RECORD NOT FOUND, JNZ CHKSK ;DO A CHECK ON SEEK. CHKOK: MOV A,D ;RESTORE ERROR BITS. ORA A ;SET FLAGS, RET ;AND RETURN. ;CHECK FOR SEEK TO CORRECT TRACK, ;AND CHANGE IF NECESSARY. CHKSK: MVI A,0C4H ;SEND COMMAND TO 1771 OUT DCOM ;TO READ ADDRESS. IN WAIT ;WAIT FOR DRQ OR INTRQ. IN DDATA ;READ THE TRACK ADDRESS. MOV B,A ;SAVE IN REGISTER B. CHKS2: IN WAIT ;WAIT FOR INTRQ. JM CHKS2 ;NOT IF DRQ. MOV A,B ;UPDATE TRACK REGISTER. OUT TRACK LDA TRK ;GET REQUIRED TRACK NO. CALL SEEK ;MOVE THE HEAD TO IT. JMP CHKOK ;EXIT FROM ERROR CHECK. DSKSET: STA ERCNT ;STORE IN ERROR CTR. MVI A,0D0H ;CAUSE INTERRUPT. OUT DCOM XTHL ;SOME XTHL ; DELAY LHLD DMAADD ;GET STARTING ADDR. LDA SECT ;GET SECTOR NUMBER. OUT SECTP ;SET SECTOR INTO 1771. CALL HDLD ;GET HEAD-LOAD BIT? RET ;RETURN TO CALLER ; ; WRITE THE SECTOR AT SECT, ON THE PRESENT TRACK. ; USE STARTING ADDRESS AT DMAADD. ; WRITE: MVI A,RTCNT ;GET RETRY COUNT. WRETRY: STA ERCNT ;STORE IN ERROR COUNTER. LDA SECT ;GET SECTOR NUMBER. LHLD DMAADD ;GET STARTING ADR. WRITE1: OUT SECTP ;SET THE SECTOR INTO 1771. MVI A,0ACH ;SET UP 1771 FOR WRITE. OUT DCOM WLOOP: IN WAIT ;WAIT FOR READY. ORA A ;SET FLAGS. JP WDONE ;HOP OUT WHEN DONE. MOV A,M ;GET BYTE FROM MEM. OUT DDATA ;WRITE ONTO DISK. INX H ;INCREMENT MEM PTR. JMP WLOOP ;KEEP WRITING. WDONE: IN DSTAT ;READ DISK STATUS. ANI 0FDH ;LOOK AT THESE BITS. RZ ;RETURN IF NO ERR. CALL ERCHK ;CHECK/CORRECT SEEK ERR. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ WRETRY ;TRY TO WRITE AGAIN. CALL RECOV ;CHECK FOR ABORT JMP WRITE ;RETRY WRITE AGAIN. ;NOTE: AS THERE ARE ONLY SIX (6) SECTORS ;AVAILABLE FOR CBIOS ON THE SECOND SYSTEM TRACK (1), ;THE LAST ADDRESS BEFORE THIS POINT SHOULD BE NO ;GREATER THAN THE CBIOS STARTING ADDRESS + 037F (HEX). ;THIS WILL NORMALLY BE XD7F (HEX). ; ; BIOS SCRATCH AREA. ; TRK: DS 1 ;CURRENT TRACK NUMBER. SECT: DS 1 ;CURRENT SECTOR NUMBER. DMAADD: DS 2 ;DISK TRANSFER ADDRESS. ; ; THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND ; ENDZ, ARE SET TO ZERO AT COLD BOOT TIME. ; STARTZ: ;START OF ZEROED AREA. DISKNO: DS 2 ;DISK NUMBER ; SPECIAL FLAGS. HLSF: DS 1 ;HEAD-LOAD SELECT FLAG. LFCNT: DS 1 ;PAGING LINE-FEED COUNT. ; ; TRTAB - DISK TRACK TABLE - PRESENT POSITION OF ; HEADS FOR UP TO 4 DRIVES. ; TRTAB: DS 4 COUNT: DS 1 ;LINE COUNT ENDZ: ;END OF ZEROED AREA. ERCNT: DS 1 ;ERROR COUNT FOR RETRIES. SERCNT: DS 1 ;SEEK RETRY COUNTER. TEMP: DS 1 ;TEMPORARY STORAGE. LATCH: DS 1 ;NEW CODE FOR LATCH. CLATCH: DS 1 ;CURRENT CODE IN LATCH. BEGDAT EQU $ DIRBUF: DS 128 ;DIRECTORY BUFFER ALV0: DS 31 CSV0: DS 24 ALV1: DS 31 CSV1: DS 24 ALV2: DS 31 CSV2: DS 24 ALV3: DS 31 CSV3: DS 24 ENDDAT EQU $ DATSIZ EQU $-BEGDAT ;TOTAL SIZE OF DISK PARM STORAGE. END