home *** CD-ROM | disk | FTP | other *** search
- ; MDS I/O DRIVERS FOR CP/M
- ; (FOUR DRIVE SINGLE DENSITY VERSION)
- ; VERSION 1.4 JANUARY, 1978
- ; CUSTOMIZED FOR NATIONAL SEMICONDUCTOR BLC 8221 DISK CONT.
- ; BY Robert A. Van Valzah 2/23/79
- ;
- CBIVERS EQU 09 ;CBIOS VERSION NUMBER
- CPMVERS EQU 14 ;CP/M VERSION NUMBER
- ;
- ; COPYRIGHT (C) 1978
- ; DIGITAL RESEARCH
- ; BOX 579, PACIFIC GROVE
- ; CALIFORNIA, 93950
- ;
- ;
- TRUE EQU 0FFFFH ;VALUE OF "TRUE"
- FALSE EQU NOT TRUE ;"FALSE"
- REL EQU FALSE ;TRUE TO GENERATE RELOCATABLE CODE
- MSIZE EQU 32 ;MEMORY AND CPM SYSTEM SIZE IN K BYTES
- ;
- IF REL
- BIAS EQU 0 ;GENERATE CPM IMAGE ORGED FOR ZERO
- ENDIF
- IF NOT REL
- BIAS EQU (MSIZE-16)*1024+2900H
- ENDIF
- ;
- PATCH EQU 1500H+BIAS
- ;
- ORG PATCH
- CPMB EQU 000H+BIAS ;BASE OF CPM CONSOLE PROCESSOR
- BDOS EQU 806H+BIAS ;BASIC DOS (RESIDENT PORTION)
- CPML EQU $-CPMB ;LENGTH (IN BYTES) OF CPM SYSTEM
- NSECTS EQU CPML/128 ;NUMBER OF SECTORS TO LOAD
- OFFSET EQU 2 ;NUMBER OF DISK TRACKS USED BY CP/M
- CDISK EQU 0004H ;ADDRESS OF LAST LOGGED DISK ON WARM START
- BUFF EQU 0080H ;DEFAULT BUFFER ADDRESS
- ;
- ; PERFORM FOLLOWING FUNCTIONS
- ; BOOT COLD START
- ; WBOOT WARM START (SAVE I/O BYTE)
- ; (BOOT AND WBOOT ARE THE SAME FOR MDS)
- ; CONST CONSOLE STATUS
- ; REG-A = 00 IF NO CHARACTER READY
- ; REG-A = FF IF CHARACTER READY
- ; CONIN CONSOLE CHARACTER IN (RESULT IN REG-A)
- ; CONOUT CONSOLE CHARACTER OUT (CHAR IN REG-C)
- ; LIST LIST OUT (CHAR IN REG-C)
- ; PUNCH PUNCH OUT (CHAR IN REG-C)
- ; READER PAPER TAPE READER IN (RESULT TO REG-A)
- ; HOME MOVE TO TRACK 00
- ;
- ; (THE FOLLOWING CALLS SET-UP THE IO PARAMETER BLOCK FOR THE
- ; MDS, WHICH IS USED TO PERFORM SUBSEQUENT READS AND WRITES)
- ; SELDSK SELECT DISK GIVEN BY REG-C (0,1,2...)
- ; SETTRK SET TRACK ADDRESS (0,...76) FOR SUBSEQUENT READ/WRITE
- ; SETSEC SET SECTOR ADDRESS (1,...,26) FOR SUBSEQUENT READ/WRITE
- ; SETDMA SET SUBSEQUENT DMA ADDRESS (INITIALLY 80H)
- ;
- ; (READ AND WRITE ASSUME PREVIOUS CALLS TO SET UP THE IO PARAMETERS)
- ; READ READ TRACK/SECTOR TO PRESET DMA ADDRESS
- ; WRITE WRITE TRACK/SECTOR FROM PRESET DMA ADDRESS
- ;
- ; JUMP VECTOR FOR INDIVIUAL ROUTINES
- JMP BOOT
- WBOOTE: JMP WBOOT
- JMP CONST
- JMP CONIN
- JMP CONOUT
- JMP LIST
- JMP PUNCH
- JMP READER
- JMP HOME
- JMP SELDSK
- JMP SETTRK
- JMP SETSEC
- JMP SETDMA
- JMP READ
- JMP WRITE
- ;
- NODISKS DB 1 ;NUMBER OF PHYSICAL DRIVES
- ;
- ;
- ; END OF CONTROLLER - INDEPENDENT CODE, THE REMAINING SUBROUTINES
- ; ARE TAILORED TO THE PARTICULAR OPERATING ENVIRONMENT, AND MUST
- ; BE ALTERED FOR ANY SYSTEM WHICH DIFFERS FROM THE INTEL MDS.
- ;
- ; THE FOLLOWING CODE ASSUMES THE MDS MONITOR EXISTS AT 0F800H
- ; AND USES THE I/O SUBROUTINES WITHIN THE MONITOR
- ;
- REVRT EQU 0FDH ;INTERRUPT REVERT PORT
- INTC EQU 0FCH ;INTERRUPT MASK PORT
- ICON EQU 0F3H ;INTERRUPT CONTROL PORT
- INTE EQU 0111$1110B ;ENABLE RST 0(WARM BOOT), RST 7 (MONITOR)
- ;
- ; MDS MONITOR EQUATES
- MON80 EQU 0F800H ;MDS MONITOR
- RMON80 EQU 0FF0FH ;RESTART MON80 (BOOT ERROR)
- CI EQU 0F803H ;CONSOLE CHARACTER TO REG-A
- RI EQU 0F806H ;READER IN TO REG-A
- CO EQU 0F809H ;CONSOLE CHAR FROM C TO CONSOLE OUT
- PO EQU 0F80CH ;PUNCH CHAR FROM C TO PUNCH DEVICE
- LO EQU 0F80FH ;LIST FROM C TO LIST DEVICE
- CSTS EQU 0F812H ;CONSOLE STATUS 00/FF TO REGISTER A
- ;
- ; DISK PORTS AND COMMANDS
- BASE EQU 70H ;BASE OF DISK COMMAND IO PORTS
- READY EQU BASE+1 ;READY, RETRY, AND ERROR BITS
- ERRBITS EQU BASE ;ERROR TYPE BITS
- ;
- BUSY EQU 1000$0000B ;CONTROLLER BUSY STATUS BIT
- RTRYBIT EQU 0010$0000B ;INDICATES THAT THE EXECUTED COMMAND HAD A RETRY
- ;
- ILOW EQU BASE+1 ;IOPB LOW ADDRESS (OUTPUT)
- IHIGH EQU BASE+2 ;IOPB HIGH ADDRESS (OUTPUT)
- ;
- READFUN EQU 8 ;READ A SECTOR FUNCTION
- WRITEFUN EQU 9 ;WRITE A SECTOR FUNCTION
- CR EQU 0DH ;CARRIAGE RETURN
- LF EQU 0AH ;LINE FEED
- ;
- SIGNON: ;SIGNON MESSAGE: XXK CP/M VERS Y.Y-Z.Z NS
- DB CR,LF,LF
- IF NOT REL
- DB '0'+MSIZE/10, '0'+MSIZE MOD 10
- ENDIF
- IF REL
- DB '00' ;MEMORY SIZE FILLED BY RELOCATOR
- ENDIF
- DB 'K CP/M VERS '
- DB CPMVERS/10+'0', '.', CPMVERS MOD 10+'0'
- DB '-'
- DB '0'+CBIVERS/10, '.', '0'+CBIVERS MOD 10
- DB ' NS', CR, LF, 0
- ;
- BOOT: ;PRINT SIGNON MESSAGE AND GO TO CCP
- ; (NOTE: MDS BOOT INITIALIZED IOBYTE AT 0003H)
- LXI SP,BUFF+80H
- LXI H,SIGNON
- CALL PRMSG ;PRINT MESSAGE
- XRA A ;CLEAR ACCUMULATOR
- STA CDISK ;SET INITIALLY TO DISK A
- JMP GOCPM ;GO TO CP/M
- ;
- ;
- WBOOT:; LOADER ON TRACK 0, SECTOR 1, WHICH WILL BE SKIPPED FOR WARM
- ; READ CP/M FROM DISK - ASSUMING THERE IS A 128 BYTE COLD START
- ; START.
- ;
- LXI SP,BUFF+80H ;SETUP TEMP STACK IN LOW MEM
- MVI C,0 ;SELECT DRIVE A FOR BOOTING
- CALL SELDSK
- CALL DO$SEL
- ;
- ; SEND ADDRESS OF FIRST IOPB TO CONTROLLER
- ;
-
- MVI B,2 ;NUMBER OF IOPBS TO SEND
- LXI H,BTIOPB1
- SENDADR:
- MOV A,L
- OUT ILOW
- MOV A,H
- OUT IHIGH
- BTWAIT: ;WAIT FOR CONTROLLER TO FINISH
- IN READY
- ANI BUSY
- JNZ BTWAIT
- IN ERRBITS ;GET ERROR BITS FROM CONTROLLER
- ORA A ;ANY ERRORS?
- JNZ BOOTERR ;NO - PRINT ERROR AND GIVE UP
- DCR B ;DONE WITH BOTH IOPB'S?
- JZ GOCPM ;YES - INSTALL LOW MEM JMPS ETC
- LXI H,BTIOPB2 ;NO - SEND SECOND IOPB
- JMP SENDADR
- ;
- ; DONE WITH THE LOAD, RESET DEFAULT BUFFER ADDRESS
- GOCPM: ;(ENTER HERE FROM COLD START BOOT)
- ; ENABLE RST0 AND RST7
- DI
- MVI A,12H ;INITIALIZE COMMAND
- OUT REVRT
- XRA A
- OUT INTC ;CLEARED
- MVI A,INTE ;RST0 AND RST7 BITS ON
- OUT INTC
- XRA A
- OUT ICON ;INTERRUPT CONTROL
- ;
- ; SET DEFAULT BUFFER ADDRESS TO 80H
- LXI B,BUFF
- CALL SETDMA
- ;
- ; RESET MONITOR ENTRY POINTS
- MVI A,JMP
- STA 0
- LXI H,WBOOTE
- SHLD 1 ;JMP WBOOT AT LOCATION 00
- STA 5
- LXI H,BDOS
- SHLD 6 ;JMP BDOS AT LOCATION 5
- STA 7*8 ;JMP TO MON80 (MAY HAVE BEEN CHANGED BY DDT)
- LXI H,MON80
- SHLD 7*8+1
- ; LEAVE IOBYTE SET
- ; PREVIOUSLY SELECTED DISK WAS B, SEND PARAMETER TO CPM
- LDA CDISK ;LAST LOGGED DISK NUMBER
- MOV C,A ;SEND TO CCP TO LOG IT IN
- EI
- JMP CPMB
- ;
- ; ERROR IN BOOTING, PRINT MESSAGE AND GIVE UP
- ;
- BOOTERR:
- LXI H,BOOTMSG
- CALL PRMSG
- JMP RMON80 ;MDS HARDWARE MONITOR
- ;
- BOOTMSG:
- DB '?BOOT',0
- ;
- ;
- CONST: ;CONSOLE STATUS TO REG-A
- ; (EXACTLY THE SAME AS MDS CALL)
- JMP CSTS
- ;
- CONIN: ;CONSOLE CHARACTER TO REG-A
- CALL CI
- ANI 7FH ;REMOVE PARITY BIT
- RET
- ;
- CONOUT: ;CONSOLE CHARACTER FROM C TO CONSOLE OUT
- PUSH B ;SAVE CHARACTER TO SEND
- CALL DO$SEL ;ASK USER TO MOUNT CORRECT DISK
- POP B ;GET CHARACTER FOR CONOUT
- JMP CO
- ;
- LIST: ;LIST DEVICE OUT
- ; (EXACTLY THE SAME AS MDS CALL)
- MOV A,C ;THROW AWAY LINE FEEDS
- CPI LF
- RZ
- JMP LO
- ;
- PUNCH: ;PUNCH DEVICE OUT
- ; (EXACTLY THE SAME AS MDS CALL)
- JMP PO
- ;
- READER: ;READER CHARACTER IN TO REG-A
- ; (EXACTLY THE SAME AS MDS CALL)
- JMP RI
- ;
- HOME: ;MOVE TO HOME POSITION
- ; TREAT AS TRACK 00 SEEK
- MVI C,0
- JMP SETTRK
- ;
- ; SELECT THE DRIVE IN REG C.
- ;
- SELDSK:
- MOV A,C ;SAVE SELECT REQUEST UNTIL READ OR WRITE TIME
- STA SELREQ
- RET
- ;
- ; ACTUALLY PERFORM THE SELECTION OF THE DRIVE IN SELREQ
- ;
- DO$SEL:
- LDA SELREQ ;GET REQUESTED DRIVE NUMBER
- MOV C,A ;INTO REG C
- LDA LASTSEL ;SEE IF REQUEST IS SAME AS LAST DRIVE SELECTED?
- CMP C
- RZ ;IF SO WE ARE DONE - RETURN
- MOV A,C ;IF NOT - UPDATE LAST DRIVE SELECTED BYTE
- STA LASTSEL
- PUSH B ;SAVE REQUESTED DRIVE
- CALL CONST ;CLEAR ANY CHARACTER WAITING IN INPUT LATCHES
- ORA A
- CNZ CONIN
- LXI H,MMSG ;SEND MOUNT MESSAGE
- CALL PRMSG
- POP B ;GET REQUEST
- PUSH B ;AND SAVE AGAIN
- MVI A,'A' ;CONVERT REQUEST DRIVE NO TO ASCII 'A' - 'D'
- ADD C
- MOV C,A
- CALL CONOUT ;SEND IT FOLLOWING MOUNT MESSAGE
- CALL CONIN ;WAIT FOR USER TO SRIKE ANY KEY
- POP B ;GET REQUESTED DRIVE
- ;SEE IF REQUESTED DISK > NODISKS
- LDA NODISKS
- MOV B,A ;SAVE NODISK IN REG B FOR SELMOD
- DCR A
- CMP C
- JNC SELPHYS ;NO - JUST SELECT REQUESTED PHYSICAL DRIVE
- MOV A,C ;GET REQUESTED DRIVE INTO REG A
- SELMOD: ;TAKE REQUEST MOD NODISKS BY SUBTRACTION
- SUB B
- JNC SELMOD ;SUBTRACT UNTIL OVERDRAFT
- ADD B ;RESTORE OVERDRAFT
- MOV C,A ;REQUEST MOD NODISKS TO REG C FOR SELECTION
- SELPHYS: ;SELECT PHYSICAL DRIVE IN REG C
- MOV A,C ;GET DRIVE NUMBER
- ANI 11B ;LEAVE ONLY SIGNIFICANT BITS
- RRC ;MOVE TO B7, B6 FOR IOPB
- RRC
- MOV C,A ;BACK TO REG C WITH IT
- LDA IOPB ;GET EXISTING IOPB COMMAND
- ANI 0011$1111B ;MASK OUT OLD DRIVE SELECT BITS
- ORA C ;OR IN NEW BITS
- STA IOPB ;REPLACE UPDATED COMMAND
- RET
- ;
- MMSG: DB CR, LF, 'MOUNT ', 0
- ;
- ;
- SETTRK: ;SET TRACK ADDRESS GIVEN BY C
- LXI H,IOT
- MOV M,C
- RET
- ;
- SETSEC: ;SET SECTOR NUMBER GIVEN BY C
- MOV A,C ;SECTOR NUMBER TO ACCUM
- STA IOS ;STORE SECTOR NUMBER TO IOPB
- RET
- ;
- SETDMA: ;SET DMA ADDRESS GIVEN BY REGS B,C
- MOV L,C
- MOV H,B
- SHLD IOD
- RET
- ;
- READ:
- MVI E,READFUN ;LOAD UP CONTROLLER READ COMMAND
- JMP DOIO ;CONTINUE AT COMMON DISK IO ROUTINE
- WRITE:
- MVI E,WRITEFUN ;LOAD UP CONTROLLER WRITE COMMNAD
- ;AND FALL THRU TO COMMON DISK IO
- DOIO:
- PUSH D ;SAVE R/W FLAG
- CALL DO$SEL ;SELECT CORRECT DRIVE
- POP D ;GET R/W FLAG BACK
- LXI H,IOPB ;POINT TO IOPB AND FUNCTION BYTE
- MOV A,M ;GET EXISTING FUNCTION
- ANI 1111$1000B ;MASK OUT OLD FUNCTION
- ORA E ;OR IN NEW FUNCTION
- MOV M,A ;REPLACE NEW FUNCTION INTO IOPB
- MOV A,L ;START DISK IO BY SENDING IOPB ADDRESS
- OUT ILOW
- MOV A,H ;SEND HIGH ORDER IOPB ADDRESS
- OUT IHIGH
- IOWAIT:
- IN READY ;WAIT FOR CONTROLLE TO FINISH
- ANI BUSY ;IS IT STILL BUSY?
- JNZ IOWAIT ;YES - KEEP WAITING
- IN READY ;SEE IF COMMAND HAD A RETRY
- ANI RTRYBIT
- JZ NORTRY ;NO RETRY - SKIP RETRY MESSAGE
- LXI H,RTRYMSG ;HAD A RETRY, WARN OPPERATOR WITH A MESSAGE
- CALL PRMSG
- NORTRY:
- IN ERRBITS ;GET ERROR STATUS
- ORA A ;RETURN REG A ZERO IF OK
- RZ
- PUSH PSW ;SAVE ERROR BITS
- LXI H,ERRMSG ;PRINT ERROR STATUS MESSAGE
- CALL PRMSG
- POP PSW ;GET ERROR BITS BACK
- CALL PRHEX ;PRINT THEM IN HEX
- MVI A,1 ;SEND ERROR FLAG BACK TO BDOS
- RET
- ;
- RTRYMSG:
- DB 'RETRYING ', 0
- ;
- ERRMSG:
- DB 'ERROR STAT (HEX)=', 0
- ;
- ;
- ; UTILITY SUBROUTINES
- PRMSG: ;PRINT MESSAGE AT H,L TO 0
- MOV A,M
- ORA A ;ZERO?
- RZ
- ; MORE TO PRINT
- PUSH H
- MOV C,A
- CALL CONOUT
- POP H
- INX H
- JMP PRMSG
- ;
- ; PRINT A BYTE AS TWO HEX DIGITS, BYTE TO PRINT IN REG A
- ;
- PRHEX:
- PUSH PSW ;SAVE BYTE
- RRC! RRC! RRC! RRC ;PRINT HIGH NIBBLE FIRST
- CALL PRNIB
- POP PSW ;GET BYTE BACK
- ;FALL THRU TO PRINT LOW NIBBLE
- ;
- ; PRINT A NIBBLE AS ONE HEX DIGIT, NIBBLE IN REG A B0 - B3
- ;
- PRNIB:
- ANI 0000$1111B ;LEAVE ONLY LOW NIBBLE
- ADI 90H ;ASK INTEL HOW THE NEXT FOUR LINES WORK
- DAA
- ACI 40H
- DAA
- MOV C,A ;ASCII CHR TO PRINT TO REG C
- JMP CONOUT ;PRINT & RETURN FROM CONOUT
- ;
- ;
- ; DATA AREAS (MUST BE IN RAM)
- ;
- LASTSEL DB 0 ;LAST DRIVE SELECTED (INITIALIZE TO DRIVE A)
- SELREQ DB 0 ;DRIVE SELECT REQUEST
- ;
- ; MAIN READ / WRITE IOPB
- ;
- IOPB:
- DB READFUN ;READ COMMAND, NO INTERRUPTS
- DB 1 ;ONE SECTOR READ AT A TIME
- IOT: DB OFFSET ;TRACK NUMBER
- IOS: DB 1 ;SECTOR NUMBER
- IOD: DW 80H ;DMA ADDRESS
- DB 1 ;SECTOR LENGTH = 128 BYTES
- DB 0FFH ;NORMAL DATA MARK, 3 RETRYS,
- ;IBM FORMAT, 128 BYTE TRANSFER
- DB 0 ;IGNORE BLOCK TAG
- DB 4 ;SIDE 0, UNBUFFERED, SINGLE DENSITY,
- ;LAST IOPB
- DW 0 ;NO NEXT IOPB
- ;
- ; FIRST BOOT IOPB, READS TRACK 0 STARTING WITH SECTOR 2 INTO CPMB
- ;
- BTIOPB1:
- DB READFUN ;READ WITH NO INTERRUPTS
- DB 26-1 ;READ ALL OF TRACK 0 BUT SECTOR 1 (WHICH HOLDS BOOT)
- DB 0 ;TRACK 0
- DB 2 ;STARTING WITH SECTOR 2
- DW CPMB ;START LOADING AT CPMB
- DB 1 ;SECTOR LENGTH = 128 BYTES
- DB 0FFH ;NORMAL DATA MARK, 3 RETRYS, IBM FORMAT
- ;AND 128 BYTE TRANSFER
- DB 0 ;IGNORE BLOCK TAG
- DB 100B ;SIDE 0, UNBUFFERED, SINGLE DENSITY, LAST IOPB
- DW 0 ;NO NEXT IOPB
- ;
- ; SECOND BOOT IOPB, READ REMAINDER OF DOS FROM TRACK 1 INTO FOLLOWING
- ; MEMORY ADDRESSES
- ;
- BTIOPB2:
- DB READFUN ;READ WITH NO INTERRUPTS
- DB (PATCH-CPMB)/128-(26-1) ;NUMBER OF SECTORS ON TRACK 1
- DB 1 ;TRACK 1
- DB 1 ;STARTING WITH SECTOR 1
- DW CPMB+(26-1)*128 ;ADDRESS FOLLOWING READ OF FIRST IOPB
- DB 1 ;SECTOR LENGTH = 128 BYTES
- DB 0FFH ;NORMAL DATA MARK, 3 RETRYS, IBM FORMAT,
- ;AND 128 BYTE TRANSFER
- DB 0 ;IGNORE BLOCK TAG
- DB 100B ;SIDE 0, UNBUFFERED, SINGLE DENSITY, LAST IOPB
- DW 0 ;NO NEXT IOPB ADDRESS
- ;
- END
-