home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / OS2-ST01 / st_io.asm < prev    next >
Assembly Source File  |  1992-07-02  |  19KB  |  918 lines

  1.     SUBTTL    ST01 Module
  2.         INCLUDE DEFS.INC
  3.     include    sysinfo.inc
  4.  
  5.     include    debug.inc
  6.  
  7. EnableFast    equ    1    ;Fast transfer mode
  8. EnableBlock    equ    0    ;Block transfer mode (not for 486)
  9. BlockSize    equ    512    ;Max block transfer size
  10. WrtWait        equ    12    ;Wait loop at fast write
  11.  
  12. ;
  13. ; Register conventions:
  14. ;
  15. ; DS:    data segment
  16. ; ES:    available, not preserved
  17. ; FS:    port segment, preserved
  18. ; GS:    available, not preserved
  19. ;
  20. ; Caution: The device helper functions Block and Yield
  21. ; clear FS and GS - im Gegensatz zur Doku!
  22. ;
  23.  
  24.     if JR
  25. PhysIO        equ    0C9A00h    ;Physical address of ST01 I/O ports
  26.     else
  27. PhysIO        equ    0CFA00h    ;Physical address of ST01 I/O ports
  28.     endif
  29. IRQnum        equ    5    ;IRQ number
  30. HostID        equ    6    ;Host adapter SCSI ID
  31.     if JR
  32. TargetID    equ    4    ;Target SCSI ID
  33.     else
  34. TargetID    equ    4    ;Target SCSI ID
  35.     endif
  36.  
  37. TimeSlice    equ    2000    ;Time to sleep in execution phase
  38.  
  39. _cmd    equ    0000h    ;Control/status port
  40. _dat    equ    0200h    ;Data port (1KB)
  41.  
  42. cmd    equ    byte ptr fs:[_cmd]    ;usually
  43. dat    equ    byte ptr fs:[_dat]
  44.  
  45. CEN    equ    80h    ;enable
  46. CIE    equ    40h    ;interrupt enable
  47. CPE    equ    20h    ;parity enable
  48. CARB    equ    10h    ;start arbitration
  49. CATN    equ    08h
  50. CBSY    equ    04h
  51. CSEL    equ    02h
  52. CRST    equ    01h
  53.  
  54. SARB    equ    80h    ;arbitration complete
  55. SPE    equ    40h    ;parity error
  56. SSEL    equ    20h
  57. SREQ    equ    10h
  58. SCD    equ    08h
  59. SIO    equ    04h
  60. SMSG    equ    02h
  61. SBSY    equ    01h
  62.  
  63. ;    Message-In/Out Codes
  64. MsgComplete    equ    00h
  65. MsgSavePointer    equ    02h
  66. MsgRestPointer    equ    03h
  67. MsgDisconnect    equ    04h
  68. MsgError    equ    05h
  69. MsgAbort    equ    06h
  70. MsgReject    equ    07h
  71. MsgNop        equ    08h
  72. MsgParity    equ    09h
  73. MsgLinkedCompl    equ    0Ah
  74. MsgLinkedComplF    equ    0Bh
  75. MsgReset    equ    0Ch
  76. MsgIdentify    equ    80h
  77.  
  78. ;; MsgCanDisconn    equ    0h
  79. MsgCanDisconn    equ    40h
  80.  
  81. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  82.  
  83. StartData
  84.  
  85.     public    host_id
  86.     public    target_id
  87.     public    irq_num
  88.     public    phys_addr
  89.  
  90.     public    sysinfo_seg
  91.  
  92.     extrn    DevHlpPtr:dword
  93.  
  94. ;
  95. ; Set by command line switches
  96. ;
  97.         even
  98. phys_addr    dd    PhysIO        ;Physical address of I/O ports
  99. irq_num        dw    IRQnum        ;IRQ number
  100. host_id        db    1 shl HostID    ;Host adapter SCSI ID mask
  101. target_id    db    1 shl TargetID    ;Target SCSI ID mask
  102.  
  103. ;
  104. ; Other data
  105. ;
  106.         even
  107. port_seg    dw    0        ;Protected mode I/O port selector
  108. sysinfo_seg    dw    0        ;Bimodal sysinfo segment address
  109. yield_ptr    dd    0        ;Bimodal ptr to yield flag
  110. timeout        dd    0        ;Start time
  111. event_id    dd    0        ;Dummy phys addr used as event ID
  112. data_ptr    dd    0        ;Virtual data transfer address
  113. data_len    dw    0        ;Requested transfer length
  114. actual_len    dw    0        ;Actual transfer length
  115. cmdptr        dw    0        ;Near pointer to next command byte
  116. xstatus        dw    0        ;Execute returns this on completion
  117. status        db    0        ;Status byte
  118. wait_for_int    db    0        ;Waiting for reselection interrupt
  119. reconnect_flag    db    0        ;Reconnection interrupt occurred
  120. msg_byte    db    0        ;Send this in message out phase
  121. fast_xfer    db    0        ;Fast block transfer mode
  122.  
  123. EndData
  124.  
  125. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  126.  
  127. StartCode
  128.  
  129.     public    dev_interrupt
  130.     public    command
  131.     public    bus_reset
  132.     public    device_reset
  133.     public    init_io
  134.     public    delay
  135.  
  136.     public    ST_INIT_null
  137. ST_INIT_null:
  138.  
  139. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  140.  
  141. ;
  142. ; Set time to now + CX
  143. ;
  144. set_time    proc near
  145.     mov    es, sysinfo_seg
  146.     movzx    ecx, cx
  147.     add    ecx, es:[0].msec_timer
  148.     mov    timeout, ecx
  149.     ret
  150. set_time    endp
  151.  
  152. ;
  153. ; Compare time to saved time
  154. ;
  155. cmp_time    proc near
  156.     mov    es, sysinfo_seg
  157.     mov    eax, es:[0].msec_timer
  158.     cmp    eax, timeout
  159.     ret
  160. cmp_time    endp
  161.  
  162. ;
  163. ; Wait CX msec
  164. ;
  165. delay        proc near
  166.     outtext    10, 'Delay '
  167.     outword    10, cx
  168.     outchar    10, '$'
  169.     push    fs
  170.     pusha
  171.     mov    ax, cs
  172.     mov    bx, offset delay
  173.     sub    di, di
  174.     mov    dh, 1        ;not interruptible
  175.     DevHlp    DevHlp_Block
  176.     popa
  177.     pop    fs
  178.     ret
  179. delay        endp
  180.  
  181. ;
  182. ; Wait for event (interruptible), max CX msec
  183. ; Return: C=0:    event wakeup
  184. ;      C=1:    Z=1:  timeout
  185. ;        Z=0:  interrupted
  186. ;
  187. sleep        proc near
  188.     outtext    5, 'Sleep '
  189.     outword    5, cx
  190.     push    fs
  191.     push    di
  192.     mov    ax, event_id._hi
  193.     mov    bx, event_id._lo
  194.     sub    di, di
  195.     mov    dh, 0
  196.     DevHlp    DevHlp_Block
  197.     pop    di
  198.     pop    fs
  199.     if    trace
  200.     pushf
  201.     jc    short sl_1
  202.     outtext    5, ': event$'
  203.     jmp    short sl_2
  204. sl_1:    outtext    5, ': timeout$'
  205. sl_2:    popf
  206.     endif
  207.     ret
  208. sleep        endp
  209.  
  210. yield        proc near
  211.     push    dx
  212.     push    bx
  213.     les    bx, yield_ptr
  214.     cmp    byte ptr es:[bx], 0
  215.     je    short yield1
  216.     outtext    5, 'Yield$'
  217.     push    fs
  218.     DevHlp    DevHlp_Yield
  219.     pop    fs
  220. yield1:    pop    bx
  221.     pop    dx
  222. yield2:    ret
  223. yield        endp
  224.  
  225. ;
  226. ; Wait for (status & DH) == DL, max CX msec
  227. ;    C=1: timeout
  228. wait_for    proc near
  229.     outtext    10, 'Wait '
  230.     outword    10, cx
  231.     outtext    10, ' for (status & '
  232.     outbyte    10, dh
  233.     outtext    10, ') == '
  234.     outbyte    10, dl
  235.     outchar    10, '$'
  236.     pusha
  237.     popa
  238.     mov    al, cmd
  239.     and    al, dh
  240.     cmp    al, dl
  241.     jne    short wf_wait
  242. wf_ok:    clc
  243.     ret
  244. wf_wait:call    set_time
  245. wf_loop:    ;;!! call    yield
  246.         mov    al, cmd
  247.         and    al, dh
  248.         cmp    al, dl
  249.         je    short wf_ok
  250.         call    cmp_time
  251.         jb    short wf_loop
  252. wf_to:    stc
  253.     ret
  254. wait_for    endp
  255.  
  256. waitfor        macro    mask, comp, time
  257.     mov    dx, (mask) * 256 + (comp)
  258.     mov    cx, time
  259.     call    wait_for
  260.         endm
  261.  
  262. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  263.  
  264. ;
  265. ; Device interrupt
  266. ; - Check for proper reselection and wakeup driver if
  267. ;   waiting for reconnection.
  268. ; - Take care of race conditions in a system with
  269. ;   multiple host adapters on the same bus.
  270. ; - The CIE bit does not to seem to be what its name
  271. ;   suggests, so accept but ignore interrupts at other
  272. ;   times.
  273. ; - Cannot use waitfor, since Yield is unusable at
  274. ;   interrupt time.
  275. ;
  276. dev_interrupt    proc far
  277.     push    fs
  278.     push    DevHlpPtr        ;Setup for DevHlp calls.
  279.     mov    bp, sp
  280.  
  281.     outtext    3, '-IRQ-'
  282.     cmp    wait_for_int, 0        ;Perhaps unexpected?
  283.     mov    wait_for_int, 0
  284.     je    int_ign
  285.  
  286.     smsw    ax            ;Set I/O segment for each mode.
  287.     test    al, 1
  288.     jnz    short int_pm
  289. int_rm:    mov    eax, phys_addr        ;The interrupt can occur in real mode.
  290.     shr    eax, 4
  291.     mov    fs, ax
  292.     jmp    short int_cont
  293. int_pm:    mov    fs, port_seg
  294. int_cont:
  295.  
  296.     mov    cmd, CPE        ;Disable ST01 interrupts
  297.     mov    ax, irq_num        ;Allow all other interrupts
  298.     DevHlp    DevHlp_EOI        ;to reduce interrupt latency.
  299.  
  300.     test    cmd, SSEL        ;The SEL line should be active since
  301.     jz    int_bad            ;it triggered the interrupt.
  302.  
  303.     mov    cx, 1000        ;Wait for release of BSY for IO
  304. int_1:    test    cmd, SBSY        ;line and ID bits to become active.
  305.     loopnz    int_1
  306.     jnz    short int_bad
  307.  
  308.     mov    al, cmd            ;Check for a valid reselection.
  309.     test    al, SIO            ;Is it a reselection?
  310.     jz    short int_bad
  311.     test    al, SPE            ;Ignore reselections with bad parity.
  312.     jnz    short int_bad
  313.  
  314.     mov    al, dat            ;Check initiator & target IDs.
  315.     xor    al, host_id
  316.     xor    al, target_id
  317.     jnz    short int_bad
  318.  
  319.     test    cmd, SSEL        ;The SEL line should still be active
  320.     jz    short int_bad        ;but maybe another host adapter
  321.                     ;got selected and the ID bits on the
  322.                     ;data bus were garbage. In this case,
  323.                     ;the SEL line should now be inactive.
  324.  
  325.     mov    cmd, CEN+CPE+CBSY    ;Acknowledge reselection.
  326.     mov    cx, 10000        ;Wait for end of SEL.
  327. int_2:    test    cmd, SSEL
  328.     loopnz    int_2
  329.     jcxz    int_bad
  330.     mov    cmd, CEN+CPE+CIE    ;Now the targed controls BSY.
  331.  
  332.     mov    ax, event_id._hi    ;Wakeup waiting driver.
  333.     mov    bx, event_id._lo
  334.     DevHlp    DevHlp_Run
  335.  
  336.     mov    reconnect_flag, 1    ;Show the world.
  337.     outtext    10, 'OK-'
  338.     
  339. int_r:    lea    sp, [bp+4]
  340.     pop    fs
  341.     clc                ;The interrupt is ok.
  342.     ret
  343.  
  344. int_ign:
  345.     outtext    3, 'IGN-'
  346.     mov    ax, irq_num
  347.     DevHlp    DevHlp_EOI
  348.     jmp    short int_r
  349.  
  350. int_bad:
  351.     outtext    3, 'BAD-'
  352.     mov    cmd, CPE+CIE        ;Rearm for next (re-)selection.
  353.     jmp    short int_r
  354.  
  355. dev_interrupt    endp
  356.  
  357. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  358.  
  359. ;
  360. ; Initiate SCSI bus operations
  361. ;    C=1, AX=error-code
  362. arbitrate    proc near
  363.     outtext    3, 'Arbitration$'
  364.  
  365. arb_loop:
  366.     mov    cmd, CPE        ;Clear pending parity errors.
  367.     mov    al, host_id        ;Send host adapter SCSI ID.
  368.     mov    dat, al
  369.     mov    cmd, CEN+CPE+CARB    ;Start bus arbitration.
  370.     waitfor    SARB, SARB, 100        ;Wait for success.
  371.     jnc    short arb_select
  372.  
  373.     mov    cx, TimeSlice        ;Takes long, go to sleep.
  374.     call    sleep
  375.     jnc    short arb_loop
  376.     jz    short arb_loop
  377.  
  378.     mov    ax, STERR+11h        ;Character I/O call interrupted.
  379.     stc
  380.     ret
  381.  
  382. arb_select:
  383.     outtext    4, 'Select target$'
  384.  
  385.     mov    al, target_id        ;Send both host & target SCSI IDs.
  386.     or    dat, al
  387.     mov    cmd, CEN+CPE+CATN+CSEL    ;Signal target selection. Request
  388.     waitfor    SBSY, SBSY, 250        ;a message out phase via ATN.
  389.     jc    short dev_not_ready
  390.     mov    cmd, CEN+CPE+CATN    ;Now target controls SEL.
  391.  
  392.     outtext    4, 'Arbitration done$'
  393.     clc
  394.     ret
  395.  
  396. dev_not_ready:
  397.     outtext    1, 'Initiation error$'
  398.     mov    ax, STERR+02h
  399.     stc
  400.     ret
  401.  
  402. arbitrate    endp
  403.  
  404. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  405.  
  406. ;
  407. ; Disconnected. Wait for reselection
  408. ; Interrupts are disabled on entry.
  409. ;    C=1, AX=error-code
  410. reconnect    proc near
  411.     outtext    3, 'Waiting for reselection$'
  412. res_loop:
  413.     cli
  414.     cmp    reconnect_flag, 0    ;Check the flag to be sure
  415.     jne    res_ok            ;the interrupt didn't get lost.
  416.     mov    cx, 1000        ;Wait for reselection.
  417.     call    sleep
  418.     sti
  419.     jnc    short res_ok        ;Event?
  420.     jnz    short res_int        ;Interrupt?
  421.     jmp    short res_loop        ;Timeout.
  422. res_ok:
  423.     sti
  424.     outtext    3, 'Reconnected$'
  425.     mov    wait_for_int, 0
  426.     clc
  427.     ret
  428. res_int:
  429.     outtext    1, 'Reconnection interrupted$'
  430.     mov    ax, STERR+11h        ;Character I/O call interrupted.
  431.     mov    wait_for_int, 0
  432.     stc
  433.     ret
  434. reconnect    endp
  435.  
  436. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  437.  
  438. ;
  439. ; On SCSI bus. Execute transfer as controlled by target.
  440. ;    C=1, AX=error-code on error
  441. ;
  442. execute        proc near
  443.     outtext    3, 'Execute$'
  444.  
  445.     push    di
  446.     push    si
  447.     mov    xstatus, 0
  448.     jmp    x_loop
  449.  
  450.     even            ;CD  IO  MSG    phase
  451. x_table    dw    x_data_out    ;0   0   0    data out
  452.     dw    x_inv_bus    ;0   0   1    -invalid-
  453.     dw    x_data_in    ;0   1   0    data in
  454.     dw    x_inv_bus    ;0   1   1    -invalid-
  455.     dw    x_cmd_out    ;1   0   0    command
  456.     dw    x_msg_out    ;1   0   1    message out
  457.     dw    x_stat_in    ;1   1   0    status
  458.     dw    x_msg_in     ;1   1   1    message in
  459.  
  460. x_inv_bus:
  461.     outtext    1, 'X: Invalid bus state$'
  462.     call    bus_reset        ;Bus reset required.
  463.     mov    ax, STERR+0Ch        ;General failure.
  464.     jmp    x_error
  465.  
  466. x_parity:
  467.     outtext    1, 'X: Parity error$'
  468.     mov    cmd, CEN+CPE+CATN    ;Request message phase
  469.     mov    msg_byte, MsgError    ;to inform the target of the problem.
  470.     jmp    x_loop            ;Target should terminate the command.
  471.  
  472. x_loop:    mov    bl, cmd            ;First check for next byte.
  473.     outtext    20, 'X_Loop '
  474.     outbyte    20, bl
  475.     outchar    20, '$'
  476.     test    bl, SBSY
  477.     jz    x_not_bsy
  478.     test    bl, SREQ
  479.     jz    short x_wait
  480.     test    bl, SPE
  481.     jnz    short x_parity
  482. x_jump:    and    bx, SCD+SIO+SMSG    ;Execute next byte or block.
  483.     jmp    x_table[bx]
  484.  
  485. x_wait:    mov    cx, 100            ;Not yet avail., setup for timeout.
  486.     call    set_time
  487. x_test:    mov    bl, cmd            ;Wait for next byte or timeout.
  488.     outtext    20, 'X_Loop '
  489.     outbyte    20, bl
  490.     outchar    20, '$'
  491.     test    bl, SBSY
  492.     jz    x_not_bsy
  493.     test    bl, SREQ
  494.     jnz    short x_jump
  495.     test    bl, SPE
  496.     jnz    x_parity
  497.     call    yield
  498.     call    cmp_time
  499.     jb    short x_test
  500.  
  501.     mov    cx, TimeSlice        ;Takes a long time
  502.     call    sleep            ;so give up timeslices.
  503.     jnc    short x_test
  504.     jnz    short x_interrupted
  505.  
  506.     mov    al, msg_byte        ;Timeout.
  507.     test    al, MsgIdentify        ;Message out phase pending?
  508.     jnz    short x_test
  509.     cmp    al, MsgReject
  510.     je    short x_test
  511. x_no_response:
  512.     outtext    1, 'X: No response$'    ;Target did not respond to message out.
  513.     call    bus_reset        ;phase request. Reset the bus.
  514.     mov    ax, STERR+02h        ;Device not ready
  515.     jmp    x_error
  516.  
  517. x_interrupted:
  518.     outtext    1, 'X: Interrupted$'
  519.     cmp    msg_byte, MsgAbort    ;Repeated?
  520.     je    short x_no_response
  521.     mov    cmd, CEN+CPE+CIE+CATN    ;Request message phase
  522.     mov    msg_byte, MsgAbort    ;to abort the running command.
  523.     mov    xstatus, STERR+11h    ;Character I/O call interrupted.
  524.     jmp    x_loop
  525.  
  526. x_not_bsy:
  527.     cmp    msg_byte, MsgReset    ;Bus free due to reset message?
  528.     je    short x_retx
  529.     cmp    msg_byte, MsgAbort    ;Bus free due to abort message?
  530.     je    short x_retx
  531.     outtext    1, 'X: Not BSY$'    ;No, a real failure.
  532.     mov    ax, STERR+0Ch        ;General failure.
  533.     jmp    x_error
  534.  
  535. x_ovf:
  536.     mov    cmd, CEN+CPE+CIE+CATN    ;Request message phase
  537.     outtext    1, 'X: Overflow$'
  538.     mov    msg_byte, MsgAbort    ;to abort the running command.
  539.     mov    xstatus, STERR+0Ch    ;General failure.
  540.     mov    data_len, 0
  541.     jmp    x_loop
  542.  
  543. x_error:
  544.     pop    si
  545.     pop    di
  546.     stc
  547.     ret
  548.  
  549. x_retx:    mov    ax, xstatus
  550.     test    ax, ax
  551.     jnz    short x_error
  552. x_ret:    pop    si
  553.     pop    di
  554.     clc
  555.     ret
  556.  
  557. x_data_in:
  558.     cld
  559.     if    EnableFast
  560.     cmp    fast_xfer, 0
  561.     jne    x_fast_in
  562.     endif
  563.     mov    al, dat
  564.     sub    data_len, 1
  565.     jc    x_ovf
  566.     outtext    5, 'Slow data in: '
  567.     outbyte    5, al
  568.     outtext    5, ' at '
  569.     outword    5, actual_len
  570.     outchar    5, '$'
  571.     les    di, data_ptr
  572.     stos    byte ptr es:[di]
  573.     mov    data_ptr._off, di
  574.     inc    actual_len
  575.     jmp    x_loop
  576.  
  577.     if    EnableFast
  578. x_fi_0:    mov    fast_xfer, 0
  579.     jmp    x_ovf
  580. x_fast_in:
  581.     mov    cx, data_len
  582.     cmp    cx, BlockSize
  583.     jb    short x_fi_1
  584.     mov    cx, BlockSize
  585. x_fi_1:    jcxz    x_fi_0
  586.     outtext    4, 'Fast data in: '
  587.     outword    4, cx
  588.     outtext    4, ' at '
  589.     outword    4, actual_len
  590.     outchar    4, '$'
  591.     add    actual_len, cx
  592.     sub    data_len, cx
  593.     mov    si, _dat
  594.     les    di, data_ptr
  595.     rep movs byte ptr es:[di], byte ptr fs:[si]
  596.     mov    data_ptr._off, di
  597.     jmp    x_loop
  598.     endif
  599.  
  600. x_data_out:
  601.     cld
  602.     if    EnableFast
  603.     cmp    fast_xfer, 0
  604.     jne    x_fast_out
  605.     endif
  606.     sub    data_len, 1
  607.     jc    x_do_0
  608.     les    si, data_ptr
  609.     lods    byte ptr es:[si]
  610.     mov    data_ptr._off, si
  611.     mov    dat, al
  612.     outtext    5, 'Slow data out: '
  613.     outbyte    5, al
  614.     outtext    5, ' at '
  615.     outword    5, actual_len
  616.     outchar    5, '$'
  617.     inc    actual_len
  618.     jmp    x_loop
  619. x_do_0:    mov    dat, 0
  620.     jmp    x_ovf
  621.  
  622.     if    EnableFast
  623. x_fo_0:    mov    fast_xfer, 0
  624.     jmp    x_ovf
  625. x_fast_out:
  626.     mov    cx, data_len
  627.     cmp    cx, BlockSize
  628.     jb    short x_fo_1
  629.     mov    cx, BlockSize
  630. x_fo_1:    jcxz    x_fo_0
  631.     outtext    4, 'Fast data out: '
  632.     outword    4, cx
  633.     outtext    4, ' at '
  634.     outword    4, actual_len
  635.     outchar    4, '$'
  636.     add    actual_len, cx
  637.     sub    data_len, cx
  638.     lgs    si, data_ptr
  639.     mov    ax, fs
  640.     mov    es, ax
  641.     mov    di, _dat
  642.      if EnableBlock
  643.     rep    movs byte ptr es:[di], byte ptr gs:[si]
  644.      else
  645. x_fo_2:    movs    byte ptr es:[di], byte ptr gs:[si]
  646.     push    cx
  647.     mov    cx, WrtWait
  648.     loop    $
  649.     pop    cx
  650.     loop    x_fo_2
  651.      endif
  652.     mov    data_ptr._off, si
  653.     jmp    x_loop
  654.     endif
  655.  
  656. x_msg_in:
  657.     outtext    4, 'Message in: '
  658.     cli
  659.     mov    wait_for_int, 1        ;Enable full interrupt management,
  660.     mov    reconnect_flag, 0
  661.     mov    cmd, CEN+CPE+CIE    ;don't miss reselection interrupt.
  662.     mov    al, dat
  663.     cmp    al, MsgDisconnect
  664.     je    short x_disconnect
  665.     mov    wait_for_int, 0        ;Not a disconnect, forget about
  666.     sti                ;interrupts.
  667.     cmp    al, MsgComplete
  668.     je    short x_complete
  669.     test    al, MsgIdentify        ;Check for other known messages.
  670.     jnz    short x_msg_ok
  671.     cmp    al, MsgSavePointer
  672.     je    short x_msg_ok
  673.     cmp    al, MsgRestPointer
  674.     je    short x_msg_ok
  675.     mov    cmd, CEN+CPE+CIE+CATN    ;Unknown message, request message out
  676.     mov    msg_byte, MsgReject    ;phase and signal message reject.
  677.     outtext    4, 'Rejected '
  678.     outbyte    4, al
  679. x_msg_ok:
  680.     outchar    4, '$'
  681.     jmp    x_loop
  682.  
  683. x_disconnect:
  684.     outtext    4, 'Disconnect$'
  685.     waitfor    SBSY, 0, 100        ;Wait until bus free
  686.     mov    cmd, CPE+CIE        ;    and release bus.
  687.     call    reconnect
  688.     jnc    x_loop
  689.     push    ax            ;Reconnection failed, abort command.
  690.     call    abort
  691.     pop    ax
  692.     jmp    x_error
  693.  
  694. x_complete:
  695.     outtext    4, 'Complete$'
  696.     waitfor    SBSY, 0, 100        ;Wait until bus free
  697.     mov    cmd, CPE+CIE        ;    and release bus.
  698.     jmp    x_retx
  699.  
  700. x_msg_out:
  701.     outtext    4, 'Message out: '
  702.     outbyte    4, msg_byte
  703.     outchar    4, '$'
  704.     mov    cmd, CEN+CPE+CIE    ;Release message phase request.
  705.     mov    al, msg_byte
  706.     mov    dat, al
  707.     jmp    x_loop
  708.  
  709. x_cmd_out:
  710.     mov    si, cmdptr
  711.     lodsb
  712.     mov    dat, al
  713.     mov    cmdptr, si
  714.     outtext    5, 'Command out: '
  715.     outbyte    5, al
  716.     outchar    5, '$'
  717.     jmp    x_loop
  718.  
  719. x_stat_in:
  720.     mov    al, dat
  721.     mov    status, al
  722.     outtext    4, 'Status in: '
  723.     outbyte    4, al
  724.     outchar    4, '$'
  725.     jmp    x_loop
  726.  
  727. execute        endp
  728.  
  729. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  730.  
  731. ;
  732. ; Reset SCSI bus.
  733. ;
  734. bus_reset    proc near
  735.     push    fs
  736.     mov    fs, port_seg
  737.     outtext    2, 'Bus reset$'
  738.     mov    cmd, CEN+CPE+CRST
  739.     mov    cx, 100
  740.     call    delay
  741.     mov    cmd, 0
  742.     mov    cx, 100
  743.     call    delay
  744.     pop    fs
  745.     clc
  746.     ret
  747. bus_reset    endp
  748.  
  749. ;
  750. ; Reset device.
  751. ;
  752. device_reset    proc near
  753.     push    fs
  754.     mov    fs, port_seg
  755.     outtext    2, 'Device reset$'
  756.     mov    msg_byte, MsgReset
  757.     call    arbitrate
  758.     jc    short drst_r
  759.     call    execute
  760. drst_r:    pop    fs
  761.     ret
  762. device_reset        endp
  763.  
  764. ;
  765. ; Abort command.
  766. abort        proc near
  767.     push    fs
  768.     mov    fs, port_seg
  769.     outtext    2, 'Abort command$'
  770.     mov    msg_byte, MsgAbort
  771.     call    arbitrate
  772.     jc    short abrt_r
  773.     call    execute
  774. abrt_r:    pop    fs
  775.     ret
  776. abort        endp
  777.  
  778. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  779.  
  780. ;
  781. ; Execute SCSI command
  782. ; In:
  783. ;    AL    = 0 for slow, 1 for fast transfer
  784. ;    EBX    = virtual data transfer address
  785. ;    CX    = expected data length
  786. ;    DX    = pointer to command record
  787. ; Out:
  788. ;    C    = set on error
  789. ;    AX    = error code, 0 if no error
  790. ;    CX    = number of data bytes actually transferred
  791. ;    DL    = status byte, 0FFh if no status available
  792. ;
  793. command        proc near
  794.     push    fs
  795.     push    es
  796.  
  797.     if    trace
  798.     pusha
  799.     outtext    2, 'Command, len='
  800.     outword    2, cx
  801.     outtext    2, ', cmd:'
  802.     mov    si, dx
  803.     mov    cx, 6
  804. cmd1:    lodsb
  805.     outchar    2, ' '
  806.     outbyte    2, al
  807.     loop    cmd1
  808.     outchar    2, '$'
  809.     popa
  810.     endif
  811.  
  812.     mov    fast_xfer, al
  813.     mov    data_ptr, ebx
  814.     mov    data_len, cx
  815.     mov    cmdptr, dx
  816.     mov    actual_len, 0
  817.     mov    status, 0FFh
  818.     mov    fs, port_seg
  819.  
  820.     mov    msg_byte, MsgIdentify+MsgCanDisconn+0
  821.     call    arbitrate
  822.     jc    short cmd_e
  823.     call    execute
  824.     jc    short cmd_e
  825.  
  826.     mov    dl, status
  827.     mov    cx, actual_len
  828.     outtext    2, 'Command status='
  829.     outbyte    2, dl
  830.     outtext    2, ', length='
  831.     outword    2, cx
  832.     outchar    2, '$'
  833.  
  834.     pop    es
  835.     pop    fs
  836.     clc
  837.     ret
  838.  
  839. cmd_e:    mov    dl, status
  840.     mov    cx, actual_len
  841.     outtext    2, 'Command error='
  842.     outword    2, ax
  843.     outtext    2, ', status='
  844.     outbyte    2, dl
  845.     outtext    2, ', length='
  846.     outword    2, cx
  847.     outchar    2, '$'
  848.  
  849.     pop    es
  850.     pop    fs
  851.     stc
  852.     ret
  853. command        endp
  854.  
  855. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  856.  
  857. init_io        proc near
  858.     push    di
  859.     push    si
  860.  
  861.     outtext    2, 'ST_Tape IO init$'
  862.  
  863.     mov    ax, phys_addr._hi    ;Clear cmd register.
  864.     mov    bx, phys_addr._lo
  865.     mov    cx, 1000h
  866.     mov    dh, 1
  867.     DevHlp    DevHlp_PhysToVirt
  868.     jc    init_r
  869.     mov    byte ptr es:[di+_cmd], 0
  870.     DevHlp    DevHlp_UnPhysToVirt
  871.  
  872.     mov    al, 1            ;Get sysinfo segment (for msec timer).
  873.     DevHlp    DevHlp_GetDOSVar
  874.     jc    init_r
  875.     mov    es, ax
  876.     mov    ax, es:[bx]
  877.     mov    sysinfo_seg, ax
  878.  
  879.     mov    al, 8            ;Get pointer to yield flag.
  880.     DevHlp    DevHlp_GetDOSVar
  881.     jc    init_r
  882.     mov    yield_ptr._seg, ax
  883.     mov    yield_ptr._off, bx
  884.  
  885.     sub    si, si            ;The physical address of the driver's
  886.     DevHlp    DevHlp_VirtToPhys    ;data segment is used as event ID.
  887.     mov    event_id._hi, ax
  888.     mov    event_id._lo, bx
  889.  
  890.     mov    ax, ds            ;Allocate port I/O segment selector.
  891.     mov    es, ax
  892.     mov    di, offset port_seg
  893.     mov    cx, 1
  894.     DevHlp    DevHlp_AllocGDTSel
  895.     jc    short init_r
  896.  
  897.     mov    ax, phys_addr._hi    ;Set port I/O segment address.
  898.     mov    bx, phys_addr._lo
  899.     mov    cx, 1000h
  900.     mov    si, port_seg
  901.     DevHlp    DevHlp_PhysToGDTSel
  902.     jc    short init_r
  903.  
  904.     mov    ax, offset dev_interrupt
  905.     mov    bx, irq_num         ;Set interrupt handler.
  906.     mov    dh, 0
  907.     DevHlp    DevHlp_SetIRQ
  908.     jc    short init_r
  909.  
  910. init_r:    pop    si
  911.     pop    di
  912.     ret
  913. init_io        endp
  914.  
  915. EndCode
  916.  
  917.     end
  918.