home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 165 / ST0102.ZIP / SCSI.ASM < prev    next >
Assembly Source File  |  1991-11-28  |  15KB  |  656 lines

  1. ;
  2. ; Simple SCSI Device Driver
  3. ;
  4.  
  5.         PAGE    60,85
  6.  
  7.         INCLUDE    options.inc
  8.         INCLUDE    equ.inc
  9.         INCLUDE    struct.inc
  10.  
  11.         ife oldcode
  12.         .286
  13.         else
  14.         .8086
  15. pusha        macro
  16.         push    ax
  17.         push    bx
  18.         push    cx
  19.         push    dx
  20.         push    si
  21.         push    di
  22.         endm
  23.  
  24. popa        macro
  25.         pop    di
  26.         pop    si
  27.         pop    dx
  28.         pop    cx
  29.         pop    bx
  30.         pop    ax
  31.         endm
  32.         endif
  33.  
  34. ;
  35. ; Start of Code and Data
  36. ;
  37. _TEXT        segment    word public 'CODE'
  38.         assume    cs:_TEXT, ds:_TEXT, es:_TEXT
  39.  
  40.         org    0
  41.  
  42. ;
  43. ; Device Header Required By DOS
  44. ;
  45. scsi:
  46. tape_link_ofs    dw    disk_link_ofs    ;Forward Link
  47. tape_link_seg    dw    -1
  48.         dw    0C800h        ;Char Device
  49.         dw    tape_strategy    ;Address of 1st DOS Call
  50.         dw    dev_interrupt    ;Address of 2nd DOS Call
  51.         db    'SCSITAPE'    ;Device Name
  52.  
  53. disk_link_ofs    dw    -1        ;Forward Link
  54. disk_link_seg    dw    -1
  55.         if large_drives
  56.         dw    06042h        ;Ioctl R/W, Block Device, Non-IBM, Get/Set, 32 bit
  57.         else
  58.         dw    06040h        ;Ioctl R/W, Block Device, Non-IBM, Get/Set
  59.         endif
  60.         dw    disk_strategy    ;Address of 1st DOS Call
  61.         dw    dev_interrupt    ;Address of 2nd DOS Call
  62. disk_count    db    0        ;Number of Disks Present
  63.         db    7 dup(?)
  64.  
  65. ;
  66. ; Work Space For Our Device Driver
  67. ;
  68.         even
  69. rh_off        dw    ?        ;Request Header Offset
  70. rh_seg        dw    ?        ;Request Header Segment
  71. rh_type        db    ?        ;Request Type
  72.  
  73. write_flag    db    FALSE        ;TRUE When Tape Write Seen
  74. read_flag    db    FALSE        ;TRUE When Tape Read Seen
  75. error_flag    db    FALSE        ;TRUE When Tape Error Seen
  76. load_flag    db    TRUE        ;TRUE When Tape should Load/Unload
  77. cur_drive    db    -1
  78. vol_id        db    'NO NAME    ',0
  79.  
  80. ;
  81. ; The Original INT 24 Vector
  82. ;
  83. vect_int_24    equ    word ptr 4 * 24h
  84. orig_int_24    dd    ?            ;Original INT 24 Vector
  85.  
  86. ;
  87. ; Define our own personal Stack
  88. ;
  89.         even
  90. new_stack    db    STACK_SIZE-2 dup (?)    ;Our Local Stack
  91. new_stack_top    dw    ?
  92.  
  93. stack_ptr    dw    ?            ;Old Stack Pointer
  94. stack_seg    dw    ?            ;Old Stack Segment
  95.  
  96. ;
  97. ; Command Table
  98. ;
  99. cmdtab        label    byte        ;* = Char Only Devices
  100.         dw    INITIALIZATION    ;Initialization
  101.         dw    MEDIA_CHECK    ;Media Check (Block Only)
  102.         dw    GET_BPB        ;Build BPB (Block Only)
  103.         dw    unknown        ;IOCTL Read
  104.         dw    READ        ;Read Data
  105.         dw    done        ;*Non Destructive Read
  106.         dw    done        ;*Read Status
  107.         dw    done        ;*Flush Read Buffer
  108.         dw    WRITE        ;Write Data
  109.         dw    WRITE_VERIFY    ;Write With Verify
  110.         dw    done        ;*Write Status
  111.         dw    done        ;*Flush Write Buffer
  112.         dw    WRITE_IOCTL    ;IOCTL Write
  113.         dw    OPEN_DEV    ;Device Open
  114.         dw    CLOSE_DEV    ;Device Close
  115.         dw    done        ;Removable Check
  116.         dw    unknown        ;*Write Until Busy
  117.         dw    unknown        ;Unknown Call
  118.         dw    unknown        ;Unknown Call
  119.         dw    IOCTL        ;Generic Ioctl
  120.         dw    unknown        ;Unknown Call
  121.         dw    unknown        ;Unknown Call
  122.         dw    unknown        ;Unknown Call
  123.         dw    GET_DEV        ;Get Device
  124.         dw    SET_DEV        ;Set Device
  125.  
  126. ;
  127. ; Int 24 (Fatal Error Handler)
  128. ;
  129. ; The test for our tape device only works because the
  130. ; device header for the tape is located at the start
  131. ; of the driver binary.
  132. ;
  133. our_int_24    proc    far
  134.         push    ax
  135.         mov    ax,cs        ;Is it our Segment
  136.         cmp    bp,ax
  137.         jnz    not_our_tape
  138.         cmp    si,0        ;Is it the Tape Device
  139.         jnz    not_our_tape
  140.         pop    ax
  141.         mov    al,3        ;Fail the System Call
  142.         iret
  143. not_our_tape:    pop    ax
  144.         jmp    cs:orig_int_24    ;Pass the Request On
  145. our_int_24    endp
  146.  
  147. ;
  148. ; Strategy Procedure
  149. ;
  150. disk_strategy    proc    far
  151.         mov    cs:rh_seg,es        ;Save Request Header Ptr Segment
  152.         mov    cs:rh_off,bx        ;Save Request Header Ptr Offset
  153.         mov    cs:rh_type,DISK_REQUEST
  154.         ret
  155. disk_strategy    endp
  156.  
  157. tape_strategy    proc    far
  158.         mov    cs:rh_seg,es        ;Save Request Header Ptr Segment
  159.         mov    cs:rh_off,bx        ;Save Request Header Ptr Offset
  160.         mov    cs:rh_type,TAPE_REQUEST
  161.         ret
  162. tape_strategy    endp
  163.  
  164. ;
  165. ; Interrupt Procedure
  166. ;
  167. dev_interrupt    proc    far
  168.         pushf                ;Save Machine State On Entry
  169.         cli
  170.         push    ds
  171.         push    es
  172.         push    ax
  173.         push    bx
  174.         push    cx
  175.         push    dx
  176.         push    si
  177.         push    di
  178.         push    bp
  179.  
  180.         mov    cs:stack_seg,ss        ;Save Old Stack
  181.         mov    cs:stack_ptr,sp
  182.  
  183.         mov    ax,cs            ;Save us the Segment Override Crap
  184.         mov    ds,ax
  185.         mov    es,ax
  186.  
  187.         mov    ss,ax            ;Setup Our Local Stack
  188.         lea    ax,new_stack_top
  189.         mov    sp,ax
  190.         sti                ;We're Safe Now
  191.  
  192. ;
  193. ; Perform branch based on the command passed in the Request Header
  194. ;
  195.         mov    es,rh_seg        ;Point us at the Request Header
  196.         mov    bx,rh_off
  197.  
  198.         mov    al,es:[bx].rh_cmd    ;Get Command Code
  199.         rol    al,1            ;Get offset into table
  200.         lea    di,cmdtab        ;Get address of command table
  201.         mov    ah,0            ;Clear hi order byte
  202.         add    di,ax            ;Add offset
  203.         jmp    word ptr [di]        ;Jump Indirect
  204.  
  205. ;
  206. ; Command Procedures
  207. ;
  208. INITIALIZATION:    cmp    rh_type,TAPE_REQUEST    ;Is this SCSITAPE: Init?
  209.         jz    init_skip
  210.         mov    al,es:[bx].rh0_drv_ltr    ;Save the starting Drive
  211.         add    al,041h
  212.         mov    cur_drive,al
  213.         call    initial            ;Setup
  214.         if use_kludge
  215.         call    patch_us_in
  216.         endif
  217.         mov    bx,rh_off
  218.         mov    es,rh_seg
  219. init_skip:    lea    ax,initial        ;Set The Break Address
  220.         mov    es:[bx].rh0_brk_ofs,ax
  221.         mov    es:[bx].rh0_brk_seg,cs
  222.         mov    al,disk_count        ;Number of Disk Devices Supported
  223.         mov    es:[bx].rh0_nunits,al
  224.         lea    dx,bpb_array        ;BPB Array
  225.         mov    es:[bx].rh0_bpb_tbo,dx
  226.         mov    es:[bx].rh0_bpb_tbs,cs
  227.         jmp    done
  228.  
  229. ;
  230. ; Has the Media Changed
  231. ;
  232. MEDIA_CHECK:    call    find_unit
  233.         jc    mc_jmp_err
  234.         mov    di,cur_unit
  235.         mov    al,[di].unit_mcheck    ;Get Initial Status
  236.         mov    [di].unit_mcheck,1    ;Always OK from then on
  237.         mov    es:[bx].rh1_md_stat,al
  238.         lea    dx,vol_id        ;Address of Volume ID
  239.         mov    es:[bx].rh1_volid_ofs,dx
  240.         mov    es:[bx].rh1_volid_seg,cs
  241.         jmp    done
  242. mc_jmp_err:    jmp    bad_unit
  243.  
  244. ;
  245. ; Get Disk Parameter Block
  246. ;
  247. GET_BPB:    call    find_unit
  248.         jc    get_jmp_err
  249.         mov    dx,cur_bpb        ;Address of BPB
  250.         mov    es:[bx].rh2_pbpbo,dx
  251.         mov    es:[bx].rh2_pbpbs,cs
  252.         jmp    done
  253. get_jmp_err:    jmp    bad_unit
  254.  
  255. ;
  256. ; Read some data from the disk/tape
  257. ;
  258. READ:        cmp    rh_type,DISK_REQUEST
  259.         jz    read_a_disk
  260.         mov    ax,tape_unit        ;Do We Have a Tape?
  261.         cmp    ax,-1
  262.         jz    read_jmp_err1
  263.         mov    cur_unit,ax
  264.         call    tape_read
  265.         jc    read_jmp_err2
  266.         jmp    done
  267. read_a_disk:    call    find_unit
  268.         jc    read_jmp_err1
  269.         call    disk_read
  270.         jc    read_jmp_err2
  271.         jmp    done
  272. read_jmp_err1:    jmp    bad_unit
  273. read_jmp_err2:    jmp    bad_read
  274.  
  275. ;
  276. ; Write some data to the disk/tape
  277. ;
  278. WRITE        equ    $
  279. WRITE_VERIFY:    cmp    rh_type,DISK_REQUEST
  280.         jz    write_a_disk
  281.         mov    ax,tape_unit        ;Do We Have a Tape?
  282.         cmp    ax,-1
  283.         jz    write_jmp_err1
  284.         mov    cur_unit,ax
  285.         call    tape_write
  286.         jc    write_jmp_err2
  287.         jmp    done
  288. write_a_disk:    call    find_unit
  289.         jc    write_jmp_err1
  290.         call    disk_write
  291.         jc    write_jmp_err2
  292.         jmp    done
  293. write_jmp_err1:    jmp    bad_unit
  294. write_jmp_err2:    jmp    bad_write
  295. write_jmp_err3:    jmp    unknown
  296.  
  297. ;
  298. ; Write Ioctl Packet
  299. ;
  300. WRITE_IOCTL:    cmp    rh_type,DISK_REQUEST
  301.         jz    ioctl_a_disk
  302.         mov    ax,tape_unit            ;Do we have a SCSITAPE?
  303.         cmp    ax,-1
  304.         jz    write_jmp_err1
  305.         mov    cur_unit,ax
  306.         jmp    short ioctl_do
  307. ioctl_a_disk:    call    find_unit
  308.         jc    write_jmp_err1
  309. ioctl_do:    call    scsi_ioctl_write
  310.         jc    write_jmp_err3
  311.         jmp    done
  312.  
  313. ;
  314. ; Special Control Functions
  315. ;
  316. IOCTL:        call    find_unit
  317.         jc    ioctl_jmp_err1
  318.         call    scsi_ioctl
  319.         jc    ioctl_jmp_err2        ;Must have been a Verify error
  320.         jmp    done
  321. ioctl_jmp_err1:    jmp    bad_unit
  322. ioctl_jmp_err2:    jmp    bad_read
  323.  
  324. ;
  325. ; Open Tape Device
  326. ;
  327. OPEN_DEV:    mov    di,tape_unit
  328.         cmp    di,-1            ;Do We have a SCSITAPE: Unit?
  329.         jnz    open_tape
  330.         jmp    bad_unit
  331. open_tape:    mov    cur_unit,di            ;New Current Unit
  332.         lea    bx,[di].unit_sense        ;Buffer Offset
  333.         push    ds                ;Buffer Segment
  334.         pop    es
  335.         mov    cx,size sense            ;Buffer Size
  336.         lea    di,cmd_sense            ;Command
  337.         call    docmd
  338.         jc    open_err
  339.         cmp    load_flag,TRUE            ;Should we LOAD?
  340.         jnz    open_ok
  341.         ife mini_inquire
  342.         mov    di,cur_unit            ;Check Unit Type
  343.         mov    ax,word ptr [di].unit_inq_buf.inq_manufact
  344.         lea    di,cmd_rewind            ;Default to Rewind
  345.         cmp    ax,'ET'                ;If this is a TEAC Unit
  346.         jz    open_rewind
  347.         endif
  348.         lea    di,cmd_load            ;Now Load Tape
  349.         mov    [di].load_cmd_type,LOAD_TAPE
  350. open_rewind:    call    docmd
  351.         jnc    open_ok
  352.         call    scsi_sense
  353. open_err:    jmp    general
  354. open_ok:    mov    write_flag,FALSE        ;No Writes Seen
  355.         mov    read_flag,FALSE            ;No Reads Seen
  356.         mov    error_flag,FALSE        ;No Error Yet
  357.         if use_kludge
  358.         mov    opened_flag,TRUE        ;We are Open
  359.         endif
  360.         mov    ax,0                ;Patch Ourselves into
  361.         mov    es,ax                ;the INT 24 Vector
  362.         mov    ax,es:[vect_int_24]        ;Offset
  363.         mov    word ptr orig_int_24,ax
  364.         lea    ax,our_int_24
  365.         mov    es:[vect_int_24],ax
  366.         mov    ax,es:[vect_int_24+2]        ;Segment
  367.         mov    word ptr orig_int_24+2,ax
  368.         mov    ax,cs
  369.         mov    es:[vect_int_24+2],ax
  370.         jmp    done
  371.  
  372. ;
  373. ; Close Tape Device
  374. ;
  375. CLOSE_DEV:    mov    di,tape_unit
  376.         cmp    di,-1        ;Do We have a SCSITAPE: Unit?
  377.         jnz    close_tape
  378.         jmp    bad_unit
  379. close_tape:    mov    ax,0                ;Restore
  380.         mov    es,ax                ;the INT 24 Vector
  381.         mov    word ptr orig_int_24,ax
  382.         mov    es:[vect_int_24],ax        ;Offset
  383.         mov    word ptr orig_int_24+2,ax
  384.         mov    es:[vect_int_24+2],ax        ;Segment
  385.         mov    cur_unit,di            ;New Current Unit
  386.         cmp    error_flag,TRUE            ;Any Tape Errors
  387.         jz    skip_extras
  388.         cmp    write_flag,TRUE            ;Were We Writing?
  389.         jnz    not_writing
  390.         lea    di,cmd_twritefm            ;End Tape with FM(s)
  391.         mov    [di].fm_cmd_cnt_b0,CLOSE_FM_CNT
  392.         call    docmd
  393.         jnc    skip_extras
  394.         call    get_sense
  395.         jmp    short skip_extras
  396. not_writing:    cmp    read_flag,TRUE            ;Were We Reading?
  397.         jnz    skip_extras
  398.         cmp    load_flag,TRUE            ;No Rewind?
  399.         jz    skip_extras
  400.         lea    di,cmd_space            ;Space Forward
  401.         mov    [di].space_cmd_code,1        ;By FileMark
  402.         mov    [di].space_cmd_cnt2,0
  403.         mov    [di].space_cmd_cnt1,0
  404.         mov    [di].space_cmd_cnt0,1
  405.         call    docmd
  406.         jnc    skip_extras
  407.         call    get_sense
  408. skip_extras:    cmp    load_flag,TRUE            ;Should we Unload?
  409.         jnz    close_ok    
  410.         ife mini_inquire
  411.         mov    di,cur_unit            ;Check Unit Type
  412.         mov    ax,word ptr [di].unit_inq_buf.inq_manufact
  413.         lea    di,cmd_rewind
  414.         cmp    ax,'ET'                ;Rewind instead of
  415.         jz    close_rewind            ;Unload TEAC Unit
  416.         endif
  417.         lea    di,cmd_load            ;Now Unload Tape
  418.         mov    [di].load_cmd_type,UNLOAD_TAPE
  419. close_rewind:    call    docmd
  420.         jnc    close_ok
  421.         call    scsi_sense
  422.         jmp    general
  423. close_ok:    jmp    done
  424.  
  425. ;
  426. ; Get Device Assignment
  427. ;
  428. GET_DEV:    mov    es:[bx].rh_unit,0
  429.         jmp    done
  430.  
  431. ;
  432. ; Set Device Assignment
  433. ;
  434. SET_DEV:    jmp    done
  435.  
  436. bad_unit:    mov    es,rh_seg        ;Point us at the Request Header
  437.         mov    bx,rh_off
  438.         or    es:[bx].rh_status,8001h
  439.         jmp    short done
  440.  
  441. unknown:    mov    es,rh_seg        ;Point us at the Request Header
  442.         mov    bx,rh_off
  443.         or    es:[bx].rh_status,8003h
  444.         jmp    short done
  445.  
  446. bad_write:    mov    es,rh_seg        ;Point us at the Request Header
  447.         mov    bx,rh_off
  448.         or    es:[bx].rh_status,800Ah
  449.         jmp    short done
  450.  
  451. bad_read:    mov    es,rh_seg        ;Point us at the Request Header
  452.         mov    bx,rh_off
  453.         or    es:[bx].rh_status,800Bh
  454.         jmp    short done
  455.  
  456. general:    mov    es,rh_seg        ;Point us at the Request Header
  457.         mov    bx,rh_off
  458.         or    es:[bx].rh_status,800Ch
  459.         jmp    short done
  460.  
  461. busy:        mov    es,rh_seg        ;Point us at the Request Header
  462.         mov    bx,rh_off
  463.         or    es:[bx].rh_status,0200h
  464.  
  465. done:        mov    es,rh_seg        ;Point us at the Request Header
  466.         mov    bx,rh_off
  467.         or    es:[bx].rh_status,0100h
  468.  
  469.         cli                ;Make sure we're left alone
  470.         mov    ax,cs:stack_seg        ;Restore DOS Stack
  471.         mov    ss,ax
  472.         mov    ax,cs:stack_ptr
  473.         mov    sp,ax
  474.  
  475.         pop    bp            ;Restore All Registers
  476.         pop    di
  477.         pop    si
  478.         pop    dx
  479.         pop    cx
  480.         pop    bx
  481.         pop    ax
  482.         pop    es
  483.         pop    ds
  484.         popf
  485.         ret
  486.  
  487.         INCLUDE    units.asm
  488.         INCLUDE    subs.asm
  489.         INCLUDE    ioctl.asm
  490.         INCLUDE    dump.asm
  491.         if use_kludge
  492.         INCLUDE    kludge.asm
  493.         endif
  494.  
  495. ;
  496. ; End of Program
  497. ; Stuff Placed Here Gets Handed Back To DOS For Re-use
  498. ;
  499. initial        proc    near
  500.         lea    dx,hello_msg        ;Tell them the driver version
  501.         call    puts
  502.         push    cs
  503.         pop    dx
  504.         lea    bx,seg_msg_value
  505.         call    hex2asc4
  506.         lea    dx,seg_msg        ;And Were We Loaded
  507.         call    puts
  508.  
  509.         call    scsi_reset        ;Reset the bus
  510.  
  511.         mov    cx,0            ;Scan for devices
  512. scan:        mov    ax,cx
  513.         add    al,030h
  514.         mov    scan_dev,al
  515.         mov    ax,1            ;Create Select Bit
  516.         shl    ax,cl
  517.         mov    di,cur_unit
  518.         mov    [di].unit_select,al
  519.         mov    [di].unit_num_drv,0    ;No Drives to start with
  520.         mov    al,disk_count        ;We will start with
  521.         mov    [di].unit_1st_drv,al    ;Drive Number if any
  522.  
  523.         lea    dx,scan_dev        ;Print the device number
  524.         call    puts
  525.         call    scsi_inquire        ;Inquire as to its type
  526.         jnc    scan_inq_ok
  527.  
  528.         lea    dx,no_dev        ;If the error was
  529.         cmp    al,CNOCONNECT        ;'No Such Device'
  530.         jz    puts_jmp
  531.  
  532.         lea    dx,dumb_disk_msg    ;Assume it is a 'SCSI I'
  533.         jmp    short scan_is_drv    ;Old style disk
  534.  
  535. scan_inq_ok:    mov    di,cur_unit
  536.         if mini_inquire
  537.         lea    dx,disk_dev_msg
  538.         else
  539.         lea    dx,[di].unit_inq_buf.inq_manufact
  540.         mov    [di].unit_inq_term,'$'
  541.         endif
  542.         mov    al,[di].unit_inq_buf.inq_dev_type
  543.         or    al,al            ;Look at device type
  544.         jz    scan_is_drv
  545.         if mini_inquire
  546.         lea    dx,tape_dev_msg
  547.         endif
  548.         cmp    tape_unit,-1        ;Do We Already Have A Tape?
  549.         jnz    puts_jmp
  550.         call    puts            ;Make this our SCSITAPE: Unit
  551.         mov    tape_unit,di
  552.         lea    dx,tape_msg
  553. puts_jmp:    jmp    scan_puts
  554.  
  555. scan_is_drv:    call    puts            ;Output the Device String
  556.         call    scsi_capacity        ;Inquire as to its size
  557.         lea    dx,err_size
  558.         jc    scan_puts        ;Do not use unknown drives
  559.         lea    dx,crlf
  560.         call    puts
  561.  
  562. scan_next_drv:    mov    di,cur_unit
  563.         mov    al,disk_count        ;Number Of Drives Found
  564.         inc    al
  565.         mov    disk_count,al
  566.         mov    al,[di].unit_num_drv    ;We have a valid Drive
  567.         inc    al
  568.         mov    [di].unit_num_drv,al
  569.         mov    al,cur_drive        ;Get Current Drive Letter
  570.         mov    drv_msg_let,al        ;Insert it in message
  571.         inc    al            ;Bump Drive Letter
  572.         mov    cur_drive,al
  573.         call    make_bpb        ;Setup the BPB for this drive
  574.         mov    di,cur_bpb        ;Current Working BPB
  575.         if large_drives
  576.         mov    dx,[di].bpb_ts_msw
  577.         mov    ax,[di].bpb_ts_lsw
  578.         else
  579.         mov    dx,0
  580.         mov    ax,[di].bpb_ts
  581.         endif
  582.         mov    bx,2048
  583.         div    bx
  584.         inc    ax
  585.         lea    bx,drv_msg_size
  586.         call    bin_ascii
  587.         mov    bx,bpb_hw_mark        ;Get the BPB High Water Mark
  588.         inc    bx            ;Bump HW Mark for next time
  589.         inc    bx
  590.         mov    ax,[bx]            ;Get the BPB
  591.         mov    cur_bpb,ax        ;Make it the current BPB
  592.         mov    bpb_hw_mark,bx
  593.         lea    dx,drv_msg
  594.         call    puts
  595.         ife large_drives
  596.         mov    bx,cur_unit
  597.         mov    ah,0
  598.         mov    al,[bx].unit_num_drv    ;Insert Drive Offset
  599.         dec    al            ;Into BPB for this Drive
  600.         mov    [di].bpb_hs_msw,ax
  601.         mov    al,[bx].unit_cap_buf.cap_sectors_b3
  602.         or    al,[bx].unit_cap_buf.cap_sectors_b2
  603.         or    al,[bx].unit_cap_buf.cap_sectors_b1
  604.         or    al,[bx].unit_cap_buf.cap_sectors_b0
  605.         jnz    scan_next_drv        ;Room left for another Drive
  606.         endif
  607.         jmp    short scan_next
  608.  
  609. scan_puts:    call    puts
  610.         lea    dx,crlf
  611.         call    puts
  612.  
  613. scan_next:    inc    cx
  614.         cmp    cx,MAXUNIT    ;End of devices?
  615.         jg    scan_exit
  616.         mov    bx,cx        ;Bump to next unit
  617.         shl    bx,1
  618.         mov    ax,word ptr unit_array[bx]
  619.         mov    cur_unit,ax
  620.         jmp    scan
  621.  
  622. scan_exit:    lea    dx,crlf
  623.         call    puts
  624.         ret
  625. initial        endp
  626.  
  627. ;
  628. ; Data Area Used Only During Initialization
  629. ;
  630. hello_msg    db    0dh,0ah,'SCSI Device Driver Version 2.0, '
  631.         if oldcode
  632.         db    '8086 Flavor',0Dh,0Ah,'$'
  633.         else
  634.         db    '80286 Flavor',0Dh,0Ah,'$'
  635.         endif
  636. seg_msg        db    'Driver Loaded At Segment '
  637. seg_msg_value    db    '0000',0dh,0ah,'$'
  638. scan_dev    db    'X - ','$'
  639. no_dev        db    '(No Installed Device)$'
  640. err_size    db    '(Unknown Size)$'
  641. drv_msg        db    '  - Drive '
  642. drv_msg_let    db    'X: '
  643. drv_msg_size    db    'XXXXXX Meg',0dh,0ah,'$'
  644. tape_msg    db    0dh,0ah,'  - Is The SCSITAPE: Device$'
  645. dumb_disk_msg    db    'UNKNOWN DUMB DISK $'
  646. crlf        db    0dh,0ah,'$'
  647.         if mini_inquire
  648. disk_dev_msg    db    'Disk Device $'
  649. tape_dev_msg    db    'Tape Device $'
  650.         endif
  651.  
  652.  
  653. dev_interrupt    endp
  654. _TEXT        ends
  655.         end
  656.