home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol050 / bios2 < prev    next >
Encoding:
Text File  |  1984-04-29  |  15.4 KB  |  934 lines

  1. ;
  2. ;
  3. ;
  4. ;    S E L E C T   D I S K   D R I V E
  5. ;
  6. ;    Select the disk drive for subsequent disk transfers and
  7. ;    return the appropriate DPB address.   This routine
  8. ;    diverges from the normal CP/M implementation of just
  9. ;    saving the disk selection value until the transfer is
  10. ;    performed.  This divergence is required because floppy
  11. ;    disks are a removable media and come in more than one
  12. ;    format.  This routine determines the correct format and
  13. ;    initializes the DPH with the appropriate values for the
  14. ;    format type.
  15. ;
  16. ;    ENTRY    C = disk delection value.
  17. ;        DE and 1 = 0, must determine disk type.
  18. ;                 = 1, drive type has been determined.
  19. ;
  20. ;    EXIT    HL = 0, if drive not selectable.
  21. ;        HL = DPH address if drive is selectable.
  22. ;
  23. ;        DPH is intialized for the appropriate floppy
  24. ;        disk format.
  25.  
  26. SELDSK:
  27.     MOV    A,C
  28.     CPI    NDSK
  29.     JNC    SELD2        ;If invalid drive
  30.     PUSH    D        ;Save drive selection mask
  31.     MVI    B,0
  32.     PUSH    B        ;Save drive number
  33.     CALL    HOME        ;Flush buffers
  34.     POP    B        ;Restore disk selection
  35.  
  36.     MOV    A,C
  37.     STA    SEKDSK        ;Save disk selection code
  38.  
  39.     LXI    H,DTYPE
  40.     DAD    B
  41.     DAD    B
  42.     MOV    A,M
  43.     PUSH    H        ;Save pointer to Class 6, op code 0
  44.  
  45.     MOV    L,C        ;Compute DPH address
  46.     MOV    H,B
  47.     DAD    H        ;*2
  48.     DAD    H        ;*4
  49.     DAD    H        ;*8
  50.     DAD    H        ;*16
  51.     LXI    D,DPH
  52.     DAD    D        ;HL = DPH address
  53.  
  54.     STA    SEKTYP        ;Save disk type
  55.     XTHL            ;Get pointer to Class 6, op code 0
  56.                 ; and save DPH address.
  57.     ANI    TYPEFPY+TYPEMIN        ;Floppy?
  58.     JZ    SELD1
  59. SELD0:
  60.     INX    H        ;Yes. Get Class 6, op code 0 type
  61.     MOV    A,M
  62.     STA    CIOFS+5
  63.     LXI    H,DSKMSK    ;Get LUN
  64.     DAD    B
  65.     MOV    A,M
  66.     STA    CIOFS+1
  67.     STA    CIOPB+1        ;Set for error handling
  68.     LXI    H,CIOFS        ;Set track format code
  69.     CALL    EXEC
  70.     CZ    WAITF
  71.     CALL    SFINAL        ;Check for errors
  72.     JZ    SELD1
  73.     POP    H        ;Error. Restore stack
  74.     POP    D
  75.     JMP    SELD2
  76. SELD1:
  77.     POP    H        ;Restore DPH address
  78.     POP    D        ;Restore Drive selction mask
  79.     RET
  80.  
  81. SELD2:    LXI    H,0
  82.     LDA    CDISK
  83.     SUB    C
  84.     RNZ            ;If default drive not in error
  85.     STA    CDISK
  86.     RET
  87.  
  88. CIOFS:    DB    FSCMD,0,0,0,0,0
  89. ;
  90. ;    H O M E
  91. ;
  92. ;    Return disk to home.  This routine sets the track number
  93. ;    to zero.  The current host disk buffer is flushed to the
  94. ;    disk.
  95.  
  96. HOME:
  97.     CALL    FLUSH        ;Flush host buffer
  98.     XRA    A
  99.     STA    HSTACT        ;Clear host active flag
  100.     STA    UNACNT        ;Clear sector count
  101.     STA    SEKTRK
  102.     STA    SEKTRK+1
  103.     RET
  104. ;
  105. ;
  106. ;
  107. ;
  108. ;    S E T   T R A C K.
  109. ;
  110. ;    Set track number.  The track number is saved for later
  111. ;    use during a disk transfer operation.
  112. ;
  113. ;    ENTRY    BC = track number.
  114.  
  115. SETTRK:
  116.     MOV    L,C
  117.     MOV    H,B
  118.     SHLD    SEKTRK
  119.  
  120.     LHLD    UNATRK
  121.     MOV    A,L
  122.     XRA    C
  123.     MOV    C,A
  124.     MOV    A,H
  125.     XRA    B
  126.     ORA    A
  127.     RZ            ;If same track
  128. ;    JMP    CUNACT
  129. ;
  130. ;
  131. ;
  132. ;
  133. ;
  134. ;
  135. ;
  136. ;
  137. ;    Clear Unallocated block count (force pre-reads).
  138.  
  139. CUNACT:    XRA    A        ;A = 0
  140.     STA    UNACNT        ;Clear unallocated block count
  141.     RET
  142. ;
  143. ;
  144. ;
  145. ;
  146. ;    Set the sector for later use in the disk transfer.  No
  147. ;    actual disk operations are perfomed.
  148. ;
  149. ;    Entry    BC = sector number.
  150.  
  151. SETSEC:    MOV    A,C
  152.     STA    SAVSEC        ;sector to seek
  153.     RET
  154. ;
  155. ;
  156. ;
  157. ;
  158. ;    Set Disk memory address for subsequent disk read or
  159. ;    write routines.  This address is saved in DMAADR until
  160. ;    the disk transfer is performed.
  161. ;
  162. ;    ENTRY    BC = Disk memory address.
  163. ;
  164. ;    EXIT    DMAADR = BC.
  165.  
  166. SETDMA:
  167.     MOV    H,B
  168.     MOV    L,C
  169.     SHLD    DMAADR
  170.     RET
  171. ;
  172. ;
  173. ;
  174. ;
  175. ;    Translate sector number from logical to physical.
  176. ;
  177. ;    ENTRY    DE = 0, no translation required.
  178. ;        DE = translation table address.
  179. ;        BC = sector number to translate.
  180. ;
  181. ;    EXIT    HL = translated sector.
  182.  
  183. SECTRN:
  184.     LDA    UNASEC
  185.     CMP    C
  186.     CNZ    CUNACT        ;If sectors do not match
  187.     MOV    A,C
  188.     STA    LOGSEC
  189.     MOV    L,C
  190.     MOV    H,B
  191.     MOV    A,D
  192.     ORA    E
  193.     RZ            ;If no translation
  194.     DAD    D
  195.     MOV    L,M
  196.     MVI    H,0
  197.     RET
  198. ;    B o o t   C P / M   f r o m   d i s k.
  199. ;
  200. ;    The WBOOT entry point gets control when a warm start
  201. ;    occurs, a ^C from the console, a jump to BDOS (function
  202. ;    0), or a jump to location zero.  The WBOOT routine reads
  203. ;    the CCP and BDOS from the apprpriate Hard disk sectors.
  204. ;    WBOOT must also re-initialize locations 0,1,2 and 5,6,7.
  205. ;    The WBOOT routines exits with the C register set to the
  206. ;    appropriate drive selection value.  The exit address
  207. ;    is to the CCP routine.
  208.  
  209.  
  210.  
  211. WBOOT:
  212.     LXI    SP,DBUF
  213.     LDA    CIOBFS+5    ;Floppy?
  214.     CPI    0FFh
  215.     JZ    WBOOT1
  216.     LXI    H,CIOBFS    ;Yes.  Select track format
  217.     CALL    EXEC
  218.     CZ    WAITF
  219.     CALL    SFINAL
  220.     JNZ    WBOOT
  221. WBOOT1:
  222.  
  223.     LXI    H,CIOBT
  224.     LXI    D,CCP
  225.     CALL    RDISK        ;Read data into memory
  226.  
  227.     MOV    A,C
  228.     ANI    FERR
  229.     JNZ    WBOOT        ;If errors retry
  230.  
  231. GOCPM:    LXI    H,DBUF
  232.     SHLD    DMAADR        ;Set default address
  233.     MVI    A,0C3h        ;Store jumps in low memory
  234.     STA    0
  235.     STA    5
  236.     LXI    H,BIOS+3
  237.     SHLD    1
  238.     LXI    H,BDOS
  239.     SHLD    6
  240.     LDA    CDISK
  241.     MOV    C,A
  242.     JMP    CCP        ;Go to CPM
  243.  
  244.  
  245. CIOBFS:    DB    FSCMD,0,0,0,0,0
  246. CIOBT:    DB    RDCMD        ;Command = read
  247. BTLUN:    DB    0        ;Physical drive = hard disk
  248.     DB    0
  249. BTSLA0:
  250.     DB    0
  251. BTNSEC:    DB    0        ;# CCP and BDOS sector
  252.  
  253.     DB    0
  254.  
  255. ;    Read a CP/M 128 byte sector.
  256. ;
  257. ;    EXIT    A = 0, successful read operation.
  258. ;        A = 1, unsucessful read operation.
  259.  
  260. READ:    CALL    CHKBKD        ;Check for blocked drive
  261.     JC    FREAD        ;If non-blocked transfer
  262.  
  263.     XRA    A        ;Set flag to force a read
  264.     STA    UNACNT        ;Clear sector counter
  265.     CALL    FILL        ;Fill buffer with data
  266.     POP    H
  267.     POP    D
  268.  
  269.     MVI    C,128
  270.     CALL    MOVDTA        ;Move 128 bytes
  271.     LDA    ERFLAG
  272.     ORA    A
  273.     RZ
  274.     XRA    A
  275.     STA    HSTACT
  276.     ORI    001h
  277.     RET
  278. ;
  279. ;
  280. ;
  281. ;
  282. ;    Write the selected 128 byte CP/M sector.
  283. ;
  284. ;    ENTRY    C = 0, write to a previously allocated block.
  285. ;        C = 1, write to the directory.
  286. ;        C = 2, write to the first sector of unallocated
  287. ;        data block.
  288. ;
  289. ;    EXIT    A = 0, write was successful.
  290. ;        A = 1, write was unsucessful.
  291.  
  292. WRITE:    CALL    CHKBKD        ;Check for blocked drive
  293.     JC    FWRITE        ;If non-blocked transfer
  294.  
  295.     MOV    A,C        ;Move write type
  296.     STA    WRTYPE
  297.     CPI    WRUAL
  298.     JNZ    WRIT1        ;If not write to unallocated
  299.     MVI    A,HSTSIB-1    ;Set new unallocated parameters
  300.     STA    UNACNT
  301.     LHLD    SEKTRK
  302.     SHLD    UNATRK        ;UNATRK = SEKTRK
  303.     LDA    LOGSEC
  304.     INR    A
  305.     JMP    WRIT2
  306.  
  307. WRIT1:    LDA    UNACNT
  308.     ORA    A
  309.     JZ    WRIT3        ;If no sectors left in block
  310.     DCR    A
  311.     STA    UNACNT
  312.     LDA    UNASEC        ;Increment unallocated sectors
  313.     INR    A
  314.     CPI    CPMSPT
  315.     JNZ    WRIT3        ;If not new track
  316.     LHLD    UNATRK
  317.     INX    H
  318.     SHLD    UNATRK        ;UNATRK = UNATRK+1
  319.     XRA    A        ;A = 0
  320.  
  321. WRIT2:    STA    UNASEC
  322.     MVI    A,0FFh
  323.  
  324. WRIT3:    CALL    FILL
  325.     POP    D
  326.     POP    H
  327.  
  328.     MVI    C,128
  329.     CALL    MOVDTA        ;Move 128 bytes
  330.     MVI    A,1
  331.     STA    HSTWRT        ;HSTWRT = 1
  332.     LDA    ERFLAG
  333.     ORA    A
  334.     RNZ            ;If any errors occurred
  335.  
  336.     LDA    WRTYPE        ;write type
  337.     CPI    WRDIR        ;to directory?
  338.     CZ    FLUSH        ;Force write of directory
  339.     LDA    ERFLAG
  340.     ORA    A
  341.     RET
  342. ;
  343. ;
  344. ;
  345. ;
  346. ;    FILL - fill host buffer with approprite host sector.
  347. ;
  348. ;    ENTRY    A = 0, Read required if not in buffer.
  349. ;        0therwise read not required.
  350. ;
  351. ;    EXIT    On exit the stack will contain the following
  352. ;        values:
  353. ;           POP     x    ;x = host record address.
  354. ;           POP     y    ;y = caller's buffer address.
  355.  
  356. FILL:    STA    RDFLAG        ;Save read flag
  357.     LHLD    DMAADR
  358.     XTHL            ;Set caller's buffer address
  359.     PUSH    H
  360.     LDA    ACTTYP        ;Get physical sector size
  361.     ANI    TYPESEC
  362.     RAR
  363.     MOV    B,A
  364.     MOV    C,A
  365.     XRA    A        ;Generate sector mask
  366. FILL0:
  367.     STC
  368.     DCR    B
  369.     JM    FILL1
  370.     RAL
  371.     JMP    FILL0
  372. FILL1:
  373.     MOV    B,A
  374.     LDA    SEKSEC        ;Compute relative record number
  375.     ANA    B
  376.     LXI    H,HSTBUF    ;Compute host record address
  377.     LXI    D,128
  378. FILL2:
  379.     DCR    A
  380.     JM    FILL3
  381.     DAD    D
  382.     JMP    FILL2
  383. FILL3:
  384.     XTHL            ;Put buffer address of record on stack
  385.     PUSH    H
  386.  
  387.     LDA    SEKSEC        ;Convert to physical sector numver
  388. FILL4:
  389.     DCR    C
  390.     JM    FILL5
  391.     ANA    A        ;Carry = 0
  392.     RAR
  393.     JMP    FILL4
  394. FILL5:
  395.     STA    SEKSEC
  396.  
  397.     LXI    H,HSTACT    ;host active flag
  398.     MOV    A,M
  399.     MVI    M,1        ;always becomes 1
  400.     ORA    A
  401.     JZ    FILL6        ;If host buffer inactive
  402.     LXI    H,HSTDSK
  403.     CALL    CMPSEK        ;Compare HST with SEK
  404.     RZ            ;If everything same
  405.  
  406.     CALL    FLUSH        ;Flush host buffer
  407.  
  408. FILL6:    LHLD    SEKDSK        ;Move disk and type
  409.     SHLD    HSTDSK
  410.     SHLD    ACTDSK
  411.     LHLD    SEKTRK
  412.     SHLD    HSTTRK
  413.     SHLD    ACTTRK
  414.     LDA    SEKSEC
  415.     STA    HSTSEC
  416.     STA    ACTSEC
  417.     LDA    RDFLAG
  418.     ORA    A
  419.     RNZ            ;If no read required
  420.  
  421. FREAD:    MVI    A,RDCMD        ;Set read command
  422.     LXI    H,RDISK        ;Set transfer routine address
  423.     JMP    FINAL
  424. ;
  425. ;
  426. ;
  427. ;
  428. ;    FLUSH - Write out active host buffer onto disk.
  429.  
  430. FLUSH:
  431.     LXI    H,HSTWRT
  432.     MOV    A,M
  433.     ORA    A
  434.     RZ            ;If host buffer already on disk
  435.     MVI    M,0
  436.     LHLD    HSTDSK        ;Move disk and type
  437.     SHLD    ACTDSK
  438.     LHLD    HSTTRK
  439.     SHLD    ACTTRK
  440.     LDA    HSTSEC
  441.     STA    ACTSEC
  442.  
  443. FWRITE:    MVI    A,WTCMD        ;Set write command
  444.     LXI    H,WDISK        ;Set transfer routine address
  445. ;    JMP    FINAL
  446. ;
  447. ;
  448. ;
  449. ;
  450. ;    F I N A L   --  Preform final tranfer processing.
  451. ;
  452. ;    ENTRY    A = Command.
  453. ;        HL = transfer routine address.
  454.  
  455. FINAL:
  456.     CALL    SETUP
  457.  
  458. SFINAL:                ;Called from SELDSK
  459.     IF    I696
  460.     LXI    H,NMSG2        ;Set message address
  461.     ORA    A
  462.     JNZ    FNL3        ;If message byte is non-zero
  463.     LXI    H,NMSG        ;Set message address
  464.     MOV    A,B
  465.     ANI    MSSG
  466.     JZ    FNL3        ;If message bit zero
  467.     ENDIF
  468.  
  469.     MOV    A,C
  470.     ANI    FERR        ;mask for errors
  471.     STA    ERFLAG
  472.     RZ            ;If no errors
  473.  
  474.     MOV    A,C
  475.     ANI    CERR+TERR
  476.     LXI    H,CERMSG
  477.     PUSH    B
  478.     CNZ    PRINT        ;If controller error
  479.     POP    B
  480.     LXI    H,TOMSG        ;Check for timeout
  481.     MOV    A,C
  482.     ANI    TERR
  483.     JNZ    FNL3
  484.  
  485. FNL1:    MOV    A,C
  486.     ANI    PERR
  487.     JZ    FNL2        ;If no parity errors
  488.     LXI    H,PERMSG
  489.     JMP    FNL3
  490.  
  491. FNL2:    LDA    CIOPB+1
  492.     ANI    0E0H
  493.     STA    CIOER+1
  494.     LXI    H,CIOER
  495.     LXI    D,TEMPBF
  496.     CALL    RDISK
  497.  
  498.     LXI    H,TYPMSG    ;Issue type message
  499.     CALL    PRINT
  500.     LDA    TEMPBF        ;Get type
  501.     RRC
  502.     RRC
  503.     RRC
  504.     RRC
  505.     ANI    3
  506.     CALL    OHN        ;Output hex nibble
  507.     LXI    H,CODMSG
  508.     CALL    PRINT        ;Issue code message
  509.     LDA    TEMPBF        ;Get code
  510.     ANI    0Fh
  511.     CALL    OHN        ;Output hex nibble
  512.  
  513.     LXI    H,ENDMSG
  514. FNL3:    CALL    PRINT
  515.     ORI    1
  516.     STA    ERFLAG
  517.     RET
  518.  
  519. CIOER:    DB    ESCMD,0,0,0,0,0    ;Request Error code
  520.  
  521. CERMSG:    DB    CR,LF,'Controller error',0
  522.  
  523. TYPMSG:    DB    '    Type <',0
  524. CODMSG:    DB    '>, Code <',0
  525. ENDMSG:    DB    '>',CR,LF,0
  526. TOMSG:    DB    '    Timeout',0
  527.  
  528.     IF    I696
  529. NMSG:    DB    CR,LF,'No message bit',0
  530.  
  531. NMSG2:    DB    CR,LF,'Message byte non-zero',0
  532.     ENDIF
  533.  
  534. PERMSG:    DB    CR,LF,'Parity error.',0
  535. ;
  536. ;
  537. ;
  538. ;
  539. ;    S E T U P - Setup the CIOPB area.
  540. ;
  541. ;    ENTRY    A = Command.
  542. ;        HL = transfer routine address.
  543.  
  544. SETUP:
  545.     PUSH    H        ;Set next phase address
  546.     STA    CIOPB+0        ;Set command
  547.  
  548.     LXI    D,0
  549.     LDA    ACTDSK        ;Get LUN
  550.     MOV    E,A
  551.     LXI    H,DSKMSK    ;Get LUN
  552.     DAD    D
  553.     MOV    C,M
  554.     LXI    H,DSKOFF
  555.     DAD    D
  556.     DAD    D
  557.     DAD    D
  558.     MOV    A,M
  559.     INX    H
  560.     MOV    D,M
  561.     INX    H
  562.     MOV    E,M
  563.     ORA    C        ;LUN in bits 5-7
  564.     MOV    C,A
  565.  
  566. SETP1:    PUSH    B        ;Save unit selection
  567.     LHLD    ACTTRK        ;Get track number
  568.     MOV    B,H        ;BC = 1*TRK
  569.     MOV    C,L
  570.     DAD    H        ;HL = 2*TRK
  571.     DAD    B        ;HL = (2+1)*TRK = 3*TRK
  572.     DAD    H        ;HL = 6*TRK
  573.     DAD    H        ;HL = 12*TRK
  574.     DAD    B        ;HL = (12+1)*TRK = 13*TRK
  575.     DAD    H        ;Hl = 26*TRK
  576.     LDA    ACTSEC
  577.     MVI    B,0
  578.     MOV    C,A
  579.     DAD    B        ;HL = 26*TRK+SEC
  580.     POP    B        ;Restore BC
  581.     XRA    A        ;A = 0
  582.     DAD    D
  583.     ADC    C
  584.     XCHG
  585.     LXI    H,CIOPB+1
  586.     MOV    M,A
  587.     INX    H
  588.     MOV    M,D
  589.     INX    H
  590.     MOV    M,E
  591.     INX    H
  592.     MVI    M,1        ;Read one sector
  593.     INX    H
  594.     MVI    M,00h        ;Force ECC correction
  595.  
  596.     LHLD    BUFADR
  597.     XCHG
  598.     LXI    H,CIOPB
  599.     RET            ;Dispatch to routine
  600. ;    Disk I/O Routines
  601. ;
  602. ;
  603.     IF    I696
  604. ;    E X E C
  605.  
  606. EXEC:    MVI    B,BUSY        ;Wait for not busy.
  607.     MVI    C,BUSY and (not BUSY)
  608.     CALL    WAITM
  609.     RNZ
  610.     
  611.  
  612.     MVI    A,SLCT        ;Alert controller
  613.     OUT    DIO+1
  614. EXEC1:
  615.     MOV    C,B        ;Wait for controller busy
  616.     CALL    WAITM
  617.     RNZ
  618.  
  619.     MVI    A,DODTA        ;Enable data in
  620.     OUT    DIO+1
  621.  
  622. EXEC2:    IN    DIO+2        ;Get status
  623.     XRI    0FFh
  624.     JM    EXEC2        ;If not requesting next byte
  625.     ANI    CMND+DIROUT
  626.     JNZ    EXEC3        ;If CMND or DIROUT false
  627.     MOV    A,M
  628.     INX    H
  629.     OUT    DIO        ;Send byte from command buffer
  630.     JMP    EXEC2
  631.  
  632. EXEC3:    CMP    A        ;Z:=1
  633.     RET
  634. ;
  635. ;
  636. ;
  637. ;
  638. ;    WDISK - Output from memory buffer.
  639. ;    ENTRY:    HL = COMMAND BUFFER ADDRESS
  640. ;        DE = DATA BUFFER ADDRESS
  641. ;
  642.  
  643. WDISK:    CALL    EXEC        ;Output command
  644.     RNZ            ;Return if timeout
  645. WDISK1:    IN    DIO+2        ;Read status
  646.     ORA    A
  647.     JP    WDISK1        ;If request is present
  648.     ANI    CMND
  649.     JNZ    GCMPS        ;If done with transfer
  650.     LDAX    D        ;Get the data byte
  651.     OUT    DIO
  652.     INX    D        ;Advance buffer address
  653.     JMP    WDISK1
  654. ;
  655. ;
  656. ;
  657. ;
  658. ;    RDISK - Input to memory buffer.
  659. ;
  660. ;    Entry:    HL = command buffer address
  661. ;        DE = data buffer address
  662.  
  663. RDISK:    CALL    EXEC
  664.     RNZ            ;Return if timeout
  665. RDISK1:    IN    DIO+2        ;Read status
  666.     ORA    A
  667.     JP    RDISK1        ;If request is present
  668.     ANI    CMND
  669.     JNZ    GCMPS
  670.     IN    DIO
  671.     STAX    D
  672.     INX    D
  673.     JMP    RDISK1
  674. ;
  675. ;
  676. ;
  677. ;
  678. ;    WAITF - Wait for function to complete.
  679.  
  680. WAITF:    MVI    B,REQ+CMND    ;Wait for both REQ and CMND
  681.     MOV    C,B
  682.     CALL    WAITM
  683.     RNZ
  684. ;
  685. ;    Get completion status.
  686.  
  687. GCMPS:    IN    DIO        ;Get completion status
  688.     MOV    C,A
  689.  
  690. GCMP1:    IN    DIO+2
  691.     ORA    A
  692.     JP    GCMP1        ;If REQ not set
  693.  
  694.     MOV    B,A
  695.     IN    DIO        ;Get message byte
  696.     RET
  697.     ENDIF
  698. ;
  699.  
  700. ;
  701. ;
  702. ;
  703.     IF    I796
  704. ;    EXEC - Output the command
  705. ;
  706. ;    Enter:    HL is the command buffer address
  707. ;        DE - data transfer address.
  708.  
  709. EXEC:
  710.     MOV    A,E        ;Output DMA address
  711.     OUT    DIO+2
  712.     MOV    A,D
  713.     OUT    DIO+3
  714.     MOV    A,L
  715.     OUT    DIO+4
  716.     MOV    A,H
  717.     OUT    DIO+5
  718.     MVI    A,0
  719.     OUT    DIO+6
  720.     OUT    DIO+7
  721.     OUT    DIO
  722.     CMP    A        ;Z:=1
  723.     RET
  724.  
  725.  
  726. ;    Disk read/write
  727. ;
  728. ;    Entry:    same as EXEC
  729. ;
  730. RDISK:
  731. WDISK:    CALL    EXEC
  732.     RNZ            ;Return if timeout
  733.  
  734. ;    WAITF - Wait until transfer done
  735. ;
  736. ;    Enter:    none
  737. ;    Exit:    when transfer completed
  738.  
  739. WAITF:    MVI    B,CMDDON    ;Wait for CMDDON
  740.     MOV    C,B
  741.     CALL    WAITM
  742.     RNZ            ;Return if timeout
  743. ;
  744.  
  745. ;    GCMPS - Get completion status
  746. ;
  747. ;    Enter:    none
  748. ;    Exit:    Status in C
  749. GCMPS:    IN    DIO+1
  750.     MOV    C,A
  751.     RET
  752.     ENDIF
  753.  
  754. ;    WAITM - Wait for controller with timeout
  755. ;
  756. ;    Entry:    B=Status mask
  757. ;        C=Status value
  758. ;    Exit:    Z=1 if OK, else timeout with A=C=TERR
  759. ;
  760. WAITM:
  761.     PUSH    D        ;Save D
  762.     PUSH    H
  763.     LXI    H,138        ;Two minute timeout
  764.     LXI    D,0        ;Max wait @4MHZ is 868 ms
  765. WAITML:
  766.     IF    I696
  767.     IN    DIO+2
  768.     ENDIF
  769.     IF    I796
  770.     IN    DIO
  771.     ENDIF
  772.     ANA    B        ;Mask wait bits
  773.     CMP    C        ;Check value
  774.     JZ    WAITM1
  775.     DCX    D        ;Not ready.  Decrement time
  776.     MOV    A,D
  777.     ORA    E
  778.     JNZ    WAITML
  779.     DCX    H
  780.     MOV    A,H
  781.     ORA    L
  782.     JNZ    WAITML
  783.     MVI    B,0        ;Timeout
  784.     MVI    A,TERR
  785.     ORA    A
  786. WAITM1:
  787.     POP    H
  788.     POP    D        ;Restore D
  789.     MOV    C,A        ;Return status in C
  790.     RET
  791. ;    MOVDTA    - Move data in memory.
  792. ;
  793. ;    ENTRY    C = number of bytes to move
  794. ;        DE = destination address.
  795. ;        HL = source address.
  796.  
  797. MOVDTA:
  798.     MOV    A,M        ;source character
  799.     STAX    D        ;to dest
  800.     INX    H
  801.     INX    D
  802.     DCR    C        ;loop 128 times
  803.     JNZ    MOVDTA        ;If transfer not complete
  804.     RET
  805. ;
  806. ;
  807. ;
  808. ;
  809. ;    Check blocked disk transfer.
  810. ;
  811. ;    EXIT    Cbit set, unblocked device.
  812. ;        Cbit clear, blocked device.
  813.  
  814. CHKBKD:
  815.     XRA    A
  816.     STA    ERFLAG        ;Clear error flag
  817.     LDA    SEKTYP
  818.     MOV    H,A
  819.     ANI    TYPESEC
  820.     MOV    A,H
  821.     JZ    CBKD2        ;If not blocked device
  822.     ANI    TYPEFPY+TYPEMIN
  823.     MOV    A,H
  824.     JZ    CBKD1        ;If hard disk
  825. CBKD0:
  826.     PUSH    H
  827.     LHLD    SEKTRK
  828.     MOV    A,H
  829.     ORA    L
  830.     POP    H
  831.     MOV    A,H
  832.     JNZ    CBKD1
  833.     ANI    NOT TYPESEC AND 0FFh    ;Non-blocked
  834.     JMP    CBKD2
  835. CBKD1:
  836.     STA    ACTTYP
  837.     LXI    H,HSTBUF
  838.     SHLD    BUFADR
  839.     MVI    A,BXADR        ;BIOS extended address
  840.     STA    BUFADE
  841.     LDA    SAVSEC
  842.     STA    SEKSEC
  843.     XRA    A        ;Clear carry flag
  844.     RET
  845.  
  846. SETACT:    LDA    SEKTYP
  847. CBKD2:    STA    ACTTYP        ;Set actual disk type
  848.     LHLD    DMAADR
  849.     SHLD    BUFADR
  850.     LDA    DMAADE
  851.     STA    BUFADE
  852.  
  853.     LDA    SEKDSK
  854.     STA    ACTDSK
  855.     LHLD    SEKTRK
  856.     SHLD    ACTTRK
  857.     LDA    SAVSEC
  858.     STA    ACTSEC
  859.     STC            ;Set carry flag
  860.     RET
  861. ;
  862. ;
  863. ;
  864. ;
  865. ;    Utility subroutine for 16-bit compare
  866.  
  867. CMPSEK:
  868.     LXI    D,SEKDSK
  869.     MVI    C,SEKSEC-SEKDSK+1
  870. CMPS1:    LDAX    D        ;low byte compare
  871.     CMP    M
  872.     RNZ            ;If not the same
  873.     INX    D
  874.     INX    H
  875.     DCR    C
  876.     JNZ    CMPS1        ;If not all checked
  877.     RET
  878. ;
  879. ;
  880. ;
  881. ;
  882. ;    Output hex nibble.
  883.  
  884. OHN:    ADI    90h
  885.     DAA
  886.     ACI    40h
  887.     DAA
  888.     MOV    C,A
  889.     JMP    CONOUT
  890. ;
  891. ;
  892. ;
  893. ;
  894. ;    Print message terminated by zero byte.
  895. ;
  896. ;    ENTRY    HL -> message buffer, terminated by zero.
  897. ;
  898. ;    EXIT    HL -> zero byte.
  899. ;        A = 0.
  900. ;        Z bit set.
  901. ;
  902. ;    Destroys only HL, Flags, and A registers.
  903.  
  904. PRINT:    MOV    A,M        ;Get a character
  905.     ORA    A
  906.     RZ            ;If zero the terminate
  907.     INX    H
  908.     PUSH    B
  909.     MOV    C,A
  910.     CALL    CONOUT        ;Output to the console
  911.     POP    B
  912.     JMP    PRINT
  913. ;    Physical data buffer address ((DMAADR) or HSTBUF)
  914.  
  915. BUFADR:    DW    0        ;Lower 16 bits (least, middle)
  916. BUFADE:    DB    0        ;Extended address
  917.  
  918. ;    User data buffer address
  919.  
  920. DMAADR:    DW    0        ;Lower 16 bits (least, middle)
  921. DMAADE:    DB    0        ;Extended address
  922. ;
  923. ;
  924. ;
  925. ;
  926. ;    BIOS blocking / deblocking flags.
  927.  
  928. HSTACT:    DB    0        ;host active flag
  929. HSTWRT:    DB    0        ;host written flag
  930. UNACNT:    DB    0        ;unalloc rec CNT
  931. UNATRK:    DW    0        ;Track
  932. UNASEC:    DB    CPMSPT+1    ;Sector
  933. LOGSEC    DB    0        ;Logical sector
  934.