home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol076
/
fast.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
21KB
|
779 lines
;
; TITLE CP/M SPEED-UP BY DISK I/O BUFFERING
; FILENAME FAST.ASM
; AUTHOR Robert A. Van Valzah 12/25/78
; LAST REVISED 8-Oct-1981 David Bennett
; REASON Upgrade to CP/M 2.0 compatibility
;
;
; \\\\\\\\\\\\\\\\\ /////////////////
; >>>>>>>>>>>>>>>>> E Q U A T E S <<<<<<<<<<<<<<<<<
; ///////////////// \\\\\\\\\\\\\\\\\
;
BASE EQU 100H ;ORG FOR THIS ASSEMBLY OF FAST
VERS EQU 201 ;FAST VERSION NUMBER
;
; CP/M SYSTEM ENTRY POINTS AND RAM EQUATES
;
BOOT EQU 0 ;ADDRESS OF WARM BOOT VECTOR
CURDSK EQU 4 ;ADDRESS OF CURRENTLY LOGGED DRIVE
BDOS EQU 5 ;ADDRESS OF BDOS ENTRY VECTOR
DBUF EQU 80H ;BUFFER USED FOR COMMAND LINE HOLDING
TPA EQU 100H ;TRANSIENT PROGRAM AREA
;
; GLOBAL EQUATES
;
SECLEN EQU 80H ;LENGTH OF A SECTOR IN BYTES
DIRTRK EQU 2 ;TRACK WHICH HOLDS DIRECTORY
;
; TOKEN VALUE EQUATES
;
SENTTOK EQU 1 ;TOKEN SHOWING DRIVE & TRACK INFO SENT
UPDTTOK EQU 1 ;TOKEN SHOWING SECTOR GETS WRITTEN
ONLNTOK EQU 3 ;TOKEN SHOWING THAT A DRIVE IS 'ON LINE'
;
; ASCII CHARACTER EQUATES
;
CR EQU 13 ;CARRIAGE RETURN
LF EQU 10 ;LINE FEED
;
; BDOS FUNCTION NUMBER EQUATES
;
READ EQU 20 ;READ A RECORD FROM A FILE
OPEN EQU 15 ;OPEN A FILE FOR READING
SETDMA EQU 26 ;CHANGE DMA ADDRESS
PAGE
;
;
; \\\\\\\\\\\\\\\\ ////////////////
; >>>>>>>>>>>>>>>> M A C R O S <<<<<<<<<<<<<<<<
; //////////////// \\\\\\\\\\\\\\\\
;
$-MACRO
;
; THE CPM MACRO CALLS BDOS TO EXECUTE THE FUNCTION PASSED
; AS THE FIRST ARGUMENT. THE SECOND ARGUMENT IS THE
; 'INFORMATION' TO PASSED TO CP/M (IF ANY).
;
CPM MACRO FUNC,INFO
MVI C,FUNC
IF NOT NUL INFO
LXI D,INFO
ENDIF
CALL BDOS
ENDM
PAGE
;
; \\\\\\\\\\\\\\\\ F A S T ////////////////
; >>>>>>>>>>>>>>>> I N I T <<<<<<<<<<<<<<<<
; //////////////// M O D U L E \\\\\\\\\\\\\\\\
;
;
; THIS MODULE MAY BE COMPLETELY OVERLAID ONCE FAST HAS BEEN
; SUCCESSFULLY INSTALLED IN THE SYSTEM. IT BECOMES PART OF
; THE TPA.
;
;
; CONTROL IS TRANSFERED TO THIS ADDRESS (THE BASE OF FAST)
; UPON COMPLETION OF THE PACKUP MODULE. HERE, WE INSTALL
; FAST AND LOAD THE TRANSIENT.
;
ORG BASE
JMP FASTNTRY ;JUMP AROUND FIRST PARAMETER BLOCK
;
; THIS IS THE FIRST (OF TWO) PARAMETER PASSING BLOCKS.
; INFORMATION IS PASSED BETWEEN THE FAST AND PACKUP MODULES.
; ANY CHANGES MADE TO THIS BLOCK MUST ALSO BE MADE TO THE
; CORRESPONDING BLOCK IN THE PACKUP MODULE.
;
;**************************************************************
; *
LEN: ; *
DW CODELEN ;RELOCATION LENGTH *
; *
FCB: ;FCB USED TO LOAD COM FILE *
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; *
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; *
; *
;**************************************************************
;
; END OF FIRST PARAMETER BLOCK
;
FASTNTRY:
LXI SP,STACK ;USE LOCAL STACK SPACE
CALL LINKUP ;INSTALL FAST BY LINKING TO CP/M
LDA CURDSK ;INIT DDB POINTERS TO CURRENT DRIVE
MOV C,A
CALL FSETDSK
CALL LOADTRAN ;LOAD THE TRANSIENT
CALL MSGP ;PRINT FAST SIGNON MESSAGE
DB 'Alfred Hospital FAST '
;DEFINE VERSION NUMBER IN ASCII
DB '0'+vers/100
db '.'
DB '0'+(VERS/10) mod 10
DB '0'+VERS MOD 10
DB CR, LF+80H
JMP BEGINE ;BEGIN EXECUTION OF TRANSIENT
PAGE
;
; LINKUP INSTALLS FAST IN A CP/M SYSTEM IN TWO STEPS.
; INTERNALLY REFERENCED ROUTINE.
; FIRST, THE EXISTING BIOS JUMP TABLE IS SAVED AND IT IS
; REPLACED WITH A JUMP TABLE INTO FAST, AND
; SECOND, THE BDOS VECTOR IS MODIFIED TO JUMP TO THE BASE OF
; FAST, WHICH, IN TURN, JUMPS TO THE REAL BDOS. THUS,
; TRANSIENTS THINK THE TPA ENDS BELOW FAST INSTEAD OF BELOW
; BDOS.
;
LINKUP:
; STEP 1
LDA BOOT+2 ;GET BIOS BASE ADDRESS INTO DE
MOV D,A
MVI E,0
PUSH D ;SAVE FOR SECOND PART OF TRANSFER
LXI H,SAVEJMP
MVI C,jtablen ;length of jump table
CALL XF1 ;MOVE FROM BIOS INTO SAVEJMP
;REPLACE OLD TABLE WITH LINK TO FAST
LXI D,FASTLINK
POP H
MVI C,jtablen
CALL XF1 ;MOVE FROM FAST LINK INTO BIOS
; STEP 2
LHLD BDOS+1 ;GET CURRENT BDOS BASE ADDRESS
SHLD NEWBVECT+1 ;COPY IT INTO THE NEW BDOS VECTOR
LXI H,NEWBVECT ;MODIFY BDOS VECTOR TO JMP TO
SHLD BDOS+1 ;NEW BDOS VECTOR
RET
;
; LOADTRAN LOAD THE TRANSIENT NAMED IN THE ARGUMENT TO FAST
; INTO THE TPA WITH CHECKING FOR OVERLAY (LOAD ERROR -
; TRANSIENT TOO BIG OR TPA TOO SMALL).
; RETURNS ONLY IF LOAD WENT OK. BAILS OUT WITH ERROR MESSAGE
; VIA UNLINK OTHERWISE.
; INTERNALLY REFERENCED ROUTINE.
;
LOADTRAN:
LXI D,TPA ;SET DMA ADDRESS INTO TPA FOR OPEN
PUSH D ;SAVE DMA ADDRESS FOR INCREMENTING
CPM SETDMA
CPM OPEN,FCB ;OPEN THE COM FILE
INR A ;WAS OPEN SUCCESSFULL?
JZ NOCMERR ;NO - ISSUE NO COM FILE ERROR
READSEC:
POP D ;GET DMA ADDRESS FROM STACK
PUSH D ;AND SAVE BACK FOR LATER
MVI A,HIGH (BASE-100H) ;MAX ALLOWABLE DMA ADDRESS
CMP D ;IS COM FILE TOO BIG?
JC LOADERR ;YES - ISSUE LOAD ERROR
CPM SETDMA ;PASS DMA ADDRESS TO CP/M
POP D ;INCREMENT DMA ADDRESS BY ONE SECTOR
LXI H,SECLEN
DAD D
PUSH H ;PUT NEW DMA ADDRESS BACK
CPM READ,FCB ;READ A SECTOR FROM COM FILE INTO TPA
ORA A ;WAS READ OK?
JZ READSEC ;YES - KEEP READING
;NOPE - ALL DONE LOADING
CPM SETDMA,DBUF ;SET DMA ADDRESS LIKE CCP WOULD
POP B ;CLEAN GARBAGE DMA ADDRESS OFF STACK
RET
;
LOADERR:
CALL MSGP ;PRINT LOAD ERROR MESSAGE
DB 'OUT OF MEMOR', 'Y'+80H
JMP UNLINK ;RETURN TO CP/M
;
NOCMERR:
CALL MSGP ;PRINT 'NO COM FILE'
DB 'NO COM FIL', 'E'+80H
JMP UNLINK ;RETURN TO CP/M
;
; END OF INIT MODULE
PAGE
;
; \\\\\\\\\\\\\\\\ ////////////////
; >>>>>>>>>>>>>>>> F A S T <<<<<<<<<<<<<<<<
; //////////////// M O D U L E \\\\\\\\\\\\\\\\
;
;
; THIS MODULE CONTAINS THE ACTUAL DISK I/O BUFFERING CODE.
;
; THIS ADDRESS BECOMES THE NEW TOP OF THE TPA.
;
ORG (($-1) OR 255) + 1 ;ORG TO PAGE BOUNDRY
DS 6 ;SO BDOS VECTOR ADDRESS = XXX6
NEWBVECT:
JMP $-$ ;ADDRESS WILL BE MODIFIED BY LINKUP
;
; DDB ADDRESS BUFFERS. EACH BUFFER IS FOUR W-O-R-D-S LONG,
; ONE WORD FOR THE ADDRESS OF THE BUFFER FOR EACH OF FOUR
; POSSIBLE DRIVES. IF THERE IS NO DDB FOR A GIVEN DRIVE,
; THE DDB ADDRESS IS ZERO.
;
RDBUF DW 0, 0, 0, 0
WRBUF DW 0, 0, 0, 0
DIRBUF DW 0, 0, 0, 0
;
; 8-10-81 upgrade to CP/M compatibility
; when off-line disc is first used, BIOS routine SETDSK is called
; CP/M 2.x BIOS returns a vital parameter in HL, which must be
; passed back to BDOS. It is stored here for that purpose.
;
online dw 0, 0, 0, 0 ; stored HL return from SETDSK
;
; USER PATCHABLE MEMORY HIT (ERROR) ROUTINE
; INTERNALLY REFERENCED ROUTINE.
;
MEMHIT:
PUSH D ! PUSH B ;SAVE REGISTERS
CALL MSGP
DB 'MEMORY HI', 'T'+80H
POP B ! POP D
RET
;
FASTLINK: ;JMP TABLE TO REPLACE EXISTING BIOS'S
JMP UNLINK ;FOR EITHER BOOT, REMOVE FAST AND BOOT
JMP UNLINK
JMP CCONST ;JUST PASS ALL CHARACTER I/O THRU
JMP FCONIN ;EXCEPT CONSOLE IN
JMP CCONOUT
JMP CLIST
JMP CPUNCH
JMP CREADER
JMP FHOME ;USE FAST HOME INSTEAD OF BIOS
JMP FSETDSK ;USE FAST SET DISK
JMP FSETTRK ;USE FAST SET TRACK
JMP FSETSEC ;USE FAST SET SECTOR
JMP FSETDMA ;USE FAST SET DMA
JMP FREAD ;USE FAST READ SECTOR
JMP FWRITE ;USE FAST WRITE SECTOR
jtablen equ $-fastlink
;
;
BEGINE: ;ENTRY POINT FROM INIT TO EXEC. TRANS.
CALL TPA ;EXECUTE TRANS.
;IF HE RETURNS, FALL THRU TO UNLINK
;
; UNLINK IS THE COMPLIMENTARY ROUTINE TO LINKUP. IT RESTORES
; THE BIOS JUMP TABLE AND THE BDOS VECTOR TO THEIR STATES
; BEFORE FAST WAS INSTALLED (BY LINKUP).
; INTERNALLY AND EXTERNALLY REFERENCED ROUTINE.
;
UNLINK:
LXI SP,STACK ;SETUP LOCAL STACK
;RETURN BIOS VECTORS UNHARMED
LXI D,SAVEJMP
LDA BOOT+2 ;GET BIOS BASE INTO DE
MOV H,A
MVI L,0
MVI C,jtablen ;length of jump table
CALL XF1 ;MOVE FROM SAVEJMP TO BIOS BASE
LHLD NEWBVECT+1 ;GET REAL BDOS VECTOR ADDRESS
SHLD BDOS+1 ;STORE IT INTO REAL BDOS VECTOR
CALL CLOSE ;EMPTY ANY DDB'S WHICH MAY HAVE DATA
CALL MSGP ;PRINT FAST SIGN OFF MESSAGE
DB CR, LF
DB 'FAST terminate', 'd'+80H
JMP BOOT ;AND REBOOT
;
; FAST CONSOLE IN
; EXTERNALLY REFERENCED ROUTINE
; WRITES ALL SECTORS WAITING TO BE WRITTEN SO THAT USER
; CAN'T GET HIMSELF INTO TROUBLE BY REMOVING THE DISK
; EXTERNALLY REFERENCED ROUTINE.
;
FCONIN:
CALL CLOSE ;WRITE ALL DDB'S
JMP CCONIN ;NOW DO THE CONSOLE INPUT
;
; FAST HOME ROUTINE
; INTERNALLY AND EXTERNALLY REFERENCED
;
FHOME:
MVI C,0 ;JUST PASS 0 TO FAST SET TRACK
;FALL THRU
;
; FAST SET TRACK
; EXTERNALLY REFERENCED ROUTINE
; REQUESTED TRACK IS JUST STORED AWAY UNTIL
; A READ OR WRITE REQUEST COMES IN.
;
FSETTRK:
MOV A,C ;GET REQUEST TO REG A
STA REQTRK ;STORE IT
RET
;
; FAST SET SECTOR
; EXTERNALLY REFERENCED ROUTINE
; THE REQUESTED SECTOR IS JUST
; STORED AWAY UNTIL A READ OR WRITE COMES IN.
;
FSETSEC:
MOV A,C ;GET REQUESTED SECTOR TO REG A
STA REQSEC ;STORE IT
RET
;
; FAST SET DMA ADDRESS
; EXTERNALLY REFERENCED ROUTINE.
;
FSETDMA:
MOV H,B ;REQUESTED DMA ADR INTO HL
MOV L,C
SHLD REQDMA ;SAVE IT
RET
;
; FAST SET DISK DRIVE
; EXTERNALLY REFERENCED ROUTINE
;
FSETDSK:
MOV E,C ;SAVE DRIVE FOR ON LINE CODE
MOV A,C ;GET REQUESTED DRIVE
STA REQDSK ;SAVE FOR PASS THRU
ADD A
MOV C,A ;FORM word INDEX IN REG BC
MVI B,0
LXI H,DIRBUF ;GET NEW DIR DDB POINTER
CALL INDXIND
SHLD DIRADR ;AND SAVE IT
LXI H,RDBUF ;GET NEW READ TRACK DDB POINTER
CALL INDXIND
SHLD RDADR ;AND SAVE IT
LXI H,WRBUF ;GET NEW WRITE TRACK DDB POINTER
CALL INDXIND
SHLD WRADR
LXI H,ONLINE ;BASE OF 'ON LINE' VECTOR
call indxind
MOV A,h ;IS THIS DRIVE ON LINE?
ORA l
RNZ ;->yes, return to BDOS with HL set
; get this drive on-line
push b ;preserve word index into table
mov c,e
CALL CSETDSK ;first, really select it
pop b
mov a,h ;check the return in HL
ora l
rz ;->zero is error, return to BDOS with HL zero
push h ;ok, save (HL)
lxi h,online;..in online table
dad b ;..word-indexed by drive number
pop b
mov m,c
inx h
mov m,b
push b ;we still need this for later
lda reqdsk ;get disc again, home it
mov c,a
CALL CHOME
LHLD DIRADR ;AND READ THE DIRECTORY IF IT IS BUFFERED
call RDDDB
pop h
ret ;return to BDOS with HL set
;
; FAST READ SECTOR
; EXTERNALLY REFERENCED ROUTINE.
;
FREAD:
LHLD RDADR ;GET ADDRESS OF READ TRACK DDB
CALL GETSEC ;TRY TO FIND SECTOR IN READ DDB
RC ;FOUND IT
LHLD DIRADR ;TRY TO FIND SECTOR IN DIRECTORY DDB
CALL GETSEC
RC ;FOUND IT
LHLD WRADR ;TRY TO FIND SECTOR IN WRITE DDB
CALL GETWSEC
RC ;FOUND IT
LHLD RDADR ;SEE IF THERE IS A READ TRACK BUFFER
MOV A,H
ORA L
JZ RDPASS ;NO - THEN JUST PASS THE READ THRU
LDA REQTRK ;YES - SEE IF READING FROM NON-DIRECTORY
CPI DIRTRK ;SECTORS OF DIRECTORY TRACK
JZ RDPASS ;YES - JUST LET THAT PASS THRU
PUSH PSW ;NO - WRITE ANY DATA IN READ BUFFER
PUSH H
CALL WRDDB
POP H
POP PSW
MOV M,A ;FILL NEW TRACK INTO READ DDB
PUSH H ;SAVE READ DDB ADDRESS
CALL RDDDB ;AND FILL NEW DDB WITH DATA
POP H ;GET READ DDB ADDRESS BACK
JMP GETSEC ;TRANSFER SECTOR FROM DDB TO CALLER
;AND RETURN FROM GETSEC
;
; FAST SECTOR WRITE
; EXTERNALLY REFERENCED ROUTINE.
;
FWRITE:
LHLD WRADR ;TRY TO PUT SECTOR INTO WRITE BUFFER
CALL PUTSEC
RC ;IT WENT - ALL DONE
LHLD DIRADR ;TRY TO PUT IT INTO DIRECTORY BUFFER
CALL PUTSEC
RC ;IT WENT - ALL DONE
LHLD RDADR ;TRY TO PUT INTO READ BUFFER
CALL PUTSEC
RC ;IT WENT - ALL DONE
LHLD WRADR ;IS THERE A WRITE TRACK BUFFER?
MOV A,H
ORA L
JZ WRPASS ;NO - JUST PASS THIS WRITE THRU
LDA REQTRK ;YES - SEE IF THIS IS A NON-DIRECTORY
CPI DIRTRK ;SECTOR ON THE DIRECTORY TRACK?
JZ WRPASS ;YES - JUST PASS THAT THRU
PUSH PSW ;NO - DUMP EXISTING WRITE BUFFER TO DISK
PUSH H
CALL WRDDB
POP H
POP PSW
MOV M,A ;AND BUFFER UP REQUESTED TRACK
CALL PUTSEC ;MOVE SECTOR INTO WRITE BUFFER
LDA WRTERRF ;RETURN WRITE ERROR FLAG
RET
;
; CLOSE ALL OPEN DDB'S. WRITE ANY DATA LEFT IN THEM OUT TO
; DISK
; INTERNALLY REFERENCED ROUTINE.
;
CLOSE:
MVI C,4*3 ;DDB COUNT
LXI H,RDBUF ;START OF DDB ADDRESS TABLES
CLOS:
MOV E,M ;GET DDB ADDRESS TO REG DE
INX H
MOV D,M
INX H
PUSH H ;SAVE TABLE ADDRESS
PUSH B
XCHG ;DDB ADDRESS TO REG HL
CALL WRDDB ;CLOSE ONE DDB
LDA WRTERRF ;ANY WRITE ERRORS IN CLOSING?
ORA A
JZ CLOSOK ;NO - KEEP CLOSING
CALL MSGP
DB 'DISK WRITE ERROR', CR, LF+80H
CLOSOK:
POP B ;GET COUNT
POP H ;GET TABLE ADDRESS
DCR C ;DONE ALL DDBS YET?
JNZ CLOS ;NO - KEEP CLOSING
RET ;YES - ALL DONE
;
; INDEXED INDIRECT ADDRESSING. RETURNS THE WORD AT THE
; ADDRESS BASE + INDEX
; INTERNALLY REFERENCED ROUTINE.
;
INDXIND:
DAD B ;ADD IN INDEX
MOV A,M ;GET LOW ORDER OF RESULT
INX H
MOV H,M ;GET HIGH ORDER OF RESULT
MOV L,A
RET
;
; GET A SECTOR FROM A WRITE DDB INTO REQDMA. MATCHES ONLY
; IF UPDATE FLAG IS SET. RETURNS FLAG IF FOUND.
; INTERNALLY REFERENCED ROUTINE.
;
GETWSEC:
CALL SRCHDDB ;FIND A SECTOR AND TRACK MATCH?
RNC ;NO - RETURN WITHOUT FLAG
INX H ;YES - SEE IF SECTOR HAS BEEN
MOV A,M ;WRITTEN (UPDATE FLAG=1)?
ORA A
JNZ GS1 ;YES - TRANSFER FROM WRITE DDB
CALL RDPASS ;NO - BYPASS BUFFERING
STC ;SET FOUND IT FLAG
RET
;
; GET A SECTOR FROM A DDB INTO REQDMA. FLAG SET IF FOUND.
; INTERNALLY REFERENCED ROUTINE.
;
GETSEC:
CALL SRCHDDB ;DO WE HAVE THE REQUESTED SECTOR?
RNC ;NO - RETURN WITHOUT FLAG
INX H ;YES - POINT TO SECTOR DATA
GS1: ;ENTRY FROM GETWSEC (ABOVE)
INX H
XCHG ;DATA ADDRESS TO REG DE
LHLD REQDMA ;DESTINATION TO REG HL
CALL XFER ;PERFORM THE TRANSFER
LDAX D ;GET GOOD/BAD FLAG
STC ;SET 'FOUND IT' FLAG
RET
;
; SEARCH A DDB FOR THE REQUESTED TRACK AND SECTOR
; INTERNALLY REFERENCED ROUTINE.
;
SRCHDDB:
MOV A,H ;SEE IF DDB IS PRESENT AT ALL
ORA L
RZ ;NO - WE DON'T HAVE IT
LDA REQTRK ;YES - SEE IF REQTRK MATCHES DDB TRACK
XRA M
RNZ ;NO MATCH - WE DON'T HAVE IT
INX H ;TRACKS MATCH - CHECK SECTORS
INX H
LDA REQSEC
MOV C,A
LXI D,SECLEN+3 ;BYTES BETWEEN SECTOR NUMBERS
SRCH1:
MOV A,M ;GET A SECTOR NUMBER FROM DDB
ORA A ;END OF DDB?
RZ ;YES - RETURN WITHOUT FLAG
CMP C ;NO - SEE IF REQSEC MATCHES DDB SECTOR
STC ;PREPARE TO RETURN FLAG IF SO
RZ ;THEY MATCH - RETURN FLAG
DAD D ;NO MATCH - ON TO NEXT SECTOR
JMP SRCH1
;
RDPASS:
CALL PASSTHRU
JMP CREAD
;
; MOVE A SECTOR FROM MEMORY INTO A DDB
; INTERNALLY REFERENCED ROUTINE.
;
PUTSEC:
CALL SRCHDDB ;DOES IT GO IN THIS DDB?
RNC ;NO - RETURN WITHOUT FLAG
INX H ;POINT TO DATA FIELD OF DDB
MVI M,UPDTTOK ;SET UPDATE FLAG
INX H
XCHG ;SAVE DDB ADDRESS IN REG DE
LHLD REQDMA ;GET SOURCE ADDRESS INTO REG HL
XCHG ;NOW REG HL=DDB ADDRESS (DEST) AND . .
CALL XFER ;REG DE=MEMORY (SOURCE)
XRA A ;RETURN WITHOUT WRITE ERROR
MOV M,A ;SET GOOD/BAD FLAG TO GOOD
STC ;SET SECTOR PUT FLAG
RET
WRPASS:
CALL PASSTHRU
JMP CWRITE
;
; PASS ALL DISK I/O PARAMETERS THRU TO BIOS
; INTERNALLY REFERENCED ROUTINE
;
PASSTHRU:
LDA REQDSK ;PASS REQUESTED DISK THRU
MOV C,A
CALL CSETDSK
LDA REQTRK ;PASS REQUESTED TRACK THRU
MOV C,A
CALL CSETTRK
LDA REQSEC ;PASS REQUESTED SECTOR
MOV C,A
CALL CSETSEC
LHLD REQDMA ;PASS REQUESTED DMA ADDRESS
MOV B,H
MOV C,L
JMP CSETDMA ;RETURN FROM CSETDMA
;
; READ A DDB FROM DISK. ALL SECTORS ARE FILED IN, AND THEIR
; UPDATE FLAGS ARE RESET.
; INTERNALLY REFERENCED ROUTINE.
;
RDDDB:
MOV A,H ;DO NOTHING FI NO DDB
ORA L
RZ
PUSH H ;SAVE DDB ADDRESS
CALL SENDDT ;SEND DRIVE AND TRACK INFO TO BIOS
POP H ;GET DDB ADDRESS
INX H ;POINT TO FIRST SECTOR BYTE
INX H
RDDSEC:
MOV A,M ;GET SECTOR NUMBER
ORA A ;END OF DDB?
RZ ;YES - ALL DONE
MOV C,A ;PASS SECTOR TO BIOS
PUSH H ;SAVE WHILE CALLING
CALL CSETSEC
POP H ;GET DDB ADDRESS BACK
INX H ;POINT TO UPDATE FLAG
MVI M,0 ;RESET UPDATE FLAG
INX H ;POINT TO DATA FIELD
PUSH H ;SAVE DATA POINTER
MOV B,H ;DATA ADDRESS TO REG BC
MOV C,L
CALL CSETDMA ;PASS DATA ADDRESS TO BIOS
CALL CREAD ;PERFORM THE READ
POP H ;GET DATA ADDRESS BACK
LXI B,SECLEN ;BYTES TO GOOD/BAD FLAG
DAD B
MOV M,A ;STORE GOOD/BAD FLAG FROM BIOS IN DDB
INX H
JMP RDDSEC ;ON TO NEXT SECTOR
;
; WRITE A DDB BACK TO DISK. ONLY SECTORS WITH THE UPDATE FLAG
; SET GET WRITTEN.
; THE DRIVE AND TRACK INFORMATION FROM THE DDB IS SAVED BY
; THIS ROUTINE AND PASSED TO THE BIOS BY RCLDT ONLY IF
; A SECTOR IS TO BE WRITTEN. THIS IS DONE TO BYPASS BIOS
; DELAYS WHEN SWITCHING DRIVES AND TO PREVENT NEEDLESS
; SEEKING TO TRACKS WHICH MIGHT NOT RECIEVE ANY DATA.
; INTERNALLY REFERENCED ROUTINE.
;
WRDDB:
XRA A ;CLEAR WRITE ERROR FLAG
STA WRTERRF
MOV A,H ;SEE IF A DDB IS PRESENT
ORA L
RZ ;NO - ALL DONE WRITING
MOV A,M ;GET TRACK NUMBER
INR A ;TRACK = 0FFH (MEANING EMPTY)?
RZ ;YES - NO WRITING TO DO
SHLD TRKPTR ;NO - SAVE DISK & TRACK POINTER FOR
XRA A ;RECALL LATER, AND RESET FLAG
STA SENTFLG ;SHOWING THAT THEY HAVEN'T BEEN SENT
INX H ;POINT TO FIRST SECTOR NUMBER
INX H
TSTUPDT:
MOV A,M ;GET SECTOR TO REG A
ORA A ;END OF DDB?
RZ ;YES - ALL DONE
MOV C,A ;SAVE SECTOR IN REG C
INX H ;POINT TO UPDATE FLAG
MOV A,M ;GET UPDATE FLAG
ORA A ;DOES THIS SECTOR NEED UPDATING ON DISK?
CNZ WRSEC ;YES - WRITE IT BACK
LXI D,SECLEN+2 ;BYTES TO NEXT SECTOR NUMBER
DAD D
JMP TSTUPDT ;CHECK THE NEXT UPDATE FLAG
;
; WRITE A SECTOR FROM A DDB BACK OUT TO DISK.
; INTERNALLY REFERENCED ROUTINE.
;
WRSEC:
MVI M,0 ;RESET UPDATE FLAG
PUSH H ;SAVE UPDATE FLAG POINTER
CALL CSETSEC ;PASS SECTOR NUBER TO BIOS
CALL RCLDT ;PASS DRIVE AND TRACK TO BIOS
POP H ;GET UPDATE FLAG POINTER
PUSH H ;AND SAVE AGAIN
INX H ;POINT TO DATA
MOV B,H ;DATA ADDRESS TO REG BC
MOV C,L
CALL CSETDMA ;PASS DMA ADDRESS TO BIOS
CALL CWRITE ;WRITE THE DATA OUT
LXI H,WRTERRF ;OR THIS WRITE ERROR FLAG IN WITH
ORA M ;THE REST FROM THIS WRDDB
MOV M,A
POP H ;GET CALLERS REG HL BACK
RET
;
; RECALL DISK AND TRACK INFO FROM A DDB, PASS IT TO THE BIOS,
; AND SET FLAG SHOWING THAT IS HAS BEEN SENT.
; INTERNALLY REFERENCED ROUTINE.
;
RCLDT:
LXI H,SENTFLG ;HAS THIS INFO ALREADY BEEN SENT?
MOV A,M
ORA A
RNZ ;YES - SKIP SENDING AGAIN
MVI M,SENTTOK ;NO - SET FLAG SHOWING IT HAS BEEN SENT
LHLD TRKPTR ;GET POINTER TO DRIVE & TRACK INFO
;AND FALL THRU TO SEND IT TO BIOS
;
; SEND DRIVE AND TRACK INFO FROM A DDB TO THE BIOS.
; INTERNALLY REFERENCED ROUTINE.
;
SENDDT:
PUSH H ;SAVE TRACK POINTER
INX H ;POINT TO DRIVE
MOV C,M ;GET DRIVE TO REG C
CALL CSETDSK ;PASS DISK
POP H ;GET TRACK POINTER
MOV C,M ;GET TRACK TO REG C
JMP CSETTRK ;PASS TRACK AND RETURN FROM THERE
;
; MOVE A SECTOR FROM ONE PLACE IN MEMORY TO ANOTHER. GIVE
; ERROR MESSAGE IF DATA CAN'T BE WRITTEN INTO DESTINATION.
; INTERNALLY REFERENCED ROUTINE.
;
XFER:
MVI C,SECLEN ;COUNT NUMBER OF BYTES TO XFER IN C
XF1:
LDAX D ;GET BYTE FROM SOURCE
MOV M,A ;STORE INTO DESTINATION
XRA M ;DID IT GO?
CNZ MEMHIT ;NO - GIVE WARNING MESSAGE
INX H ;INCREMENT DEST POINTER
INX D ;INCREMENT SOURCE POINTER
DCR C ;DONE WITH MOVE YET?
JNZ XF1 ;NO - KEEP MOVING
RET ;YES - ALL DONE
;
; LOCAL MESSAGE PRINTER. WE CAN'T USE BDOS BECAUSE BDOS IS NOT
; RE-ENTRANT (WE MIGHT HAVE GOTTEN HERE VIA BDOS). FOLLOW
; THE CALL TO MSGP WITH THE TEXT OF THE MESSAGE. THE LAST
; CHARACTER OF THE MESSAGE MUST HAVE BIT SEVEN ON (I.E. +80H)
; INTERNALLY REFERENCED ROUTINE.
;
MSGP:
XTHL ;GET MESSAGE ADDRESS TO REG HL
MSG1:
MOV C,M ;GET MESSAGE CHARACTER
PUSH H ;SAVE MESSAGE ADDRESS DURING PRINTING
CALL CCONOUT ;SEND IT
POP H ;RESTORE MESSAGE ADDRESS
MOV A,M ;GET CHR JUST SENT
INX H ;POINT TO NEXT CHARACTER
ORA A ;WAS THAT THE LAST CHR TO PRINT?
JP MSG1 ;NO - KEEP PRINTING
XTHL ;YES - PUT MODIFIED RETURN ADDREESS
RET ;BACK ON STACK AND RETURN PAST MESSAGE
PAGE
;
; \\\\\\\\\\\\\\\\ ////////////////
; >>>>>>>>>>>>>>>> R A M <<<<<<<<<<<<<<<<
; //////////////// A R E A S \\\\\\\\\\\\\\\\
;
;
; SAVE SPACE FOR A COPY OF THE BIOS JUMP TABLE BEFORE THE
; INSTALLATION OF FAST
;
SAVEJMP:
CBOOT: JMP $-$
CWBOOT: JMP $-$
CCONST: JMP $-$
CCONIN: JMP $-$
CCONOUT: JMP $-$
CLIST: JMP $-$
CPUNCH: JMP $-$
CREADER: JMP $-$
CHOME: JMP $-$
CSETDSK: JMP $-$
CSETTRK: JMP $-$
CSETSEC: JMP $-$
CSETDMA: JMP $-$
CREAD: JMP $-$
CWRITE: JMP $-$
;
DIRADR DW 0 ;ADDRESS OF CURRENT DIRECTORY DDB
RDADR DW 0 ;ADDRESS OF CURRENT READ TRACK DDB
WRADR DW 0 ;ADDRESS OF CURRENT WRITE TRACK DDB
;
TRKPTR DW 0 ;POINTER TO TRACK & DRIVE INFO IN DDB
SENTFLG DB 0 ;ZERO IF TRACK & DRIVE HAVEN'T BEEN SENT
WRTERRF DB 0 ;WRITE DDB ERROR FLAG, 0 IF NO ERROR
;
REQDSK DB 0FFH
REQTRK DB 0FFH
REQSEC DB 0FFH
REQDMA DW 0FFFFH
;
DS 10H ;AT LEAST AS MUCH STACK AS CCP
;
ORG (($-1) OR 255) + 1 ;ORG TO NEXT PAGE BOUNDRY
STACK:
;
CODELEN EQU $-BASE
;
ORG CODELEN ;INFORM OPERATOR OF CODE LENGTH
END FASTNTRY