home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol076 / fast.asm < prev    next >
Assembly Source File  |  1984-04-29  |  21KB  |  779 lines

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