; ; CBIOS (CUSTOM BASIC INPUT OUTPUT SYSTEM) MODULE FOR USE ; WITH CP/M AND A TARBELL/WD1771 DISK CONTROLLER ; USING PERSCI VOICE-COIL POSITIONER DISKETTE DRIVES ; IN A P.T. SOL-20 COMPUTER ; ; BY BARRY A. WATZMAN 8/4/78 ; ; ;MEMORY SIZE ; MEMT EQU 0C000H ;MEMORY SIZE = 48K ;WHERE TO ENTER CP/M AFTER WARM OR COLD BOOT CPMB EQU MEMT-1B00H ;SIZE OF CP/M MODULES CCPSIZ EQU 8*256 ;8 FOR 1.4; 9 FOR 1.3 BDOSIZ EQU 13*256 ;13 FOR 1.4; 12 FOR 1.3 ;BDOS INITIALIZATION ENTRY BDOS EQU CPMB+CCPSIZ+6 ;BIOS BASE BIOS EQU CPMB+CCPSIZ+BDOSIZ ;I/O BYTE IN LOWER RAM IOBYT EQU 3 ;WHERE CPM PUTS LOGGED IN DISK LOGDSK EQU 4 ;NO OF SECTORS TO READ FROM DISK ON WARM BOOT NSECTS EQU 51 ;READ IN ENTIRE SYSTEM ;NO OF RETRY'S ON ERROR RTCNT EQU 10 ;I/O PORT EQUATES DISK EQU 0E8H ;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 DCONT EQU DISK+4 ;DISK CONTROL PORT TTY EQU 0F9H TTYS EQU 0F8H KEY EQU 0FCH KEYS EQU 0FAH VDM1 EQU 0CC00H VDMPT EQU 0FEH ;VDM-1 I/O PORT ORG BIOS ; ; ENTRY POINT TABLE ; JMP BOOT ;FROM COLD START LOADER JMP WBOOT ;FROM WARM BOOT JMP CONST ;CHECK CONSOLE STAT JMP CONIN ;READ CONSOLE CHAR JMP CONOUT ;WRITE CONSOLE CHAR JMP LIST ;WRITE LISTING CHAR JMP PUNCH ;WRITE PUNCH CHAR JMP READER ;READ CHAR FROM READER JMP HOME ;MOVE DISK TO TRACK ZERO JMP SETDSK ;SELECT DISK DRIVE JMP SETTRK ;SEEK TO TRACK IN REG A JMP SETSEC ;SET SECTOR NO. JMP SETDMA ;SET STARTING ADDR FOR R/W JMP READ ;READ SELECTED SECTOR JMP WRITE ;WRITE SELECTED SECTOR ; ; BOOT - EXECUTED FOR COLD START ; BOOT: IN 0FFH ;READ SENSE SWITCHES ORA A ;ALL ZEROS ? JNZ SETIOB ;IF NOT, USE THEM AS I/O BYTE MVI A,95H ;ELSE USE 95H SETIOB: STA IOBYT ;SET I/O BYTE LXI H,SMSG ;PRINT SIGN-ON MSG CALL PMSG STA LOGDSK ;ZERO WAS LEFT FROM PMSG GOCPM: MVI A,0C3H ;PUT JMP TO WBOOT LXI H,BIOS+3 STA 0 ;AT ZERO SHLD 1 LXI H,BDOS ;PUT JUMP TO BDOS STA 5 SHLD 6 ;AT ADDR 5,6,7 LXI H,NXM STA 038H SHLD 038H+1 LXI H,80H ;SET DEFAULT DMA ADR SHLD DMAADD LDA LOGDSK ;GET DISK NO TO STA DISKNO MOV C,A ;PASS TO CCP IN C JMP CPMB ;JUMP TO CCP. ; ; WARM-BOOT: READ ALL OF CPM BACK IN ; EXCEPT BIOS, THEN JUMP TO CCP. ; WBOOT: LXI SP,MEMT ;SET STACK POINTER MVI A,0 ;THIS BIOS ALWAYS BOOTS OFF 0 STA DISKNO ;SELECT A: DISK CALL SELDSK ;SELECT DRIVE 0 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 ;GO TO TRACK IN B STA TRK CALL SEEK ;SEEK TO TRACK MOV A,C ;READ STARTING AT SECTOR IN C CALL READ1 RBLK1: JNZ BOOTER ;IF ERROR, PRINT MESSAGE DCR D ;DCR SECTOR COUNT JZ GOCPM 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 RBLK2: OUT SECTP ;SET SECTOR NO INTO 1771 MVI A,88H ;CODE FOR READ W/O HEAD LOAD CALL READE ;READ A SECTOR JMP RBLK1 ; BOOTER: LXI H,BTMSG ;GET ADDRESS OF "BOOT ERROR" CALL PMSG ;PRINT IT CALL CONIN ;WAIT FOR CHAR TO TRY AGAIN JMP WBOOT ;DO A WARM BOOT ; ;HOME - SEEK HEAD TO TRACK 0 ; HOME: MVI C,0 ;TRACK 0 ; ;SETTRK ROUTINE TO SET A TRACK ADDRESS ; SETTRK: MOV A,C ;GET TRACK TO A STA TRK ; RET ;DONE ; ;SETDSK - ROUTINE TO SELECT A DISK DRIVE ; SETDSK: MOV A,C ;GET DISK STA DISKNO ;SAVE IT RET ;DONE ; ; SET DISK SECTOR NUMBER. ; SETSEC: MOV A,C ;GET SECTOR NO STA SECT ;PUT AT SECT # ADDR RET ;DONE ; ; SET DISK DMA ADDRESS. ; SETDMA: MOV H,B ;MOVE B,C TO H,L MOV L,C SHLD DMAADD ;PUT AT DMA ADDR RET ;DONE ; ; READ THE SECTOR AT SECT, FROM THE PRESENT TRACK. ; USE STARTING ADDRESS AT DMAADD. ; READ: MVI A,RTCNT ;GET RETRY COUNT RRETRY: STA ERCNT ;STORE IN ERR CTR CALL SELDSK ;SELECT PROPER DISK CALL SEEK ;SEEK TO TRACK LHLD DMAADD ;GET START ADDR MVI A,0D0H ;CAUSE INTERRUPT TO 1771 OUT DCOM XTHL ;SOME DELAY XTHL ;MORE IN DSTAT ;READ STATUS ANI 20H ;LOOK AT HD LOAD BIT LDA SECT ;GET SECTOR NO READ1: OUT SECTP ;SET SECTOR INTO 1771 MVI A,8CH ;READ WITH HEAD LOAD JZ READE ;HEAD NOT LOADED MVI A,88H ;CODE FOR READ W/O HD LD READE: OUT DCOM ;SENT COMMAND TO 1771 RLOOP: IN WAIT ;WAIT FOR DRQ OR INTRQ ORA A ;SET FLAGS JP RDDONE ;DONE IF INTRQ IN DDATA ;READ A BYTE FM DISK MOV M,A ;PUT IT INTO MEMORY INX H ;INR MEMORY POINTER JMP RLOOP ;KEEP ON READING RDDONE: IN DSTAT ;READ DISK STATUS ANI 9DH ;LOOK AT ERROR BITS RZ ;RET IF NONE CALL ERCHK ;CHECK FOR SEEK ERROR LXI H,RECNT ;GET RD ERR COUNT ADDR INR M ;ONE MORE ERROR LDA ERCNT ;GET ERROR COUNT DCR A ;DCR COUNT JNZ RRETRY ;TRY AGAIN LXI H,RDMSG ;PRINT "READ " ERMSG: CALL PMSG ;PRINT ORIGIN MESSAGE ERMSG1: MOV A,D ;GET ERROR BITS ANI 80H ;IF BIT 7 HIGH LXI H,NRMSG ;"NOT READY" CNZ PMSG MOV A,D ;GET ERROR BITS ANI 10H ;IF BIT 4 HIGH LXI H,RNMSG ;PRINT "RECORD NOT FOUND" CNZ PMSG MOV A,D ;GET ERROR BITS ANI 08H ;IF BIT 3 HIGH LXI H,CRCMSG ;PRINT "CRC ERROR" CNZ PMSG MOV A,D ;GET ERROR BITS ANI 04H ;IF BIT 2 HIGH LXI H,LDMSG ;PRINT "LOST DATA" CNZ PMSG MOV A,D ;GET ERROR BITS ANI 1 ;IF BIT 1 IS HIGH LXI H,BSYMSG ;PRINT "BUSY" CNZ PMSG LXI H,ERRMSG ;PRINT "ERROR" CALL PMSG MVI A,1 ;SET FOR PERM ERR MSG ORA A ;SET FLAGS RET ; ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR. ; ERCHK: MOV D,A ;SAVE ERROR BITS IN D ANI 10H ;IF RCD NOT FOUND JNZ CHKSK ;THEN DOUBLE CHECK SEEK MOV A,D ;OTHERWISE RESTORE BITS ORA A ;SET RET CODE 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 ADDR MOV B,A ;SAVE IN REG B CHKS2: IN WAIT ;WAIT FOR INTRQ ORA A ;SET FLAGS JP CHKS3 ;DONE WITH READ ADDR OP IN DDATA ;READ ANOTHER BYTE JMP CHKS2 ;DO IT AGAIN CHKS3: IN DSTAT ;READ DISK STATUS ORA A ;SET FLAGS JZ CHKS4 ;READ ADDR OK IF 0 MVI A,0B2H ;RESTORE A: DRIVE OUT DCONT ;DO IT (RESTORES BOTH) MVI A,3 ;1771 HOME COMAND OUT DCOM ;ISSUE IT (RESTORES 1771) IN WAIT ;WAIT TILL COMPLETE CALL SELDSK ;SELECT CURRENT DISK JMP CHKS5 CHKS4: MOV A,B ;UPDATE TRACK REGISTER OUT TRACK CHKS5: CALL SEEK ;MOVE HEAD TO IT MOV A,D ;GET ERROR BITS ORA A ;SET FLAGS RET ;RETURN FROM ERCHK ; ; SELECT DISK NUMBER ACCORDING TO REGISTER C. ; SELDSK: LDA DISKNO ;GET DISK NUMBER CMA ;BITS INVERTED INTO LATCH ADD A ;PUT BITS 1 & 2 AT 4 & 5 ADD A ADD A ADD A ORI 2 ;MAKE LATCH COMMAND DSK1: OUT DCONT ;SET THE LATCH WITH CODE XRA A ;SET A = 0 RET ;RET FROM SELDSK ; ; 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 CALL SELDSK ;SELECT DISK CALL SEEK ;SEEK TO TRACK LHLD DMAADD ;GET STARTING ADDR MVI A,0D0H ;STAT INTERUPT FOR 1771 OUT DCOM ;COMMAND 1771 XTHL ;A SMALL DELAY XTHL ;MORE IN DSTAT ;GET 1771 STAT ANI 20H ;CHECK FOR HEAD LOAD LDA SECT ;GET SECTOR NO OUT SECTP ;SET THE SECTOR INTO 1771 MVI A,0ACH ;SET UP FOR WRITE JZ WRITE2 ;HEAD IS NOT LOADED MVI A,0A8H ;CODE FOR WRITE W/O HD LD WRITE2: 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 TO DISK INX H ;INR MEM PTR JMP WLOOP ;KEEP WRITING WDONE: IN DSTAT ;READ DISK STATUS ANI 0FDH ;LOOK AT THESE BITS RZ ;RET IF NO ERROR CALL ERCHK ;CHECK CORRECT SEEK LXI H,WECNT ;GET ADR OF WRITE ERR CTR INR M ;ONE MORE WRITE ERROR LDA ERCNT ;GET ERROR COUNT DCR A ;DCR COUNT JNZ WRETRY ;TRY TO WRITE AGAIN LXI H,WTMSG ;PRINT "WRITE " CALL PMSG MOV A,D ;GET ERROR BITS ANI 40H ;LOOK AT BIT 6 LXI H,WPMSG ;PRINT "PROTECT " CNZ PMSG MOV A,D ;GET ERROR BITS ANI 20H ;LOOK AT BIT 5 LXI H,WFMSG ;PRINT "FAULT " CNZ PMSG JMP ERMSG1 ;DO COMMON MESSAGES ; ; MOVE THE HEAD TO THE TRACK IN REGISTER A. ; SEEK: PUSH B ;SAVE B,C LDA TRK ;GET TRACK TO SEEK TO MOV B,A ;SAVE DEST TRACK MVI A,RTCNT ;GET RETRY COUNT SRETRY: STA SERCNT ;STORE IN ERR COUNTER IN TRACK ;READ PRESENT TRACK NO MOV C,A ;SAVE IN C CMP B ;SAME AS NEW TRACK NO. ? JZ THERE ;JUMP IF NOT THERE MVI A,40H ;IF CARRY = 1 JC SDIR ;STEP IN MVI A,60H ;OTHERWISE OUT SDIR: OUT DCOM ;ISSUE STEP DIR MVI A,20 ;DELAY LOOP COUNT DLOOP: DCR A ;DCR COUNTER JNZ DLOOP MOV A,C ;GET PRESENT TRK SUB B ;FIGURE TRACKS TO STEP JP STEP ;IF NEG, CMA ;FIGURE THE INR A ;TWO'S COMPL STEP: MOV C,A ;GET DIFFERENCE MVI A,1 ;PERSCI STEP COMMAND STEP1: OUT DCONT ;STEP PERSCI (E-14) DCR C ;COUNT THE STEP JNZ STEP1 ;STEP UNTIL C = 0 IN WAIT ;CLEAR 1771 IN DSTAT MOV A,B ;GET DEST TRACK OUT TRACK ;UPDATE TRACK REG LDA DISKNO ;GET DISK NO RLC ;SHIFT LEFT 4 BITS RLC RLC RLC ANI 10H ;LOOK AT BIT 4 CMA ;INVERT MOV B,A ;SAVE IN B ANI 72H ;MAKE COMMAND TO OUT DCONT ;SWITCH WAIT FOR IN WAIT ;SEEK COMPLETE MOV A,B ;RESTORE ORIG BITS ANI 0F2H ;SWITCH WAIT BACK OUT DCONT XRA A ;MAKE GOOD RET THERE: POP B ;RESTORE B,C RET ; ;********************************************** ; ; LOGICAL DEVICE ROUTINES ; ; IMPLEMENTATION OF IOBYTE AS ; DESCRIBED IN CPM ALTERATION GUIDE ; ; CONSOLE STATUS ; CONST: CALL CONS ;GET STAT OF SPECIFIC DEVICE ORA A RZ ;IF NOT READY RETURN 0 IN A MVI A,0FFH ;ELSE RETURN FF RET ; CONS: LDA IOBYT ;USE BITS 1-0 FOR CON DEV. CALL INDXIT DW TTYSTAT DW KEYSTAT DW RDRST ;2: BATCH MODE, USE READER DEV. DW RDRST ; ;READER STATUS FOR BATCH MODE ; RDRST: LDA IOBYT RRC CALL GOTOIT DW TTYIN DW RDRIN DW KEYIN DW CUTSIN ; ; CONSOLE IN ; CONIN: LDA IOBYT CALL INDXIT DW TTYIN ;0: TTY DW KEYIN ;1; CRT DW READER ;2: BATCH MODE: READER INPUT DW READER ; ; CONSOLE OUT ; CONOUT: MOV A,C ;GET CHAR CPI 7FH ;DEL ? RZ ;RETURN IF SO LDA LASTIN ;GET LAST CHAR INPUT CPI 7FH ;WAS IT A DELETE ? JNZ NORM ;NORMAL PROCESSING IF NOT MVI C,08H ;ASCII BACKSPACE CALL NORM ;SEND IT OUT MVI C,' ' ;GET A SPACE CALL NORM ;SEND IT OUT MVI C,08H ;ANOTHER BACKSPACE NORM: LDA IOBYT CALL INDXIT ;GO TO ONE OF FOLLOWING ADDRS DW TTYOUT ;BITS=0: USE TTY AS CONSOLE DW CRTOUT ;1: CRT DW LIST ;2: BATCH MODE: OUTPUT TO LST: DW PUNCH ; ; LIST OUT ; LIST: LDA IOBYT RLC ;BITS 7-6 TO 2-1 RLC CALL INDXIT DW TTYOUT ;0: TTY DW CRTOUT ;1: CRT DW LPTOUT ;2; LINE PRINTER DW PUNCH ; ; PUNCH OUT ; PUNCH: LDA IOBYT ;BITS 4-5 TO 1-2 RRC RRC RRC CALL GOTOIT DW TTYOUT ;0: TTY DW PUNO ;1: HIGH SPEED PUNCH DW CRTOUT ;2: CRT DW CUTSOT ; ; READER IN ; READER: LDA IOBYT ;BITS 3-2 TO 2-1 RRC CALL GOTOIT DW TTYIN ;0: TTY DW RDRIN ;1: HIGH SPEED READER DW KEYIN ;2: CRT DW CUTSIN ; ;SUBROUTINE TO DISPATCH TO ONE OF 4 FOLLOWING ADDRESSES ;DEPENDING ON IOBYT BITS CALLER HAS POSITIONED IN ;BITS 2 AND 1 OF A. ;RETURNS TO SUBROUTINE CALL PRIOR TO CALL TO GOTOIT. ; INDXIT: RLC GOTOIT: ANI 06H ;MASK BITS XTHL ;SAVE CALLER'S H, GET TABLE ADDR PUSH D ; MOV E,A MVI D,0 ;SET UP FOR DAD DAD D ;INDEX INTO TABLE MOV A,M INX H MOV H,M ;TABLE WORD TO HL MOV L,A ; POP D ; XTHL ;PUT ADDRESS OF ROUTINE, GET CALLER'S H RET ;GO TO ROUTINE ! ; ;***************************************************** ; ; PHYSICAL DEVICE ROUTINES ; ; ACCESSED VIA LOGICAL DEVICE ROUTINES ABOVE ; ; TELETYPE INPUT ; TTYIN: CALL TTYSTAT JZ TTYIN ;WAIT FOR CHAR TO BE AVAILABLE IN TTY ;INPUT IT ANI 7FH ;REMOVE PARITY STA LASTIN RET ; TTYSTAT:IN TTYS ;GET STATUS ANI 40H ;MASK BIT RET ;A IS NON-0 IF CHAR AVAILABLE ; ; TELETYPE OUTPUT ; TTYOUT: IN TTYS ;STATUS ANI 80H JZ TTYOUT ;WAIT TILL READY TO ACCEPT CHAR MOV A,C OUT TTY ;OUTPUT THE CHAR RET ;DONE EXCEPT CR ; ; KEYBOARD INPUT ; KEYIN: CALL KEYSTAT JZ KEYIN IN KEY PUSH B ;SAVE B,C (NOT REALLY NEC) PUSH H ;SAME LXI H,TABLE ;POINT TO TRANSLATE TABLE MOV C,A ;SAVE CHAR IN C TT1: MOV A,M ;GET CHAR FROM TABLE INX H ;POINT TO IT'S VALUE CMP C ;CHAR SAME AS INPUT ? JZ TT3 ;YES - SUBSTITUTE ORA A ;NO - SEE IF END OF TABLE INX H ;POINT TO NEXT TABLE ENTRY JNZ TT1 ;TEST IT IF NOT TABLE END MOV A,C ;END, NO MATCH, RESTORE CHAR TT2: POP H ;RESTORE REGS POP B ; STA LASTIN ;UPDATE LAST CHAR INPUT RET ;DONE TT3: MOV A,M ;MATCH, SUBSTITUTE JMP TT2 ;RETURN WITH IT ; ;TRANSLATE TABLE FOR THE ELECTRIC PENCIL & OTHERS ; TABLE: DB 0B0H ;LEFT DB 'A'-40H DB 0AEH ;RIGHT DB 'S'-40H DB 0B2H ;DOWN DB 'Z'-40H DB 0ABH ;ROLL DOWN DB 'X'-40H DB 0B1H ;UP DB 'W'-40H DB 0B3H ;ROLL UP DB 'E'-40H DB 0AAH ;INSERT DB 'F'-40H DB 0ADH ;DELT DB 'D'-40H DB 0B6H ;ERASE TO END OF LINE DB 'T'-40H DB 08EH ;HOME KEY DB 'N'-40H DB 0B7H ;DELETE LINE DB 'Y'-40H DB 0B8H ;INSERT LINE DB 'G'-40H DB 08CH ;FORM FEED DB 'L'-40H DB 081H ;LOAD/SAVE DB ']'-40H DB 093H ;PRINT DB 'P'-40H DB 08BH ;CLEAR SCREEN DB 'K'-40H DB 0B9H ;ERASE INPUT DB '\'-40H DB 0AFH ;NEWLINE CURSOR ONLY DB 'J'-40H DB 097H ;RESET DB '['-40H DB 09AH ;ENTER DB 'Q'-40H DB 0B4H ;NEXT PAGE DB '^'-40H DB 0B5H ;PREV PAGE DB 1FH DB 0 ; KEYSTAT:IN KEYS CMA ANI 01H RET ; ; CRT OUTPUT ; CRTOUT: LDA LSTOUT ;GET LAST OUTPUT CHAR CPI 0DH ;WAS IT C/R ? JNZ CRTOT1 ;NO, DO OUTPUT CMP C ;IS THIS CHAR C/R ALSO ? RZ ;DON'T SEND TWO IN A ROW CRTOT1: MOV A,C ;CHAR TO A STA LSTOUT ;SAVE AS LAST CHAR OUTPUT MVI A,0 ;USE VDM-1 MOV B,C ;GET CHAR TO B JMP 0C01CH ;SOLOS'S AOUT ENTRY POINT ; ; LINE PRINTER OUT ; LPTOUT: IN 0FDH ;PARALLEL DATA PORT ANI 1 ;TEST BUSY BIT JNZ LPTOUT ;LOOP TILL NOT BUSY MOV A,C ;GET CHAR OUT 1 ;WRITE IT RET ;DONE ; ; CUTS TAPE INPUT ; CUTSIN: RET ; ; CUTS TAPE OUTPUT ; CUTSOT: RET ; ; HEATHKIT PUNCH OUTPUT ; PUNO: RET ; ; HEATHKIT PUNCH IN ; RDRIN: RET ; ; ; PRINT THE MESSAGE AT H&L UNTIL A ZERO. ; PMSG: MOV A,M ;GET A CHAR ORA A ;IF IT'S A ZERO RZ ;RET MOV C,A ;OTHERWISE CALL CONOUT ;PRINT IT INX H ;INR H,L JMP PMSG ;AND GET ANOTHER ; ;NXM ROUTINE FOR SYSTEM CRASHES ; NXM: POP B ;B HAS PC OF CRASH (MAYBE) LXI SP,MEMT ;RESET STACK PUSH B ;SAVE PC LXI H,NXMMSG ;"CRASH" MESSAGE CALL PMSG ;PRINT IT POP H ;GET BACK PC OF CRASH MOV A,H ;GET HIGH BYTE CALL HOUT ;PRINT IT IN ASCII MOV A,L ;LOW BYTE CALL HOUT ;L, TOO MVI C,' ' ;PUT OUT A SPACE CALL CONOUT ; DCX H ;GET ADDR OF RST 7 INST MOV A,M ;GET IT (USUALLY 0FFH) CALL HOUT ;PRINT IT JMP WBOOT ;REBOOT THE SYSTEM ; ;HEX OUTPUT ROUTINE FOR ABOVE ; HOUT: PUSH PSW ;SAVE RRC RRC RRC RRC CALL NIBBLE POP PSW NIBBLE: ANI 0FH CPI 10 JM NIBBL1 ADI 7 NIBBL1: ADI '0' MOV C,A JMP CONOUT ; ; CBIOS MESSAGES ; NRMSG: DB 'NOT READY ',0 RNMSG: DB 'RECORD NOT FOUND ',0 CRCMSG: DB 'CRC ',0 LDMSG: DB 'LOST DATA ',0 BSYMSG: DB 'BUSY ',0 WPMSG: DB 'PROTECT ',0 WFMSG: DB 'FAULT ',0 ERRMSG: DB 'ERROR',0DH,0AH,0 RDMSG: DB 0DH,0AH,'READ ',0 WTMSG: DB 0DH,0AH,'WRITE ',0 BTMSG: DB 0DH,0AH,'BOOT ERROR',0DH,0AH,0 SKMSG: DB 0DH,0AH,'SEEK ',0 SMSG: DB 0DH,0AH,'48K CP/M RELEASE 1.4.0',0AH,0DH,0H NXMMSG: DB 0DH,0AH,'"CRASH" ',0 ; ; ERROR COUNTS. THESE LOCATIONS KEEP TRACK OF THE ; NUMBER OF ERRRS THAT OCCUR DURING READ OR WRITE ; OPERATIONS. THEY ARE INITIALIZED ONLY ; WHEN A COLD-START IS PERFORMED BY THE BOOOTSTRAP. ; RECNT: DB 0 ;READ ERROR COUNT WECNT: DB 0 ;WRITE ERROR COUNT. ; ;NOTE: AS THERE ARE ONLY 9 SECTORS AVAILABLE FOR THE ;CBIOS ON THE 2ND TRACK, THE LAST ADDRESS ;BEFORE THIS POINT SHOULD BE NO HIGHER THAN CBIOS + 047FH. ;THIS WILL NORMALLY BE XE7F (HEX). ; LASTIN: DS 1 ;LAST CHAR INPUT FROM CONSOLE LSTOUT: DS 1 ;LAST CHAR OUTPUT TO VDM-1 ERCNT: DS 1 ;ERROR COUNT FOR RETRIES. SERCNT: DS 1 ;SEEK RETRY COUNTER. TRK: DS 1 ;CURRENTLY SELECTED TRACK. SECT: DS 1 ;CURRENTLY SELECTED SECTOR. DISKNO: DS 1 ;CURRENT DISK NO. DMAADD: DS 2 ;CURRENT READ/WRITE ADDRESS. END