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 / CPM / CPM3 / BIOS3.AQM / BIOS3.ASM
Assembly Source File  |  2000-06-30  |  38KB  |  1,318 lines

  1. *****************************************************************
  2. *                                *
  3. * BIOS and Loader BIOS for CP/M Plus (Beta V1.2) for DJ2D    *
  4. * controller.                            *
  5. * Written November 1982 by Dave Hardy and Ken Jackson        *
  6. *                                *
  7. *****************************************************************
  8.  
  9.     TITLE    'BIOS and Loader BIOS For CP/M Plus'
  10.  
  11. *****************************************************************
  12. *                                *
  13. * To install this BIOS into CP/M Plus, perform the following    *
  14. * steps:                            *
  15. *    1. Add your own console and printer I/O to this file    *
  16. *       at CONIN:, CONOUT:, CONST:, LIST:, and LISTST:    *
  17. *    2. Add any initialization that you need at TINIT:    *
  18. *    3. Set the LDRBIOS equate in this file to TRUE        *
  19. *    4. RMAC SCB $PZ -S    (assemble SCB.ASM, supplied)    *
  20. *    5. RMAC BIOS3 $PZ -S    (assemble LDRBIOS)        *
  21. *    6. REN LDRBIOS.REL=BIOS3.REL                *
  22. *    7. Set the LDRBIOS equate in this file FALSE        *
  23. *    8. RMAC BIOS3 $PZ -S    (assemble BIOS)            *
  24. *    9. LINK BIOS3[B]=BIOS3,SCB                *
  25. *      10. GENCPM                        *
  26. *        (answer all questions with a carriage return,    *
  27. *         except answer "N" at "Bank switched memory?"    *    
  28. *         question, and answer with your top page of    *
  29. *         memory when asked "Top page of memory?")    *
  30. *      11. LINK CPMLDR[L100]=CPMLDR,LDRBIOS            *
  31. *      12. CPMLDR        (Load and run CP/M Plus)    *
  32. *                                *
  33. *****************************************************************
  34.  
  35. FALSE    EQU    0        ;Define TRUE and FALSE
  36. TRUE    EQU    NOT FALSE
  37.  
  38. *****************************************************************
  39. *                                *
  40. * The following revision number is in reference to the CP/M    *
  41. * Plus BIOS.                             *
  42. *                                *
  43. *****************************************************************
  44.  
  45. REVNUM    EQU    10        ;BIOS revision number
  46. CPMREV    EQU    30        ;CP/M revision number
  47.  
  48. *****************************************************************
  49. *                                *
  50. * These are the routines called from the DJ2D's built-in EPROM.    *
  51. * (model B only)                        *
  52. *                                *
  53. *****************************************************************
  54.  
  55. ORIGIN    EQU    0F800H        ;EPROM origin of your DJ2D board
  56. DJRAM    EQU    ORIGIN+400H    ;DJ2D RAM address
  57. DJHOME    EQU    DJRAM+9H    ;DJ2D track zero seek
  58. DJTRK    EQU    DJRAM+0CH    ;DJ2D track seek routine
  59. DJSEC    EQU    DJRAM+0FH    ;DJ2D set sector routine
  60. DJDMA    EQU    DJRAM+012H    ;DJ2D set DMA address
  61. DJREAD    EQU    DJRAM+15H    ;DJ2D read routine
  62. DJWRITE    EQU    DJRAM+18H    ;DJ2D write routine
  63. DJSEL    EQU    DJRAM+1BH    ;DJ2D select drive routine
  64. DJSTAT    EQU    DJRAM+27H    ;DJ2D status routine
  65. DJSIDE    EQU    DJRAM+30H    ;DJ2D set side routine
  66.  
  67. *****************************************************************
  68. *                                *
  69. * Miscellaneous internal BIOS equates.                *
  70. * We've tried to maintain compatibility with the Morrow's DJ2D    *
  71. * BIOS.                                *
  72. *                                *
  73. *****************************************************************
  74.  
  75. LDRBIOS    EQU    FALSE        ;TRUE, if want to assemble as Loader BIOS
  76. UD2    EQU    TRUE        ;TRUE, if want to use User/Drive byte @ addr 4
  77. CDISK    EQU    4        ;Address of last logged disk
  78. BUFF    EQU    80H        ;Default buffer address
  79. TPA    EQU    100H        ;Transient memory
  80. ENTRY    EQU    5        ;BDOS entry jump address
  81. RETRIES    EQU    10        ;Max retries on disk i/o before error
  82. ACR    EQU    0DH        ;A carriage return
  83. ALF    EQU    0AH        ;A line feed
  84. MAXDISK    EQU    4        ;Maximum # of disk drives
  85. CLEAR    EQU    1AH        ;Clear Screen code for LDRBIOS
  86.  
  87. *****************************************************************
  88. *                                *
  89. * PUBLIC and EXTERNAL declarations required for CP/M Plus.    *
  90. *                                *
  91. *****************************************************************
  92.  
  93.     CSEG
  94.     PUBLIC    ?BOOT,?WBOOT,?CONST,?CONIN,?CONO,?LIST,?AUXO,?AUXI
  95.     PUBLIC    ?HOME,?SLDSK,?STTRK,?STSEC,?STDMA,?READ,?WRITE
  96.     PUBLIC    ?LISTS,?SCTRN
  97.     PUBLIC    ?CONOS,?AUXIS,?AUXOS,?DVTAB,?DEVIN,?DRTBL,?MLTIO,?FLUSH
  98.     PUBLIC    ?MOV,?TIM,?BNKSL,?STBNK,?XMOV
  99.     IF    NOT LDRBIOS
  100.     PUBLIC    ?INIT,?LDCCP
  101.     EXTRN    @CIVEC,@COVEC,@AIVEC,@AOVEC,@LOVEC,@MXTPA
  102.     ENDIF
  103.  
  104. *****************************************************************
  105. *                                *
  106. *  THE BIOS JUMP TABLE                        *
  107. *                                *
  108. * The jump table below must remain in the same order, the     *
  109. * routines may be changed, but the function executed must be    *
  110. * the same.  There are 33 jumps in the CP/M Plus BIOS vector.    *
  111. *                                *
  112. *****************************************************************
  113.  
  114. ;
  115. ?BOOT:    JMP    CBOOT            ; cold start entry point
  116. WBOOTE:
  117. ?WBOOT:    JMP    WBOOT            ; warm start entry point
  118. ?CONST:    JMP    CONST            ; console status A=ff=ready
  119. ?CONIN:    JMP    CONIN            ; console input  data in A
  120. COUT:
  121. ?CONO:    JMP    CONOUT            ; console output data in C
  122. ?LIST:    JMP    LIST            ; list device    data in C
  123. ?AUXO:    JMP    AUXOUT            ; punch device   none
  124. ?AUXI:    JMP    AUXIN              ; reader device  none
  125. ?HOME    JMP    HOME            ; seek home track
  126. ?SLDSK:    JMP    SETDRV            ; select disk    disk in C
  127. ?STTRK:    JMP    SETTRK            ; seek track     track in BC
  128. ?STSEC:    JMP    SETSEC            ; set sector     sector in BC
  129. ?STDMA:    JMP    SETDMA            ; set dma        dma in BC
  130. ?READ:    JMP    READ            ; read sector
  131. ?WRITE:    JMP    WRITE            ; write sector
  132. ?LISTS:    JMP    LISTST            ; return list status A=FF=ready
  133. ?SCTRN:    JMP    SECTRAN            ; sector translate  sector in BC
  134. ?CONOS:    JMP    CONOST            ; Return Output Status of Console
  135. ?AUXIS:    JMP    AUXIST            ; Return Input Status of Aux. Port
  136. ?AUXOS:    JMP    AUXOST            ; Return Output Status of Aux. Port
  137. ?DVTAB:    JMP    DEVTBL            ; Return Address of Char. I/O Table
  138. ?DEVIN:    JMP    DEVINI            ; Initialize Char. I/O Devices
  139. ?DRTBL:    JMP    DRVTBL            ; Return Address of Disk Drive Table
  140. ?MLTIO:    JMP    MULTIO            ; Set number of logically conseqcuitive
  141.                     ;  sectors to be read or written
  142. ?FLUSH:    JMP    FLUSH            ; Force Physical Buffer Flushing for 
  143.                     ;  user-supported deblocking
  144. ?MOV:    JMP    MOVE            ; Memory Move for Large Memory Copy
  145. ?TIM:    JMP    ?TIME            ; Get The Time
  146. ?BNKSL:    JMP    SELMEM            ; Select Alternate Bank of Memory
  147. ?STBNK:    JMP    SETBNK            ; Select Bank for DMA Operation
  148. ?XMOV:    JMP    XMOVE            ; Set Bank When a Buffer is in a Bank
  149.                     ;  other than 0 or 1
  150. DJDRV    JMP    DJSEL            ; Hook for SINGLE.COM program
  151.                     ; Reserved for System Implementor
  152.     JMP    RESERV1            ; Reserved for CP/M Plus
  153.     JMP    RESERV2            ; Reserved for CP/M Plus
  154. ;
  155. ;  Device Table is not implemented, so return HL=0
  156. DEVTBL:    LXI    H,0
  157.     RET
  158. ;
  159. ;  Flush routine is not implemented, so return A=0
  160. FLUSH:    XRA    A
  161.     RET
  162. ;
  163. ;  Drive Table is not used, so return HL=0FFFEH
  164. DRVTBL:    LXI    H,0FFFEH
  165.     RET
  166. ;
  167. ;  The following jumps from the BIOS jump vector are not implemented:
  168. CONOST:
  169. AUXIST:
  170. AUXOUT:
  171. AUXIN:
  172. AUXOST:
  173. DEVINI:
  174. MULTIO:
  175. XMOVE:
  176. SELMEM:
  177. SETBNK:
  178. RESERV1:
  179. RESERV2:
  180. ?TIME:
  181.     RET
  182.  
  183. *****************************************************************
  184. *                                *
  185. * Cold-boot sign-on message                    *
  186. *                                *
  187. *****************************************************************
  188.  
  189. PROMPT:
  190.     IF    LDRBIOS
  191.     DB    ACR,ALF,ALF
  192.     DB    'Loader for Morrow Designs DJ2D Controller.'
  193.     DB    ACR,ALF,0
  194.     ENDIF
  195. ;
  196.     IF    NOT LDRBIOS
  197.     DB    ACR,ALF,ALF
  198.     DB    'CP/M Plus (V'        ;CP/M version number
  199.     DB    CPMREV/10+'0'
  200.     DB    '.'
  201.     DB    (CPMREV MOD 10)+'0'
  202.     DB    '), BIOS rev '
  203.     DB    REVNUM/10+'0','.'    ;Cbios revision number
  204.     DB    REVNUM MOD 10+'0'
  205.     DB    ACR,ALF
  206.     DB    'For Morrow Designs DJ2D Controller '
  207.     DB    '@ 0'
  208.  
  209.     IF    ORIGIN/4096 > 10    ;Controller origin (HEX)
  210.     DB    ORIGIN/4096+'A'-10
  211.     ELSE
  212.     DB    ORIGIN/4096+'0'
  213.     ENDIF
  214.  
  215.     IF    (ORIGIN/256 AND 0FH) > 10
  216.     DB    (ORIGIN/256 AND 0FH)+'A'-10
  217.     ELSE
  218.     DB    (ORIGIN/256 AND 0FH)+'0'
  219.     ENDIF
  220.     DB    '00H.'
  221.     DB    ACR,ALF,0
  222.     ENDIF
  223.  
  224. *****************************************************************
  225. *                                *
  226. * Utility subroutine to output the message pointed at by H&L,    *
  227. * terminated with a null.  Used only during cold boot.        *
  228. *                                *
  229. *****************************************************************
  230.  
  231. MESSAGE    MOV    A,M        ;Get a character of the message
  232.     INX    H        ;Bump text pointer
  233.     ANA    A        ;Test for end
  234.     RZ            ;Return if done
  235.     PUSH    H        ;Save pointer to text
  236.     MOV    C,A        ;Output character in C
  237.     CALL    COUT        ;Output the character
  238.     POP    H        ;Restore the pointer
  239.     JMP    MESSAGE        ;Continue until null reached
  240.  
  241. *****************************************************************
  242. *                                *
  243. * System initialization Subroutine                *
  244. * Put any initialization procedures required by your system    *
  245. * here (e.g. setting up UARTS, etc.)                *
  246. *                                *
  247. *****************************************************************
  248.  
  249.     IF    LDRBIOS        ;Then perform any initializations
  250. TINIT:    MVI    C,CLEAR        ; that your system requires
  251.     CALL    COUT        ;Clear the console screen
  252.     RET
  253.     ENDIF
  254.  
  255. *****************************************************************
  256. *                                *
  257. * Cold boot routines                        *
  258. *                                *
  259. *****************************************************************
  260.  
  261. CBOOT:
  262.     IF    LDRBIOS        ;Then Initialize terminal or whatever
  263.     CALL    TINIT
  264.     ENDIF
  265. ;
  266.     IF    NOT LDRBIOS
  267.     LXI    SP,TPA        ;Set up stack
  268.     ENDIF
  269. ;
  270.     LXI    H,PROMPT    ;Prep for sending signon message
  271.     CALL    MESSAGE        ;Send the prompt
  272.     XRA    A        ;Select disk A
  273.     STA    CPMDRV
  274.     STA    CDISK
  275. ;
  276.     IF    NOT LDRBIOS
  277.     CALL    ?INIT        ;Initialize page zero and SCB
  278.     JMP    WBOOT        ;Warm-boot
  279. ;
  280. ;  System initialization subroutine
  281. ?INIT:    MVI    A,JMP        ;Set up jumps at addresses 0 and 5
  282.     STA    0
  283.     STA    5
  284.     LXI    H,WBOOTE
  285.     SHLD    1
  286.     LHLD    @MXTPA
  287.     SHLD    6
  288.     LXI    H,1        ;Initialize System Control Block
  289.     SHLD    @CIVEC
  290.     SHLD    @COVEC
  291.     LXI    H,2
  292.     SHLD    @LOVEC
  293.     LXI    H,4
  294.     SHLD    @AIVEC
  295.     SHLD    @AOVEC
  296.     LXI    H,LOG$MSG    ;Print sign-on message on console
  297.     CALL    MESSAGE
  298.     RET
  299.  
  300. *****************************************************************
  301. *                                *
  302. *  Subroutine to load the CCP into memory at address 100H    *
  303. *                                *
  304. *****************************************************************
  305.  
  306. ?LDCCP:    XRA    A
  307.     STA    CCP$FCB+15    ;Start with extent 0
  308.     LXI    H,0
  309.     SHLD    FCB$NR        ;Record 0
  310.     LXI    D,CCP$FCB
  311.     CALL    OPEN        ;Open file CCP.COM
  312.     INR    A
  313.     JZ    NO$CCP        ;Tell if no file found
  314.     LXI    D,0100H        ;Else
  315.     CALL    SETBUF        ;Set to load into TPA
  316.     LXI    D,128
  317.     CALL    SETMULTI    ;Allow up to 16k bytes
  318.     LXI    D,CCP$FCB
  319.     CALL    REBOOT        ;Read file into memory
  320.     RET
  321. ;
  322. ;  Print error message if can't find CCP.COM on default drive
  323. NO$CCP:    LXI    H,CCP$MSG
  324.     CALL    MESSAGE        ;REPORT THIS
  325.     CALL    ?CONIN        ;GET A RESPONSE
  326.     JMP    ?LDCCP        ;AND TRY AGAIN
  327.  
  328. ;
  329. ;  CP/M BDOS function interface used to load CCP.COM
  330. OPEN:    MVI    C,15
  331.     JMP    BDOSGO        ;OPEN FILE CONTROL
  332.  
  333. SETMULTI:
  334.     MVI    C,44
  335.     JMP    BDOSGO        ;SET MULTI RECORD COUNT
  336.  
  337. REBOOT:    MVI    C,20
  338.     JMP    BDOSGO        ;READ RECORDS
  339.  
  340. SETBUF:    MVI    C,26
  341.     JMP    BDOSGO        ;SETDMA
  342.  
  343. BDOSGO:    LHLD    @MXTPA
  344.     PCHL    
  345. ;
  346. ;  Miscellaneous messages for console
  347. LOG$MSG:
  348.     DB    13,10,13,10,'CP/M Version 3.0',00
  349. CCP$MSG:
  350.     DB    13,10,'BIOS Err on A: NO CCP.COM file',00
  351. ;
  352. ;  File Control Block used to load CCP.COM
  353. CCP$FCB:
  354.     DB    1,'CCP     ','COM',0,0,0,0
  355.     DS    16
  356. FCB$NR:    DB    0,0,0
  357.     ENDIF    ;NOT LDRBIOS
  358.  
  359. *****************************************************************
  360. *                                *
  361. *  Warm-boot subroutine                        *
  362. *                                *
  363. *****************************************************************
  364.  
  365.  
  366. WBOOT:
  367.     IF    NOT LDRBIOS
  368.     LXI    SP,TPA        ;Set up stack pointer
  369.     ENDIF
  370. ;
  371.     LXI    D,BUFF        ;Set up initial DMA address
  372.     CALL    SETDMA
  373. ;
  374.     IF    NOT LDRBIOS
  375.     CALL    ?LDCCP        ;Load the CCP.COM file into the TPA
  376.     ENDIF
  377. ;
  378.     MVI    A,JMP        ;Set up jumps at addresses 0 and 5
  379.     STA    0
  380.     STA    5
  381.     LXI    H,WBOOTE
  382.     SHLD    1
  383. ;
  384.     IF    NOT LDRBIOS
  385.     LHLD    @MXTPA
  386.     SHLD    6
  387. ;
  388.     IF    UD2
  389. ;  This conditional is used if you want the system to read the 
  390. ;  USER/DRIVE byte at address 4 during each warm-boot, to maintain
  391. ;  compatibility with certain CP/M 2.2 programs that modify this byte
  392. ;  to change default user area of drive.  Making this conditional TRUE
  393. ;  may cause some unusual side-effects when you warm-boot while logged
  394. ;  into any drive other than 'A' drive.  Note also that the location of
  395. ;  the warm-boot user and drive bytes in the SCB is undocumented, so it
  396. ;  may be changed from the address assumed here.  This may also have been
  397. ;  changed since the Beta 1.2 version that we evaluated, so use it with
  398. ;  a great deal of caution.
  399. ;
  400. ;  Copy USER/DRIVE byte from address 4 into the System Control Block
  401.     LHLD    1    ;Get address page of BIOS
  402.     DCR    H    ;Point to default drive byte in SCB
  403.     MVI    L,0AFH
  404.     LDA    4    ;Get default drive from User/Drive byte
  405.     ANI    0FH
  406.     MOV    M,A    ;Store DRIVE in SCB
  407.     INX    H    ;Point to default user byte in SCB
  408.     LDA    4    ;Get default user from User/Drive byte
  409.     RRC
  410.     RRC
  411.     RRC
  412.     RRC
  413.     ANI    0FH
  414.     MOV    M,A    ;Store USER in SCB
  415. ;
  416.     ENDIF    ;UD2
  417.     ENDIF    ;NOT LDRBIOS
  418. ;
  419.     LDA    CDISK    ;Put current disk into A
  420.     MOV    C,A
  421. ;
  422.     IF    NOT LDRBIOS
  423.     JMP    0100H    ;Jump to CCP
  424.     ENDIF
  425. ;
  426.     IF    LDRBIOS
  427.     RET        ;Return to loader
  428.       ENDIF
  429.  
  430. *****************************************************************
  431. *                                *
  432. * General purpose memory move subroutine.            *
  433. * Moves BC bytes from DE to HL                    *
  434. *                                *
  435. *****************************************************************
  436.  
  437. MOVE:    LDAX    D
  438.     MOV    M,A
  439.     INX    D
  440.     INX    H
  441.     DCR    C
  442.     JNZ    MOVE
  443.     MOV    A,B
  444.     ORA    C
  445.     RZ
  446.     DCR    B
  447.     JMP    MOVE
  448.  
  449. *****************************************************************
  450. *                                *
  451. * Setsec subroutine saves the desired sector to seek to until    *    
  452. * an actual read or write is attempted.                *
  453. *                                *
  454. *****************************************************************
  455.  
  456. SETSEC    MOV    A,C        ;Save the sector number
  457.     STA    CPMSEC
  458.     RET
  459.  
  460. *****************************************************************
  461. *                                *
  462. * Setdma subroutine saves the DMA address for the data transfer.*
  463. *                                *
  464. *****************************************************************
  465.  
  466. SETDMA    MOV    H,B        ;Save DMA address that is in BC
  467.     MOV    L,C
  468.     SHLD    CPMDMA
  469.     RET
  470.  
  471. *****************************************************************
  472. *                                *
  473. * Home subroutine does a seek to track zero.            *
  474. *                                *
  475. *****************************************************************
  476.  
  477. HOME    MVI    C,0        ;Track to seek to
  478.  
  479. *****************************************************************
  480. *                                *
  481. * Settrk subroutine saves the TRK # to seek to. Nothing is done *
  482. * until an actual read or write.                *
  483. *                                *
  484. *****************************************************************
  485.  
  486. SETTRK    MOV    A,C
  487.     STA    CPMTRK
  488.     RET
  489.  
  490. *****************************************************************
  491. *                                *
  492. * Sectran subroutine translates a logical sector # into a    *
  493. * physical sector #.  Note that this routine is similar to the    *
  494. * original one used in the DJ2D CP/M 2 BIOS, but has some    *
  495. * significant differences.                    *
  496. *                                *
  497. *****************************************************************
  498.  
  499. SECTRAN    INX    B
  500.     PUSH    D        ;Save table address
  501.     PUSH    B        ;Save sector #
  502.     CALL    GETDPB        ;Get DPB address into HL
  503.     MOV    A,M        ;Get # of CP/M sectors/track
  504.     ORA    A        ;Clear carry
  505.     RAR            ;Divide by two
  506.     SUB    C
  507.     PUSH    PSW        ;Save adjusted sector
  508.     JM    SIDETWO
  509. SIDEA    POP    PSW        ;Discard adjusted sector
  510.     POP    B        ;Restore sector requested
  511.     POP    D        ;Restor address of xlt table
  512. SIDEONE    XCHG            ;exchange DPB and table address
  513.     DAD    B        ;bc = offset into table
  514.     MOV    L,M        ;hl <- physical sector
  515.     MVI    H,0
  516.     RET
  517.  
  518. SIDETWO    LXI    B,17        ;Offset to side bit
  519.     DAD    B
  520.     MOV    A,M
  521.     ANI    8        ;Test for double sided
  522.     JZ    SIDEA        ;Media is only single sided
  523.     POP    PSW        ;Retrieve adjusted sector
  524.     POP    B
  525.     CMA            ;Make sector request positive
  526.     INR    A
  527.     MOV    C,A        ;Make new sector the requested sector
  528.     POP    D
  529.     CALL    SIDEONE
  530.     MVI    A,80H        ;Side two bit
  531.     ORA    L        ;    and sector
  532.     MOV    L,A
  533.     RET
  534.  
  535. *****************************************************************
  536. *                                *
  537. * Setdrv subroutine selects the next drive to be used in    *
  538. * read/write operations. If the drive has never been selected    *
  539. * before, a parameter table is created which correctly        *
  540. * describes the diskette currently in the drive. Diskettes can    *
  541. * be of four different sector sizes:                *    
  542. *    1) 128 bytes single density.                *
  543. *    2) 256 bytes double density.                *
  544. *    3) 512 bytes double density.                *
  545. *    4) 1024 bytes double density.                *
  546. *  Note the changes made for CP/M 3.0                *
  547. *                                *
  548. *****************************************************************
  549.  
  550. SETDRV    MOV    A,C        ;Save the drive #
  551.     STA    CPMDRV
  552.     CPI    MAXDISK        ;Check for a valid drive #
  553.     JNC    ZRET        ;Illegal drive #
  554.     MOV    A,E        ;Test if drive ever logged in before
  555.     ANI    1
  556.     JNZ    SETDRV1        ;Bit 0 of E = 0 means never selected before
  557.     MVI    A,1        ;Select sector 1 of track 1
  558.     STA    TRUESEC
  559.     STA    CPMTRK
  560.     CALL    FILL        ;Flush buffer and refill
  561.     JC    ZRET        ;Test for error return
  562.     CALL    DJSTAT        ;Get status on current drive
  563.     ANI    2CH        ;Look at side and denstiy bits
  564.     MOV    E,A
  565.     ANI    20H
  566.     MOV    A,E
  567.     JNZ    SETDR1
  568.     ORI    10H
  569. SETDR1:    RAR
  570.     PUSH    PSW        ;Save DJSTAT single/double-sided info
  571.     ANI    6
  572.     LXI    H,XLTS        ;Table of XLT addresses
  573.     PUSH    H
  574.     MOV    E,A
  575.     MVI    D,0
  576.     DAD    D
  577.     PUSH    H        ;Save pointer to proper XLT
  578.     CALL    GETDPB        ;Get DPH pointer into DE
  579.     XCHG            ;
  580.     POP    D
  581.     MVI    B,2        ;Number of bytes to move
  582.     CALL    MOVLOP        ;Move the address of XLT
  583.     LXI    D,10        ;Offset to DPB pointer
  584.     DAD    D        ;Point HL to DPB address
  585.     XCHG            ;Point HL to DBP base, DE to &DPH.DPB
  586.     POP    H
  587.     POP    PSW        ;Offset to correct DPB
  588.     MOV    C,A
  589.     MVI    B,0
  590.     DAD    B        ;Add to translate table to point to density
  591.                 ;(The DPB table is cleverly located right
  592.                 ; after the xlt table)
  593.     XCHG            ;Put DPB address in DPH
  594.     MVI    B,2        ;Move DPB address into DPH
  595.     CALL    MOVLOP
  596. SETDRV1    CALL    GETDPB        ;Get address of DPB in HL
  597.     LXI    B,17        ;Offset to sector size
  598.     DAD    B
  599.     MOV    A,M        ;Get sector size
  600.     ANI    7H
  601.     STA    SECSIZ
  602.     MOV    A,M
  603.     RAR
  604.     RAR
  605.     RAR
  606.     RAR
  607.     ANI    0FH
  608.     STA    SECPSEC        ;Single/double-sided flag
  609.     XCHG            ;HL to DPH
  610.     RET
  611.  
  612. ZRET    LXI    H,0        ;Seldrv error exit
  613.     RET
  614.  
  615. *****************************************************************
  616. *                                *
  617. * Getdpb subroutine returns HL pointing to the DPB of the    *
  618. * currently selected drive, DE pointing to DPH.            *
  619. *                                *
  620. *****************************************************************
  621.  
  622. GETDPB:    LDA    CPMDRV        ;Get drive #
  623.     LXI    H,DPZERO
  624.     LXI    D,19H
  625. GETDP1:    ORA    A
  626.     JZ    GETDP2
  627.     DAD    D
  628.     DCR    A
  629.     JMP    GETDP1
  630. ;
  631. GETDP2:    PUSH    H        ;Save address of DPH
  632.     LXI    D,12        ;Offset to DPB
  633.     DAD    D
  634.     MOV    A,M        ;Get low byte of DPB address
  635.     INX    H
  636.     MOV    H,M        ;Get low byte of DPB
  637.     MOV    L,A
  638.     POP    D
  639.     RET
  640.  
  641. *****************************************************************
  642. *                                *
  643. * xlts points to a table of addresses that point to each    *
  644. * of the xlt tables for each sector size.            *
  645. *                                *
  646. * The table following the xlt's is a table of the DPB's, used    *
  647. * by the SETDRV subroutine to calculate density            *
  648. *                                *
  649. *****************************************************************
  650.  
  651. XLTS    DW    XLT128        ;Xlt for 128 byte sectors
  652.     DW    XLT256        ;Xlt for 256 byte sectors
  653.     DW    XLT512        ;Xlt for 512 byte sectors
  654.     DW    XLT124        ;Xlt for 1024 byte sectors
  655. ;
  656.     DW    DPB128S        ;DPB FOR 128 BYTE SECTORS SINGLE SIDE
  657.     DW    DPB256S        ;DPB FOR 256 BYTE SECTORS SINGLE SIDE
  658.     DW    DPB512S        ;DPB FOR 512 BYTE SECTORS SINGLE SIDE
  659.     DW    DP1024S        ;DPB FOR 1024 BYTE SECTORS SINGLE SIDE
  660.     DW    DPB128D        ;DPB FOR 128 BYTE SECTORS DOUBLE SIDE
  661.     DW    DPB256D        ;DPB FOR 256 BYTE SECTORS DOUBLE SIDE
  662.     DW    DPB512D        ;DPB FOR 512 BYTE SECTORS DOUBLE SIDE
  663.     DW    DP1024D        ;DPB F0R 1024 BYTE SECTORS DOUBLE SIDE
  664.  
  665. *****************************************************************
  666. *                                *
  667. * Write subroutine moves data from memory into the buffer. If    *
  668. * the desired CP/M sector is not contained in the disk buffer,    *
  669. * the buffer is first flushed to the disk if it has ever been    *
  670. * written into, then a read is performed into the buffer to get    *
  671. * the desired sector. Once the correct sector is in memory, the    *
  672. * buffer written indicator is set, so the buffer will be    *
  673. * flushed, then the data is transferred into the buffer.     *
  674. *                                *
  675. *****************************************************************
  676.  
  677. WRITE    MOV    A,C        ;Save write command type
  678.     STA    WRITTYP
  679.     MVI    A,1        ;Set write command
  680.     DB    (MVI) OR (B*8)    ;Fake "mvi b" instruction will
  681.                 ; cause the following "xra a" to
  682.                 ; be skipped over.
  683.                 ;This is the same (ugh) trick that
  684.                 ;Morrow's used, but it works...
  685.  
  686. *****************************************************************
  687. *                                *
  688. * Read subroutine to buffer data from the disk. If the sector     *
  689. * requested from CP/M is in the buffer, then the data is simply    *
  690. * transferred from the buffer to the desired dma address. If    *
  691. * the buffer does not contain the desired sector, the buffer is    *
  692. * flushed to the disk if it has ever been written into, then    *
  693. * filled with the sector from the disk that contains the    *
  694. * desired CP/M sector.                        *
  695. *                                *
  696. *****************************************************************
  697.  
  698. READ    XRA    A        ;Set the command type to read
  699.     STA    RDWR        ;Save command type
  700.  
  701. ;
  702. ; Redwrt calculates the physical sector on the disk that
  703. ; contains the desired CP/M sector, then checks if it is the
  704. ; sector currently in the buffer. If no match is made, the
  705. ; buffer is flushed if necessary and the correct sector read
  706. ; from the disk.
  707. REDWRT    MVI    B,0        ;The 0 is modified to contain the log2
  708. SECSIZ    EQU    $-1        ;    of the physical sector size/128
  709.                 ;    on the currently selected disk.
  710.                 ;(Another Morrow trick)
  711.     LDA    CPMSEC        ;Get the desired CP/M sector #
  712.     PUSH    PSW        ;Temporary save
  713.     ANI    80H        ;Save only the side bit
  714.     MOV    C,A        ;Remember the side
  715.     POP    PSW        ;Get the sector back
  716.     ANI    7FH        ;Forget the side bit
  717.     DCR    A        ;Temporary adjustment
  718. DIVLOOP    DCR    B        ;Update repeat count
  719.     JZ    DIVDONE
  720.     ORA    A        ;Clear the carry flag
  721.     RAR            ;Divide the CP/M sector # by the size
  722.                 ;    of the physical sectors
  723.     JMP    DIVLOOP        ;
  724. DIVDONE    INR    A
  725.     ORA    C        ;Restore the side bit
  726.     STA    TRUESEC        ;Save the physical sector number
  727.     LXI    H,CPMDRV    ;Pointer to desired drive,track, and sector
  728.     LXI    D,BUFDRV    ;Pointer to buffer drive,track, and sector
  729.     MVI    B,4        ;Count loop
  730. DTSLOP    DCR    B        ;Test if done with compare
  731.     JZ    SECMOV        ;Yes, match. Go move the data
  732.     LDAX    D        ;Get a byte to compare
  733.     CMP    M        ;Test for match
  734.     INX    H        ;Bump pointers to next data item
  735.     INX    D
  736.     JZ    DTSLOP        ;Match, continue testing
  737.  
  738. ;
  739. ; If drive, track, and sector don't match, then flush the buffer if
  740. ; necessary and refill.
  741.     CALL    FILL        ;Get correct physical sector into buffer
  742.     RC            ;Return error if no good
  743.  
  744. ;
  745. ; SECMOV has been previously modified to cause either a transfer
  746. ; into or out of the buffer. (Yet another Morrow trick)
  747. SECMOV    LDA    CPMSEC        ;Get the CP/M sector to transfer
  748.     DCR    A        ;Adjust to proper sector in buffer
  749.     ANI    0        ;Strip off high ordered bits
  750. SECPSEC    EQU    $-1        ;The 0 is modified to represent the # of
  751.                 ;    CP/M sectors per physical sectors
  752.     MOV    L,A        ;Put into HL
  753.     MVI    H,0
  754.     DAD    H        ;Form offset into buffer
  755.     DAD    H
  756.     DAD    H
  757.     DAD    H
  758.     DAD    H
  759.     DAD    H
  760.     DAD    H
  761.     LXI    D,BUFFER    ;Beginning address of buffer
  762.     DAD    D        ;Form beginning address of sector to transfer
  763.     XCHG            ;DE = address in buffer
  764.     LXI    H,0        ;Get DMA address, the 0 is modified to
  765.                 ;    contain the DMA address
  766. CPMDMA    EQU    $-2
  767.     MVI    A,0        ;The zero gets modified to contain
  768.                 ;    a zero if a read, or a 1 if write
  769. RDWR    EQU    $-1
  770.     ANA    A        ;Test which kind of operation
  771.     JNZ    INTO        ;Transfer data into the buffer
  772.     CALL    MOVER
  773.     XRA    A
  774.     RET
  775.  
  776. INTO    XCHG            ;
  777.     CALL    MOVER        ;Move the data, HL = destination
  778.                 ;    DE = source
  779.     MVI    A,1
  780.     STA    BUFWRTN        ;Set buffer written into flag
  781.     MVI    A,0        ;Check for directory write
  782. WRITTYP    EQU    $-1
  783.     DCR    A
  784.     MVI    A,0
  785.     STA    WRITTYP        ;Set no directory write
  786.     RNZ            ;No error exit
  787.  
  788. *****************************************************************
  789. *                                *
  790. * FLUSHA subroutine writes the contents of the buffer out to    *
  791. * the disk if it has ever been written into.            *
  792. *                                *
  793. *****************************************************************
  794.  
  795. FLUSHA    MVI    A,0        ;The 0 is modified to reflect if
  796.                 ; the buffer has been written into
  797. BUFWRTN    EQU    $-1
  798.     ANA    A        ;Test if written into
  799.     RZ            ;Not written, all done
  800.     LXI    H,DJWRITE    ;Write operation
  801. ;
  802. ; Prep prepares to read/write the disk. Retries are attempted.
  803. ; Upon entry, H&L must contain the read or write operation
  804. ; address.
  805. PREP    XRA    A        ;Reset buffer written flag
  806.     STA    BUFWRTN
  807.     SHLD    RETRYOP        ;Set up the read/write operation
  808.     MVI    B,RETRIES    ;Maximum number of retries to attempt
  809. RETRYLP    PUSH    B        ;Save the retry count
  810.     LDA    BUFDRV        ;Get drive number involved in the operation
  811.     MOV    C,A
  812.     CALL    DJDRV        ;Select the drive
  813.     LDA    BUFTRK
  814.     ANA    A        ;Test for track zero
  815.     MOV    C,A
  816.     PUSH    B
  817.     CZ    DJHOME        ;Home the drive if track 0
  818.     POP    B        ;Restore track #
  819.     CALL    DJTRK        ;Seek to proper track
  820.     LDA    BUFSEC        ;Get sector involved in operation
  821.     PUSH    PSW        ;Save the sector #
  822.     RLC            ;Bit 0 of A equals side #
  823.     ANI    1        ;Strip off unnecessary bits
  824.     MOV    C,A        ;C <- side #
  825.     CALL    DJSIDE        ;Select the side
  826.     POP    PSW        ;A <- sector #
  827.     ANI    7FH        ;Strip off side bit
  828.     MOV    C,A        ;C <- sector #
  829.     CALL    DJSEC        ;Set the sector to transfer
  830.     LXI    B,BUFFER    ;Set the DMA address
  831.     CALL    DJDMA
  832.     CALL    DJREAD        ;The read operation is modified to write
  833. RETRYOP    EQU    $-2
  834.     POP    B        ;Restore the retry counter
  835.     MVI    A,0        ;No error exit status
  836.     RNC            ;Return no error
  837.     DCR    B        ;Update the retry counter
  838.     STC            ;Assume retry count expired
  839.     MVI    A,0FFH        ;Error return
  840.     RZ
  841.     JMP    RETRYLP        ;Try again
  842.  
  843. *****************************************************************
  844. *                                *
  845. * Fill subroutine fills the buffer with a new sector        *
  846. * from the disk.                        *
  847. *                                *
  848. *****************************************************************
  849.  
  850. FILL    CALL    FLUSHA        ;Flush buffer first
  851.     RC            ;Check for error
  852.     LXI    D,CPMDRV    ;Update the drive, track, and sector
  853.     LXI    H,BUFDRV    
  854.     MVI    B,3        ;Number of bytes to move
  855.     CALL    MOVLOP        ;Copy the data
  856.     LXI    H,DJREAD
  857.     JMP    PREP        ;Select drive, track, and sector.
  858.                 ;    Then read the buffer
  859.  
  860. *****************************************************************
  861. *                                *
  862. * Mover subroutine moves 128 bytes of data. Source pointer    *
  863. * in DE, Dest pointer in HL.                    *
  864. *                                *
  865. *****************************************************************
  866.  
  867. MOVER    MVI    B,128        ;Length of transfer
  868. MOVLOP    LDAX    D        ;Get a bte of source
  869.     MOV    M,A        ;Move it
  870.     INX    D        ;Bump pointers
  871.     INX    H
  872.     DCR    B        ;Update counter
  873.     JNZ    MOVLOP        ;Continue moving until done
  874.     RET
  875.  
  876. *****************************************************************
  877. *                                *
  878. * Terminal driver subroutines.  Note that the console device    *
  879. * is NOT the DJ2D memory-mapped serial I/O port.        *
  880. *                                *
  881. *****************************************************************
  882.  
  883. *****************************************************************
  884. *                                *
  885. * const: get the status for the console                *
  886. *                                *
  887. *****************************************************************
  888.  
  889. CONST    IN    80H        ;Read console status port
  890.     ANI    40H
  891.     MVI    A,0
  892.     RZ            ;Return A=0, if no character waiting
  893.     INR    A
  894.     RET            ;Else return A=01H
  895.  
  896. *****************************************************************
  897. *                                *
  898. * conin: get a character from the console            *
  899. *                                *
  900. *****************************************************************
  901.  
  902. CONIN:    IN    80H        ;Read console status port
  903.     ANI    40H
  904.     JZ    CONIN        ;Wait for a character
  905.     IN    81H        ;Read the console data port
  906.     ANI    7FH        ;Mask the MSB
  907.     RET            ;Return with the character in A
  908.  
  909. *****************************************************************
  910. *                                *
  911. * conout: send a character to the console            *
  912. *                                *
  913. *****************************************************************
  914.  
  915. CONOUT    IN    80H        ;Read the console status port
  916.     ANI    80H
  917.     JZ    CONOUT        ;Wait until character can be sent
  918.     MOV    A,C
  919.     OUT    81H        ;Send character to console data port
  920.     RET            ;Return
  921.  
  922. *****************************************************************
  923. *                                *
  924. * listst: get the status for the list device.  Note that the    *
  925. * list device used is the memory-mapped DJ2D serial I/O port.    *
  926. *                                *
  927. *****************************************************************
  928.  
  929. LISTST:    LDA    ORIGIN+3F9H    ;Read printer status port (memory mapped)
  930.     CMA            ; (invert to positive logic)
  931.     ANI    08H
  932.     MVI    A,00H
  933.     RZ            ;return A=0, if not ready
  934.     MVI    A,0FFH        ;return A=0FFH, if ready 
  935.     RET
  936.  
  937. *****************************************************************
  938. *                                *
  939. * list: send a character to the list device            *
  940. *                                *
  941. *****************************************************************
  942.  
  943. LIST:    LDA    ORIGIN+3F9H    ;Read list device status (memory mapped)
  944.     CMA            ; (invert it to positive logic)
  945.     ANI    08H        ;Wait until ok to send
  946.     JZ    LIST
  947.     MOV    A,C        ;Send the character
  948.     CMA            ; (invert it to positive logic)
  949.     STA    ORIGIN+3F8H      ; to memory mapped I/O.
  950.     RET
  951.  
  952. *****************************************************************
  953. *                                *
  954. * Xlt tables (sector skew tables)  These tables            *
  955. * define the sector translation that occurs when mapping CP/M    *
  956. * sectors to physical sectors on the disk. There is one skew    *
  957. * table for each of the possible sector sizes.             *
  958. *                                *
  959. *****************************************************************
  960.  
  961. XLT128    DB    0
  962.     DB    1,7,13,19,25
  963.     DB    5,11,17,23
  964.     DB    3,9,15,21
  965.     DB    2,8,14,20,26
  966.     DB    6,12,18,24
  967.     DB    4,10,16,22
  968.  
  969. XLT256    DB    0
  970.     DB    1,2,19,20,37,38
  971.     DB    3,4,21,22,39,40
  972.     DB    5,6,23,24,41,42
  973.     DB    7,8,25,26,43,44
  974.     DB    9,10,27,28,45,46
  975.     DB    11,12,29,30,47,48
  976.     DB    13,14,31,32,49,50
  977.     DB    15,16,33,34,51,52
  978.     DB    17,18,35,36
  979.  
  980.  
  981. xlt512    db    0
  982.     db    1,2,3,4,17,18,19,20
  983.     db    33,34,35,36,49,50,51,52
  984.     db    5,6,7,8,21,22,23,24
  985.     db    37,38,39,40,53,54,55,56
  986.     db    9,10,11,12,25,26,27,28
  987.     db    41,42,43,44,57,58,59,60
  988.     db    13,14,15,16,29,30,31,32
  989.     db    45,46,47,48
  990.  
  991. XLT124    DB    0
  992.     DB    1,2,3,4,5,6,7,8
  993.     DB    25,26,27,28,29,30,31,32
  994.     DB    49,50,51,52,53,54,55,56
  995.     DB    9,10,11,12,13,14,15,16
  996.     DB    33,34,35,36,37,38,39,40
  997.     DB    57,58,59,60,61,62,63,64
  998.     DB    17,18,19,20,21,22,23,24
  999.     DB    41,42,43,44,45,46,47,48
  1000.  
  1001. *****************************************************************
  1002. *                                *
  1003. * DISK PARAMETER BLOCKS.  The following sizes and densities are *
  1004. * specified to maintain compatibility with DJ2D CP/M 2.2:    *
  1005. *    128 bytes, SSSD                        *
  1006. *    256 bytes, SSDD                        *
  1007. *    512 bytes, SSDD                        *
  1008. *      1024 bytes, SSDD                        *
  1009. *    128 bytes, DSDD                        *
  1010. *    256 bytes, DSDD                        *
  1011. *    512 bytes, DSDD                        *
  1012. *      1024 bytes, DSDD                        *
  1013. *                                *
  1014. *****************************************************************
  1015.  
  1016. *****************************************************************
  1017. *                                *
  1018. * The following DPB defines a  diskette for 128 byte sectors,    *
  1019. * single density, and single sided.                *
  1020. *                                *
  1021. *****************************************************************
  1022.  
  1023. DPB128S    DW    26        ;SPT  Number of CP/M sectors/track
  1024.     DB    3        ;BSH  Block Shift Factor
  1025.     DB    7        ;BLM  Block Mask
  1026.     DB    0        ;EXM  Extent Mask
  1027.     DW    242        ;DSM  Disk Space Maximum
  1028.     DW    63        ;DRM  Directory Maximum
  1029.     DB    0C0H        ;AL0  Initial Allocation Vectors
  1030.     DB    0        ;AL1
  1031.     DW    16        ;CKS  Directory Check Size
  1032.     DW    2        ;OFF  Track Offset
  1033.     DB    00        ;PSH  Physical Record Shift factor
  1034.     DB    00        ;PHM  Physical Record Mask
  1035.                 ;(Following byte is used only by the BIOS)
  1036.     DB    1H        ;16*((#cpm sectors/physical sector) -1) +
  1037.                 ;log2(#bytes per sector/128) + 1 +
  1038.                 ;8 if double sided.
  1039.  
  1040. *****************************************************************
  1041. *                                *
  1042. * The following DPB defines a diskette for 256 byte sectors,    *
  1043. * double density, and single sided.                *
  1044. *                                *
  1045. *****************************************************************
  1046.  
  1047. DPB256S    DW    52        ;CP/M sectors/track
  1048.     DB    4        ;BSH
  1049.     DB    15        ;BLM
  1050.     DB    0        ;EXM
  1051.     DW    242        ;DSM
  1052.     DW    127        ;DRM
  1053.     DB    0C0H        ;AL0
  1054.     DB    0        ;AL1
  1055.     DW    32        ;CKS
  1056.     DW    2        ;OFF
  1057.     DB    00        ;PSH
  1058.     DB    00        ;PHM
  1059.                 ;
  1060.     DB    12H        ;16*((#cpm sectors/physical sector) -1) +
  1061.                 ;log2(#bytes per sector/128) + 1 +
  1062.                 ;8 if double sided.
  1063.  
  1064. *****************************************************************
  1065. *                                *
  1066. * The following DPB defines a diskette as 512 byte sectors,    *
  1067. * double density, and single sided.                *
  1068. *                                *
  1069. *****************************************************************
  1070.  
  1071. DPB512S    DW    60        ;CP/M sectors/track
  1072.     DB    4        ;BSH
  1073.     DB    15        ;BLM
  1074.     DB    0        ;EXM
  1075.     DW    280        ;DSM
  1076.     DW    127        ;DRM
  1077.     DB    0C0H        ;AL0
  1078.     DB    0        ;AL1
  1079.     DW    32        ;CKS
  1080.     DW    2        ;OFF
  1081.     DB    00        ;PSH
  1082.     DB    00        ;PHM
  1083.                 ;
  1084.     DB    33H        ;16*((#cpm sectors/physical sector) -1) +
  1085.                 ;log2(#bytes per sector/128) + 1 +
  1086.                 ;8 if double sided.
  1087.  
  1088. *****************************************************************
  1089. *                                *
  1090. * The following DPB defines a diskette as 1024 byte sectors,    *
  1091. * double density, and single sided.                *
  1092. *                                *
  1093. *****************************************************************
  1094.  
  1095. DP1024S    DW    64        ;CP/M sectors/track
  1096.     DB    4        ;BSH
  1097.     DB    15        ;BLM
  1098.     DB    0        ;EXM
  1099.     DW    299        ;DSM
  1100.     DW    127        ;DRM
  1101.     DB    0C0H        ;AL0
  1102.     DB    0        ;AL1
  1103.     DW    32        ;CKS
  1104.     DW    2        ;OFF
  1105.     DB    00        ;PSH
  1106.     DB    00        ;PHM
  1107.                 ;
  1108.     DB    74H        ;16*((#cpm sectors/physical sector) -1) +
  1109.                 ;log2(#bytes per sector/128) + 1 +
  1110.                 ;8 if double sided.
  1111.  
  1112. *****************************************************************
  1113. *                                *
  1114. * The following DPB defines a diskette for 128 byte sectors,    *
  1115. * single density, and double sided.                *
  1116. *                                *
  1117. *****************************************************************
  1118.  
  1119. DPB128D    DW    52        ;CP/M sectors/track
  1120.     DB    4        ;BSH
  1121.     DB    15        ;BLM
  1122.     DB    1        ;EXM
  1123.     DW    242        ;DSM
  1124.     DW    127        ;DRM
  1125.     DB    0C0H        ;AL0
  1126.     DB    0        ;AL1
  1127.     DW    32        ;CKS
  1128.     DW    2        ;OFF
  1129.     DB    00        ;PSH
  1130.     DB    00        ;PHM
  1131.                 ;
  1132.     DB    9H
  1133.  
  1134. *****************************************************************
  1135. *                                *
  1136. * The following DPB defines a diskette as 256 byte sectors,    *
  1137. * double density, and double sided.                *
  1138. *                                *
  1139. *****************************************************************
  1140.  
  1141. DPB256D    DW    104        ;CP/M sectors/track
  1142.     DB    4        ;BSH
  1143.     DB    15        ;BLM
  1144.     DB    0        ;EXM
  1145.     DW    486        ;DSM
  1146.     DW    255        ;DRM
  1147.     DB    0F0H        ;AL0
  1148.     DB    0        ;AL1
  1149.     DW    64        ;CKS
  1150.     DW    2        ;OFF
  1151.     DB    00        ;PSH
  1152.     DB    00        ;PHM
  1153.                 ;
  1154.     DB    1AH
  1155.  
  1156. *****************************************************************
  1157. *                                *
  1158. * The following DPB defines a diskette as 512 byte sectors,    *
  1159. * double density, and double sided.                *
  1160. *                                *
  1161. *****************************************************************
  1162.  
  1163. DPB512D    DW    120        ;CP/M sectors/track
  1164.     DB    4        ;BSH
  1165.     DB    15        ;BLM
  1166.     DB    0        ;EXM
  1167.     DW    561        ;DSM
  1168.     DW    255        ;DRM
  1169.     DB    0F0H        ;AL0
  1170.     DB    0        ;AL1
  1171.     DW    64        ;CKS
  1172.     DW    2        ;OFF
  1173.     DB    00        ;PSH
  1174.     DB    00        ;PHM
  1175.                 ;
  1176.     DB    3BH
  1177.  
  1178. *****************************************************************
  1179. *                                *
  1180. * The following DPB defines a diskette as 1024 byte sectors,    *
  1181. * double density, and double sided.                *
  1182. *                                *
  1183. *****************************************************************
  1184.  
  1185. DP1024D    DW    128        ;CP/M sectors/track
  1186.     DB    4        ;BSH
  1187.     DB    15        ;BLM
  1188.     DB    0        ;EXM
  1189.     DW    599        ;DSM
  1190.     DW    255        ;DRM
  1191.     DB    0F0H        ;AL0
  1192.     DB    0        ;AL1
  1193.     DW    64        ;CKS
  1194.     DW    2        ;OFF
  1195.     DB    00        ;PSH
  1196.     DB    00        ;PHM
  1197.                 ;
  1198.     DB    7CH
  1199.  
  1200. *****************************************************************
  1201. *                                *
  1202. * DISK PARAMETER HEADERS (for four drives)            *
  1203. *                                *
  1204. *****************************************************************
  1205.  
  1206. DPZERO    DW    0        ;XLT  Address of translation table (filled
  1207.                 ;    in by setdrv)
  1208.     DW    0,0,0,0        ;-0-  BDOS Scratch Area
  1209.     DB    0
  1210.     DB    0        ;MF   Media Flag
  1211.     DW    0        ;DPB  Address of DPB (filled in by setdrv)
  1212.     DW    CSV0        ;CSV  Directory check vector
  1213.     DW    ALV0        ;ALV  Allocation vector
  1214.     DW    DIRBCB        ;DIRBCB  Directory Buffer Control Block
  1215.     DW    0FFFFH        ;DTABCB  Data Buffer Control Block
  1216.     DW    0FFFFH        ;HASH   Directory Hashing Table
  1217.     DB    0        ;HBANK  Bank number of Hash Table
  1218. ;
  1219. DPONE    DW    0
  1220.     DW    0,0,0,0
  1221.     DB    0
  1222.     DB    0
  1223.     DW    0
  1224.     DW    CSV1
  1225.     DW    ALV1
  1226.     DW    DIRBCB
  1227.     DW    0FFFFH
  1228.     DW    0FFFFH
  1229.     DB    0
  1230. ;
  1231. DPTWO    DW    0
  1232.     DW    0,0,0,0
  1233.     DB    0
  1234.     DB    0
  1235.     DW    0
  1236.     DW    CSV1
  1237.     DW    ALV1
  1238.     DW    DIRBCB
  1239.     DW    0FFFFH
  1240.     DW    0FFFFH
  1241.     DB    0
  1242. ;
  1243. DPTHRE    DW    0
  1244.     DW    0,0,0,0
  1245.     DB    0
  1246.     DB    0
  1247.     DW    0
  1248.     DW    CSV1
  1249.     DW    ALV1
  1250.     DW    DIRBCB
  1251.     DW    0FFFFH
  1252.     DW    0FFFFH
  1253.     DB    0
  1254.  
  1255. *****************************************************************
  1256. *                                *
  1257. *  Directory Buffer Control Block                *
  1258. *                                *
  1259. *****************************************************************
  1260.  
  1261. DIRBCB:    DB    0FFH        ;DRV  Drive number
  1262.     DB    00,00,00    ;REC#  Record position in buffer
  1263.     DB    00        ;WFLG  Buffer Written flag
  1264.     DB    00        ;00  BDOS scratch byte
  1265.     DW    0000        ;TRACK   Buffer contents' phys track
  1266.     DW    0000        ;SECTOR  Buffer contents' phys sector
  1267.     DW    DIRBUF        ;BUFFAD  Buffer address
  1268.  
  1269. *****************************************************************
  1270. *                                *
  1271. * Miscellaneous ram locations used by the BIOS            *
  1272. *                                *
  1273. *****************************************************************
  1274.  
  1275. CPMSEC    DB    0        ;CP/M sector #
  1276. CPMDRV    DB    0        ;CP/M drive #
  1277. CPMTRK    DB    0        ;CP/M track #
  1278. TRUESEC    DB    0        ;Disk Jockey sector that contains CP/M sector
  1279. BUFDRV    DB    0        ;Drive that buffer belongs to
  1280. BUFTRK    DB    0        ;Track that buffer belongs to
  1281. BUFSEC    DB    0        ;Sector that buffer belongs to
  1282. BUFFER    DS    1024        ;Maximum size buffer for 1K sectors
  1283.  
  1284. *****************************************************************
  1285. *                                *
  1286. *  Allocation Vectors (for four drives)                *
  1287. *  Each vector requires 2 bits for each block on the drive    *
  1288. *                                *
  1289. *****************************************************************
  1290.  
  1291. ALV0    DS    150        ;Allocation vector for drive A
  1292. ALV1    DS    150        ;Allocation vector for drive B
  1293. ALV2    DS    150        ;Allocation vector for drive C
  1294. ALV3    DS    150        ;Allocation vector for drive D
  1295.  
  1296. *****************************************************************
  1297. *                                *
  1298. *  Checksum Vectors (for four drives)                *
  1299. *  Each vector requires 1 bit for every four directory entries    *
  1300. *                                *
  1301. *****************************************************************
  1302.  
  1303. CSV0    DS    64        ;Directory check vector for drive A
  1304. CSV1    DS    64        ;Directory check vector for drive B
  1305. CSV2    DS    64        ;Directory check vector for drive C
  1306. CSV3    DS    64        ;Directory check vector for drive D
  1307.  
  1308. *****************************************************************
  1309. *                                *
  1310. *  Directory Buffer                        *
  1311. *                                *
  1312. *****************************************************************
  1313.  
  1314. DIRBUF    DS    128
  1315.  
  1316. ;
  1317.     END
  1318.