home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / fast2 / fast2.ark / FAST2.ASM < prev    next >
Assembly Source File  |  1985-02-09  |  21KB  |  772 lines

  1.   TITLE        'FAST - CP/M SPEED-UP BY DISK I/O BUFFERING'
  2. ; FILENAME    FAST.ASM
  3. ; AUTHOR    Robert A. Van Valzah    12/25/78
  4. ; LAST REVISED    Bruce R. Ratoff    5/2/80
  5. ; REASON    CP/M VERSION 2.X COMPATIBILITY
  6. ;
  7. ;
  8. ;  \\\\\\\\\\\\\\\\\                   /////////////////
  9. ;   >>>>>>>>>>>>>>>>>  E Q U A T E S  <<<<<<<<<<<<<<<<<
  10. ;  /////////////////                   \\\\\\\\\\\\\\\\\
  11. ;
  12. BASE    EQU    $    ;ORG FOR THIS ASSEMBLY OF FAST (100H IF $+R WAS USED)
  13. MAJVERS    EQU    1    ;FAST MAJOR VERSION NUMBER
  14. MINVERS    EQU    01    ;FAST MINOR VERSION NUMBER
  15. ;
  16. ;    CP/M SYSTEM ENTRY POINTS AND RAM EQUATES
  17. ;
  18. BOOT    EQU    0    ;ADDRESS OF WARM BOOT VECTOR
  19. CURDSK    EQU    4    ;ADDRESS OF CURRENTLY LOGGED DRIVE
  20. BDOS    EQU    5    ;ADDRESS OF BDOS ENTRY VECTOR
  21. DBUF    EQU    80H    ;BUFFER USED FOR COMMAND LINE HOLDING
  22. TPA    EQU    100H    ;TRANSIENT PROGRAM AREA
  23. ;
  24. ;    GLOBAL EQUATES
  25. ;
  26. SECLEN    EQU    80H    ;LENGTH OF A SECTOR IN BYTES
  27. DIRTRK    EQU    2    ;TRACK WHICH HOLDS DIRECTORY
  28. ;
  29. ;    TOKEN VALUE EQUATES
  30. ;
  31. SENTTOK    EQU    1    ;TOKEN SHOWING DRIVE & TRACK INFO SENT
  32. UPDTTOK    EQU    1    ;TOKEN SHOWING SECTOR GETS WRITTEN
  33. ONLNTOK    EQU    3    ;TOKEN SHOWING THAT A DRIVE IS 'ON LINE'
  34. ;
  35. ;    ASCII CHARACTER EQUATES
  36. ;
  37. CR    EQU    13    ;CARRIAGE RETURN
  38. LF    EQU    10    ;LINE FEED
  39. ;
  40. ;    BDOS FUNCTION NUMBER EQUATES
  41. ;
  42. READ    EQU    20    ;READ A RECORD FROM A FILE
  43. OPEN    EQU    15    ;OPEN A FILE FOR READING
  44. SETDMA    EQU    26    ;CHANGE DMA ADDRESS
  45.     PAGE
  46. ;
  47. ;
  48. ;   \\\\\\\\\\\\\\\\                 ////////////////
  49. ;    >>>>>>>>>>>>>>>>  M A C R O S  <<<<<<<<<<<<<<<<
  50. ;   ////////////////             \\\\\\\\\\\\\\\\
  51. ;
  52. ;
  53. ; THE CPM MACRO CALLS BDOS TO EXECUTE THE FUNCTION PASSED
  54. ; AS THE FIRST ARGUMENT.  THE SECOND ARGUMENT IS THE
  55. ; 'INFORMATION' TO PASSED TO CP/M (IF ANY).
  56. ;
  57. CPM    MACRO    FUNC,INFO
  58.     MVI    C,FUNC
  59.     IF    NOT NUL INFO
  60.       LXI    D,INFO
  61.     ENDIF
  62.     CALL    BDOS
  63.     ENDM
  64.     PAGE
  65. ;
  66. ;  \\\\\\\\\\\\\\\\     F A S T     ////////////////
  67. ;   >>>>>>>>>>>>>>>>    I N I T    <<<<<<<<<<<<<<<<
  68. ;  ////////////////   M O D U L E   \\\\\\\\\\\\\\\\
  69. ;
  70. ;
  71. ; THIS MODULE MAY BE COMPLETELY OVERLAID ONCE FAST HAS BEEN
  72. ; SUCCESSFULLY INSTALLED IN THE SYSTEM.  IT BECOMES PART OF
  73. ; THE TPA.
  74. ;
  75. ;
  76. ; CONTROL IS TRANSFERED TO THIS ADDRESS (THE BASE OF FAST)
  77. ; UPON COMPLETION OF THE PACKUP MODULE.  HERE, WE INSTALL
  78. ; FAST AND LOAD THE TRANSIENT.
  79. ;
  80.     ORG    0    ;MAC $+R OPTION WILL TAKE CARE OF HIGH ORIGIN
  81.     JMP    FASTNTRY ;JUMP AROUND FIRST PARAMETER BLOCK
  82. ;
  83. ; THIS IS THE FIRST (OF TWO) PARAMETER PASSING BLOCKS.
  84. ; INFORMATION IS PASSED BETWEEN THE FAST AND PACKUP MODULES.
  85. ; ANY CHANGES MADE TO THIS BLOCK MUST ALSO BE MADE TO THE
  86. ; CORRESPONDING BLOCK IN THE PACKUP MODULE.
  87. ;
  88. ;**************************************************************
  89. ;                                  *
  90. LEN:            ;                      *
  91.     DW    CODELEN    ;RELOCATION LENGTH              *
  92. ;                                  *
  93. FCB:            ;FCB USED TO LOAD COM FILE          *
  94.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;          *
  95.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;          *
  96. ;                                  *
  97. ;**************************************************************
  98. ;
  99. ; END OF FIRST PARAMETER BLOCK
  100. ;
  101. FASTNTRY:
  102.     LXI    SP,STACK ;USE LOCAL STACK SPACE
  103.     CALL    LINKUP    ;INSTALL FAST BY LINKING TO CP/M
  104.     LDA    CURDSK    ;INIT DDB POINTERS TO CURRENT DRIVE
  105.     MOV    C,A
  106.     CALL    FSETDSK
  107.     CALL    LOADTRAN ;LOAD THE TRANSIENT
  108.     CALL    MSGP    ;PRINT FAST SIGNON MESSAGE
  109.     DB    'Beginning execution under FAST '
  110.         ;DEFINE VERSION NUMBER IN ASCII
  111.     DB    '0'+MAJVERS
  112.     DB    '.'
  113.     DB    '0'+MINVERS/10
  114.     DB    '0'+MINVERS MOD 10
  115.     DB    CR, LF+80H
  116.     JMP    BEGINE    ;BEGIN EXECUTION OF TRANSIENT
  117.     PAGE
  118. ;
  119. ; LINKUP INSTALLS FAST IN A CP/M SYSTEM IN TWO STEPS.
  120. ; INTERNALLY REFERENCED ROUTINE.
  121. ; FIRST, THE EXISTING BIOS JUMP TABLE IS SAVED AND IT IS
  122. ; REPLACED WITH A JUMP TABLE INTO FAST, AND
  123. ; SECOND, THE BDOS VECTOR IS MODIFIED TO JUMP TO THE BASE OF
  124. ; FAST, WHICH, IN TURN, JUMPS TO THE REAL BDOS.  THUS,
  125. ; TRANSIENTS THINK THE TPA ENDS BELOW FAST INSTEAD OF BELOW
  126. ; BDOS.
  127. ;
  128. LINKUP:
  129.     ; STEP 1
  130.     LDA    BOOT+2 ;GET BIOS BASE ADDRESS INTO DE
  131.     MOV    D,A
  132.     MVI    E,0
  133.     PUSH    D    ;SAVE FOR SECOND PART OF TRANSFER
  134.     LXI    H,SAVEJMP
  135.     MVI    C,15*3    ;15 JMPS IN TABLE * 3 BYTES PER JMP
  136.     CALL    XF1    ;MOVE FROM BIOS INTO SAVEJMP
  137.             ;REPLACE OLD TABLE WITH LINK TO FAST
  138.     LXI    D,FASTLINK
  139.     POP    H
  140.     MVI    C,15*3
  141.     CALL    XF1    ;MOVE FROM FAST LINK INTO BIOS
  142.     ; STEP 2
  143.     LHLD    BDOS+1 ;GET CURRENT BDOS BASE ADDRESS
  144.     SHLD    NEWBVECT+1 ;COPY IT INTO THE NEW BDOS VECTOR
  145.     LXI    H,NEWBVECT ;MODIFY BDOS VECTOR TO JMP TO
  146.     SHLD    BDOS+1 ;NEW BDOS VECTOR
  147.     RET
  148. ;
  149. ; LOADTRAN LOAD THE TRANSIENT NAMED IN THE ARGUMENT TO FAST
  150. ; INTO THE TPA WITH CHECKING FOR OVERLAY (LOAD ERROR - 
  151. ; TRANSIENT TOO BIG OR TPA TOO SMALL).
  152. ; RETURNS ONLY IF LOAD WENT OK.  BAILS OUT WITH ERROR MESSAGE
  153. ; VIA UNLINK OTHERWISE.
  154. ; INTERNALLY REFERENCED ROUTINE.
  155. ;
  156. LOADTRAN:
  157.     LXI    D,TPA    ;SET DMA ADDRESS INTO TPA FOR OPEN
  158.     PUSH    D    ;SAVE DMA ADDRESS FOR INCREMENTING
  159.     CPM    SETDMA
  160.     CPM    OPEN,FCB ;OPEN THE COM FILE
  161.     INR    A    ;WAS OPEN SUCCESSFULL?
  162.     JZ    NOCMERR    ;NO - ISSUE NO COM FILE ERROR
  163. READSEC:
  164.     POP    D    ;GET DMA ADDRESS FROM STACK
  165.     PUSH    D    ;AND SAVE BACK FOR LATER
  166.     MVI    A,HIGH (BASE-100H) ;MAX ALLOWABLE DMA ADDRESS
  167.     CMP    D    ;IS COM FILE TOO BIG?
  168.     JC    LOADERR    ;YES - ISSUE LOAD ERROR
  169.     CPM    SETDMA    ;PASS DMA ADDRESS TO CP/M
  170.     POP    D    ;INCREMENT DMA ADDRESS BY ONE SECTOR
  171.     LXI    H,SECLEN
  172.     DAD    D
  173.     PUSH    H    ;PUT NEW DMA ADDRESS BACK
  174.     CPM    READ,FCB ;READ A SECTOR FROM COM FILE INTO TPA
  175.     ORA    A    ;WAS READ OK?
  176.     JZ    READSEC    ;YES - KEEP READING
  177.             ;NOPE - ALL DONE LOADING
  178.     CPM    SETDMA,DBUF ;SET DMA ADDRESS LIKE CCP WOULD
  179.     POP    B    ;CLEAN GARBAGE DMA ADDRESS OFF STACK
  180.     RET
  181. ;
  182. LOADERR:
  183.     CALL    MSGP    ;PRINT LOAD ERROR MESSAGE
  184.     DB    'OUT OF MEMOR', 'Y'+80H
  185.     JMP    UNLINK    ;RETURN TO CP/M
  186. ;
  187. NOCMERR:
  188.     CALL    MSGP    ;PRINT 'NO COM FILE'
  189.     DB    'NO COM FIL', 'E'+80H
  190.     JMP    UNLINK    ;RETURN TO CP/M
  191. ;
  192. ; END OF INIT MODULE
  193.     PAGE
  194. ;
  195. ;  \\\\\\\\\\\\\\\\                  ////////////////
  196. ;   >>>>>>>>>>>>>>>>    F A S T     <<<<<<<<<<<<<<<<
  197. ;  ////////////////   M O D U L E    \\\\\\\\\\\\\\\\
  198. ;
  199. ;
  200. ; THIS MODULE CONTAINS THE ACTUAL DISK I/O BUFFERING CODE.
  201. ;
  202. ; THIS ADDRESS BECOMES THE NEW TOP OF THE TPA.
  203. ;
  204.     ORG    (($-1) OR 255) + 1 - BASE    ;ORG TO PAGE BOUNDRY
  205.     DS    6    ;SO BDOS VECTOR ADDRESS = XXX6
  206. NEWBVECT:
  207.     JMP    $-$    ;ADDRESS WILL BE MODIFIED BY LINKUP
  208. ;
  209. ; DDB ADDRESS BUFFERS.  EACH BUFFER IS FOUR W-O-R-D-S LONG,
  210. ; ONE WORD FOR THE ADDRESS OF THE BUFFER FOR EACH OF FOUR
  211. ; POSSIBLE DRIVES.  IF THERE IS NO DDB FOR A GIVEN DRIVE,
  212. ; THE DDB ADDRESS IS ZERO.
  213. ;
  214. RDBUF    DW    0, 0, 0, 0
  215. WRBUF    DW    0, 0, 0, 0
  216. DIRBUF    DW    0, 0, 0, 0
  217. ;
  218. ; USER PATCHABLE MEMORY HIT (ERROR) ROUTINE
  219. ; INTERNALLY REFERENCED ROUTINE.
  220. ;
  221. MEMHIT:
  222.     PUSH D ! PUSH B ;SAVE REGISTERS
  223.     CALL    MSGP
  224.     DB    'MEMORY HI', 'T'+80H
  225.     POP B ! POP D
  226.     RET
  227. ;
  228. FASTLINK:        ;JMP TABLE TO REPLACE EXISTING BIOS'S
  229.     JMP    UNLINK    ;FOR EITHER BOOT, REMOVE FAST AND BOOT
  230.     JMP    UNLINK
  231.     JMP    CCONST    ;JUST PASS ALL CHARACTER I/O THRU
  232.     JMP    FCONIN    ;EXCEPT CONSOLE IN
  233.     JMP    CCONOUT
  234.     JMP    CLIST
  235.     JMP    CPUNCH
  236.     JMP    CREADER
  237.     JMP    FHOME    ;USE FAST HOME INSTEAD OF BIOS
  238.     JMP    FSETDSK    ;USE FAST SET DISK
  239.     JMP    FSETTRK    ;USE FAST SET TRACK
  240.     JMP    FSETSEC    ;USE FAST SET SECTOR
  241.     JMP    FSETDMA    ;USE FAST SET DMA
  242.     JMP    FREAD    ;USE FAST READ SECTOR
  243.     JMP    FWRITE    ;USE FAST WRITE SECTOR
  244. ;
  245. ;
  246. BEGINE:            ;ENTRY POINT FROM INIT TO EXEC. TRANS.
  247.     CALL    TPA    ;EXECUTE TRANS.
  248.             ;IF HE RETURNS, FALL THRU TO UNLINK
  249. ;
  250. ; UNLINK IS THE COMPLIMENTARY ROUTINE TO LINKUP.  IT RESTORES
  251. ; THE BIOS JUMP TABLE AND THE BDOS VECTOR TO THEIR STATES
  252. ; BEFORE FAST WAS INSTALLED (BY LINKUP).
  253. ; INTERNALLY AND EXTERNALLY REFERENCED ROUTINE.
  254. ;
  255. UNLINK:
  256.     LXI    SP,STACK ;SETUP LOCAL STACK
  257.             ;RETURN BIOS VECTORS UNHARMED
  258.     LXI    D,SAVEJMP
  259.     LDA    BOOT+2 ;GET BIOS BASE INTO DE
  260.     MOV    H,A
  261.     MVI    L,0
  262.     MVI    C,15*3    ;15 JMPS IN TABLE * 3 BYTES PER JMP
  263.     CALL    XF1    ;MOVE FROM SAVEJMP TO BIOS BASE
  264.     LHLD    NEWBVECT+1 ;GET REAL BDOS VECTOR ADDRESS
  265.     SHLD    BDOS+1 ;STORE IT INTO REAL BDOS VECTOR
  266.     CALL    CLOSE    ;EMPTY ANY DDB'S WHICH MAY HAVE DATA
  267.     CALL    MSGP    ;PRINT FAST SIGN OFF MESSAGE
  268.     DB    CR, LF
  269.     DB    'Execution under FAST now complet', 'e'+80H
  270.     JMP    BOOT        ;AND REBOOT
  271. ;
  272. ; FAST CONSOLE IN
  273. ; EXTERNALLY REFERENCED ROUTINE
  274. ; WRITES ALL SECTORS WAITING TO BE WRITTEN SO THAT USER
  275. ; CAN'T GET HIMSELF INTO TROUBLE BY REMOVING THE DISK
  276. ; EXTERNALLY REFERENCED ROUTINE.
  277. ;
  278. FCONIN:
  279.     CALL    CLOSE    ;WRITE ALL DDB'S
  280.     JMP    CCONIN    ;NOW DO THE CONSOLE INPUT
  281. ;
  282. ; FAST HOME ROUTINE
  283. ; INTERNALLY AND EXTERNALLY REFERENCED
  284. ;
  285. FHOME:
  286.     MVI    C,0    ;JUST PASS 0 TO FAST SET TRACK
  287.             ;FALL THRU
  288. ;
  289. ; FAST SET TRACK
  290. ; EXTERNALLY REFERENCED ROUTINE
  291. ; REQUESTED TRACK IS JUST STORED AWAY UNTIL
  292. ; A READ OR WRITE REQUEST COMES IN.
  293. ;
  294. FSETTRK:
  295.     MOV    A,C    ;GET REQUEST TO REG A
  296.     STA    REQTRK    ;STORE IT
  297.     RET
  298. ;
  299. ; FAST SET SECTOR
  300. ; EXTERNALLY REFERENCED ROUTINE
  301. ; THE REQUESTED SECTOR IS JUST
  302. ; STORED AWAY UNTIL A READ OR WRITE COMES IN.
  303. ;
  304. FSETSEC:
  305.     MOV    A,C    ;GET REQUESTED SECTOR TO REG A
  306.     STA    REQSEC    ;STORE IT
  307.     RET
  308. ;
  309. ; FAST SET DMA ADDRESS
  310. ; EXTERNALLY REFERENCED ROUTINE.
  311. ;
  312. FSETDMA:
  313.     MOV    H,B    ;REQUESTED DMA ADR INTO HL
  314.     MOV    L,C
  315.     SHLD    REQDMA    ;SAVE IT
  316.     RET
  317. ;
  318. ; FAST SET DISK DRIVE
  319. ; EXTERNALLY REFERENCED ROUTINE
  320. ;
  321. FSETDSK:
  322.     MOV    E,C    ;SAVE DRIVE FOR ON LINE CODE
  323.     MOV    A,C    ;GET REQUESTED DRIVE
  324.     STA    REQDSK    ;SAVE FOR PASS THRU
  325.     ADD    A    ;DOUBLE TO FORM WORD INDEX
  326.     MOV    C,A    ;FORM INDEX IN REG BC
  327.     MVI    B,0
  328.     LXI    H,DIRBUF ;GET NEW DIR DDB POINTER
  329.     CALL    INDXIND
  330.     SHLD    DIRADR    ;AND SAVE IT
  331.     LXI    H,RDBUF    ;GET NEW READ TRACK DDB POINTER
  332.     CALL    INDXIND
  333.     SHLD    RDADR    ;AND SAVE IT
  334.     LXI    H,WRBUF    ;GET NEW WRITE TRACK DDB POINTER
  335.     CALL    INDXIND
  336.     SHLD    WRADR
  337.     LXI    H,ONLINE ;BASE OF 'ON LINE' VECTOR
  338.     DAD    B    ;ADD INDEX TO BASE
  339.     MOV    A,M    ;IS THIS DRIVE ON LINE?
  340.     INX    H    ;(SEE IF WE HAVE ITS .DPH)
  341.     MOV    H,M    ;SET UP TO RETURN .DPH
  342.     MOV    L,A
  343.     ORA    H    ;IS .DPH(DRIVE) NONZERO?
  344.     SHLD    REQDPH
  345.     RNZ        ;YES - DONE WITH SELECTION
  346.     MOV    C,E    ;SET UP FOR SELECT
  347.     CALL    CSETDSK    ;SELECT THE SPECIFIED DRIVE
  348.     XCHG        ;SAVE .DPH RETURNED BY CSETDSK
  349.     LHLD    REQDSK    ;GET DRIVE #
  350.     MVI    H,0
  351.     DAD    H    ;TIMES 2
  352.     LXI    B,ONLINE;PLUS BASE OF ONLINE VECTOR
  353.     DAD    B
  354.     MOV    M,E    ;STORE .DPH
  355.     INX    H
  356.     MOV    M,D
  357.     XCHG
  358.     SHLD    REQDPH    ;SAVE LOCALLY
  359.     CALL    CHOME    ;HOME THE DRIVE
  360.     LHLD    DIRADR    ;AND READ THE DIRECTORY IF IT IS BUFFERED
  361.     CALL    RDDDB
  362.     LHLD    REQDPH    ;RETURN DPH TO CALLER
  363.     RET
  364. ;
  365. ; FAST READ SECTOR
  366. ; EXTERNALLY REFERENCED ROUTINE.
  367. ;
  368. FREAD:
  369.     LHLD    RDADR    ;GET ADDRESS OF READ TRACK DDB
  370.     CALL    GETSEC    ;TRY TO FIND SECTOR IN READ DDB
  371.     RC        ;FOUND IT
  372.     LHLD    DIRADR    ;TRY TO FIND SECTOR IN DIRECTORY DDB
  373.     CALL    GETSEC
  374.     RC        ;FOUND IT
  375.     LHLD    WRADR    ;TRY TO FIND SECTOR IN WRITE DDB
  376.     CALL    GETWSEC
  377.     RC        ;FOUND IT
  378.     LHLD    RDADR    ;SEE IF THERE IS A READ TRACK BUFFER
  379.     MOV    A,H
  380.     ORA    L
  381.     JZ    RDPASS    ;NO - THEN JUST PASS THE READ THRU
  382.     LDA    REQTRK    ;YES - SEE IF READING FROM NON-DIRECTORY
  383.     CPI    DIRTRK    ;SECTORS OF DIRECTORY TRACK
  384.     JZ    RDPASS    ;YES - JUST LET THAT PASS THRU
  385.     PUSH    PSW    ;NO - WRITE ANY DATA IN READ BUFFER
  386.     PUSH    H
  387.     CALL    WRDDB
  388.     POP    H
  389.     POP    PSW
  390.     MOV    M,A    ;FILL NEW TRACK INTO READ DDB
  391.     PUSH    H    ;SAVE READ DDB ADDRESS
  392.     CALL    RDDDB    ;AND FILL NEW DDB WITH DATA
  393.     POP    H    ;GET READ DDB ADDRESS BACK
  394.     JMP    GETSEC    ;TRANSFER SECTOR FROM DDB TO CALLER
  395.             ;AND RETURN FROM GETSEC
  396. ;
  397. ; FAST SECTOR WRITE
  398. ; EXTERNALLY REFERENCED ROUTINE.
  399. ;
  400. FWRITE:
  401.     LHLD    WRADR    ;TRY TO PUT SECTOR INTO WRITE BUFFER
  402.     CALL    PUTSEC
  403.     RC        ;IT WENT - ALL DONE
  404.     LHLD    DIRADR    ;TRY TO PUT IT INTO DIRECTORY BUFFER
  405.     CALL    PUTSEC
  406.     RC        ;IT WENT - ALL DONE
  407.     LHLD    RDADR    ;TRY TO PUT INTO READ BUFFER
  408.     CALL    PUTSEC
  409.     RC        ;IT WENT - ALL DONE
  410.     LHLD    WRADR    ;IS THERE A WRITE TRACK BUFFER?
  411.     MOV    A,H
  412.     ORA    L
  413.     JZ    WRPASS    ;NO - JUST PASS THIS WRITE THRU
  414.     LDA    REQTRK    ;YES - SEE IF THIS IS A NON-DIRECTORY
  415.     CPI    DIRTRK    ;SECTOR ON THE DIRECTORY TRACK?
  416.     JZ    WRPASS    ;YES - JUST PASS THAT THRU
  417.     PUSH    PSW    ;NO - DUMP EXISTING WRITE BUFFER TO DISK
  418.     PUSH    H
  419.     CALL    WRDDB
  420.     POP    H
  421.     POP    PSW
  422.     MOV    M,A    ;AND BUFFER UP REQUESTED TRACK
  423.     CALL    PUTSEC    ;MOVE SECTOR INTO WRITE BUFFER
  424.     LDA    WRTERRF    ;RETURN WRITE ERROR FLAG
  425.     RET
  426. ;
  427. ; CLOSE ALL OPEN DDB'S.  WRITE ANY DATA LEFT IN THEM OUT TO
  428. ; DISK
  429. ; INTERNALLY REFERENCED ROUTINE.
  430. ;
  431. CLOSE:
  432.     MVI    C,4*3    ;DDB COUNT
  433.     LXI    H,RDBUF    ;START OF DDB ADDRESS TABLES
  434. CLOS:
  435.     MOV    E,M    ;GET DDB ADDRESS TO REG DE
  436.     INX    H
  437.     MOV    D,M
  438.     INX    H
  439.     PUSH    H    ;SAVE TABLE ADDRESS
  440.     PUSH    B
  441.     XCHG        ;DDB ADDRESS TO REG HL
  442.     CALL    WRDDB    ;CLOSE ONE DDB
  443.     LDA    WRTERRF    ;ANY WRITE ERRORS IN CLOSING?
  444.     ORA    A
  445.     JZ    CLOSOK    ;NO - KEEP CLOSING
  446.     CALL    MSGP
  447.     DB    'DISK WRITE ERROR', CR, LF+80H
  448. CLOSOK:
  449.     POP    B    ;GET COUNT
  450.     POP    H    ;GET TABLE ADDRESS
  451.     DCR    C    ;DONE ALL DDBS YET?
  452.     JNZ    CLOS    ;NO - KEEP CLOSING
  453.     RET        ;YES - ALL DONE
  454. ;
  455. ; INDEXED INDIRECT ADDRESSING.  RETURNS THE WORD AT THE
  456. ; ADDRESS BASE + INDEX
  457. ; INTERNALLY REFERENCED ROUTINE.
  458. ;
  459. INDXIND:
  460.     DAD    B    ;ADD IN INDEX
  461.     MOV    A,M    ;GET LOW ORDER OF RESULT
  462.     INX    H
  463.     MOV    H,M    ;GET HIGH ORDER OF RESULT
  464.     MOV    L,A
  465.     RET
  466. ;
  467. ; GET A SECTOR FROM A WRITE DDB INTO REQDMA.  MATCHES ONLY
  468. ; IF UPDATE FLAG IS SET.  RETURNS FLAG IF FOUND.
  469. ; INTERNALLY REFERENCED ROUTINE.
  470. ;
  471. GETWSEC:
  472.     CALL    SRCHDDB    ;FIND A SECTOR AND TRACK MATCH?
  473.     RNC        ;NO - RETURN WITHOUT FLAG
  474.     INX    H    ;YES - SEE IF SECTOR HAS BEEN
  475.     MOV    A,M    ;WRITTEN (UPDATE FLAG=1)?
  476.     ORA    A
  477.     JNZ    GS1    ;YES - TRANSFER FROM WRITE DDB
  478.     CALL    RDPASS    ;NO - BYPASS BUFFERING
  479.     STC        ;SET FOUND IT FLAG
  480.     RET
  481. ;
  482. ; GET A SECTOR FROM A DDB INTO REQDMA.  FLAG SET IF FOUND.
  483. ; INTERNALLY REFERENCED ROUTINE.
  484. ;
  485. GETSEC:
  486.     CALL    SRCHDDB    ;DO WE HAVE THE REQUESTED SECTOR?
  487.     RNC        ;NO - RETURN WITHOUT FLAG
  488.     INX    H    ;YES - POINT TO SECTOR DATA
  489. GS1:            ;ENTRY FROM GETWSEC (ABOVE)
  490.     INX    H
  491.     XCHG        ;DATA ADDRESS TO REG DE
  492.     LHLD    REQDMA    ;DESTINATION TO REG HL
  493.     CALL    XFER    ;PERFORM THE TRANSFER
  494.     LDAX    D    ;GET GOOD/BAD FLAG
  495.     STC        ;SET 'FOUND IT' FLAG
  496.     RET
  497. ;
  498. ; SEARCH A DDB FOR THE REQUESTED TRACK AND SECTOR
  499. ; INTERNALLY REFERENCED ROUTINE.
  500. ;
  501. SRCHDDB:
  502.     MOV    A,H    ;SEE IF DDB IS PRESENT AT ALL
  503.     ORA    L
  504.     RZ        ;NO - WE DON'T HAVE IT
  505.     LDA    REQTRK    ;YES - SEE IF REQTRK MATCHES DDB TRACK
  506.     XRA    M
  507.     RNZ        ;NO MATCH - WE DON'T HAVE IT
  508.     INX    H    ;TRACKS MATCH - CHECK SECTORS
  509.     INX    H
  510.     LDA    REQSEC
  511.     MOV    C,A
  512.     LXI    D,SECLEN+3 ;BYTES BETWEEN SECTOR NUMBERS
  513. SRCH1:
  514.     MOV    A,M    ;GET A SECTOR NUMBER FROM DDB
  515.     ORA    A    ;END OF DDB?
  516.     RZ        ;YES - RETURN WITHOUT FLAG
  517.     CMP    C    ;NO - SEE IF REQSEC MATCHES DDB SECTOR
  518.     STC        ;PREPARE TO RETURN FLAG IF SO
  519.     RZ        ;THEY MATCH - RETURN FLAG
  520.     DAD    D    ;NO MATCH - ON TO NEXT SECTOR
  521.     JMP    SRCH1
  522. ;
  523. RDPASS:
  524.     CALL    PASSTHRU
  525.     JMP    CREAD
  526. ;
  527. ; MOVE A SECTOR FROM MEMORY INTO A DDB
  528. ; INTERNALLY REFERENCED ROUTINE.
  529. ;
  530. PUTSEC:
  531.     CALL    SRCHDDB    ;DOES IT GO IN THIS DDB?
  532.     RNC        ;NO - RETURN WITHOUT FLAG
  533.     INX    H    ;POINT TO DATA FIELD OF DDB
  534.     MVI    M,UPDTTOK ;SET UPDATE FLAG
  535.     INX    H
  536.     XCHG        ;SAVE DDB ADDRESS IN REG DE
  537.     LHLD    REQDMA    ;GET SOURCE ADDRESS INTO REG HL
  538.     XCHG        ;NOW REG HL=DDB ADDRESS (DEST) AND . .
  539.     CALL    XFER    ;REG DE=MEMORY (SOURCE)
  540.     XRA    A    ;RETURN WITHOUT WRITE ERROR
  541.     MOV    M,A    ;SET GOOD/BAD FLAG TO GOOD
  542.     STC        ;SET SECTOR PUT FLAG
  543.     RET
  544. WRPASS:
  545.     CALL    PASSTHRU
  546.     JMP    CWRITE
  547. ;
  548. ; PASS ALL DISK I/O PARAMETERS THRU TO BIOS
  549. ; INTERNALLY REFERENCED ROUTINE
  550. ;
  551. PASSTHRU:
  552.     LDA    REQDSK    ;PASS REQUESTED DISK THRU
  553.     MOV    C,A
  554.     CALL    CSETDSK
  555.     LDA    REQTRK    ;PASS REQUESTED TRACK THRU
  556.     MOV    C,A
  557.     CALL    CSETTRK
  558.     LDA    REQSEC    ;PASS REQUESTED SECTOR
  559.     MOV    C,A
  560.     CALL    CSETSEC
  561.     LHLD    REQDMA    ;PASS REQUESTED DMA ADDRESS
  562.     MOV    B,H
  563.     MOV    C,L
  564.     JMP    CSETDMA    ;RETURN FROM CSETDMA
  565. ;
  566. ; READ A DDB FROM DISK.  ALL SECTORS ARE FILED IN, AND THEIR
  567. ; UPDATE FLAGS ARE RESET.
  568. ; INTERNALLY REFERENCED ROUTINE.
  569. ;
  570. RDDDB:
  571.     MOV    A,H    ;DO NOTHING FI NO DDB
  572.     ORA    L
  573.     RZ
  574.     PUSH    H    ;SAVE DDB ADDRESS
  575.     CALL    SENDDT    ;SEND DRIVE AND TRACK INFO TO BIOS
  576.     POP    H    ;GET DDB ADDRESS
  577.     INX    H    ;POINT TO FIRST SECTOR BYTE
  578.     INX    H
  579. RDDSEC:
  580.     MOV    A,M    ;GET SECTOR NUMBER
  581.     ORA    A    ;END OF DDB?
  582.     RZ        ;YES - ALL DONE
  583.     MOV    C,A    ;PASS SECTOR TO BIOS
  584.     PUSH    H    ;SAVE WHILE CALLING
  585.     CALL    CSETSEC
  586.     POP    H    ;GET DDB ADDRESS BACK
  587.     INX    H    ;POINT TO UPDATE FLAG
  588.     MVI    M,0    ;RESET UPDATE FLAG
  589.     INX    H    ;POINT TO DATA FIELD
  590.     PUSH    H    ;SAVE DATA POINTER
  591.     MOV    B,H    ;DATA ADDRESS TO REG BC
  592.     MOV    C,L
  593.     CALL    CSETDMA    ;PASS DATA ADDRESS TO BIOS
  594.     CALL    CREAD    ;PERFORM THE READ
  595.     POP    H    ;GET DATA ADDRESS BACK
  596.     LXI    B,SECLEN ;BYTES TO GOOD/BAD FLAG
  597.     DAD    B
  598.     MOV    M,A    ;STORE GOOD/BAD FLAG FROM BIOS IN DDB
  599.     INX    H
  600.     JMP    RDDSEC    ;ON TO NEXT SECTOR
  601. ;
  602. ; WRITE A DDB BACK TO DISK.  ONLY SECTORS WITH THE UPDATE FLAG
  603. ; SET GET WRITTEN.
  604. ; THE DRIVE AND TRACK INFORMATION FROM THE DDB IS SAVED BY
  605. ; THIS ROUTINE AND PASSED TO THE BIOS BY RCLDT ONLY IF
  606. ; A SECTOR IS TO BE WRITTEN.  THIS IS DONE TO BYPASS BIOS
  607. ; DELAYS WHEN SWITCHING DRIVES AND TO PREVENT NEEDLESS
  608. ; SEEKING TO TRACKS WHICH MIGHT NOT RECIEVE ANY DATA.
  609. ; INTERNALLY REFERENCED ROUTINE.
  610. ;
  611. WRDDB:
  612.     XRA    A    ;CLEAR WRITE ERROR FLAG
  613.     STA    WRTERRF
  614.     MOV    A,H    ;SEE IF A DDB IS PRESENT
  615.     ORA    L
  616.     RZ        ;NO - ALL DONE WRITING
  617.     MOV    A,M    ;GET TRACK NUMBER
  618.     INR    A    ;TRACK = 0FFH (MEANING EMPTY)?
  619.     RZ        ;YES - NO WRITING TO DO
  620.     SHLD    TRKPTR    ;NO - SAVE DISK & TRACK POINTER FOR
  621.     XRA    A    ;RECALL LATER, AND RESET FLAG 
  622.     STA    SENTFLG    ;SHOWING THAT THEY HAVEN'T BEEN SENT
  623.     INX    H    ;POINT TO FIRST SECTOR NUMBER
  624.     INX    H
  625. TSTUPDT:
  626.     MOV    A,M    ;GET SECTOR TO REG A
  627.     ORA    A    ;END OF DDB?
  628.     RZ        ;YES - ALL DONE
  629.     MOV    C,A    ;SAVE SECTOR IN REG C
  630.     INX    H    ;POINT TO UPDATE FLAG
  631.     MOV    A,M    ;GET UPDATE FLAG
  632.     ORA    A    ;DOES THIS SECTOR NEED UPDATING ON DISK?
  633.     CNZ    WRSEC    ;YES - WRITE IT BACK
  634.     LXI    D,SECLEN+2 ;BYTES TO NEXT SECTOR NUMBER
  635.     DAD    D
  636.     JMP    TSTUPDT    ;CHECK THE NEXT UPDATE FLAG
  637. ;
  638. ; WRITE A SECTOR FROM A DDB BACK OUT TO DISK.
  639. ; INTERNALLY REFERENCED ROUTINE.
  640. ;
  641. WRSEC:
  642.     MVI    M,0    ;RESET UPDATE FLAG
  643.     PUSH    H    ;SAVE UPDATE FLAG POINTER
  644.     CALL    CSETSEC    ;PASS SECTOR NUBER TO BIOS
  645.     CALL    RCLDT    ;PASS DRIVE AND TRACK TO BIOS
  646.     POP    H    ;GET UPDATE FLAG POINTER
  647.     PUSH    H    ;AND SAVE AGAIN
  648.     INX    H    ;POINT TO DATA
  649.     MOV    B,H    ;DATA ADDRESS TO REG BC
  650.     MOV    C,L
  651.     CALL    CSETDMA    ;PASS DMA ADDRESS TO BIOS
  652.     CALL    CWRITE    ;WRITE THE DATA OUT
  653.     LXI    H,WRTERRF ;OR THIS WRITE ERROR FLAG IN WITH
  654.     ORA    M    ;THE REST FROM THIS WRDDB
  655.     MOV    M,A
  656.     POP    H    ;GET CALLERS REG HL BACK
  657.     RET
  658. ;
  659. ; RECALL DISK AND TRACK INFO FROM A DDB, PASS IT TO THE BIOS,
  660. ; AND SET FLAG SHOWING THAT IS HAS BEEN SENT.
  661. ; INTERNALLY REFERENCED ROUTINE.
  662. ;
  663. RCLDT:
  664.     LXI    H,SENTFLG ;HAS THIS INFO ALREADY BEEN SENT?
  665.     MOV    A,M
  666.     ORA    A
  667.     RNZ        ;YES - SKIP SENDING AGAIN
  668.     MVI    M,SENTTOK ;NO - SET FLAG SHOWING IT HAS BEEN SENT
  669.     LHLD    TRKPTR    ;GET POINTER TO DRIVE & TRACK INFO
  670.             ;AND FALL THRU TO SEND IT TO BIOS
  671. ;
  672. ; SEND DRIVE AND TRACK INFO FROM A DDB TO THE BIOS.
  673. ; INTERNALLY REFERENCED ROUTINE.
  674. ;
  675. SENDDT:
  676.     PUSH    H    ;SAVE TRACK POINTER
  677.     INX    H    ;POINT TO DRIVE
  678.     MOV    C,M    ;GET DRIVE TO REG C
  679.     CALL    CSETDSK    ;PASS DISK
  680.     POP    H    ;GET TRACK POINTER
  681.     MOV    C,M    ;GET TRACK TO REG C
  682.     JMP    CSETTRK    ;PASS TRACK AND RETURN FROM THERE
  683. ;
  684. ; MOVE A SECTOR FROM ONE PLACE IN MEMORY TO ANOTHER.  GIVE
  685. ; ERROR MESSAGE IF DATA CAN'T BE WRITTEN INTO DESTINATION.
  686. ; INTERNALLY REFERENCED ROUTINE.
  687. ;
  688. XFER:
  689.     MVI    C,SECLEN ;COUNT NUMBER OF BYTES TO XFER IN C
  690. XF1:
  691.     LDAX    D    ;GET BYTE FROM SOURCE
  692.     MOV    M,A    ;STORE INTO DESTINATION
  693.     XRA    M    ;DID IT GO?
  694.     CNZ    MEMHIT    ;NO - GIVE WARNING MESSAGE
  695.     INX    H    ;INCREMENT DEST POINTER
  696.     INX    D    ;INCREMENT SOURCE POINTER
  697.     DCR    C    ;DONE WITH MOVE YET?
  698.     JNZ    XF1    ;NO - KEEP MOVING
  699.     RET        ;YES - ALL DONE
  700. ;
  701. ; LOCAL MESSAGE PRINTER.  WE CAN'T USE BDOS BECAUSE BDOS IS NOT
  702. ; RE-ENTRANT (WE MIGHT HAVE GOTTEN HERE VIA BDOS).  FOLLOW
  703. ; THE CALL TO MSGP WITH THE TEXT OF THE MESSAGE.  THE LAST
  704. ; CHARACTER OF THE MESSAGE MUST HAVE BIT SEVEN ON (I.E. +80H)
  705. ; INTERNALLY REFERENCED ROUTINE.
  706. ;
  707. MSGP:
  708.     XTHL        ;GET MESSAGE ADDRESS TO REG HL
  709. MSG1:
  710.     MOV    C,M    ;GET MESSAGE CHARACTER
  711.     PUSH    H    ;SAVE MESSAGE ADDRESS DURING PRINTING
  712.     CALL    CCONOUT    ;SEND IT
  713.     POP    H    ;RESTORE MESSAGE ADDRESS
  714.     MOV    A,M    ;GET CHR JUST SENT
  715.     INX    H    ;POINT TO NEXT CHARACTER
  716.     ORA    A    ;WAS THAT THE LAST CHR TO PRINT?
  717.     JP    MSG1    ;NO - KEEP PRINTING
  718.     XTHL        ;YES - PUT MODIFIED RETURN ADDREESS
  719.     RET        ;BACK ON STACK AND RETURN PAST MESSAGE
  720.     PAGE
  721. ;
  722. ;  \\\\\\\\\\\\\\\\                ////////////////
  723. ;   >>>>>>>>>>>>>>>>    R A M     <<<<<<<<<<<<<<<<
  724. ;  ////////////////   A R E A S    \\\\\\\\\\\\\\\\
  725. ;
  726. ;
  727. ; SAVE SPACE FOR A COPY OF THE BIOS JUMP TABLE BEFORE THE
  728. ; INSTALLATION OF FAST
  729. ;
  730. SAVEJMP:
  731. CBOOT:     JMP    $-$
  732. CWBOOT:     JMP    $-$
  733. CCONST:     JMP    $-$
  734. CCONIN:     JMP    $-$
  735. CCONOUT: JMP    $-$
  736. CLIST:     JMP    $-$
  737. CPUNCH:     JMP    $-$
  738. CREADER: JMP    $-$
  739. CHOME:     JMP    $-$
  740. CSETDSK: JMP    $-$
  741. CSETTRK: JMP    $-$
  742. CSETSEC: JMP    $-$
  743. CSETDMA: JMP    $-$
  744. CREAD:     JMP    $-$
  745. CWRITE:     JMP    $-$
  746. ;
  747. DIRADR    DW    0    ;ADDRESS OF CURRENT DIRECTORY DDB
  748. RDADR    DW    0    ;ADDRESS OF CURRENT READ TRACK DDB
  749. WRADR    DW    0    ;ADDRESS OF CURRENT WRITE TRACK DDB
  750. ;
  751. TRKPTR    DW    0    ;POINTER TO TRACK & DRIVE INFO IN DDB
  752. SENTFLG    DB    0    ;ZERO IF TRACK & DRIVE HAVEN'T BEEN SENT
  753. WRTERRF    DB    0    ;WRITE DDB ERROR FLAG, 0 IF NO ERROR
  754. ;
  755. REQDPH    DW    0
  756. REQDSK    DB    0FFH
  757. REQTRK    DB    0FFH
  758. REQSEC    DB    0FFH
  759. REQDMA    DW    0FFFFH
  760. ;
  761. ONLINE    DW    0, 0, 0, 0 ;DRIVE ON LINE VECTOR (STORES .DPH IN VERS 2)
  762. ;
  763.     DS    10H    ;AT LEAST AS MUCH STACK AS CCP
  764. ;
  765.     ORG    (($-1) OR 255) + 1 - BASE    ;ORG TO NEXT PAGE BOUNDRY
  766. STACK:
  767. ;
  768. CODELEN    EQU    $-BASE
  769. ;
  770.     ORG    CODELEN-BASE    ;INFORM OPERATOR OF CODE LENGTH
  771.     END    FASTNTRY
  772.