home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG040.ARK
/
NSCBIOS.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
12KB
|
466 lines
; 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