home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / OS2-ST01 / st_tape.asm < prev    next >
Assembly Source File  |  1992-05-23  |  16KB  |  709 lines

  1.     SUBTTL    Main Module
  2.         INCLUDE DEFS.INC                    ; which includes some other .incs
  3.  
  4.     include    debug.inc
  5.  
  6. StartData
  7.  
  8. ;====================================================
  9. ;
  10. ; Device Header -
  11. ;
  12. ;====================================================
  13.  
  14. TAPE_DEV LABEL WORD
  15.     DD    -1            ; SYSINIT handles the segment part
  16.     DW    DEV_CHAR_DEV or DEV_PROTECT or DEV_OPEN or DEVLEV_2 or DEV_GIOCTL
  17.                     ; Use equates in DEVHDR.INC
  18.                     ; to define Attribute word
  19.     DW    STRAT            ; offset to strategy routine entry point
  20.     DW    0            ; IDC entry point
  21.     DB    'TAPE$4  '        ; Name of device
  22. DPS    DB    8 DUP (?)        ; More reserved
  23.  
  24. ; End of the device header.
  25. ;============================================================================
  26.  
  27. ;
  28. ;  data structure used by this device driver
  29. ;
  30.  
  31.     EVEN
  32. DISPTAB LABEL WORD
  33.  
  34.     DW    TAPE_INIT    ;00: Init
  35.     DW    TAPE_EXIT1    ;01: Media Check (Block Devices Only)
  36.     DW    TAPE_EXIT1    ;02: Build BPB (Block Devices Only)
  37.     DW    TAPE_EXIT1    ;03: Reserved (used to be Ioctl Input)
  38.     DW    TAPE_INPUT    ;04: Input (Read)
  39.     DW    TAPE_INPNOWAIT     ;05: Non-Destructive Input, no wait.
  40.     DW    TAPE_INPSTATUS     ;06: Input Status
  41.     DW    TAPE_INPFLUSH    ;07: Input Flush
  42.     DW    TAPE_OUTPUT    ;08: Output (Write)
  43.     DW    TAPE_OUTVERIFY    ;09: Output (Write) with verify
  44.     DW    TAPE_OUTSTATUS    ;0A: Output Status
  45.     DW    TAPE_OUTFLUSH    ;0B: Output Flush
  46.     DW    TAPE_EXIT1    ;0C: Reserved (used to be Ioctl Output)
  47.     DW    TAPE_OPEN    ;0D: Device Open
  48.     DW    TAPE_CLOSE    ;0E: Device Close
  49.     DW    TAPE_EXIT1    ;0F: Removable Media
  50.     DW    TAPE_GIOCTL    ;10: Generic Ioctl
  51.     DW    TAPE_EXIT1    ;11: Reset Media
  52.     DW    TAPE_EXIT1    ;12: Get Logical Drive Map
  53.     DW    TAPE_EXIT1    ;13: Set Logical Drive Map
  54.     DW    TAPE_EXIT1    ;14: DeInstall
  55.     DW    TAPE_EXIT1    ;15: Port Access
  56.     DW    TAPE_EXIT1    ;16: Partitionable HDs
  57.     DW    TAPE_EXIT1    ;17: Logical Unit Mal
  58.     DW    TAPE_EXIT1    ;18: -
  59.     DW    TAPE_EXIT1    ;19: -
  60.     DW    TAPE_EXIT1    ;1A: -
  61.     DW    TAPE_EXIT1    ;1B: -
  62.  
  63. MAXCMD = (($ - DispTab)/2) - 1
  64.  
  65.     public    DevHlpPtr
  66.  
  67.         even
  68. DevHlpPtr    dd    0
  69. ReqPkt        dd    0
  70.  
  71. waiting        db    0    ;someone is waiting
  72. lock_flag    db    0    ;[0]: parm, [1]: data
  73.  
  74.         even
  75. para_handle    dd    0    ;ioctl param handle
  76. data_handle    dd    0    ;ioctl data handle
  77. data_ptr    dd    0    ;data pointer
  78.  
  79. cmd_read    db    08h, 01h, 0, 0,  0, 0
  80. cmd_write    db    0Ah, 01h, 0, 0,  0, 0
  81. cmd_sense    db    03h, 00h, 0, 0, 16, 0
  82. sense_data    db    16 dup(?)
  83. cmd_block    db    10 dup(?)
  84. sense_data_ptr    dd    offset sense_data
  85.  
  86.     if SCSI_LVL
  87. errcode        equ    12    ;SCSI standard
  88.     else
  89. errcode        equ    14    ;Tandberg
  90.     endif
  91.  
  92. EndData
  93.  
  94. StartIData
  95.     public    end_data
  96. end_data    db    0
  97. EndIData
  98.  
  99. StartICode
  100.     public    end_code
  101. end_code    db    0
  102. EndICode
  103.  
  104. StartCode
  105.  
  106.     extrn    command:near
  107.     extrn    bus_reset:near
  108.     extrn    device_reset:near
  109.     extrn    delay:near
  110.  
  111. page
  112. ;============================================================================
  113. ;
  114. ; - TAPE_STRAT -
  115. ;
  116. ;    Device Driver strategy entry point.
  117. ;    Parameters    - es:bx = Pointer to the request block
  118. ;
  119.  
  120. STRAT    PROC    FAR
  121.     push    DevHlpPtr        ;Make DevHlp callable w/o using DS/ES
  122.     mov    bp, sp
  123.  
  124.     mov    ax, es
  125.     mov    fs, ax
  126.     mov    di, bx
  127.  
  128.     cmp    fs:[di].PktCmd, 0    ;INIT command? Debug is not yet
  129.     je    short str_1        ;initialized.
  130.  
  131.     outtext    2, 'Strategy '
  132.     outbyte    2, fs:[di].PktCmd
  133.     outchar    2, '$'
  134.  
  135. str_loop:
  136.     cmp    ReqPkt._seg, 0        ;Driver busy?
  137.     jne    str_busy
  138.  
  139. str_1:    mov    ReqPkt._off, di        ;Save the bimodal address
  140.     mov    ReqPkt._seg, fs        ;of the request packet.
  141.     movzx    eax, fs:[di].PktCmd    ;Get command from packet and execute.
  142.     cmp    al, MAXCMD
  143.     ja    str_bad
  144.     call    DISPTAB[eax*2]
  145.  
  146. str_x:    xor    ax, STDONE        ;Mark operation complete.
  147.     mov    fs:[di].PktStatus, ax
  148.  
  149.     outtext    2, 'Strategy return '
  150.     outword    2, ax
  151.     outchar    2, '$'
  152.  
  153.     cmp    waiting, 0        ;Release waiting threads.
  154.     je    short str_x1
  155.     outtext    3, 'Wakeup waiting driver$'
  156.     mov    ax, ReqPkt._seg
  157.     mov    bx, ReqPkt._off
  158.     mov    ReqPkt._seg, 0
  159.     DevHlp    DevHlp_Run
  160.     jmp    short str_r
  161. str_x1:    mov    ReqPkt._seg, 0
  162. str_r:    lea    sp, [bp+4]
  163.     ret
  164.  
  165. str_busy:                ;Driver is busy. Wait.
  166.     outtext    2, 'Driver busy$'
  167.     inc    waiting
  168.     push    fs
  169.     push    di
  170.     mov    ax, ReqPkt._seg        ;Use bimodal pointer of running
  171.     mov    bx, ReqPkt._off        ;request packet as event ID.
  172.     mov    di, 0            ;No timeout.
  173.     mov    cx, 1000
  174.     mov    dh, 0            ;Interruptible.
  175.     DevHlp    DevHlp_Block
  176.     pop    di
  177.     pop    fs
  178.     pushf
  179.     dec    waiting
  180.     popf
  181.     jnc    str_loop        ;Retry on event or timeout wakeup.
  182.     jz    str_loop
  183.  
  184.     mov    ax, STDONE+STERR+11h    ;Character I/O call interrupted.
  185.     mov    fs:[di].PktStatus, ax
  186.     jmp    short str_r
  187.  
  188. str_bad:
  189.     mov    ax, STERR+03h        ;Unknown command.
  190.     jmp    str_x
  191.  
  192. STRAT        ENDP
  193.  
  194. TAPE_EXIT1    proc near
  195.     mov    ax, STERR+03h        ;Unknown command.
  196.     ret
  197. TAPE_EXIT1    endp
  198.  
  199. ;====================================================
  200. ;
  201. ; Operations
  202. ; ----------
  203. ;
  204. ; In:    FS:DI    = ptr to request block
  205. ; Out:    AX    = exit code (incl. DONE)
  206. ;
  207. ;====================================================
  208.  
  209. TAPE_INPUT    proc near    ;04: Input (Read)
  210.     smsw    ax            ;Protected mode only.
  211.     test    al, 1
  212.     jz    short terr_1
  213.     mov    dx, offset cmd_read
  214.     jmp    rw_command
  215. terr_1:    mov    ax, STERR+01h        ;Unknown unit.
  216.     ret
  217. TAPE_INPUT    endp
  218.  
  219. TAPE_INPNOWAIT    proc near    ;05: Non-Destructive Input, no wait.
  220.     mov    ax, STBUSY    ;busy = none avail
  221.     ret
  222. TAPE_INPNOWAIT    endp
  223.  
  224. TAPE_INPSTATUS    proc near    ;06: Input Status
  225.     mov    ax, STBUSY    ;busy = none avail
  226.     ret
  227. TAPE_INPSTATUS    endp
  228.  
  229. TAPE_INPFLUSH    proc near    ;07: Input Flush
  230.     sub    ax, ax
  231.     ret
  232. TAPE_INPFLUSH    endp
  233.  
  234. TAPE_OUTPUT    proc near    ;08: Output (Write)
  235.     smsw    ax            ;Protected mode only.
  236.     test    al, 1
  237.     jz    short terr_1
  238.     mov    dx, offset cmd_write
  239.     jmp    rw_command
  240. TAPE_OUTPUT    endp
  241.  
  242. TAPE_OUTVERIFY    proc near    ;09: Output (Write) with verify
  243.     smsw    ax            ;Protected mode only.
  244.     test    al, 1
  245.     jz    short terr_1
  246.     mov    dx, offset cmd_write
  247.     jmp    rw_command
  248. TAPE_OUTVERIFY    endp
  249.  
  250. TAPE_OUTSTATUS    proc near    ;0A: Output Status
  251.     sub    ax, ax        ;no wait
  252.     cmp    waiting, 0
  253.     je    short ost_r
  254.     mov    ax, STBUSY    ;busy + done = wait required
  255. ost_r:    ret
  256. TAPE_OUTSTATUS    endp
  257.  
  258. TAPE_OUTFLUSH    proc near    ;0B: Output Flush
  259.     sub    ax, ax
  260.     ret
  261. TAPE_OUTFLUSH    endp
  262.  
  263. TAPE_OPEN    proc near    ;0D: Device Open
  264.     smsw    ax        ;Protected mode only.
  265.     test    al, 1
  266.     jz    short terr_1
  267.     sub    ax, ax
  268.     ret
  269. TAPE_OPEN    endp
  270.  
  271. TAPE_CLOSE    proc near    ;0E: Device Close
  272.     sub    ax, ax
  273.     ret
  274. TAPE_CLOSE    endp
  275.  
  276. ;====================================================
  277. ;
  278. ; Generic IOCtl
  279. ;
  280. ;====================================================
  281.  
  282. TAPE_GIOCTL    proc near    ;10: Generic Ioctl
  283.     push    si
  284.  
  285.     outtext    2, 'IOCtl '
  286.     outbyte    2, fs:[di].GIOCategory
  287.     outchar    2, ' '
  288.     outbyte    2, fs:[di].GIOFunction
  289.     outchar    2, '$'
  290.  
  291.     mov    lock_flag, 0
  292.  
  293.     movzx    eax, fs:[di].GIOFunction
  294.     cmp    fs:[di].GIOCategory, 80h    ;Own IOCtl codes?
  295.     je    short gio_cat_own
  296.     cmp    fs:[di].GIOCategory, 11        ;general IOCtl codes?
  297.     je    short gio_cat_11
  298.  
  299. gio_bad:
  300.     test    fs:[di].GIOFunction, 80h    ;Ignore invalid command?
  301.     jnz    short gio_r0
  302.     mov    ax, STERR+03h            ;No, unknown command.
  303.     jmp    short gio_r
  304.  
  305. gio_cat_11:                ;Category 11: general device control.
  306.     cmp    al, 01h            ;Flush input.
  307.     je    short gio_r0
  308.     cmp    al, 02h            ;Flush output.
  309.     je    short gio_r0
  310.     cmp    ax, 41h            ;Session switch notification?
  311.     je    short gio_r0
  312.     cmp    ax, 60h            ;Query monitor support?
  313.     mov    ax, STERR+12h        ;Monitor calls not supported.
  314.     je    short gio_r
  315.     jmp    gio_bad
  316.  
  317.     even
  318. giotab    dw    gio_scsi_slow        ;0
  319.     dw    gio_scsi_fast        ;1
  320.     dw    gio_bus_reset        ;2
  321.     dw    gio_dev_reset        ;3
  322.     dw    gio_set_trace        ;4
  323.  
  324. gio_cat_own:                ;Own IOCtl commands.
  325.     and    al, 1Fh
  326.     cmp    al, 04h
  327.     ja    short gio_bad
  328.     jmp    giotab[eax*2]
  329.  
  330. gio_scsi_slow:                ;SCSI command - slow transfer.
  331.     mov    al, 0
  332.     call    gen_scsi_cmd
  333.     jmp    short gio_r
  334.  
  335. gio_scsi_fast:                ;SCSI command - fast transfer.
  336.     mov    al, 1
  337.     call    gen_scsi_cmd
  338.     jmp    short gio_r
  339.  
  340. gio_bus_reset:                ;SCSI bus reset.
  341.     call    bus_reset
  342.     jc    short gio_r
  343.     jmp    short gio_r0
  344.  
  345. gio_dev_reset:                ;SCSI device reset.
  346.     call    device_reset
  347.     jc    short gio_r
  348.     jmp    short gio_r0
  349.  
  350. gio_set_trace:
  351.     if    trace
  352.     push    di
  353.     mov    ax, fs:[di].GIOParaPack._seg
  354.     mov    di, fs:[di].GIOParaPack._off
  355.     mov    cx, 1
  356.     mov    dl, 0            ;read-only
  357.     DevHlp    DevHlp_VerifyAccess
  358.     pop    di
  359.     jc    gio_seg
  360.     les    bx, fs:[di].GIOParaPack
  361.     mov    al, es:[bx]
  362.     mov    tracelvl, al
  363.     endif
  364.     jmp    short gio_r0
  365.  
  366. gio_r0:    sub    ax, ax
  367. gio_r:    push    ax
  368.  
  369.     test    lock_flag, 1        ;Unlock parameter and data segment.
  370.     jz    short gio_r1
  371.     mov    ax, para_handle._hi
  372.     mov    bx, para_handle._lo
  373.     DevHlp    DevHlp_Unlock
  374. gio_r1:
  375.     test    lock_flag, 2
  376.     jz    short gio_r2
  377.     mov    ax, data_handle._hi
  378.     mov    bx, data_handle._lo
  379.     DevHlp    DevHlp_Unlock
  380. gio_r2:
  381.     mov    lock_flag, 0
  382.     pop    ax
  383.     pop    si
  384.     ret
  385.  
  386. gio_seg:mov    ax, STERR+13h        ;iInvalid parameter.
  387.     jmp    short gio_r
  388. TAPE_GIOCTL    endp
  389.  
  390. ;====================================================
  391. ;
  392. ; Command Subroutines
  393. ;
  394. ;====================================================
  395.  
  396. ;
  397. ; Request sense
  398. ;
  399. ; AX = device driver error status
  400. ; CX = number from information bytes
  401. ;
  402. req_sense    proc near
  403.     push    si
  404.  
  405.     mov    al, 0                ;Execute "request sense"
  406.     mov    ebx, sense_data_ptr
  407.     mov    cx, 16
  408.     mov    dx, offset cmd_sense
  409.     call    command
  410.     jc    reqs_no_stat
  411.     cmp    cx, 4
  412.     jb    reqs_no_stat
  413.  
  414.     if    trace ge 1
  415.     outtext    1, 'Sense data:'
  416.     mov    si, offset sense_data
  417. reqs_0:        lodsb
  418.         outchar    1, ' '
  419.         outbyte    1, al
  420.         loop    reqs_0
  421.     outchar    1, '$'
  422.     endif
  423.  
  424.     mov    al, sense_data+0        ;Check for unexpected
  425.     and    al, 7Fh                ;small sense block
  426.     cmp    al, 70h
  427.     jne    short reqs_short
  428.  
  429.     cmp    sense_data+errcode, 0Ah        ;Insufficient Capacity?
  430.     jne    short reqs_std
  431.     mov    al, sense_data+2        ;EOM set but sense key
  432.     and    al, 4Fh                ;set to "NO SENSE"?
  433.     cmp    al, 40h
  434.     je    short reqs_ew
  435.  
  436. reqs_std:
  437.     mov    al, sense_data+errcode        ;Translate error class & code.
  438.     jmp    short reqs_scan
  439. reqs_short:
  440.     mov    al, sense_data+0
  441. reqs_scan:
  442.     and    al, 7Fh
  443.     mov    bx, offset reqs_t
  444.     mov    cx, reqs_tlen
  445. reqs_1:        mov    ah, cs:[bx+0]
  446.         mov    dx, cs:[bx+1]
  447.         add    bx, 3
  448.         cmp    al, ah
  449.         loopnz    reqs_1
  450.     jnz    short reqs_unknown
  451.     mov    ax, dx
  452.  
  453. reqs_r:    mov    cx, word ptr sense_data+5
  454.     xchg    ch, cl
  455.     pop    si
  456.     ret
  457.  
  458. reqs_unknown:
  459.     mov    ax, STERR+07h            ;Any other: unknown media.
  460.     jmp    reqs_r
  461.  
  462. reqs_no_stat:
  463.     mov    ax, STERR+07h            ;No sense block
  464.     mov    cx, 0FFFFh
  465.     pop    si
  466.     ret
  467.  
  468. reqs_ew:                    ;Early EOT indication
  469.     outtext    1, 'Early Warning$'
  470.     mov    ax, STERR+09h            ;"Out of paper" :-)
  471.     jmp    short reqs_r
  472.  
  473. sxlat    macro    sense, system
  474.     db    sense
  475.     dw    system
  476.     endm
  477.  
  478. reqs_t    label    byte
  479.     sxlat 00h, 0         ;no sense            no error
  480.     sxlat 02h, STERR+02h ;hardware error        drive not ready    
  481.     sxlat 04h, STERR+02h ;drive not ready        drive not ready
  482.     sxlat 09h, STERR+02h ;media not loaded        drive not ready
  483.     sxlat 0Ah, STERR+0Ah ;insufficient capacity    write fault
  484.     sxlat 11h, STERR+04h ;uncorrectable data error    CRC error
  485.     sxlat 14h, STERR+08h ;no record found        sector not found
  486.     sxlat 17h, STERR+00h ;write protected        write protect violation
  487.     sxlat 19h, STERR+04h ;bad block found        CRC error
  488.     sxlat 1Ch, 0         ;file mark detected    EOF
  489.     sxlat 1Dh, STERR+04h ;compare error        CRC error
  490.     sxlat 20h, STERR+03h ;invalid command        unknown command
  491.     sxlat 30h, STERR+0Dh ;unit attention        change disk
  492.     sxlat 33h, STERR+0Ah ;append error        write fault
  493.     sxlat 34h, STERR+0Bh ;read EOM            read fault
  494. reqs_tlen    equ    ($ - offset reqs_t) / 3
  495.  
  496. req_sense    endp
  497.  
  498. ;
  499. ; Generic R/W command
  500. ; DX = command record
  501. ;
  502. rw_command    proc near
  503.     push    si
  504.  
  505.     outtext    3, 'R/W '
  506.     outword    3, fs:[di].IOpData._hi
  507.     outword    3, fs:[di].IOpData._lo
  508.     outchar    3, ' '
  509.     outword    3, fs:[di].IOcount
  510.     outchar    3, '$'
  511.  
  512.     push    dx            ;Make virtual address
  513.     mov    ax, fs:[di].IOpData._hi
  514.     mov    bx, fs:[di].IOpData._lo
  515.     mov    cx, fs:[di].IOcount
  516.     mov    si, data_ptr._seg
  517.     DevHlp    DevHlp_PhysToGDTSel
  518.     pop    dx
  519.     mov    ax, STERR+13h        ;Invalid parameter.
  520.     jc    rw_e
  521.  
  522.     test    cx, 01FFh        ;Verify block alignment
  523.     mov    ax, STERR+13h        ;Invalid parameter.
  524.     stc
  525.     jnz    short rw_e
  526.  
  527.     mov    al, ch            ;Insert block count into command.
  528.     shr    al, 1
  529.     mov    bx, dx
  530.     mov    [bx+4], al
  531.  
  532.     mov    al, 1            ;Run the command.
  533.     mov    ebx, data_ptr
  534.     call    command
  535.     jc    short rw_ret
  536.     cmp    dl, 00h
  537.     je    short rw_ret
  538.  
  539.     stc
  540.     cmp    dl, 02h            ;Check status?
  541.     mov    ax, STERR+02h        ;No -> not ready.
  542.     jne    short rw_ret
  543.     call    req_sense        ;Do check status.
  544.     shl    cx, 9            ;Convert number of blocks not handled
  545.     sub    fs:[di].IOcount, cx    ;to number of bytes actually xferred.
  546.     pop    si
  547.     ret
  548.  
  549. rw_ret:    mov    fs:[di].IOcount, cx    ;Number of bytes actually transferred.
  550.     pop    si
  551.     ret
  552.  
  553. rw_e:    mov    fs:[di].IOcount, 0
  554.     pop    si
  555.     ret
  556. rw_command    endp
  557.  
  558. ;
  559. ; Verify and lock ioctl parameter block.
  560. ;
  561. vfy_para    proc near
  562.     cmp    fs:[di].GIOParaLength, 0
  563.     je    vfyp_1
  564.     and    lock_flag, not 1
  565.     mov    ax, fs:[di].GIOParaPack._seg
  566.     mov    bh, 0                ;Lock, short-term, any memory.
  567.     mov    bl, 0                ;Block until available.
  568.     DevHlp    DevHlp_Lock
  569.     jc    short vfyp_1
  570.     mov    para_handle._hi, ax
  571.     mov    para_handle._lo, bx
  572.     or    lock_flag, 1
  573.     push    di
  574.     mov    cx, fs:[di].GIOParaLength    ;Verify access.
  575.     mov    ax, fs:[di].GIOParaPack._seg
  576.     mov    di, fs:[di].GIOParaPack._off
  577.     mov    dh, 0                ;Read-only.
  578.     DevHlp    DevHlp_VerifyAccess
  579.     pop    di
  580. vfyp_1:    ret
  581. vfy_para    endp
  582.  
  583. ;
  584. ; Verify and lock ioctl data block.
  585. ; The data block can be NULL.
  586. ;
  587. vfy_data    proc near
  588.     cmp    fs:[di].GIODataLength, 0
  589.     je    vfyd_1
  590.     and    lock_flag, not 2
  591.     movzx    eax, fs:[di].GIODataLength    ;NULL pointer & length?
  592.     or    eax, fs:[di].GIODataPack
  593.     jz    short vfyd_1
  594.     mov    ax, fs:[di].GIODataPack._seg
  595.     mov    bh, 0                ;Lock, short-term, any memory.
  596.     mov    bl, 0                ;Block until available.
  597.     DevHlp    DevHlp_Lock
  598.     jc    short vfyd_1
  599.     mov    data_handle._hi, ax
  600.     mov    data_handle._lo, bx
  601.     or    lock_flag, 2
  602.     push    di
  603.     mov    cx, fs:[di].GIODataLength    ;Verify access.
  604.     mov    ax, fs:[di].GIODataPack._seg
  605.     mov    di, fs:[di].GIODataPack._off
  606.     mov    dh, 1                ;Read+write.
  607.     DevHlp    DevHlp_VerifyAccess
  608.     pop    di
  609. vfyd_1:    ret
  610. vfy_data    endp
  611.  
  612. ;
  613. ; Generic IOCTL,  Subfunction "general SCSI command"
  614. ; AL = 0 for slow, 1 for fast xfer
  615. ;
  616. gen_scsi_cmd    proc near
  617.     push    ax                ;Slow/fast flag.
  618.  
  619.     call    vfy_para
  620.     jc    short gen_e1
  621.     call    vfy_data
  622.     jc    short gen_e1
  623.  
  624.     mov    cx, fs:[di].GIOParaLength    ;Copy command to data segment.
  625.     cmp    cx, 10
  626.     ja    short gen_e1
  627.     push    di
  628.     push    si
  629.     lgs    si, fs:[di].GIOParaPack
  630.     mov    ax, ds
  631.     mov    es, ax
  632.     mov    di, offset cmd_block
  633.     cld
  634.     rep    movs byte ptr es:[di], byte ptr gs:[si]
  635.     pop    si
  636.     pop    di
  637.  
  638.     pop    ax                ;Slow/fast flag
  639.     mov    ebx, fs:[di].GIODataPack    ;Data pointer
  640.     mov    cx, fs:[di].GIODataLength
  641.     mov    dx, offset cmd_block        ;Execute command
  642.     call    command
  643.     jc    short gen_r
  644.     cmp    dl, 0                ;Is ok, test SCSI status byte.
  645.     je    short gen_r
  646.     mov    al, 80h                ;Not ok, return SCSI status byte.
  647.     or    al, dl
  648.     jmp    short gen_r
  649.  
  650. gen_e1:    add    sp, 2
  651. gen_e:    mov    ax, STERR+13h            ;Invalid parameters.
  652. gen_r:    ret
  653. gen_scsi_cmd    endp
  654.  
  655. ;====================================================
  656. ;
  657. ; Initialization
  658. ;
  659. ;====================================================
  660.  
  661.     extrn    init_io:near
  662.     extrn    init_debug:near
  663.  
  664. TAPE_INIT    proc near    ;00: Init
  665.     mov    eax, fs:[di].InitDevHlp    ;Set device helper vector.
  666.     mov    DevHlpPtr, eax
  667.     mov    ss:[bp], eax
  668.  
  669.     mov    sense_data_ptr._seg, ds    ;Fixup.
  670.  
  671.     push    di            ;Allocate selector for data pointer.
  672.     mov    ax, ds
  673.     mov    es, ax
  674.     mov    di, offset data_ptr._seg
  675.     mov    cx, 1
  676.     DevHlp    DevHlp_AllocGDTSel
  677.     pop    di
  678.     jc    init_e
  679.  
  680. ;    les    bx, fs:[di].InitParms
  681. ;    FIXME: Interpret command line.
  682.  
  683.     call    init_debug
  684.     jc    init_e
  685.  
  686.     call    init_io
  687.     jc    init_e
  688.  
  689.      outtext    2, 'ST_Tape Init done$'
  690.  
  691. init_r:    mov    fs:[di].InitcUnit, 0
  692.     mov    fs:[di].InitEcode, offset end_code
  693.     mov    fs:[di].InitEdata, offset end_data
  694.     mov    fs:[di].InitpBPB, 0
  695.     sub    ax, ax
  696.     ret
  697.  
  698. init_e:    mov    fs:[di].InitcUnit, 0
  699.     mov    fs:[di].InitEcode, 0
  700.     mov    fs:[di].InitEdata, 0
  701.     mov    ax, STERR+0Ch
  702.     ret
  703. TAPE_INIT    endp
  704.  
  705. EndCode
  706.  
  707.     end
  708.