home *** CD-ROM | disk | FTP | other *** search
- ; BASIC INPUT/OUTPUT OPERATING SYSTEM
- ; TARBELL ELECTRONICS
- ; 4-DRIVE VERSION OF 2-15-78
- ; (NOTE THAT CP/M VERSION 1.3 ONLY SUPPORTS 2 DRIVES,
- ; WHILE CP/M VERSION 1.4 WILL SUPPORT 4 DRIVES.)
- ;
- ; THIS MODULE CONTAINS ALL THE INPUT/OUTPUT
- ; ROUTINES FOR THE CP/M SYSTEM, INCLUDING
- ; THE DISK ROUTINES.
- ;
- MSIZE EQU 24 ;MEMORY SIZE.
-
- ; 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.
-
- INTRP EQU FALSE ;TRUE IF INTERRUPTS ALLOWED.
-
- STD EQU TRUE ;TRUE IF STANDARD I/O.
- MSIO2 EQU FALSE ;TRUE IF MITS 2SIO.
- ISIO2 EQU FALSE ;TRUE IF IMSAI SIO-2.
- TUART EQU FALSE ;TRUE IF CROMEMCO TUART.
- VDM EQU FALSE ;TRUE IF PROC TECH VDM.
- SIO2 EQU MSIO2 OR ISIO2 OR TUART
- OTHER EQU FALSE ;TRUE IF SOMETHING ELSE.
-
- CSTAT EQU 0 ;CONSOLE STATUS PORT.
- CCOM EQU 0 ;CONSOLE COMMAND PORT.
- CDATA EQU 1 ;CONSOLE DATA PORT.
-
- IF STD ;IF STANDARD I/O,
- CKBR EQU 00000001B ;KEYBOARD READY BIT.
- CPTR EQU 10000000B ;CONS OUTPUT RDY BIT.
- ENDIF
-
- IF MSIO2 ;IF MITS 2SIO,
- CKBR EQU 00000001B ;KEYBOARD READY BIT.
- CPTR EQU 00000010B ;PRINT READY BIT.
- ENDIF
-
- IF ISIO2 ;IF IMSAI SIO-2,
- CKBR EQU 00000010B ;KEYBOARD READY BIT.
- CPTR EQU 00000001B ;PRINT READY BIT.
- ENDIF
-
- IF TUART ;IF CROMEMCO TUART,
- CKBR EQU 01000000B ;KEYBOARD READY BIT.
- CPTR EQU 10000000B ;PRINT READY BIT.
- ENDIF
-
- IF OTHER ;IF SOMETHING ELSE,
- CKBR EQU 00000010B ;KEYBOARD READY BIT.
- CPTR EQU 10000000B ;PRINTER READY BIT.
- ENDIF
-
- CNULL EQU 1 ;CONSOLE NULL COUNT.
-
- LSTAT EQU 2 ;LIST STATUS PORT.
- LCOM EQU 2 ;LIST COMMAND PORT.
- LDATA EQU 3 ;LIST DATA PORT.
- LRBIT EQU CPTR ;LIST READY BIT.
- LNULL EQU 2 ;LIST NULL COUNT.
-
- DUAL EQU TRUE ;TRUE IF DUAL DRIVE.
- FAST EQU TRUE ;TRUE IF FAST SEEK.
-
- 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.
- DCONT EQU DISK+4 ;DISK CONTROL PORT.
-
- RTCNT EQU 10 ;RETRY COUNT.
-
- ORG MSIZE*1024-1536 ;FIRST ADDRESS.
-
- CBASE EQU (MSIZE-17)*1024 ;BIAS FOR LARGER THAN 17K.
- CPMB EQU CBASE+2900H ;START OF CPM.
- BDOS EQU CBASE+3106H ;START OF BDOS.
- CPML EQU $-CPMB ;LENGTH OF CPM SYSTEM-BIOS.
- NSECTS EQU CPML/128 ;NUMBER OF SECTORS IN IT.
- ;
- ; 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.
- ;
- JMP BOOT ;FROM COLD START LOADER.
- 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.
- READN: JMP READ ;READ SELECTED SECTOR.
- WRITEN: JMP WRITE ;WRITE SELECTED SECTOR.
- ; THESE ENTRY POINTS ADDED BY TARBELL ELECTRONICS.
- JMP READN ;READ WITH NO HEAD LOAD.
- JMP WRITEN ;WRITE WITH NO HEAD LOAD.
- ;
- ; 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.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- EI ;ENABLE THEM HERE.
- ENDIF
-
- IF VDM ;IF PROC TECH VDM,
- CALL CLR ;CLEAR VDM SCREEN.
- ENDIF
-
- IF STD ;IF STANDARD I/O,
- NOP!NOP!NOP!NOP ;LEAVE SPACE FOR INIT.
- NOP!NOP!NOP!NOP
- NOP!NOP!NOP!NOP
- NOP!NOP!NOP!NOP
- ENDIF
-
- IF MSIO2 ;IF MITS 2SIO,
- MVI A,3 ;INITIALIZE 2SIO.
- OUT CCOM
- OUT LCOM
- MVI A,11H
- OUT CCOM
- OUT LCOM
- ENDIF
-
- IF ISIO2 ;IF IMSAI SIO2,
- MVI A,0AAH ;INITIALIZE SIO 2-2.
- OUT CCOM
- MVI A,40H
- OUT CCOM
- MVI A,0CEH
- OUT CCOM
- MVI A,37H
- OUT CCOM
- ENDIF
-
- IF TUART ;IF CROMEMCO TUART,
- MVI A,1 ;SET A = 1.
- OUT 54H ;SELECT DEVICE A.
- OUT 52H ;RESET DEVICE B.
- LXI H,BAUDRS ;GET ADR OF BAUD RATE TABLE.
- MVI A,11H ;OCTUPLE THE CLOCK.
- IT1: OUT 02H ;& RESET CURRENT DEV.
- MOV A,M ;GET BAUD RATE FROM TABLE.
- OUT 0 ;SET BAUD RATE.
- CALL CONIN ;READ KEYBOARD.
- CALL CONIN ;READ KEYBOARD AGAIN.
- CPI 0DH ;IF NOT CARRIAGE-RETURN,
- MVI A,1 ;SLOW THE CLOCK.
- JNZ IT1 ;UNTIL A CARRIAGE-RETURN.
- ENDIF
-
- LXI H,SMSG ;PRINT OPENING MESSAGE.
- CALL PMSG
- CALL CONIN ;READ # OF DISKS.
- MOV C,A ;ECHO THE CHAR.
- CALL CONOT
- ANI 7 ;LOOK AT 3 LSB'S.
- STA NODSKS ;SAVE IT.
- XRA A ;SET DISK NUMBER = 0.
- STA DISKNO
- GOCPM: 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 DISKNO ;GET DISK NUMBER TO
- MOV C,A ;PASS TO CCP IN C.
- JMP CPMB ;JUMP TO CCP.
-
- IF TUART ;IF CROMEMCO TUART,
- BAUDRS: DB 94H,0CEH,0A2H,92H,88H,84H,82H,1
- ENDIF
-
- ;
- ; WARM-BOOT: READ ALL OF CPM BACK IN
- ; EXCEPT BIOS, THEN JUMP TO CCP.
- ;
- WBOOT: LXI SP,80H ;SET STACK POINTER.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- EI ;ALLOW THEM HERE.
- ENDIF
-
- LDA DISKNO ;SAVE DISK NUMBER.
- STA TEMP
- MVI C,0 ;SELECT DISK ZERO.
- 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.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- DI ;DISABLE THEM HERE.
- ENDIF
-
- RDBLK: MOV A,B ;GO TO 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.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- EI ;ALLOW THEM AGAIN HERE.
- ENDIF
-
- STA DISKNO
- JMP GOCPM ;GO BACK TO CPM.
- ;
- RBLK2: CALL READ2 ;READ ANOTHER TRACK.
- JMP RBLK1
- ;
- RDERR: LXI H,BTMSG ;GET ADDRESS OF "BOOT ERROR".
- CALL PMSG ;PRINT IT.
- CALL CONIN ;READ A CHAR FROM CONSOLE.
- JMP WBOOT ;DO A WARM BOOT.
- ;
- ; CHECK CONSOLE INPUT STATUS.
- ;
-
- CONST: IN CSTAT ;READ CONSOLE STATUS.
- ANI CKBR ;LOOK AT KB READY BIT.
- MVI A,0 ;SET A=0 FOR RETURN.
-
- IF STD ;IF STANDARD I/O,
- RNZ ;NOT READY WHEN NOT 0.
- ENDIF
-
- IF SIO2 ;IF MITS OR IMSAI,
- RZ ;NOT READY WHEN ZERO.
- ENDIF
-
- IF OTHER ;IF SOMETHING ELSE,
- RNZ ;IT MIGHT BE THIS.
- ENDIF
-
- CMA ;IF READY A=FF.
- RET ;RETURN FROM CONST.
-
- ;
- ; READ A CHARACTER FROM CONSOLE.
- ;
- CONIN: IN CSTAT ;READ CONSOLE STATUS.
- ANI CKBR ;IF NOT READY,
-
- IF STD ;IF STANDARD I/O,
- JNZ CONIN ;READY WHEN LOW.
- ENDIF
-
- IF SIO2 ;IF MITS OR IMSAI,
- JZ CONIN ;READY WHEN HIGH.
- ENDIF
-
- IF OTHER ;IF SOMETHING ELSE,
- JNZ CONIN ;IT MIGHT BE THIS.
- ENDIF
-
- IN CDATA ;READ A CHARACTER.
- ANI 7FH ;MAKE MOST SIG. BIT = 0.
- RET
- ;
- ; WRITE A CHARACTER TO THE CONSOLE DEVICE.
- ;
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- CONOT: MVI A,0DH ;IF IT'S A CR,
- CMP C ;THEN HOP OUT
- JZ CONUL ;TO NULL ROUTINE.
- CONOT1: IN CSTAT ;READ CONSOLE STATUS.
- ANI CPTR ;IF NOT READY,
- ENDIF
-
- IF STD AND NOT VDM ;IF STANDARD I/O,
- JNZ CONOT1 ;READY WHEN LOW.
- ENDIF
-
- IF SIO2 ;IF MITS OR IMSAI,
- JZ CONOT1 ;READY WHEN HIGH.
- ENDIF
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- MOV A,C ;GET CHARACTER.
- OUT CDATA ;PRINT IT.
- RET ;RETURN.
- CONUL: PUSH B ;SAVE B&C.
- MVI B,CNULL ;GET NULL COUNT.
- CONUL1: CALL CONOT1 ;PRINT CR.
- MVI C,0 ;GET NULL CHAR.
- DCR B ;DECREMENT COUNTER.
- JNZ CONUL1 ;DO NEXT NULL.
- POP B ;RESTORE B&C.
- MOV A,C ;RESTORE A.
- RET ;RETURN.
- ENDIF
-
- IF VDM ;IF PROC TECH VDM,
- ; VDM DRIVER FOR CBIOS.
- ; 9-24-77 VERSION
- ;
- VDMB EQU 0CC00H
- VDMP EQU 0CCH
- VDMD EQU 0C8H
- CONOT: MOV A,C ;PUT CHAR IN A.
- SHLD HLSAV ;SAVE H&L.
- LXI H,0 ;CLEAR H&L.
- DAD SP ;HL=SP.
- LXI SP,VSTACK ;SET STACK PTR.
- PUSH H ;SAVE OLD SP.
- PUSH D ;SAVE D&E.
- PUSH B ;SAVE B&C.
- PUSH PSW ;SAVE A&PSW.
- CALL SCREEN ;WRITE ON SCREEN.
- POP PSW ;RESTORE A&PSW.
- POP B ;RESTORE B&C.
- POP D ;RESTORE D&E.
- POP H ;RESTORE H&L.
- SPHL ;RESTORE SP.
- LHLD HLSAV ;RESTORE H&L.
- RET ;RETURN FROM CONOT.
- ;
- ;
- SCREEN: MOV B,A ;GET CHARACTER.
- MOV A,B
- ANI 7FH ;NOT DELETE.
- CPI 0DH ;IF IT'S CR,
- JZ CHOT2 ;TAKE CARE OF IT.
- CPI 20H ;CTL CHAR?
- RC ;DON'T DISPLAY.
- JMP CHOUT ;GO TO CHOUT.
- ;
- ; CLEAR SCREEN & INIT CURSOR.
- ;
- CLR: LXI H,VDMB ;GET VDM MEM ADR.
- MOV A,H ;FIGURE VDM MEM TOP.
- ADI 4
- CLR2: MVI M,' ' ;PUT SPACE IN MEMORY.
- INX H ;INCREMENT POINTER.
- CMP H ;AT TOP YET?
- JNZ CLR2 ;KEEP GOING IF NOT.
- XRA A ;SET A = 0.
- STA BOSL ;BEG SCRN LINE = 0.
- STA BOTL ;BEG TEXT LINE = 0.
- STA CCP ;CURSOR PTR = 0.
- CMA ;SET A = FF.
- STA CURF ;SET CURSOR ON.
- MVI A,15 ;SET CURSOR AT BOTTOM.
- STA CLN
- CALL VDMOT ;SET VDM UP.
- RET ;RETURN FROM CLR.
- ;
- ; OUTPUT BOSL & BOTL TO VDM.
- ;
- VDMOT: LDA BOSL ;INITIALIZE VDM.
- RLC ;SHIFT LEFT 4.
- RLC
- RLC
- RLC
- LXI H,BOTL
- ORA M
- OUT VDMD ;OUT TO VDM PORT.
- RET ;RETURN FROM VDMOT.
- ;
- ; STORE CHAR IN VDM MEMORY.
- ;
- CHOUT: MOV C,A ;SAVE CHARACTER.
- LDA CCP ;GET CURSOR PTR.
- MOV B,A ;PUT IN B.
- LDA CLN ;GET LINE NUMBER.
- CALL CLNA ;CONVERT TO ADR.
- MOV M,C ;PUT CHAR ON SCREEN.
- LDA CCP ;ADVANCE CURSOR.
- INR A
- CPI 64 ;WRAP AROUND?
- JNZ CHOT1
- CHOT2: LDA CCP ;GET CURSOR POS.
- MOV B,A
- LDA CLN ;GET LINE NUMBER.
- CALL CCUR ;CLEAR CURSOR.
- CALL SCRL ;SCROLL UP.
- SUB A ;CURSOR TO LEFT MARGIN.
- CHOT1: STA CCP
- MOV B,A
- LDA CLN
- JMP SCUR ;SET CURSOR ON/OFF.
- ;
- ;
- SCRL: LXI H,BOTL ;SAVE BEG. TEXT LINE.
- PUSH H
- MOV A,M
- INR M
- SUB M
- LXI B,0
- CALL CLNA ;CONVERT LINE NO.
- LXI B,2040H
- SCRL2: MOV M,B ;CLEAR BOTTOM LINE.
- INR L
- DCR C
- JNZ SCRL2
- POP H
- MOV A,M
- ANI 0FH
- MOV M,A
- JMP VDMOT
- ;
- ; CONVERT LINE NUMBER IN REG A AND CHR
- ; POSITION IN REG B TO ADDRESS IN H&L.
- ;
- CLNA: MOV L,A
- LDA BOTL
- ADD L
- RRC
- RRC
- MOV L,A
- ANI 3
- ADI VDMP
- MOV H,A
- MOV A,L
- ANI 0C0H
- ADD B
- MOV L,A
- RET
- ;
- ;
- SCUR: ANI 0FH
- STA CLN
- CALL CLNA
- MOV A,B
- STA CCP
- LDA CURF
- ORA A
- MOV A,M
- JZ CCUR2
- ORI 80H
- MOV M,A
- RET
- CCUR2: ANI 7FH
- MOV M,A
- RET
- ;
- ;
- CCUR: CALL CLNA
- MOV A,M
- ANI 7FH
- MOV M,A
- RET
- ;
- ;
- CLN: DS 1
- CCP: DS 1
- CURF: DS 1
- BOSL: DS 1
- BOTL: DS 1
- HLSAV: DS 32
- VSTACK: DS 1
- ENDIF ;END OF VDM DRIVER.
-
- ;
- ; MOVE DISK TO TRACK ZERO.
- ;
- HOME: MVI A,RTCNT ;GET RETRY COUNT.
- HRETRY: STA ERCNT ;STORE IN ERROR CTR.
- MVI A,0D0H ;CLEAR ANY PENDING COMMAND.
- OUT DCOM
- LDA DISKNO ;GET DISK NUMBER.
- MOV E,A ;PUT IN D&E.
- XRA A
- MOV D,A
- LXI H,TRTAB ;GET ADR OF TRK TABLE.
-
- IF NOT DUAL ;IF NOT A DUAL DRIVE.
- DAD D ;ADD DISK NUMBER.
- ENDIF
-
- MOV M,A ;PUT ZERO INTO TABLE.
- HOME1: IN DSTAT ;READ DISK STATUS.
- RRC ;LOOK AT LSB.
- JC HOME1 ;WAIT FOR NOT BUSY.
-
- IF FAST ;IF FAST SEEK,
- LDA NODSKS ;GET NUMBER OF DISKS.
- DCR A ;IF ONLY ONE DISK,
- JZ HOME2 ;SKIP OVER NEXT PART.
- LDA DISKNO ;GET DISK NUMBER.
- RLC!RLC!RLC!RLC ;SHIFT LEFT 4 BITS.
- ANI 10H ;LOOK AT BIT 4.
- HOME2: CMA ;INVERT.
- MOV E,A ;SAVE IT.
- ANI 0B2H ;SET PERSCI
- OUT DCONT ;RESTORE LINE.
- HLOOP: IN DSTAT ;LOOK AT STATUS
- ANI 4 ;BIT 2 (TRACK 0)
- JZ HLOOP ;AND WAIT TILL 1.
- MOV A,E ;RESTORE OLD BITS
- ANI 0F2H ;IN LATCH AND CLEAR
- OUT DCONT ;RESTORE LINE.
- ENDIF
-
- MVI A,2 ;10 MS STEP RATE.
- OUT DCOM ;ISSUE HOME COMMAND.
- IN WAIT ;WAIT FOR INTRQ.
- ORA A ;SET FLAGS.
- JM HERR ;ERROR IF DRQ.
- IN DSTAT ;READ DISK STATUS.
- MOV D,A ;SAVE IN REGISTER D.
- ANI 4 ;LOOK AT BIT 2.
- JZ HERR ;ERROR IF NOT TRK 0.
- MOV A,D ;GET STATUS BACK.
- ANI 91H ;MASK NON-ERROR BITS.
- RZ ;RETURN IF NO ERROR.
- HERR: LDA HECNT ;GET TOTAL ERROR COUNT.
- INR A ;ADD ONE.
- STA HECNT ;SAVE IT BACK.
- LDA ERCNT ;GET THIS ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- JNZ HRETRY ;TRY TO HOME AGAIN.
- LXI H,HEMSG ;PRINT "HOME ".
- MOV A,D ;MASK NON-ERROR BITS.
- ANI 91H
- MOV D,A
- JMP ERMSG ;DO COMMON ERROR MSGS.
- ;
- ; SELECT DISK NUMBER ACCORDING TO REGISTER C.
- ;
- SELDSK: MOV A,C ;GET NEW DISK NUMBER.
- ANI 3 ;ONLY LOOK AT 2 LSB'S.
- LXI H,DISKNO ;GET ADR OF OLD DISK NO.
- CMP M ;NEW = OLD?
- RZ ;IF SO, RETURN.
- PUSH A ;SAVE DISK NUMBER.
- LDA NODSKS ;GET NUMBER OF DISKS.
- DCR A ;IF MORE THAN ONE DISK,
- JNZ SELMOR ;TAKE CARE OF IT.
- LXI H,MNTMSG ;GET ADR OF MOUNT MESSAGE.
- CALL PMSG ;PRINT "MOUNT ".
- POP A ;GET DISK NUMBER.
- STA DISKNO ;UPDATE OLD WITH NEW.
- ADI 'A' ;ADD ASCII FOR 'A'.
- MOV C,A ;PUT INTO C.
- CALL CONOT ;PRINT IT.
- CALL CONIN ;READ A CARRIAGE RETURN.
- XRA A ;SET A=0 FOR NO ERRO IND.
- RET ;RETURN FROM SELDSK.
- SELMOR: POP A ;MAKE STACK RIGHT.
- MOV A,M ;GET OLD DISK NUMBER.
-
- IF DUAL ;IF DUAL DRIVE,
- ANI 0FEH ;CLEAR OUT BIT 0.
- ENDIF
-
- MOV E,A ;PUT OLD DISK NO. IN D&E.
- MVI D,0
- LXI H,TRTAB ;GET ADDRESS OF TRACK TABLE.
- 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.
-
- IF DUAL ;IF A DUAL DRIVE,
- ANI 0FEH ;CLEAR BIT 0.
- ENDIF
-
- MOV E,A ;PUT NEW DISK NO. IN D&E.
- LXI H,TRTAB ;GET ADDRESS OF TRACK TABLE.
- DAD D ;ADD DISK NO. TO ADDRESS.
- MOV A,M ;GET NEW TRACK NUMBER.
- OUT TRACK ;PUT INTO 1771 TRACK REG.
- MOV A,C ;UPDATE OLD DISK NUMBER.
- STA DISKNO
- 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 ;RETURN FROM SELDSK.
- ;
- ; SET TRACK NUMBER TO WHATEVER IS IN REGISTER C.
- ; ALSO PERFORM MOVE TO THE CORRECT TRACK (SEEK).
- ;
- SETTRK: MOV A,C ;GET NEW TRACK NUMBER.
- STA TRK ;UPDATE OLD WITH NEW.
- CALL SEEK ;MOVE TO NEW TRACK.
- RET ;RETURN FROM SETTRK ROUTINE.
- ;
- ; SET DISK SECTOR NUMBER.
- ;
- SETSEC: MOV A,C ;GET SECTOR NUMBER.
- STA SECT ;PUT AT SECT # ADDRESS.
- RET ;RETURN FROM SETSEC.
- ;
- ; 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.
- ;
- ; 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 ;STORE IN ERROR CTR.
- LHLD DMAADD ;GET STARTING ADR.
- MVI A,0D0H ;CAUSE INTERRUPT.
- OUT DCOM
- XTHL ;SOME DELAY.
- XTHL
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- DI ;DISABLE THEM HERE.
- ENDIF
-
- IN DSTAT ;READ STATUS.
- ANI 20H ;LOOK AT HLD BIT.
- LDA SECT ;GET SECTOR NUMBER.
- 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 ;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.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- EI ;ALLOW AGAIN HERE.
- ENDIF
-
- ANI 9DH ;LOOK AT ERROR BITS.
- RZ ;RETURN IF NONE.
- CHECK: 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 ;DECREMENT COUNT.
- JNZ RRETRY ;TRY TO READ AGAIN.
- LXI H,RDMSG ;PRINT "READ ".
- ERMSG: CALL PMSG ;PRINT ORIGIN MESSAGE.
- ERMSG1:
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- 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 IS HIGH,
- LXI H,RNMSG ;PRINT "RECORD NOT FOUND"
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 8H ;IF BIT 3 IS HIGH,
- LXI H,CRCMSG ;PRINT "CRC ERROR".
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 4H ;IF BIT 2 IS 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
- ENDIF
-
- PERMSG: 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 RECORD NOT FOUND,
- JNZ CHKSK ;DO A CHECK ON SEEK.
- MOV A,D ;OTHERWISE RESTORE 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.
- ORA A ;SET FLAGS.
- JP CHKS3 ;DONE WITH READ ADR OP.
- IN DDATA ;READ ANOTHER BYTE.
- JMP CHKS2 ;DO IT AGAIN.
- CHKS3: IN DSTAT ;READ DISK STATUS.
- ORA A ;SET FLAGS.
- JZ CHKS4 ;READ ADR OK IF 0.
- CALL HOME ;OTHERWISE, HOME FIRST.
- JMP CHKS5
- CHKS4: MOV A,B ;UPDATE TRACK REGISTER.
- OUT TRACK
- CHKS5: LDA TRK ;GET REQUIRED TRACK NO.
- CALL SEEK ;MOVE THE HEAD TO IT.
- MOV A,D ;GET ERROR BITS.
- ORA A ;SET FLAGS.
- RET ;RETURN FROM ERCHK.
- ;
- ; 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.
- LHLD DMAADD ;GET STARTING ADR.
- MVI A,0D0H ;STATUS INTERUPT FOR 1771.
- OUT DCOM ;COMMAND 1771.
- XTHL ;WAIT FOR STATUS.
- XTHL ;CHANGE IT BACK.
-
- IF INTRP ;IF INTERRPUTS ALLOWED,
- DI ;DISABLE THEM HERE.
- ENDIF
-
- IN DSTAT ;GET 1771 STATUS.
- ANI 20H ;CHECK FOR HEAD LOAD.
- LDA SECT ;GET SECTOR NUMBER.
- WRITE1: OUT SECTP ;SET THE SECTOR INTO 1771.
- MVI A,0ACH ;SET UP 1771 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 ONTO DISK.
- INX H ;INCREMENT MEM PTR.
- JMP WLOOP ;KEEP WRITING.
- WDONE: IN DSTAT ;READ DISK STATUS.
-
- IF INTRP ;IF INTERRUPTS ALLOWED,
- EI ;ENABLE AGAIN HERE.
- ENDIF
-
- ANI 0FDH ;LOOK AT THESE BITS.
- PROCER: RZ ;RETURN IF NO ERR.
- CALL ERCHK ;CHECK/CORRECT SEEK ERR.
- LXI H,WECNT ;GET ADR OF WRITE ERR CTR.
- INR M ;ONE MORE WRITE ERROR.
- LDA ERCNT ;GET ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- JNZ WRETRY ;TRY TO WRITE AGAIN.
- WERR0: LXI H,WTMSG ;PRINT "WRITE ".
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- 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.
- ENDIF
-
- IF VDM ;IF PROC TECH VDM,
- JMP ERMSG
- ENDIF
-
- ;
- ; 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.
- MOV C,A ;SAVE IN C.
- MOV A,C ;DELAY.
- CMP B ;SAME AS NEW TRACK NO.?
- MOV A,B ;RESTORE A FROM B.
- JNZ NOTHR ;JUMP IF NOT THERE.
- THERE: POP B ;RESTORE B&C.
- RET ;RETURN FROM SEEK.
- NOTHR:
-
- IF NOT FAST ;IF NOT FAST SEEK,
- 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,12H ;SET FOR 10 MS STEP.
- ORI 4 ;VERIFY ON LAST TRACK.
- OUT DCOM ;ISSUE SEEK COMMAND.
- IN WAIT ;WAIT FOR INTRQ.
- IN DSTAT ;READ STATUS.
- ANI 91H ;LOOK AT BITS.
- JZ THERE ;OK IF ZERO.
- ENDIF
-
- IF FAST ;IF FAST SEEK,
- MVI A,40H ;IF CARRY = 1,
- JC SDIR ;STEP IN.
- MVI A,60H ;OTHERWISE, OUT.
- SDIR: OUT DCOM ;ISSUE STEP DIRECTION.
- MVI A,20 ;DELAY LOOP COUNT.
- DLOOP: DCR A ;DECREMENT COUNTER.
- JNZ DLOOP
- MOV A,C ;GET PRESENT TRACK.
- SUB B ;FIGURE TRACKS TO STEP.
- JP STEP ;IF NEGATIVE,
- CMA ;FIGURE THE
- INR A ;TWO'S COMPLEMENT.
- 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 NUMBER.
- RLC!RLC!RLC!RLC ;SHIFT LEFT 4 BITS.
- ANI 10H ;LOOK A 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 RETURN.
- POP B ;RMSTOREE B&C.
- RET
- ENDIF
-
- IF NOT FAST ;IF NOT FAST SEEK,
- PUSH H ;SAVE H&L.
- LXI H,SECNT ;GET ADR OF SEEK ERR CTR.
- INR M ;ONE MORE SEEK ERROR.
- POP H ;RESTORE H&L.
- LDA ERCN\ ;GET ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- JNZ SRETRY ;RETRY SEK.
- POP B ;RESTORE B&C.
- LXI H,SKMSG ;PRINT "SEEK ".
- IN DSTAT ;READ DISK STATUS.
- ANI 91H ;LOOK AT ERROR BITS.
- MOV D,A ;PUT IN REG D.
- JMP ERMSG ;DO COMMON ERR MESSAGES.
- ENDIF
-
- ;
- ; PRINT THE MESSAGE AT H&L UNTIL A ZERO.
- ;
- PMSG: MOV A,M ;GET A CHARACTER.
- ORA A ;IF IT'S ZERO,
- RZ ;RETURN.
- MOV C,A ;OTHERWISE,
- CALL CONOT ;PRINT IT.
- INX H ;INCREMENT H&L,
- JMP PMSG ;AND GET ANOTHER.
- ;
- ; CBIOS MESSAGES
- ;
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- 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
- ENDIF
-
- ERRMSG: DB 'ERROR.',0
- RDMSG: DB 0DH,0AH,'READ ',0
- WTMSG: DB 0DH,0AH,'WRITE ',0
- BTMSG: DB 'BOOT ERROR',0
- SKMSG: DB 0DH,0AH,'SEEK ',0
- HEMSG: DB 0DH,0AH,'HOME ',0
- MNTMSG: DB 0DH,0AH,'MOUNT ',0
- SMSG: DB 0DH,0AH,'TARBELL '
- DB MSIZE/10+'0',MSIZE MOD 10 + '0'
- DB 'K CPM V1.4 OF 2-15-78'
- DB 0DH,0AH
-
- IF STD ;IF STANDARD I/O,
- DB 'STANDARD '
- ENDIF
-
- IF MSIO2 ;IF MITS 2SIO,
- DB '2SIO '
- ENDIF
-
- IF ISIO2 ;IF IMSAI SIO-2,
- DB 'SIO-2 '
- ENDIF
-
- IF TUART ;IF TUART,
- DB 'TUART '
- ENDIF
-
- IF VDM ;IF PROC TECH VDM,
- DB 'VDM '
- ENDIF
-
- IF FAST ;IF FAST SEEK,
- DB 'FAST SEEK '
- ENDIF
-
- IF DUAL ;IF DUAL DRIVE,
- DB 'DUAL '
- ENDIF
-
- DB 'VERSION.'
- DB 0DH,0AH,'HOW MANY DISKS? ',0
- ;
- ; WRITE A CHARACTER ON LISTING DEVICE.
- ;
- LIST:
- IF NOT VDM ;IF NOT PROC TECH VDM,
- MVI A,0DH ;IF IT'S A CR,
- CMP C ;THEN HOP OUT TO
- JZ LINUL ;NULL ROUTINE.
- ENDIF
-
- LIST1: IN LSTAT ;READ LISTER STATUS.
- ANI LRBIT ;LOOK AT READY BIT.
-
- IF STD ;IF STANDARD I/O,
- JNZ LIST1 ;READY WHEN LOW.
- ENDIF
-
- IF SIO2 ;IF MITS, IMSAI, CROM.,
- JZ LIST1 ;READY WHEN HIGH.
- ENDIF
-
- IF OTHER ;IF ANYTHING ELSE,
- JZ LIST1 ;READY WHEN HIGH.
- ENDIF
-
- MOV A,C ;GET DATA BYTE.
- OUT LDATA ;PRINT IT.
- RET ;RETURN FROM LIST.
-
- IF NOT VDM ;IF NOT PROC TECH VDM,
- LINUL: PUSH B ;SAVE B&C.
- MVI B,LNULL ;GET NULL COUNT.
- LINUL1: CALL LIST1 ;PRINT (CR FIRST).
- MVI C,0 ;GET NULL CHAR.
- DCR B ;DECREMENT COUNTER.
- JNZ LINUL1 ;DO NEXT NULL.
- POP B ;RESTORE B&C.
- MOV A,C ;RESTORE A.
- RET ;RETURN FROM LIST.
- ENDIF
-
- ;
- ; NORMALLY USED TO PUNCH PAPER TAPE, BUT IS
- ; NICE FOR AN INFINITE BIT BUCKET TO CHECK FILES.
- ;
- PUNCH:
- IF NOT VDM ;IF NOT PROC TECH VDM,
- NOP ;SPACE FOR YOUR ROUTINE.
- NOP!NOP!NOP!NOP
- NOP!NOP!NOP!NOP
- NOP
- ENDIF
-
- RET ;RETURN FROM PUNCH.
- ;
- ; NORMALLY USED TO READ PAPER TAPE.
- ; SET UP TO READ FROM CONSOLE IN STANDARD SYSTEM.
- ;
- READER:
- IF NOT VDM ;IF NOT PROC TECH VDM,
- CALL CONIN ;READ FROM CONSOLE.
- NOP!NOP!NOP!NOP ;MORE SPACE FOR YOUR ROUTINE.
- NOP!NOP!NOP!NOP
- ENDIF
-
- RET ;RETURN FROM READER.
-
- ;NOTE: AS THERE ARE ONLY NINE 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 + 047F (HEX).
- ;THIS WILL NORMALLY BE XE7F (HEX).
-
- ;
- ; ERROR COUNTS. THESE LOCATIONS KEEP TRACK OF THE
- ; NUMBER OF ERRRS THAT OCCUR DURING READ, WRITE,
- ; OR SEEK OPERATIONS. THEY ARE INITIALIZED ONLY
- ; WHEN A COLD-START IS PERFORMED BY THE BOOOTSTRAP.
- ;
- HECNT: DB 0 ;HOME ERROR COUNT.
- RECNT: DB 0 ;READ ERROR COUNT.
- WECNT: DB 0 ;WRITE ERROR COUNT.
- SECNT: DB 0 ;SEEK ERROR COUNT.
- ;
- ; TRTAB - DISK TRACK TABLE - PRESENT POSITION OF
- ; HEADS FOR UP TO 4 DRIVES.
- ;
- TRTAB: DS 4
- ;
- NODSKS: DS 1 ;NUMBER OF DISKS.
- ERCNT: DS 1 ;ERROR COUNT FOR RETRIES.
- SERCNT: DS 1 ;SEEK RETRY COUNTER.
- TEMP: DS 1 ;TEMPORARY STORAGE.
- TRK: DS 1 ;CURRENTLY SELECTED TRACK.
- SECT: DS 1 ;CURRENTLY SELECTED SECTOR.
- DMAADD: DS 2 ;CURRENT READ/WRITE ADDRESS.
- DISKNO: DS 1 ;CURRENT DISK NUMBER.
- END
-