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 / CPMUG038.ARK / FAST.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  20KB  |  755 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    R.A.V.    5/19/79
  6. ; REASON    GENERAL CODE CLEAN UP OPERATIONS
  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    50    ;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    'Beginning execution under FAST '
  111.         ;DEFINE VERSION NUMBER IN ASCII
  112.     DB    '0.'
  113.     DB    '0'+VERS/10
  114.     DB    '0'+VERS 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 ;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.     MOV    C,E    ;REG BC IS NOW BYTE INDEX
  338.     LXI    H,ONLINE ;BASE OF 'ON LINE' VECTOR
  339.     DAD    B    ;ADD INDEX TO BASE
  340.     MOV    A,M    ;IS THIS DRIVE ON LINE?
  341.     ORA    A
  342.     RNZ        ;YES - DONE WITH SECECTION
  343.     MVI    M,ONLNTOK ;NO - SET ON LINE FLAG AND . .
  344.     CALL    CSETDSK    ;HOME THE SELECTED DRIVE
  345.     CALL    CHOME
  346.     LHLD    DIRADR    ;AND READ THE DIRECTORY IF IT IS BUFFERED
  347.     JMP    RDDDB    ;RETURN FROM RDDDB
  348. ;
  349. ; FAST READ SECTOR
  350. ; EXTERNALLY REFERENCED ROUTINE.
  351. ;
  352. FREAD:
  353.     LHLD    RDADR    ;GET ADDRESS OF READ TRACK DDB
  354.     CALL    GETSEC    ;TRY TO FIND SECTOR IN READ DDB
  355.     RC        ;FOUND IT
  356.     LHLD    DIRADR    ;TRY TO FIND SECTOR IN DIRECTORY DDB
  357.     CALL    GETSEC
  358.     RC        ;FOUND IT
  359.     LHLD    WRADR    ;TRY TO FIND SECTOR IN WRITE DDB
  360.     CALL    GETWSEC
  361.     RC        ;FOUND IT
  362.     LHLD    RDADR    ;SEE IF THERE IS A READ TRACK BUFFER
  363.     MOV    A,H
  364.     ORA    L
  365.     JZ    RDPASS    ;NO - THEN JUST PASS THE READ THRU
  366.     LDA    REQTRK    ;YES - SEE IF READING FROM NON-DIRECTORY
  367.     CPI    DIRTRK    ;SECTORS OF DIRECTORY TRACK
  368.     JZ    RDPASS    ;YES - JUST LET THAT PASS THRU
  369.     PUSH    PSW    ;NO - WRITE ANY DATA IN READ BUFFER
  370.     PUSH    H
  371.     CALL    WRDDB
  372.     POP    H
  373.     POP    PSW
  374.     MOV    M,A    ;FILL NEW TRACK INTO READ DDB
  375.     PUSH    H    ;SAVE READ DDB ADDRESS
  376.     CALL    RDDDB    ;AND FILL NEW DDB WITH DATA
  377.     POP    H    ;GET READ DDB ADDRESS BACK
  378.     JMP    GETSEC    ;TRANSFER SECTOR FROM DDB TO CALLER
  379.             ;AND RETURN FROM GETSEC
  380. ;
  381. ; FAST SECTOR WRITE
  382. ; EXTERNALLY REFERENCED ROUTINE.
  383. ;
  384. FWRITE:
  385.     LHLD    WRADR    ;TRY TO PUT SECTOR INTO WRITE BUFFER
  386.     CALL    PUTSEC
  387.     RC        ;IT WENT - ALL DONE
  388.     LHLD    DIRADR    ;TRY TO PUT IT INTO DIRECTORY BUFFER
  389.     CALL    PUTSEC
  390.     RC        ;IT WENT - ALL DONE
  391.     LHLD    RDADR    ;TRY TO PUT INTO READ BUFFER
  392.     CALL    PUTSEC
  393.     RC        ;IT WENT - ALL DONE
  394.     LHLD    WRADR    ;IS THERE A WRITE TRACK BUFFER?
  395.     MOV    A,H
  396.     ORA    L
  397.     JZ    WRPASS    ;NO - JUST PASS THIS WRITE THRU
  398.     LDA    REQTRK    ;YES - SEE IF THIS IS A NON-DIRECTORY
  399.     CPI    DIRTRK    ;SECTOR ON THE DIRECTORY TRACK?
  400.     JZ    WRPASS    ;YES - JUST PASS THAT THRU
  401.     PUSH    PSW    ;NO - DUMP EXISTING WRITE BUFFER TO DISK
  402.     PUSH    H
  403.     CALL    WRDDB
  404.     POP    H
  405.     POP    PSW
  406.     MOV    M,A    ;AND BUFFER UP REQUESTED TRACK
  407.     CALL    PUTSEC    ;MOVE SECTOR INTO WRITE BUFFER
  408.     LDA    WRTERRF    ;RETURN WRITE ERROR FLAG
  409.     RET
  410. ;
  411. ; CLOSE ALL OPEN DDB'S.  WRITE ANY DATA LEFT IN THEM OUT TO
  412. ; DISK
  413. ; INTERNALLY REFERENCED ROUTINE.
  414. ;
  415. CLOSE:
  416.     MVI    C,4*3    ;DDB COUNT
  417.     LXI    H,RDBUF    ;START OF DDB ADDRESS TABLES
  418. CLOS:
  419.     MOV    E,M    ;GET DDB ADDRESS TO REG DE
  420.     INX    H
  421.     MOV    D,M
  422.     INX    H
  423.     PUSH    H    ;SAVE TABLE ADDRESS
  424.     PUSH    B
  425.     XCHG        ;DDB ADDRESS TO REG HL
  426.     CALL    WRDDB    ;CLOSE ONE DDB
  427.     LDA    WRTERRF    ;ANY WRITE ERRORS IN CLOSING?
  428.     ORA    A
  429.     JZ    CLOSOK    ;NO - KEEP CLOSING
  430.     CALL    MSGP
  431.     DB    'DISK WRITE ERROR', CR, LF+80H
  432. CLOSOK:
  433.     POP    B    ;GET COUNT
  434.     POP    H    ;GET TABLE ADDRESS
  435.     DCR    C    ;DONE ALL DDBS YET?
  436.     JNZ    CLOS    ;NO - KEEP CLOSING
  437.     RET        ;YES - ALL DONE
  438. ;
  439. ; INDEXED INDIRECT ADDRESSING.  RETURNS THE WORD AT THE
  440. ; ADDRESS BASE + INDEX
  441. ; INTERNALLY REFERENCED ROUTINE.
  442. ;
  443. INDXIND:
  444.     DAD    B    ;ADD IN INDEX
  445.     MOV    A,M    ;GET LOW ORDER OF RESULT
  446.     INX    H
  447.     MOV    H,M    ;GET HIGH ORDER OF RESULT
  448.     MOV    L,A
  449.     RET
  450. ;
  451. ; GET A SECTOR FROM A WRITE DDB INTO REQDMA.  MATCHES ONLY
  452. ; IF UPDATE FLAG IS SET.  RETURNS FLAG IF FOUND.
  453. ; INTERNALLY REFERENCED ROUTINE.
  454. ;
  455. GETWSEC:
  456.     CALL    SRCHDDB    ;FIND A SECTOR AND TRACK MATCH?
  457.     RNC        ;NO - RETURN WITHOUT FLAG
  458.     INX    H    ;YES - SEE IF SECTOR HAS BEEN
  459.     MOV    A,M    ;WRITTEN (UPDATE FLAG=1)?
  460.     ORA    A
  461.     JNZ    GS1    ;YES - TRANSFER FROM WRITE DDB
  462.     CALL    RDPASS    ;NO - BYPASS BUFFERING
  463.     STC        ;SET FOUND IT FLAG
  464.     RET
  465. ;
  466. ; GET A SECTOR FROM A DDB INTO REQDMA.  FLAG SET IF FOUND.
  467. ; INTERNALLY REFERENCED ROUTINE.
  468. ;
  469. GETSEC:
  470.     CALL    SRCHDDB    ;DO WE HAVE THE REQUESTED SECTOR?
  471.     RNC        ;NO - RETURN WITHOUT FLAG
  472.     INX    H    ;YES - POINT TO SECTOR DATA
  473. GS1:            ;ENTRY FROM GETWSEC (ABOVE)
  474.     INX    H
  475.     XCHG        ;DATA ADDRESS TO REG DE
  476.     LHLD    REQDMA    ;DESTINATION TO REG HL
  477.     CALL    XFER    ;PERFORM THE TRANSFER
  478.     LDAX    D    ;GET GOOD/BAD FLAG
  479.     STC        ;SET 'FOUND IT' FLAG
  480.     RET
  481. ;
  482. ; SEARCH A DDB FOR THE REQUESTED TRACK AND SECTOR
  483. ; INTERNALLY REFERENCED ROUTINE.
  484. ;
  485. SRCHDDB:
  486.     MOV    A,H    ;SEE IF DDB IS PRESENT AT ALL
  487.     ORA    L
  488.     RZ        ;NO - WE DON'T HAVE IT
  489.     LDA    REQTRK    ;YES - SEE IF REQTRK MATCHES DDB TRACK
  490.     XRA    M
  491.     RNZ        ;NO MATCH - WE DON'T HAVE IT
  492.     INX    H    ;TRACKS MATCH - CHECK SECTORS
  493.     INX    H
  494.     LDA    REQSEC
  495.     MOV    C,A
  496.     LXI    D,SECLEN+3 ;BYTES BETWEEN SECTOR NUMBERS
  497. SRCH1:
  498.     MOV    A,M    ;GET A SECTOR NUMBER FROM DDB
  499.     ORA    A    ;END OF DDB?
  500.     RZ        ;YES - RETURN WITHOUT FLAG
  501.     CMP    C    ;NO - SEE IF REQSEC MATCHES DDB SECTOR
  502.     STC        ;PREPARE TO RETURN FLAG IF SO
  503.     RZ        ;THEY MATCH - RETURN FLAG
  504.     DAD    D    ;NO MATCH - ON TO NEXT SECTOR
  505.     JMP    SRCH1
  506. ;
  507. RDPASS:
  508.     CALL    PASSTHRU
  509.     JMP    CREAD
  510. ;
  511. ; MOVE A SECTOR FROM MEMORY INTO A DDB
  512. ; INTERNALLY REFERENCED ROUTINE.
  513. ;
  514. PUTSEC:
  515.     CALL    SRCHDDB    ;DOES IT GO IN THIS DDB?
  516.     RNC        ;NO - RETURN WITHOUT FLAG
  517.     INX    H    ;POINT TO DATA FIELD OF DDB
  518.     MVI    M,UPDTTOK ;SET UPDATE FLAG
  519.     INX    H
  520.     XCHG        ;SAVE DDB ADDRESS IN REG DE
  521.     LHLD    REQDMA    ;GET SOURCE ADDRESS INTO REG HL
  522.     XCHG        ;NOW REG HL=DDB ADDRESS (DEST) AND . .
  523.     CALL    XFER    ;REG DE=MEMORY (SOURCE)
  524.     XRA    A    ;RETURN WITHOUT WRITE ERROR
  525.     MOV    M,A    ;SET GOOD/BAD FLAG TO GOOD
  526.     STC        ;SET SECTOR PUT FLAG
  527.     RET
  528. WRPASS:
  529.     CALL    PASSTHRU
  530.     JMP    CWRITE
  531. ;
  532. ; PASS ALL DISK I/O PARAMETERS THRU TO BIOS
  533. ; INTERNALLY REFERENCED ROUTINE
  534. ;
  535. PASSTHRU:
  536.     LDA    REQDSK    ;PASS REQUESTED DISK THRU
  537.     MOV    C,A
  538.     CALL    CSETDSK
  539.     LDA    REQTRK    ;PASS REQUESTED TRACK THRU
  540.     MOV    C,A
  541.     CALL    CSETTRK
  542.     LDA    REQSEC    ;PASS REQUESTED SECTOR
  543.     MOV    C,A
  544.     CALL    CSETSEC
  545.     LHLD    REQDMA    ;PASS REQUESTED DMA ADDRESS
  546.     MOV    B,H
  547.     MOV    C,L
  548.     JMP    CSETDMA    ;RETURN FROM CSETDMA
  549. ;
  550. ; READ A DDB FROM DISK.  ALL SECTORS ARE FILED IN, AND THEIR
  551. ; UPDATE FLAGS ARE RESET.
  552. ; INTERNALLY REFERENCED ROUTINE.
  553. ;
  554. RDDDB:
  555.     MOV    A,H    ;DO NOTHING FI NO DDB
  556.     ORA    L
  557.     RZ
  558.     PUSH    H    ;SAVE DDB ADDRESS
  559.     CALL    SENDDT    ;SEND DRIVE AND TRACK INFO TO BIOS
  560.     POP    H    ;GET DDB ADDRESS
  561.     INX    H    ;POINT TO FIRST SECTOR BYTE
  562.     INX    H
  563. RDDSEC:
  564.     MOV    A,M    ;GET SECTOR NUMBER
  565.     ORA    A    ;END OF DDB?
  566.     RZ        ;YES - ALL DONE
  567.     MOV    C,A    ;PASS SECTOR TO BIOS
  568.     PUSH    H    ;SAVE WHILE CALLING
  569.     CALL    CSETSEC
  570.     POP    H    ;GET DDB ADDRESS BACK
  571.     INX    H    ;POINT TO UPDATE FLAG
  572.     MVI    M,0    ;RESET UPDATE FLAG
  573.     INX    H    ;POINT TO DATA FIELD
  574.     PUSH    H    ;SAVE DATA POINTER
  575.     MOV    B,H    ;DATA ADDRESS TO REG BC
  576.     MOV    C,L
  577.     CALL    CSETDMA    ;PASS DATA ADDRESS TO BIOS
  578.     CALL    CREAD    ;PERFORM THE READ
  579.     POP    H    ;GET DATA ADDRESS BACK
  580.     LXI    B,SECLEN ;BYTES TO GOOD/BAD FLAG
  581.     DAD    B
  582.     MOV    M,A    ;STORE GOOD/BAD FLAG FROM BIOS IN DDB
  583.     INX    H
  584.     JMP    RDDSEC    ;ON TO NEXT SECTOR
  585. ;
  586. ; WRITE A DDB BACK TO DISK.  ONLY SECTORS WITH THE UPDATE FLAG
  587. ; SET GET WRITTEN.
  588. ; THE DRIVE AND TRACK INFORMATION FROM THE DDB IS SAVED BY
  589. ; THIS ROUTINE AND PASSED TO THE BIOS BY RCLDT ONLY IF
  590. ; A SECTOR IS TO BE WRITTEN.  THIS IS DONE TO BYPASS BIOS
  591. ; DELAYS WHEN SWITCHING DRIVES AND TO PREVENT NEEDLESS
  592. ; SEEKING TO TRACKS WHICH MIGHT NOT RECIEVE ANY DATA.
  593. ; INTERNALLY REFERENCED ROUTINE.
  594. ;
  595. WRDDB:
  596.     XRA    A    ;CLEAR WRITE ERROR FLAG
  597.     STA    WRTERRF
  598.     MOV    A,H    ;SEE IF A DDB IS PRESENT
  599.     ORA    L
  600.     RZ        ;NO - ALL DONE WRITING
  601.     MOV    A,M    ;GET TRACK NUMBER
  602.     INR    A    ;TRACK = 0FFH (MEANING EMPTY)?
  603.     RZ        ;YES - NO WRITING TO DO
  604.     SHLD    TRKPTR    ;NO - SAVE DISK & TRACK POINTER FOR
  605.     XRA    A    ;RECALL LATER, AND RESET FLAG 
  606.     STA    SENTFLG    ;SHOWING THAT THEY HAVEN'T BEEN SENT
  607.     INX    H    ;POINT TO FIRST SECTOR NUMBER
  608.     INX    H
  609. TSTUPDT:
  610.     MOV    A,M    ;GET SECTOR TO REG A
  611.     ORA    A    ;END OF DDB?
  612.     RZ        ;YES - ALL DONE
  613.     MOV    C,A    ;SAVE SECTOR IN REG C
  614.     INX    H    ;POINT TO UPDATE FLAG
  615.     MOV    A,M    ;GET UPDATE FLAG
  616.     ORA    A    ;DOES THIS SECTOR NEED UPDATING ON DISK?
  617.     CNZ    WRSEC    ;YES - WRITE IT BACK
  618.     LXI    D,SECLEN+2 ;BYTES TO NEXT SECTOR NUMBER
  619.     DAD    D
  620.     JMP    TSTUPDT    ;CHECK THE NEXT UPDATE FLAG
  621. ;
  622. ; WRITE A SECTOR FROM A DDB BACK OUT TO DISK.
  623. ; INTERNALLY REFERENCED ROUTINE.
  624. ;
  625. WRSEC:
  626.     MVI    M,0    ;RESET UPDATE FLAG
  627.     PUSH    H    ;SAVE UPDATE FLAG POINTER
  628.     CALL    CSETSEC    ;PASS SECTOR NUBER TO BIOS
  629.     CALL    RCLDT    ;PASS DRIVE AND TRACK TO BIOS
  630.     POP    H    ;GET UPDATE FLAG POINTER
  631.     PUSH    H    ;AND SAVE AGAIN
  632.     INX    H    ;POINT TO DATA
  633.     MOV    B,H    ;DATA ADDRESS TO REG BC
  634.     MOV    C,L
  635.     CALL    CSETDMA    ;PASS DMA ADDRESS TO BIOS
  636.     CALL    CWRITE    ;WRITE THE DATA OUT
  637.     LXI    H,WRTERRF ;OR THIS WRITE ERROR FLAG IN WITH
  638.     ORA    M    ;THE REST FROM THIS WRDDB
  639.     MOV    M,A
  640.     POP    H    ;GET CALLERS REG HL BACK
  641.     RET
  642. ;
  643. ; RECALL DISK AND TRACK INFO FROM A DDB, PASS IT TO THE BIOS,
  644. ; AND SET FLAG SHOWING THAT IS HAS BEEN SENT.
  645. ; INTERNALLY REFERENCED ROUTINE.
  646. ;
  647. RCLDT:
  648.     LXI    H,SENTFLG ;HAS THIS INFO ALREADY BEEN SENT?
  649.     MOV    A,M
  650.     ORA    A
  651.     RNZ        ;YES - SKIP SENDING AGAIN
  652.     MVI    M,SENTTOK ;NO - SET FLAG SHOWING IT HAS BEEN SENT
  653.     LHLD    TRKPTR    ;GET POINTER TO DRIVE & TRACK INFO
  654.             ;AND FALL THRU TO SEND IT TO BIOS
  655. ;
  656. ; SEND DRIVE AND TRACK INFO FROM A DDB TO THE BIOS.
  657. ; INTERNALLY REFERENCED ROUTINE.
  658. ;
  659. SENDDT:
  660.     PUSH    H    ;SAVE TRACK POINTER
  661.     INX    H    ;POINT TO DRIVE
  662.     MOV    C,M    ;GET DRIVE TO REG C
  663.     CALL    CSETDSK    ;PASS DISK
  664.     POP    H    ;GET TRACK POINTER
  665.     MOV    C,M    ;GET TRACK TO REG C
  666.     JMP    CSETTRK    ;PASS TRACK AND RETURN FROM THERE
  667. ;
  668. ; MOVE A SECTOR FROM ONE PLACE IN MEMORY TO ANOTHER.  GIVE
  669. ; ERROR MESSAGE IF DATA CAN'T BE WRITTEN INTO DESTINATION.
  670. ; INTERNALLY REFERENCED ROUTINE.
  671. ;
  672. XFER:
  673.     MVI    C,SECLEN ;COUNT NUMBER OF BYTES TO XFER IN C
  674. XF1:
  675.     LDAX    D    ;GET BYTE FROM SOURCE
  676.     MOV    M,A    ;STORE INTO DESTINATION
  677.     XRA    M    ;DID IT GO?
  678.     CNZ    MEMHIT    ;NO - GIVE WARNING MESSAGE
  679.     INX    H    ;INCREMENT DEST POINTER
  680.     INX    D    ;INCREMENT SOURCE POINTER
  681.     DCR    C    ;DONE WITH MOVE YET?
  682.     JNZ    XF1    ;NO - KEEP MOVING
  683.     RET        ;YES - ALL DONE
  684. ;
  685. ; LOCAL MESSAGE PRINTER.  WE CAN'T USE BDOS BECAUSE BDOS IS NOT
  686. ; RE-ENTRANT (WE MIGHT HAVE GOTTEN HERE VIA BDOS).  FOLLOW
  687. ; THE CALL TO MSGP WITH THE TEXT OF THE MESSAGE.  THE LAST
  688. ; CHARACTER OF THE MESSAGE MUST HAVE BIT SEVEN ON (I.E. +80H)
  689. ; INTERNALLY REFERENCED ROUTINE.
  690. ;
  691. MSGP:
  692.     XTHL        ;GET MESSAGE ADDRESS TO REG HL
  693. MSG1:
  694.     MOV    C,M    ;GET MESSAGE CHARACTER
  695.     PUSH    H    ;SAVE MESSAGE ADDRESS DURING PRINTING
  696.     CALL    CCONOUT    ;SEND IT
  697.     POP    H    ;RESTORE MESSAGE ADDRESS
  698.     MOV    A,M    ;GET CHR JUST SENT
  699.     INX    H    ;POINT TO NEXT CHARACTER
  700.     ORA    A    ;WAS THAT THE LAST CHR TO PRINT?
  701.     JP    MSG1    ;NO - KEEP PRINTING
  702.     XTHL        ;YES - PUT MODIFIED RETURN ADDREESS
  703.     RET        ;BACK ON STACK AND RETURN PAST MESSAGE
  704.     PAGE
  705. ;
  706. ;  \\\\\\\\\\\\\\\\                ////////////////
  707. ;   >>>>>>>>>>>>>>>>    R A M     <<<<<<<<<<<<<<<<
  708. ;  ////////////////   A R E A S    \\\\\\\\\\\\\\\\
  709. ;
  710. ;
  711. ; SAVE SPACE FOR A COPY OF THE BIOS JUMP TABLE BEFORE THE
  712. ; INSTALLATION OF FAST
  713. ;
  714. SAVEJMP:
  715. CBOOT:     JMP    $-$
  716. CWBOOT:     JMP    $-$
  717. CCONST:     JMP    $-$
  718. CCONIN:     JMP    $-$
  719. CCONOUT: JMP    $-$
  720. CLIST:     JMP    $-$
  721. CPUNCH:     JMP    $-$
  722. CREADER: JMP    $-$
  723. CHOME:     JMP    $-$
  724. CSETDSK: JMP    $-$
  725. CSETTRK: JMP    $-$
  726. CSETSEC: JMP    $-$
  727. CSETDMA: JMP    $-$
  728. CREAD:     JMP    $-$
  729. CWRITE:     JMP    $-$
  730. ;
  731. DIRADR    DW    0    ;ADDRESS OF CURRENT DIRECTORY DDB
  732. RDADR    DW    0    ;ADDRESS OF CURRENT READ TRACK DDB
  733. WRADR    DW    0    ;ADDRESS OF CURRENT WRITE TRACK DDB
  734. ;
  735. TRKPTR    DW    0    ;POINTER TO TRACK & DRIVE INFO IN DDB
  736. SENTFLG    DB    0    ;ZERO IF TRACK & DRIVE HAVEN'T BEEN SENT
  737. WRTERRF    DB    0    ;WRITE DDB ERROR FLAG, 0 IF NO ERROR
  738. ;
  739. REQDSK    DB    0FFH
  740. REQTRK    DB    0FFH
  741. REQSEC    DB    0FFH
  742. REQDMA    DW    0FFFFH
  743. ;
  744. ONLINE    DB    0, 0, 0, 0 ;DRIVE ON LINE VECTOR
  745. ;
  746.     DS    10H    ;AT LEAST AS MUCH STACK AS CCP
  747. ;
  748.     ORG    (($-1) OR 255) + 1 ;ORG TO NEXT PAGE BOUNDRY
  749. STACK:
  750. ;
  751. CODELEN    EQU    $-BASE
  752. ;
  753.     ORG    CODELEN    ;INFORM OPERATOR OF CODE LENGTH
  754.     END    FASTNTRY
  755.