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

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