home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / asm / SCSIDRV.ZIP / SUBS.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-11-06  |  21.8 KB  |  1,084 lines

  1. ;
  2. ; Data storage for local subroutines
  3. ;
  4. cmd_ready    db    SCSI_TESTREADY,0,0,0,0,0
  5. cmd_rewind    db    SCSI_REWIND,0,0,0,0,0
  6. cmd_sense    db    SCSI_REQSENSE,0,0,0,size sense,0
  7. cmd_e_sense    db    SCSI_REQSENSE,0,0,0,size e_sense,0
  8. cmd_format    db    SCSI_FORMATUNIT,FORMAT_NORMAL,0,0,0,0
  9. cmd_remap    db    SCSI_REASSIGN,0,0,0,0,0
  10. cmd_space    db    SCSI_SPACE,1,0,0,0,0
  11.         if extended_io
  12. cmd_read    db    SCSI_READBLK,0,0,0,0,0,0,0,1,0
  13. cmd_write    db    SCSI_WRITEBLK,0,0,0,0,0,0,0,1,0
  14.         else
  15. cmd_read    db    SCSI_READBLK,0,0,0,1,0
  16. cmd_write    db    SCSI_WRITEBLK,0,0,0,1,0
  17.         endif
  18. cmd_tread    db    SCSI_READBLK,1,0,0,0,0
  19. cmd_twrite    db    SCSI_WRITEBLK,1,0,0,0,0
  20. cmd_twritefm    db    SCSI_WRITEFM,0,0,0,CLOSE_FM_CNT,0
  21. cmd_inquire    db    SCSI_INQUIRY,0,0,0,size inq,0
  22. cmd_erase    db    SCSI_ERASE,1,0,0,0,0
  23. cmd_load    db    SCSI_LOAD,0,0,0,0,0
  24. cmd_capacity    db    SCSI_READSIZE,0,0,0,0,0,0,0,0,0
  25. cmd_verify    db    SCSI_VERIFYBLK,0,0,0,0,0,0,0,SECT_TRACK,0
  26.  
  27.         if large_drives
  28.         even
  29. lsect_lsw    dw    ?
  30. lsect_msw    dw    ?
  31.         endif
  32.  
  33.         even
  34. docmd_cmd    dw    ?
  35. docmd_buf    dw    ?
  36. docmd_buf_seg    dw    ?
  37. docmd_len    dw    ?
  38. docmd_ustatus    db    ?
  39. docmd_estatus    db    ?
  40. docmd_message    db    ?
  41.  
  42. sense_ustatus    db    ?
  43. sense_estatus    db    ?
  44. sense_message    db    ?
  45.  
  46. retry_cnt    db    ?
  47.  
  48.         if dump_sense
  49. sense_msg1    db    0dh,07h,'Unit '
  50. sense_unit    db    'xxh, Err '
  51. sense_err    db    'xxh, Stat '
  52. sense_ustat    db    'xxh, Msg '
  53. sense_msg    db    'xxh, Retry '
  54. sense_retry    db    'xxh$'
  55. sense_msg2    db    ', Sense '
  56. sense_code    db    'xxh, Addr '
  57. sense_addr3    db    'xx'
  58. sense_addr2    db    'xx'
  59. sense_addr1    db    'xx'
  60. sense_addr0    db    'xxh$'
  61.         ife monitor
  62. sense_msg3    db    0dh,0ah,'$'
  63.         endif
  64.         endif
  65.  
  66. ;
  67. ; Reset the SCSI Bus
  68. ;
  69. scsi_reset    proc    near
  70.         pusha
  71.  
  72.         mov    ax,SCSI_CARD_SEG    ;Point at the command port
  73.         mov    es,ax
  74.         mov    si,SCSI_CMD_PORT
  75.  
  76.         mov    byte ptr es:[si],CMDBASE or CMDRST
  77.         call    wait100us
  78.         mov    byte ptr es:[si],CMDBASE
  79.         call    wait100us
  80.  
  81.         popa
  82.         ret
  83. scsi_reset    endp
  84.  
  85. ;
  86. ; Request Sense data from a unit and display the result
  87. ; Called after every SCSI command with the exit code in 'al'
  88. ;
  89. scsi_sense    proc    near
  90.         pushf
  91.         pusha
  92.         push    es
  93.  
  94.         if dump_sense
  95. ;
  96. ; Print out the first part even if we can't retrieve any sense status
  97. ;
  98.         mov    al,docmd_estatus    ;Save for printing
  99.         mov    sense_estatus,al
  100.         mov    al,docmd_ustatus
  101.         mov    sense_ustatus,al
  102.         mov    al,docmd_message
  103.         mov    sense_message,al
  104.         mov    di,cur_unit
  105.         mov    dl,[di].unit_select
  106.         lea    bx,sense_unit        ;Unit
  107.         call    hex2asc2
  108.         mov    dl,sense_estatus    ;Error (from docmd)
  109.         lea    bx,sense_err
  110.         call    hex2asc2
  111.         mov    dl,sense_ustatus    ;Status (from unit)
  112.         lea    bx,sense_ustat
  113.         call    hex2asc2
  114.         mov    dl,sense_message    ;Msg (from unit)
  115.         lea    bx,sense_msg
  116.         call    hex2asc2
  117.         mov    dl,retry_cnt        ;Retry
  118.         lea    bx,sense_retry
  119.         call    hex2asc2
  120.         lea    dx,sense_msg1
  121.         call    puts
  122.         endif
  123.  
  124. ;
  125. ; Try to retrieve sense status
  126. ;
  127.         mov    di,cur_unit            ;Unit
  128.         lea    bx,[di].unit_sense        ;Buffer Offset
  129.         mov    cx,size sense            ;Buffer Size
  130.         lea    dx,cmd_sense            ;Command
  131.         cmp    [di].unit_sense.sense_sense,SENSE_CCS
  132.         jnz    no_e_sense
  133.         lea    bx,[di].unit_e_sense        ;Buffer Offset
  134.         mov    cx,size e_sense            ;Buffer Size
  135.         lea    dx,cmd_e_sense            ;Command
  136. no_e_sense:    push    ds                ;Buffer Segment
  137.         pop    es
  138.         mov    di,dx
  139.         call    docmd
  140.  
  141.         if dump_sense
  142. ;
  143. ; If we got something, print it
  144. ;
  145.         jnc    sense_dump
  146.         jmp    sense_exit
  147.  
  148. sense_dump:    mov    di,cur_unit
  149.         cmp    [di].unit_sense.sense_sense,SENSE_CCS
  150.         jz    dump_e_sense
  151.  
  152.         mov    dl,[di].unit_sense.sense_sense
  153.         lea    bx,sense_code        ;Sense
  154.         call    hex2asc2
  155.         mov    dl,0
  156.         lea    bx,sense_addr3
  157.         call    hex2asc2
  158.         mov    dl,[di].unit_sense.sense_lba_b2
  159.         lea    bx,sense_addr2
  160.         call    hex2asc2
  161.         mov    dl,[di].unit_sense.sense_lba_b1
  162.         lea    bx,sense_addr1
  163.         call    hex2asc2
  164.         mov    dl,[di].unit_sense.sense_lba_b0
  165.         lea    bx,sense_addr0
  166.         call    hex2asc2
  167.         jmp    short sense_print
  168.  
  169. dump_e_sense:    mov    dl,[di].unit_e_sense.e_sense_sense
  170.         lea    bx,sense_code        ;Sense
  171.         call    hex2asc2
  172.         mov    dl,[di].unit_e_sense.e_sense_lba_b3
  173.         lea    bx,sense_addr3        ;Address
  174.         call    hex2asc2
  175.         mov    dl,[di].unit_e_sense.e_sense_lba_b2
  176.         lea    bx,sense_addr2
  177.         call    hex2asc2
  178.         mov    dl,[di].unit_e_sense.e_sense_lba_b1
  179.         lea    bx,sense_addr1
  180.         call    hex2asc2
  181.         mov    dl,[di].unit_e_sense.e_sense_lba_b0
  182.         lea    bx,sense_addr0
  183.         call    hex2asc2
  184.  
  185. sense_print:    lea    dx,sense_msg2
  186.         call    puts
  187.         endif
  188.  
  189. sense_exit:    if dump_sense
  190.         if monitor
  191.         mov    cx,20000
  192. sense_wait:    call    wait100us
  193.         loop    sense_wait
  194.         else
  195.         lea    dx,sense_msg3        ;Terminate the Message
  196.         call    puts
  197.         endif
  198.         endif
  199.  
  200.         pop    es
  201.         popa
  202.         popf
  203.         ret
  204. scsi_sense    endp
  205.  
  206. ;
  207. ; Get the Extended Sense Status from the current Unit
  208. ;
  209. get_sense    proc    near
  210.         mov    di,cur_unit            ;Unit
  211.         lea    bx,[di].unit_e_sense        ;Buffer Offset
  212.         push    ds                ;Buffer Segment
  213.         pop    es
  214.         mov    cx,size e_sense            ;Buffer Size
  215.         lea    di,cmd_e_sense            ;Command
  216.         call    docmd                ;Always ask first
  217.         ret
  218. get_sense    endp
  219.  
  220. ;
  221. ; Inquire about the type of a unit
  222. ;
  223. ; This MUST be the first call to a unit after the reset is done!
  224. ;
  225. ; al = return code, 'C' error indicates an error
  226. ;
  227. scsi_inquire    proc    near
  228.         push    cx
  229.  
  230. ;
  231. ; First thing we should do is wait for the unit to be ready
  232. ; as it takes some drives a while to spin up.
  233. ;
  234.         mov    retry_cnt,READY_RETRY
  235. ready_loop1:    lea    di,cmd_ready        ;Command
  236.         call    docmd
  237.         jnc    unit_is_ready
  238.         cmp    al,CNOCONNECT        ;No such unit?
  239.         jz    ready_error
  240.         push    cx
  241.         mov    cx,10000        ;Wait 1 Second
  242. ready_loop2:    call    wait100us
  243.         loop    ready_loop2
  244.         pop    cx
  245.         dec    retry_cnt        ;RETRY Times
  246.         jns    ready_loop1
  247.         jmp    short unit_is_ready    ;Still Try the Inquire
  248. ready_error:    stc
  249.         jmp    short inquire_exit
  250.  
  251. ;
  252. ; Then requests its sense status.
  253. ; This gives us a chance to find out if the
  254. ; device supports the Command Command Set (CCS)
  255. ;
  256. unit_is_ready:    call    get_sense
  257.         jc    inquire_exit
  258.  
  259. ;
  260. ; Ok, Now find out what kind of device it is
  261. ;
  262.         mov    di,cur_unit            ;Unit
  263.         lea    bx,[di].unit_inq_buf        ;Buffer Offset
  264.         push    ds                ;Buffer Segment
  265.         pop    es
  266.         mov    cx,size inq            ;Buffer Size
  267.         lea    di,cmd_inquire            ;Command
  268.         call    docmd
  269.  
  270. inquire_exit:    pop    cx
  271.         ret
  272. scsi_inquire    endp
  273.  
  274. ;
  275. ; Determine the size of a disk
  276. ;
  277. ; al = return code, 'C' error indicates an error
  278. ;
  279. scsi_capacity    proc    near
  280.         push    cx
  281.         mov    retry_cnt,MAX_RETRY
  282.  
  283. capacity_retry:    mov    di,cur_unit            ;Unit
  284.         lea    bx,[di].unit_cap_buf        ;Buffer Offset
  285.         push    ds                ;Buffer Segment
  286.         pop    es
  287.         mov    cx,size cap            ;Buffer Size
  288.         lea    di,cmd_capacity            ;Command
  289.         call    docmd
  290.         jnc    capacity_exit
  291.         call    scsi_sense
  292.         dec    retry_cnt
  293.         jns    capacity_retry
  294.         stc
  295.  
  296. capacity_exit:    pop    cx
  297.         ret
  298. scsi_capacity    endp
  299.  
  300. ;
  301. ; Verify (cx) Sectors starting with (dx:ax)
  302. ;
  303. ; al = return code, 'C' indicates an error
  304. ;
  305.  
  306. scsi_verify    proc    near
  307.         mov    retry_cnt,0        ;Don't do retrys
  308.         lea    di,cmd_verify            ;Command
  309.         mov    [di].ver_cmd_lba_b3,dh        ;Insert Sector
  310.         mov    [di].ver_cmd_lba_b2,dl        ; into Command
  311.         mov    [di].ver_cmd_lba_b1,ah        ;Insert Sector
  312.         mov    [di].ver_cmd_lba_b0,al        ; into Command
  313.         mov    [di].ver_cmd_len_b1,ch        ;Insert Length
  314.         mov    [di].ver_cmd_len_b0,cl        ; into Command
  315.         call    docmd
  316.         jnc    verify_exit
  317.         call    scsi_sense
  318.  
  319. verify_exit:    ret
  320. scsi_verify    endp
  321.  
  322. ;
  323. ; Read Some Blocks from the disk given
  324. ; the request header in es:bx
  325. ;
  326. ; al = return code, 'C' indicates an error
  327. ;
  328. disk_read    proc    near
  329.         mov    retry_cnt,MAX_RETRY
  330.  
  331.         mov    di,bx
  332.         mov    cx,es:[di].rh4_count        ;Sector Count
  333.         if large_drives
  334.         mov    dx,es:[di].rh4_lsect_lsw    ;Starting Sector
  335.         mov    lsect_lsw,dx
  336.         mov    dx,es:[di].rh4_lsect_msw
  337.         mov    lsect_msw,dx
  338.         else
  339.         mov    dx,es:[di].rh4_sector        ;Starting Sector
  340.         endif
  341.         mov    bx,es:[di].rh4_buf_ofs        ;Buffer Offset
  342.         mov    ax,es:[di].rh4_buf_seg        ;Buffer Segment
  343.         mov    es,ax
  344.  
  345.         mov    si,cur_bpb
  346.         lea    di,cmd_read            ;Command
  347.         ife large_drives
  348.         mov    ax,[si].bpb_hs_msw        ;Drive Sector Offset
  349.         if extended_io
  350.         mov    [di].io_cmd_lba_b3,ah        ;Insert Sector
  351.         endif
  352.         mov    [di].io_cmd_lba_b2,al        ;Into the Command
  353.         endif
  354.  
  355.         if multi_sector
  356.         mov    ax,cx                ;Get Sector Count
  357.         and    ax,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  358.         jnz    disk_r_cok1            ;Check for Boundary
  359.         mov    ax,CHUNK_MAX
  360.         if oldcode
  361. disk_r_cok1:    shl    ax,1                ;Convert to Buffer Size
  362.         shl    ax,1
  363.         shl    ax,1
  364.         shl    ax,1
  365.         shl    ax,1
  366.         shl    ax,1
  367.         shl    ax,1
  368.         shl    ax,1
  369.         shl    ax,1
  370.         else
  371. disk_r_cok1:    shl    ax,9                ;Convert to Buffer Size
  372.         endif
  373.         add    ax,bx                ;Check for Wrap
  374.         else
  375.         mov    ax,bx                ;Check for Wrap
  376.         add    ax,P_SECT            ;The First Time
  377.         endif
  378. disk_r_loop:    jnc    disk_r_nowrap
  379.         mov    ax,bx                ;Normalize the
  380.         if oldcode
  381.         shr    ax,1                ;Segment and
  382.         shr    ax,1
  383.         shr    ax,1
  384.         shr    ax,1
  385.         else
  386.         shr    ax,4                ;Segment and
  387.         endif
  388.         mov    si,es                ;Offset so that
  389.         add    si,ax                ;It dosn't Wrap
  390.         mov    es,si
  391.         and    bx,000Fh
  392. disk_r_nowrap:    push    cx
  393.         if large_drives
  394.         mov    dx,lsect_msw
  395.         if extended_io
  396.         mov    [di].io_cmd_lba_b3,dh
  397.         mov    [di].io_cmd_lba_b2,dl
  398.         else
  399.         and    dl,01Fh
  400.         mov    [di].io_cmd_lba_b2,dl
  401.         endif
  402.         mov    dx,lsect_lsw
  403.         endif
  404.         mov    [di].io_cmd_lba_b1,dh        ;Insert Sector
  405.         mov    [di].io_cmd_lba_b0,dl        ;Into the Command
  406.         if multi_sector
  407.         and    cx,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  408.         jnz    disk_r_cok2            ;Check for Boundary
  409.         mov    cx,CHUNK_MAX
  410. disk_r_cok2:
  411.         if extended_io
  412.         mov    [di].io_cmd_cnt_b1,ch        ;Insert Sector Count
  413.         endif
  414.         mov    [di].io_cmd_cnt_b0,cl        ;Into the Command
  415.         if oldcode
  416.         shl    cx,1                ;Convert to Buffer Size
  417.         shl    cx,1
  418.         shl    cx,1
  419.         shl    cx,1
  420.         shl    cx,1
  421.         shl    cx,1
  422.         shl    cx,1
  423.         shl    cx,1
  424.         shl    cx,1
  425.         else
  426.         shl    cx,9                ;Convert to Buffer Size
  427.         endif
  428.         else
  429.         mov    cx,P_SECT            ;Buffer Size
  430.         endif
  431. disk_r_retry:    call    docmd
  432.         jnc    disk_r_cok3
  433.         call    scsi_sense
  434.         dec    retry_cnt
  435.         jns    disk_r_retry            ;Already Setup
  436.         pop    cx
  437.         stc
  438.         jmp    short disk_r_exit
  439.         if multi_sector
  440. disk_r_cok3:    pop    cx
  441.         mov    ax,cx                ;Get Sector Count
  442.         and    ax,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  443.         jnz    disk_r_cok4            ;Check for Boundary
  444.         mov    ax,CHUNK_MAX
  445. disk_r_cok4:    sub    cx,ax                ;Dec Sector Count
  446.         jz    disk_r_exit
  447.         if large_drives
  448.         add    lsect_lsw,ax            ;Bump to next Sector
  449.         adc    lsect_msw,0
  450.         else
  451.         add    dx,ax                ;Bump to next Sector
  452.         endif
  453.         if oldcode
  454.         shl    ax,1                ;Convert to Buffer Size
  455.         shl    ax,1
  456.         shl    ax,1
  457.         shl    ax,1
  458.         shl    ax,1
  459.         shl    ax,1
  460.         shl    ax,1
  461.         shl    ax,1
  462.         shl    ax,1
  463.         else
  464.         shl    ax,9                ;Convert to Buffer Size
  465.         endif
  466.         add    bx,ax
  467.         jmp    disk_r_loop
  468.         else
  469. disk_r_cok3:    pop    cx
  470.         if large_drives
  471.         add    lsect_lsw,1            ;Bump to next Sector
  472.         adc    lsect_msw,0
  473.         else
  474.         inc    dx                ;Bump to next Sector
  475.         endif
  476.         add    bx,P_SECT
  477.         loop    disk_r_loop
  478.         clc
  479.         endif
  480.  
  481. disk_r_exit:    mov    es,rh_seg
  482.         mov    bx,rh_off
  483.         pushf
  484.         mov    ax,es:[bx].rh4_count        ;Update the Count
  485.         sub    ax,cx
  486.         mov    es:[bx].rh4_count,ax
  487.         popf
  488.         ret
  489. disk_read    endp
  490.  
  491. ;
  492. ; Write Some Blocks to the disk given
  493. ; the request header in es:bx
  494. ;
  495. ; al = return code, 'C' indicates an error
  496. ;
  497. disk_write    proc    near
  498.         mov    retry_cnt,MAX_RETRY
  499.  
  500.         mov    di,bx
  501.         mov    cx,es:[di].rh8_count        ;Sector Count
  502.         if large_drives
  503.         mov    dx,es:[di].rh8_lsect_lsw    ;Starting Sector
  504.         mov    lsect_lsw,dx
  505.         mov    dx,es:[di].rh8_lsect_msw
  506.         mov    lsect_msw,dx
  507.         else
  508.         mov    dx,es:[di].rh8_sector        ;Starting Sector
  509.         endif
  510.         mov    bx,es:[di].rh8_buf_ofs        ;Buffer Offset
  511.         mov    ax,es:[di].rh8_buf_seg        ;Buffer Segment
  512.         mov    es,ax
  513.  
  514.         mov    si,cur_bpb
  515.         lea    di,cmd_write            ;Command
  516.         ife large_drives
  517.         mov    ax,[si].bpb_hs_msw        ;Drive Sector Offset
  518.         if extended_io
  519.         mov    [di].io_cmd_lba_b3,ah        ;Insert Sector
  520.         endif
  521.         mov    [di].io_cmd_lba_b2,al        ;Into the Command
  522.         endif
  523.  
  524.         if multi_sector
  525.         mov    ax,cx                ;Get Sector Count
  526.         and    ax,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  527.         jnz    disk_w_cok1            ;Check for Boundary
  528.         mov    ax,CHUNK_MAX
  529.         if oldcode
  530. disk_w_cok1:    shl    ax,1                ;Convert to Buffer Size
  531.         shl    ax,1
  532.         shl    ax,1
  533.         shl    ax,1
  534.         shl    ax,1
  535.         shl    ax,1
  536.         shl    ax,1
  537.         shl    ax,1
  538.         shl    ax,1
  539.         else
  540. disk_w_cok1:    shl    ax,9                ;Convert to Buffer Size
  541.         endif
  542.         add    ax,bx                ;Check for Wrap
  543.         else
  544.         mov    ax,bx                ;Check for Wrap
  545.         add    ax,P_SECT            ;The First Time
  546.         endif
  547. disk_w_loop:    jnc    disk_w_nowrap
  548.         mov    ax,bx                ;Normalize the
  549.         if oldcode
  550.         shr    ax,1                ;Segment and
  551.         shr    ax,1
  552.         shr    ax,1
  553.         shr    ax,1
  554.         else
  555.         shr    ax,4                ;Segment and
  556.         endif
  557.         mov    si,es                ;Offset so that
  558.         add    si,ax                ;It dosn't Wrap
  559.         mov    es,si
  560.         and    bx,000Fh
  561. disk_w_nowrap:    push    cx
  562.         if large_drives
  563.         mov    dx,lsect_msw
  564.         if extended_io
  565.         mov    [di].io_cmd_lba_b3,dh
  566.         mov    [di].io_cmd_lba_b2,dl
  567.         else
  568.         and    dl,01Fh
  569.         mov    [di].io_cmd_lba_b2,dl
  570.         endif
  571.         mov    dx,lsect_lsw
  572.         endif
  573.         mov    [di].io_cmd_lba_b1,dh        ;Insert Sector
  574.         mov    [di].io_cmd_lba_b0,dl        ;Into the Command
  575.         if multi_sector
  576.         and    cx,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  577.         jnz    disk_w_cok2            ;Check for Boundary
  578.         mov    cx,CHUNK_MAX
  579. disk_w_cok2:
  580.         if extended_io
  581.         mov    [di].io_cmd_cnt_b1,ch        ;Insert Sector Count
  582.         endif
  583.         mov    [di].io_cmd_cnt_b0,cl        ;Into the Command
  584.         if oldcode
  585.         shl    cx,1                ;Convert to Buffer Size
  586.         shl    cx,1
  587.         shl    cx,1
  588.         shl    cx,1
  589.         shl    cx,1
  590.         shl    cx,1
  591.         shl    cx,1
  592.         shl    cx,1
  593.         shl    cx,1
  594.         else
  595.         shl    cx,9                ;Convert to Buffer Size
  596.         endif
  597.         else
  598.         mov    cx,P_SECT            ;Buffer Size
  599.         endif
  600. disk_w_retry:    call    docmd
  601.         jnc    disk_w_cok3
  602.         call    scsi_sense
  603.         dec    retry_cnt
  604.         jns    disk_w_retry            ;Already Setup
  605.         pop    cx
  606.         stc
  607.         jmp    short disk_w_exit
  608.         if multi_sector
  609. disk_w_cok3:    pop    cx
  610.         mov    ax,cx                ;Get Sector Count
  611.         and    ax,CHUNK_MAX-1            ;Mask Off the I/O Chunk
  612.         jnz    disk_w_cok4            ;Check for Boundary
  613.         mov    ax,CHUNK_MAX
  614. disk_w_cok4:    sub    cx,ax                ;Dec Sector Count
  615.         jz    disk_w_exit
  616.         if large_drives
  617.         add    lsect_lsw,ax            ;Bump to next Sector
  618.         adc    lsect_msw,0
  619.         else
  620.         add    dx,ax                ;Bump to next Sector
  621.         endif
  622.         if oldcode
  623.         shl    ax,1                ;Convert to Buffer Size
  624.         shl    ax,1
  625.         shl    ax,1
  626.         shl    ax,1
  627.         shl    ax,1
  628.         shl    ax,1
  629.         shl    ax,1
  630.         shl    ax,1
  631.         shl    ax,1
  632.         else
  633.         shl    ax,9                ;Convert to Buffer Size
  634.         endif
  635.         add    bx,ax
  636.         jmp    disk_w_loop
  637.         else
  638. disk_w_cok3:    pop    cx
  639.         if large_drives
  640.         add    lsect_lsw,1            ;Bump to next Sector
  641.         adc    lsect_msw,0
  642.         else
  643.         inc    dx                ;Bump to next Sector
  644.         endif
  645.         add    bx,P_SECT
  646.         loop    disk_w_loop
  647.         clc
  648.         endif
  649.  
  650. disk_w_exit:    mov    es,rh_seg
  651.         mov    bx,rh_off
  652.         pushf
  653.         mov    ax,es:[bx].rh8_count        ;Update the Count
  654.         sub    ax,cx
  655.         mov    es:[bx].rh8_count,ax
  656.         popf
  657.         ret
  658. disk_write    endp
  659.  
  660. ;
  661. ; Read Some Blocks from the Tape
  662. ;
  663. tape_read    proc    near
  664.         mov    read_flag,TRUE            ;Data Read from Tape
  665.         mov    di,bx
  666.         mov    cx,es:[di].rh4_count        ;Byte Count
  667.         mov    ax,cx                ;Test for invalid
  668.         and    ax,P_SECT-1            ;Byte Count
  669.         jz    tape_r_valid
  670.         mov    error_flag,TRUE
  671.         mov    es:[di].rh4_count,0        ;Nothing Read
  672.         stc                    ;Oops
  673.         ret
  674. tape_r_valid:    mov    bx,es:[di].rh4_buf_ofs        ;Buffer Offset
  675.         mov    ax,es:[di].rh4_buf_seg        ;Buffer Segment
  676.         mov    es,ax
  677.         mov    ax,bx                ;Normalize the
  678.         if oldcode
  679.         shr    ax,1                ;Segment and
  680.         shr    ax,1
  681.         shr    ax,1
  682.         shr    ax,1
  683.         else
  684.         shr    ax,4                ;Segment and
  685.         endif
  686.         mov    si,es                ;Offset so that
  687.         add    si,ax                ;It dosn't Wrap
  688.         mov    es,si
  689.         and    bx,000Fh
  690.         lea    di,cmd_tread
  691.         mov    ax,cx                ;Convert Bytes
  692.         if oldcode
  693.         shr    ax,1                ;to Blocks
  694.         shr    ax,1
  695.         shr    ax,1
  696.         shr    ax,1
  697.         shr    ax,1
  698.         shr    ax,1
  699.         shr    ax,1
  700.         shr    ax,1
  701.         shr    ax,1
  702.         else
  703.         shr    ax,9                ;to Blocks
  704.         endif
  705.         mov    [di].tio_cmd_cnt_b1,ah        ;Insert into Command
  706.         mov    [di].tio_cmd_cnt_b0,al
  707.         call    docmd
  708.         jnc    tape_r_ok
  709. ;
  710. ; Get the Extended Sense Status to check for reading FileMark
  711. ;
  712.         call    get_sense            ;Get Extended Sense
  713.         jc    tape_r_kaboom
  714.         mov    di,cur_unit            ;Unit
  715.         cmp    [di].unit_e_sense.e_sense_sense,80h
  716.         jnz    tape_r_eom
  717. tape_r_kaboom:    mov    error_flag,TRUE            ;Real Error Occured
  718.         stc
  719.         ret
  720. tape_r_eom:    mov    es,rh_seg
  721.         mov    bx,rh_off
  722.         mov    es:[bx].rh4_count,0        ;Nothing Read
  723.         clc
  724. tape_r_ok:    ret
  725. tape_read    endp
  726.  
  727. ;
  728. ; Write Some Blocks to the Tape
  729. ;
  730. tape_write    proc    near
  731.         mov    write_flag,TRUE            ;Data Written to Tape
  732.         mov    di,bx
  733.         mov    cx,es:[di].rh8_count        ;Byte Count
  734.         mov    ax,cx                ;Test for invalid
  735.         and    ax,P_SECT-1            ;Byte Count
  736.         jz    tape_w_valid
  737.         mov    es:[di].rh8_count,0        ;Nothing Written
  738.         mov    error_flag,TRUE            ;ERROR!
  739.         stc                    ;Oops
  740.         ret
  741. tape_w_valid:    mov    cx,es:[di].rh8_count        ;Byte Count
  742.         mov    bx,es:[di].rh8_buf_ofs        ;Buffer Offset
  743.         mov    ax,es:[di].rh8_buf_seg        ;Buffer Segment
  744.         mov    es,ax
  745.         mov    ax,bx                ;Normalize the
  746.         if oldcode
  747.         shr    ax,1                ;Segment and
  748.         shr    ax,1
  749.         shr    ax,1
  750.         shr    ax,1
  751.         else
  752.         shr    ax,4                ;Segment and
  753.         endif
  754.         mov    si,es                ;Offset so that
  755.         add    si,ax                ;It dosn't Wrap
  756.         mov    es,si
  757.         and    bx,000Fh
  758.         lea    di,cmd_twrite
  759.         mov    ax,cx                ;Convert Bytes
  760.         if oldcode
  761.         shr    ax,1                ;to Blocks
  762.         shr    ax,1
  763.         shr    ax,1
  764.         shr    ax,1
  765.         shr    ax,1
  766.         shr    ax,1
  767.         shr    ax,1
  768.         shr    ax,1
  769.         shr    ax,1
  770.         else
  771.         shr    ax,9                ;to Blocks
  772.         endif
  773.         mov    [di].tio_cmd_cnt_b1,ah        ;Insert into Command
  774.         mov    [di].tio_cmd_cnt_b0,al
  775.         call    docmd
  776.         jnc    tape_w_ok
  777. ;
  778. ; Get the Sense Status and see if we hit EOM.
  779. ; This is to allow the FileMark to still be written
  780. ; during the close processing.
  781. ;
  782.         call    get_sense            ;Get Extended Sense
  783.         jc    tape_w_kaboom
  784.         mov    di,cur_unit            ;Unit
  785.         cmp    [di].unit_e_sense.e_sense_sense,40h
  786.         jz    tape_w_eom
  787. tape_w_kaboom:    mov    error_flag,TRUE            ;Real Error Occured
  788.         mov    es,rh_seg
  789.         mov    bx,rh_off
  790.         mov    es:[bx].rh8_count,0        ;Nothing Written
  791. tape_w_eom:    stc
  792. tape_w_ok:    ret
  793. tape_write    endp
  794.  
  795. ;
  796. ; Do a command
  797. ;
  798. ; bx = buffer offset
  799. ; es = buffer segment
  800. ; cx = buffer len
  801. ; di => command string
  802. ;
  803. ; al = return code, 'C' indicates an error
  804. ;
  805. docmd        proc    near
  806.         pusha
  807.         push    es
  808.  
  809.         mov    docmd_buf,bx        ;Save our arguments
  810.         mov    docmd_buf_seg,es
  811.         mov    docmd_len,cx
  812.         mov    docmd_cmd,di
  813.         mov    docmd_ustatus,0FFh
  814.  
  815.         if monitor
  816.         mov    ax,'F'            ;Arbitrate for Bus
  817.         call    show_phase
  818.         endif
  819.  
  820.         mov    ax,SCSI_CARD_SEG    ;Point at the Card
  821.         mov    es,ax
  822.         mov    si,SCSI_CMD_PORT    ;Command Port
  823.         mov    di,SCSI_DATA_PORT    ;Data Port
  824.         mov    bx,cur_unit
  825.         mov    al,[bx].unit_select    ;Get our Select Bit
  826.  
  827.         if reserve_addr
  828. ;
  829. ; Get us control of the BUS by starting Arbitration
  830. ; Wait a maximum of 250ms for Control of the Bus
  831. ;
  832.         or    al,080h            ;Add our Address
  833.         mov    byte ptr es:[si],CMDBASE
  834.         nop
  835.         mov    byte ptr es:[di],080h    ;Our Address
  836.         nop
  837.         mov    byte ptr es:[si],CMDBASE or CMDSTARB
  838.         mov    cx,2500
  839. arb_loop:    test    byte ptr es:[si],STARBCOMPL
  840.         jnz    try_sel
  841.         call    wait100us
  842.         loop    arb_loop
  843.         else
  844. ;
  845. ; Wait 250ms for the Bus to become free
  846. ;
  847.         mov    cx,2500
  848. idle_loop:    test    byte ptr es:[si],STBSY    ;Busy?
  849.         jz    try_sel
  850.         call    wait100us
  851.         loop    idle_loop
  852.         endif
  853.  
  854.         call    scsi_reset
  855.         mov    al,CBUSBUSY        ;Bus still BUSY?
  856.         jmp    docmd_exit
  857.  
  858. try_sel:    mov    byte ptr es:[di],al    ;Select Bit
  859.         nop
  860.         mov    byte ptr es:[si],CMDBASE or CMDENABLE or CMDSEL
  861.  
  862.         if monitor
  863.         mov    ax,'S'            ;Select Target
  864.         call    show_phase
  865.         endif
  866.  
  867. ;
  868. ; Wait 250 ms for the Target to be SELected
  869. ;
  870.         mov    cx,2500
  871. sel_loop:    test    byte ptr es:[si],STBSY    ;Wait for BSY
  872.         jnz    cmd_xfer
  873.         call    wait100us
  874.         loop    sel_loop
  875.  
  876.         if monitor
  877.         mov    ax,'A'            ;Abort Selection
  878.         call    show_phase
  879.         endif
  880.  
  881.         mov    byte ptr es:[si],CMDBASE or CMDSEL
  882.         call    wait100us        ;Spec says wait 200us
  883.         call    wait100us        ;to abort selection phase
  884.         test    byte ptr es:[si],STBSY    ;Look one final time
  885.         jnz    cmd_xfer        ;Device did answer
  886.         mov    al,CNOCONNECT        ;Nothing Answered
  887.         jmp    docmd_exit
  888.  
  889. ;
  890. ; Start the Command, (al) contains last known status
  891. ;
  892. cmd_xfer:    mov    byte ptr es:[si],CMDBASE or CMDENABLE
  893.         nop
  894. xfer_loop:    mov    al,es:[si]        ;Get Status Byte
  895.         test    al,STBSY        ;Look for BSY bit
  896.         jnz    still_busy
  897.         jmp    xfer_offline
  898.         if scsi_parity
  899. still_busy:    test    al,STPARERR        ;Parity Error?
  900.         jz    still_good
  901.         jmp    xfer_parerr
  902. still_good:    test    al,STREQ        ;Request?
  903.         jz    xfer_loop
  904.         else
  905. still_busy:    test    al,STREQ        ;Request?
  906.         jz    xfer_loop
  907.         endif
  908.  
  909. ;
  910. ; Figure out what type of request it is
  911. ;
  912.         and    al,REQ_MASK
  913.         cmp    al,REQ_CMDOUT        ;Is it Command Out?
  914.         jnz    try_dataout
  915.  
  916.         if monitor
  917.         mov    ax,'C'            ;Command
  918.         call    show_phase
  919.         endif
  920.  
  921.         mov    si,docmd_cmd        ;Get Command Pointer
  922.         movsb                ;Send Byte to Card
  923.         mov    docmd_cmd,si
  924.         mov    si,SCSI_CMD_PORT    ;Restore Command Port
  925.         mov    di,SCSI_DATA_PORT    ;Restore Data Port
  926.         jmp    xfer_loop
  927.  
  928. try_dataout:    cmp    al,REQ_DATAOUT        ;Is it Data Out?
  929.         jnz    try_datain
  930.  
  931.         if monitor
  932.         mov    ax,'W'            ;Write
  933.         call    show_phase
  934.         endif
  935.  
  936.         mov    bx,si
  937.         mov    cx,docmd_len        ;Get the Data Count
  938.         mov    si,docmd_buf        ;Source Offset
  939.         mov    ds,docmd_buf_seg    ;Source Segment
  940.         cld
  941.  
  942. dataout_loop:    test    byte ptr es:[bx],STBSY    ;Must be BUSY
  943.         jz    dataout_exit
  944.         test    byte ptr es:[bx],STREQ    ;Wait for REQ
  945.         jz    dataout_loop
  946.         movsb                ;Transfer a Byte
  947.         dec    di            ;Keep in Valid
  948.         loop    dataout_loop        ;Done Yet?
  949.  
  950. dataout_exit:    mov    si,bx            ;Restore the Environment
  951.         mov    ax,cs
  952.         mov    ds,ax
  953.         jmp    xfer_loop
  954.  
  955. try_datain:    cmp    al,REQ_DATAIN        ;Is it Data In?
  956.         jnz    try_statin
  957.  
  958.         if monitor
  959.         mov    ax,'R'            ;Read
  960.         call    show_phase
  961.         endif
  962.  
  963.         mov    bx,si
  964.         mov    si,di            ;Source Offset
  965.         mov    ax,es
  966.         mov    cx,docmd_len        ;Length
  967.         mov    di,docmd_buf        ;Dest Offset
  968.         mov    es,docmd_buf_seg    ;Dest Segment
  969.         mov    ds,ax            ;Source Segment
  970.         cld
  971.  
  972. datain_loop:    test    byte ptr [bx],STBSY    ;Must be BUSY
  973.         jz    datain_exit
  974.         test    byte ptr [bx],STREQ    ;Wait for REQ
  975.         jz    datain_loop
  976.         movsb                ;Transfer a Byte
  977.         dec    si            ;Keep in Valid
  978.         loop    datain_loop        ;Done Yet?
  979.  
  980. datain_exit:    mov    ax,ds            ;Restore the Environment
  981.         mov    es,ax
  982.         mov    ax,cs
  983.         mov    ds,ax
  984.         mov    di,si
  985.         mov    si,bx
  986.         jmp    xfer_loop
  987.  
  988. try_statin:    cmp    al,REQ_STATIN        ;Is it Status In?
  989.         jnz    try_msgout
  990.  
  991.         if monitor
  992.         mov    ax,'s'            ;Status
  993.         call    show_phase
  994.         endif
  995.  
  996.         mov    al,es:[di]        ;Get the Status Byte
  997.         mov    docmd_ustatus,al
  998.         jmp    xfer_loop
  999.  
  1000. try_msgout:    cmp    al,REQ_MSGOUT        ;Is it Message Out?
  1001.         jnz    try_msgin
  1002.  
  1003.         if monitor
  1004.         mov    ax,'M'            ;Message Out
  1005.         call    show_phase
  1006.         endif
  1007.  
  1008.         mov    byte ptr es:[di],MSG_REJECT
  1009.         jmp    xfer_loop
  1010.  
  1011. try_msgin:    cmp    al,REQ_MSGIN        ;Is it Message In?
  1012.         jnz    kaboom
  1013.  
  1014.         if monitor
  1015.         mov    ax,'m'            ;Message In
  1016.         call    show_phase
  1017.         endif
  1018.  
  1019.         mov    al,es:[di]        ;Get the MSG Byte
  1020.         mov    docmd_message,al    ;And Save it
  1021.         cmp    al,MSG_COMPLETE        ;Are We All Done?
  1022.         jnz    xfer_error
  1023.         cmp    docmd_ustatus,0        ;Did we have an error?
  1024.         mov    al,COK            ;Preload OK code
  1025.         jz    docmd_exit
  1026.         jmp    xfer_error        ;Oops
  1027.  
  1028. kaboom:        call    scsi_reset        ;Reset the BUS
  1029.  
  1030.         if monitor
  1031.         mov    ax,'?'            ;Message In
  1032.         call    show_phase
  1033.         endif
  1034.         
  1035. xfer_error:    mov    al,CERROR        ;Command Failed with Bad Status
  1036.         jmp    short docmd_exit
  1037. xfer_offline:    mov    al,COFFLINE        ;Unit went OffLine
  1038.         jmp    short docmd_exit
  1039. xfer_parerr:    mov    al,CPARERR        ;Parity Error Detected
  1040.         jmp    short docmd_exit
  1041. xfer_selerr:    mov    al,CSELERR        ;Re-Select?
  1042.  
  1043. docmd_exit:    mov    docmd_estatus,al
  1044.         mov    byte ptr es:[si],CMDBASE
  1045.         pop    es
  1046.         popa
  1047.         mov    al,docmd_estatus
  1048.         cmp    al,COK
  1049.         jz    docmd_exit_ok
  1050.         stc
  1051. docmd_exit_ok:    ret
  1052. docmd        endp
  1053.  
  1054. ;
  1055. ; Wait One Hundred Micros Seconds
  1056. ;
  1057. ; The value of 'cx' is computed for an 8 Mhz Clock
  1058. ;
  1059. wait100us    proc    near
  1060.         push    cx        ;   (3) = 375ns
  1061.         mov    cx,79        ;   (2) = 250ns
  1062. wait_u_loop:    loop    wait_u_loop    ;  (10) = 1250ns * X
  1063.         pop    cx        ;   (5) = 625ns
  1064.         ret            ; (11+) = 1375ns
  1065. wait100us    endp
  1066.  
  1067. ;
  1068. ; Monitor the Bus Phase on the Video Screen
  1069. ;
  1070.         if monitor
  1071. show_phase    proc
  1072.         push    es
  1073.         push    di
  1074.         or    ax,VIDEO_COLOR
  1075.         mov    di,VIDEO_SEG
  1076.         mov    es,di
  1077.         mov    di,VIDEO_OFS
  1078.         stosw
  1079.         pop    di
  1080.         pop    es
  1081.         ret
  1082. show_phase    endp
  1083.         endif
  1084.