home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / st01driv.lzh / st01.1 next >
Encoding:
Text File  |  1990-10-12  |  44.0 KB  |  1,752 lines

  1.  
  2. #!/bin/sh
  3. # This is ST01SCSI.12, a shell archive (produced by shar 3.49)
  4. # To extract the files from this archive, save it to a file, remove
  5. # everything above the "!/bin/sh" line above, and type "sh file_name".
  6. #
  7. # made 09/25/1990 02:47 UTC by briana@tau-ceti.isc-br.com
  8. # Source directory /u/briana/scsi/scsi-1.2
  9. #
  10. # existing files will NOT be overwritten unless -c is specified
  11. #
  12. # This shar contains:
  13. # length  mode       name
  14. # ------ ---------- ------------------------------------------
  15. #    497 -rw-r--r-- binmode.c
  16. #   1296 -rw-r--r-- dump.asm
  17. #   3921 -rw-r--r-- equ.inc
  18. #   3256 -rw-r--r-- ioctl.asm
  19. #   2417 -rw-r--r-- kludge.asm
  20. #    506 -rw-r--r-- makefile
  21. #   2744 -rw-r--r-- mt.c
  22. #   1165 -rw-r--r-- options.inc
  23. #   2706 -rw-r--r-- readme.10
  24. #   2983 -rw-r--r-- readme.11
  25. #   1210 -rw-r--r-- readme.12
  26. #  11458 -rw-r--r-- scsi.asm
  27. #   2518 -rw-r--r-- scsi.sys
  28. #   1931 -rw-r--r-- sformat.c
  29. #   7166 -rw-r--r-- struct.inc
  30. #  15830 -rw-r--r-- subs.asm
  31. #   3322 -rw-r--r-- units.asm
  32. #
  33. # ============= binmode.c ==============
  34. if test -f 'binmode.c' -a X"$1" != X"-c"; then
  35.     echo 'x - skipping binmode.c (File already exists)'
  36. else
  37. echo 'x - extracting binmode.c (Text)'
  38. sed 's/^X//' << 'SHAR_EOF' > 'binmode.c' &&
  39. X#ifdef MSDOS
  40. X#include <dos.h>
  41. X
  42. Xbinmode(fd)
  43. Xint fd;
  44. X{
  45. X    union REGS inregs, outregs;
  46. X
  47. X    /*
  48. X    ** get the current mode
  49. X    */
  50. X    inregs.h.ah = 0x44;            /* ioctl */
  51. X    inregs.h.al = 0x00;            /* get */
  52. X    inregs.x.bx = fd;            /* unit */
  53. X    intdos(&inregs, &outregs);
  54. X
  55. X    /*
  56. X    ** set to BINARY mode (this works for char devices)
  57. X    */
  58. X    inregs.h.ah = 0x44;            /* ioctl */
  59. X    inregs.h.al = 0x01;            /* set */
  60. X    inregs.x.bx = fd;            /* unit */
  61. X    inregs.h.dh = 0;
  62. X    inregs.h.dl = outregs.h.dl | 0x20;
  63. X    intdos(&inregs, &outregs);
  64. X}
  65. X#endif
  66. SHAR_EOF
  67. chmod 0644 binmode.c ||
  68. echo 'restore of binmode.c failed'
  69. Wc_c="`wc -c < 'binmode.c'`"
  70. test 497 -eq "$Wc_c" ||
  71.     echo 'binmode.c: original size 497, current size' "$Wc_c"
  72. fi
  73. # ============= dump.asm ==============
  74. if test -f 'dump.asm' -a X"$1" != X"-c"; then
  75.     echo 'x - skipping dump.asm (File already exists)'
  76. else
  77. echo 'x - extracting dump.asm (Text)'
  78. sed 's/^X//' << 'SHAR_EOF' > 'dump.asm' &&
  79. X;
  80. X; Convert bin (ax) to ascii (bx => buffer)
  81. X;
  82. Xbin_ascii    proc    near
  83. X        pusha
  84. X        push    ax
  85. X        mov    cx,6
  86. Xfill_buff:    mov    byte ptr [bx],' '
  87. X        inc    bx
  88. X        loop    fill_buff
  89. X        mov    si,10
  90. X        or    ax,ax
  91. X        jns    clr_dvd
  92. X        neg    ax
  93. Xclr_dvd:    sub    dx,dx
  94. X        div    si
  95. X        add    dx,'0'
  96. X        dec    bx
  97. X        mov    [bx],dl
  98. X        inc    cx
  99. X        or    ax,ax
  100. X        jnz    clr_dvd
  101. X        pop    ax
  102. X        or    ax,ax
  103. X        jns    no_more
  104. X        dec    bx
  105. X        mov    byte ptr [bx],'-'
  106. Xno_more:    popa
  107. X        ret
  108. Xbin_ascii    endp
  109. X
  110. X;
  111. X; Convert Hex (dx) to Ascii (bx => buffer)
  112. X;
  113. Xhex2asc4    proc    near
  114. X        push    cx
  115. X        push    ax
  116. X        mov    cx,4        ;Do Four Digits
  117. Xh241:        rol    dx,4
  118. X        mov    al,dl        ;Get the Current Digit
  119. X        and    al,0Fh
  120. X        cmp    al,0Ah        ;Is It Hex?
  121. X        jge    h242
  122. X        add    al,30h        ;Normal Digit
  123. X        jmp    h243
  124. Xh242:        add    al,37h        ;Hex Digit
  125. Xh243:        mov    [bx],al        ;Insert in Buffer
  126. X        inc    bx
  127. X        loop    h241
  128. X        pop    ax
  129. X        pop    cx
  130. X        ret
  131. Xhex2asc4    endp
  132. X
  133. X;
  134. X; Convert Hex (dl) to Ascii (bx => buffer)
  135. X;
  136. Xhex2asc2    proc    near
  137. X        push    cx
  138. X        push    ax
  139. X        mov    cx,2        ;Do Two Digits
  140. Xh221:        rol    dl,4
  141. X        mov    al,dl        ;Get the Current Digit
  142. X        and    al,0Fh
  143. X        cmp    al,0Ah        ;Is It Hex?
  144. X        jge    h222
  145. X        add    al,30h        ;Normal Digit
  146. X        jmp    h223
  147. Xh222:        add    al,37h        ;Hex Digit
  148. Xh223:        mov    [bx],al        ;Insert in Buffer
  149. X        inc    bx
  150. X        loop    h221
  151. X        pop    ax
  152. X        pop    cx
  153. X        ret
  154. Xhex2asc2    endp
  155. X
  156. X;
  157. X; Print a string
  158. X;
  159. X; ds:dx => string
  160. X;
  161. Xputs        proc    near
  162. X        pusha
  163. X        mov    ah,9        ;DOS print string
  164. X        int    21h
  165. X        popa
  166. X        ret
  167. Xputs        endp
  168. SHAR_EOF
  169. chmod 0644 dump.asm ||
  170. echo 'restore of dump.asm failed'
  171. Wc_c="`wc -c < 'dump.asm'`"
  172. test 1296 -eq "$Wc_c" ||
  173.     echo 'dump.asm: original size 1296, current size' "$Wc_c"
  174. fi
  175. # ============= equ.inc ==============
  176. if test -f 'equ.inc' -a X"$1" != X"-c"; then
  177.     echo 'x - skipping equ.inc (File already exists)'
  178. else
  179. echo 'x - extracting equ.inc (Text)'
  180. sed 's/^X//' << 'SHAR_EOF' > 'equ.inc' &&
  181. X;
  182. X; Equates
  183. X;
  184. XTRUE        EQU    001h
  185. XFALSE        EQU    000h
  186. X
  187. XDISK_REQUEST    EQU    000h        ;Disk I/O Request
  188. XTAPE_REQUEST    EQU    001h        ;Tape I/O Request
  189. X
  190. X;
  191. X; ST-01 Card Registers
  192. X;
  193. XSCSI_CARD_SEG    EQU    0DE00h        ;Base Segment of Card
  194. XSCSI_CMD_PORT    EQU    01A00h        ;Offset to Command Port
  195. XSCSI_DATA_PORT    EQU    01C00h        ;Offset to Data Port
  196. X
  197. XSTACK_SIZE    EQU    512        ;Our Local Stack
  198. X
  199. X;
  200. X; How the 16 bit sector number is broken down
  201. X; into a sector and cylinder number.
  202. X;
  203. X; x = Cylinder, y = track, always have only 1 head
  204. X;
  205. X; xxxx xxxx xxxx yyyy
  206. X;
  207. X; SECT_2_FS is computed as: ((unit_bpb.bpb_ts / CLUSTSIZE) * 2) / P_SECT)
  208. X;
  209. XSECT_TRACK    EQU    16        ;Logical Sectors in a Track
  210. XSECT_MASK    EQU    0000Fh        ;Mask for Sector
  211. XCYL_MASK    EQU    0FFF0h        ;Mask for Cylinder
  212. XSECT_2_CYL    EQU    4        ;How far to shift to convert
  213. X                    ;Sector to Cylinder Number
  214. XSECT_2_FS    EQU    10        ;How far to shift for
  215. X                    ;Total Sectors to Fat Sectors
  216. X
  217. X;
  218. X; The max target to check for (0-X).
  219. X; If using 'reserve_addr', this should not execede 6!
  220. X;
  221. XMAXUNIT        EQU    6        ;Maximum Unit Number
  222. X
  223. XP_SECT        EQU    512        ;Physical Sector Size
  224. XCLUSTSIZE    EQU    4        ;Number of Sectors to a Cluster
  225. X
  226. X;
  227. X; For multi_sector reads and writes,
  228. X; set the following to '1'
  229. X;
  230. X; CHUNK_MASK is the maximum number of sectors to access in one
  231. X; SCSI request.  It MUST be a power of two, and CHUNK_MASK * P_SECT
  232. X; MUST be <= 64K to prevent segment wrap problems.
  233. X;
  234. XCHUNK_MAX    EQU    32
  235. X
  236. XCMDENABLE    EQU    080h        ;Enable the output drivers
  237. XCMDENINTR    EQU    040h        ;Enable Interrupt
  238. XCMDPARITY    EQU    020h        ;Enable Parity
  239. XCMDSTARB    EQU    010h        ;Start Bus Arbitration
  240. XCMDATTN        EQU    008h        ;Assert ATTN
  241. XCMDBSY        EQU    004h        ;Assert BSY
  242. XCMDSEL        EQU    002h        ;Assert SEL
  243. XCMDRST        EQU    001h        ;Assert RST
  244. X
  245. X        if scsi_parity
  246. XCMDBASE        EQU    CMDPARITY    ;Base value of all commands
  247. X        else
  248. XCMDBASE        EQU    000h        ;Base value of all commands
  249. X        endif
  250. X
  251. XSTARBCOMPL    EQU    080h        ;Arbitration Complete
  252. XSTPARERR    EQU    040h        ;Parity Error
  253. XSTSEL        EQU    020h        ;SEL Asserted
  254. XSTREQ        EQU    010h        ;REQ Asserted
  255. XSTCD        EQU    008h        ;C/D Asserted
  256. XSTIO        EQU    004h        ;I/O Asserted
  257. XSTMSG        EQU    002h        ;MSG Asserted
  258. XSTBSY        EQU    001h        ;BSY Asserted
  259. X
  260. XFREE_MASK    EQU    03Fh
  261. X
  262. XREQ_MASK    EQU    STMSG or STCD or STIO
  263. XREQ_DATAOUT    EQU    000h        ;Data Out Phase
  264. XREQ_DATAIN    EQU    STIO        ;Data In Phase
  265. XREQ_CMDOUT    EQU    STCD        ;Command Out Phase
  266. XREQ_STATIN    EQU    STCD or STIO    ;Status In Phase
  267. XREQ_MSGOUT    EQU    STMSG or STCD    ;Msg Out Phase
  268. XREQ_MSGIN    EQU    STMSG or STCD or STIO    ;Msg In Phase
  269. X
  270. XCOK        EQU    0        ;Command Completed OK
  271. XCNOCONNECT    EQU    1        ;Unable to Connect to Target
  272. XCBUSBUSY    EQU    2        ;Bus Busy
  273. XCTIMEOUT    EQU    3        ;Timeout waiting for Response
  274. XCERROR        EQU    4        ;Target Return Error
  275. XCBUSY        EQU    5        ;Target was Busy
  276. XCDISCONNECT    EQU    6        ;Target Disconnected
  277. X
  278. XSCSI_TESTREADY    EQU    000h        ;Test Unit Ready (6 byte)
  279. XSCSI_REWIND    EQU    001h        ;Rewind (6 byte)
  280. XSCSI_REQSENSE    EQU    003h        ;Request Sense (6 byte)
  281. XSCSI_FORMATUNIT    EQU    004h        ;Format Disk (6 byte)
  282. XSCSI_WRITEFM    EQU    010h        ;Write File Marks (6 byte)
  283. XSCSI_SPACE    EQU    011h        ;Space Tape (6 byte)
  284. XSCSI_INQUIRY    EQU    012h        ;Inquire (6 byte)
  285. XSCSI_MODE_SET    EQU    015h        ;Mode Select (6 byte)
  286. XSCSI_ERASE    EQU    019h        ;Erase Tape (6 byte)
  287. XSCSI_MODE_GET    EQU    01Ah        ;Mode Sense (6 byte)
  288. XSCSI_LOAD    EQU    01Bh        ;Load / Unload Tape (6 byte)
  289. XSCSI_READSIZE    EQU    025h        ;Read Drive Capacity (10 byte)
  290. X        if extended_io
  291. XSCSI_READBLK    EQU    028h        ;Read Sectors (10 byte)
  292. XSCSI_WRITEBLK    EQU    02Ah        ;Write Sectors (10 byte)
  293. X        else
  294. XSCSI_READBLK    EQU    008h        ;Read Sectors (6 byte)
  295. XSCSI_WRITEBLK    EQU    00Ah        ;Write Sectors (6 byte)
  296. X        endif
  297. XSCSI_VERIFYBLK    EQU    02Fh        ;Verify Blocks (10 byte)
  298. X
  299. XMSG_COMPLETE    EQU    000h        ;Command is Complete
  300. XMSG_SAVE    EQU    002h        ;Save Data Pointers
  301. XMSG_RESTORE    EQU    003h        ;Restore Data Pointers
  302. XMSG_ERROR    EQU    005h        ;Error Detected
  303. XMSG_ABORT    EQU    006h        ;Abort the Command
  304. XMSG_REJECT    EQU    007h        ;Reject the Command
  305. XMSG_NOP        EQU    008h        ;No Operation
  306. XMSG_IDENTIFY    EQU    080h        ;Identify Yourself
  307. X
  308. XLOAD_TAPE    EQU    001h        ;Load
  309. XUNLOAD_TAPE    EQU    000h        ;Unload
  310. X
  311. X;
  312. X; We write one filemark at the end of a tape
  313. X; so that we can space forward over stuff.
  314. X;
  315. XCLOSE_FM_CNT    EQU    001h
  316. SHAR_EOF
  317. chmod 0644 equ.inc ||
  318. echo 'restore of equ.inc failed'
  319. Wc_c="`wc -c < 'equ.inc'`"
  320. test 3921 -eq "$Wc_c" ||
  321.     echo 'equ.inc: original size 3921, current size' "$Wc_c"
  322. fi
  323. # ============= ioctl.asm ==============
  324. if test -f 'ioctl.asm' -a X"$1" != X"-c"; then
  325.     echo 'x - skipping ioctl.asm (File already exists)'
  326. else
  327. echo 'x - extracting ioctl.asm (Text)'
  328. sed 's/^X//' << 'SHAR_EOF' > 'ioctl.asm' &&
  329. X;
  330. X; Process an ioctl request for the current unit
  331. X;
  332. X; return 'C' on error
  333. X;
  334. Xscsi_ioctl    proc
  335. X        mov    al,es:[bx].rh19_minor        ;Get the minor number
  336. X
  337. X        cmp    al,40h                ;Set Device Params?
  338. X        jnz    scsi_i_42h
  339. X        clc
  340. X        jmp    short scsi_i_exit
  341. X
  342. Xscsi_i_42h:    cmp    al,42h                ;Format and Verify?
  343. X        jnz    scsi_i_60h
  344. X        call    scsi_verify
  345. X        jmp    short scsi_i_exit
  346. X
  347. Xscsi_i_60h:    cmp    al,60h                ;Get Device Params?
  348. X        jnz    scsi_i_62h
  349. X        mov    si,cur_bpb            ;Get the Current BPB
  350. X        mov    di,es:[bx].rh19_buf_ofs        ;Get the Param Buffer
  351. X        mov    ax,es:[bx].rh19_buf_seg
  352. X        mov    es,ax
  353. X        mov    es:[di].dpb_special,05h        ;Sect Same/Use Cur BPB
  354. X        mov    es:[di].dpb_type,05h        ;Fixed Disk
  355. X        mov    es:[di].dpb_attr,0001h        ;Not Removable
  356. X        mov    ax,[si].bpb_ts
  357. X        shr    ax,SECT_2_CYL            ;Convert Sect to Cyl
  358. X        mov    es:[di].dpb_cyl,ax
  359. X        mov    es:[di].dpb_media,0        ;????
  360. X        mov    es:[di].dpb_sectors,SECT_TRACK    ;Sectors per Track
  361. X
  362. X        push    di
  363. X        lea    di,es:[di].dpb_bpb        ;Copy the bpb into
  364. X        mov    cx,size bpb            ;the requestors buffer
  365. X        cld
  366. X    rep    movsb
  367. X        pop    di
  368. X
  369. X        lea    di,es:[di].dpb_track        ;Build the Track List
  370. X        mov    cx,SECT_TRACK
  371. X        mov    ax,0                ;Start with Sector 0
  372. Xscsi_i_t_loop:    mov    es:[di],ax            ;Sector Number
  373. X        inc    ax
  374. X        inc    di
  375. X        inc    di
  376. X        mov    word ptr es:[di],P_SECT        ;Sector Size
  377. X        inc    di
  378. X        inc    di
  379. X        loop    scsi_i_t_loop
  380. X        clc
  381. X        jmp    short scsi_i_exit
  382. X
  383. Xscsi_i_62h:    cmp    al,62h                ;Verify?
  384. X        jnz    scsi_i_error
  385. X        call    scsi_verify
  386. X        jmp    short scsi_i_exit
  387. X
  388. Xscsi_i_error:    stc
  389. Xscsi_i_exit:    ret
  390. Xscsi_ioctl    endp
  391. X
  392. X;
  393. X; Process an ioctl_write request
  394. X;
  395. Xscsi_ioctl_write proc
  396. X        mov    di,es:[bx].rh12_buf_ofs        ;Get The Command
  397. X        mov    ax,es:[bx].rh12_buf_seg        ;Buffer
  398. X        mov    es,ax
  399. X        mov    ax,es:[di].ioc_command        ;What Command
  400. X
  401. X;
  402. X; Format Disk Unit
  403. X;
  404. X        cmp    al,'F'                ;Format?
  405. X        jnz    try_erase
  406. X        mov    ax,es:[di].ioc_param1        ;Get Interleave
  407. X        lea    di,cmd_format            ;Insert into Command
  408. X        mov    [di].fmt_cmd_il_b1,ah
  409. X        mov    [di].fmt_cmd_il_b0,al
  410. X        call    docmd
  411. X        jnc    format_exit
  412. X        call    scsi_sense
  413. Xformat_exit:    jmp    scsi_i_w_exit
  414. X
  415. X;
  416. X; Erase Tape Unit
  417. X;
  418. Xtry_erase:    cmp    al,'E'                ;Erase?
  419. X        jnz    try_rewind
  420. X        lea    di,cmd_erase            ;Now Erase Tape
  421. X        call    docmd
  422. X        jnc    scsi_i_w_exit
  423. X        call    scsi_sense
  424. X        jmp    scsi_i_w_error
  425. X
  426. X;
  427. X; Rewind Tape Unit
  428. X;
  429. Xtry_rewind:    cmp    al,'R'                ;Rewind?
  430. X        jnz    try_load
  431. X        lea    di,cmd_rewind            ;Now Rewind Tape
  432. X        call    docmd
  433. X        jnc    scsi_i_w_exit
  434. X        call    scsi_sense
  435. X        jmp    scsi_i_w_error
  436. X
  437. X;
  438. X; Load Tape on Open
  439. X;
  440. Xtry_load:    cmp    al,'L'                ;Load?
  441. X        jnz    try_noload
  442. X        mov    load_flag,TRUE
  443. X        jmp    scsi_i_w_exit
  444. X
  445. X;
  446. X; No Load Tape on Open
  447. X;
  448. Xtry_noload:    cmp    al,'N'                ;No Load?
  449. X        jnz    try_space
  450. X        mov    load_flag,FALSE
  451. X        jmp    scsi_i_w_exit
  452. X
  453. X;
  454. X; Space Tape
  455. X;
  456. Xtry_space:    cmp    al,'S'                ;Space?
  457. X        jnz    try_filemark
  458. X        mov    ax,es:[di].ioc_param1        ;Get Count
  459. X        mov    bx,es:[di].ioc_param2        ;Get Type
  460. X        lea    di,cmd_space            ;Insert into Command
  461. X        mov    [di].space_cmd_code,bl
  462. X        mov    [di].space_cmd_cnt2,ah        ;Dup of ah
  463. X        mov    [di].space_cmd_cnt1,ah
  464. X        mov    [di].space_cmd_cnt0,al
  465. X        call    docmd
  466. X        jnc    scsi_i_w_exit
  467. X        call    scsi_sense
  468. X        jmp    scsi_i_w_exit
  469. X
  470. X;
  471. X; Write Filemarks
  472. X;
  473. Xtry_filemark:    cmp    al,'M'                ;Mark?
  474. X        jnz    scsi_i_w_error
  475. X        mov    ax,es:[di].ioc_param1        ;Get Count
  476. X        lea    di,cmd_twritefm            ;Insert into Command
  477. X        mov    [di].fm_cmd_cnt_b1,ah
  478. X        mov    [di].fm_cmd_cnt_b0,al
  479. X        call    docmd
  480. X        jnc    scsi_i_w_exit
  481. X        call    scsi_sense
  482. X        jmp    scsi_i_w_exit
  483. X
  484. Xscsi_i_w_error:    stc
  485. Xscsi_i_w_exit:    ret
  486. Xscsi_ioctl_write endp
  487. SHAR_EOF
  488. chmod 0644 ioctl.asm ||
  489. echo 'restore of ioctl.asm failed'
  490. Wc_c="`wc -c < 'ioctl.asm'`"
  491. test 3256 -eq "$Wc_c" ||
  492.     echo 'ioctl.asm: original size 3256, current size' "$Wc_c"
  493. fi
  494. # ============= kludge.asm ==============
  495. if test -f 'kludge.asm' -a X"$1" != X"-c"; then
  496.     echo 'x - skipping kludge.asm (File already exists)'
  497. else
  498. echo 'x - extracting kludge.asm (Text)'
  499. sed 's/^X//' << 'SHAR_EOF' > 'kludge.asm' &&
  500. X;
  501. X; This code is needed because DOS insists on opening a char device
  502. X; in cooked mode.  The problem is that without adding code to every
  503. X; application that would ever use us, we have no way to alter this
  504. X; because the use of O_BINARY or setmode() do not affect char devices.
  505. X;
  506. X; The solution (kludge) is to watch open requests issued thru the
  507. X; INT 21 vector.  If we see a open request followed by a OPEN_DEV
  508. X; call to us, it must have been an open for us.  So during the return,
  509. X; force a call to the ioctl facility that will switch to raw mode.
  510. X;
  511. X
  512. X;
  513. X; The Original INT 21 Vector
  514. X;
  515. Xvect_int_21    equ    word ptr 4 * 21h
  516. Xorig_int_21    dd    ?            ;Original INT 21 Vector
  517. X
  518. X;
  519. X; OPEN_DEV flag is TRUE when we are opened
  520. X;
  521. Xopened_flag    db    FALSE
  522. X
  523. Xpatch_us_in    proc    near
  524. X        push    es
  525. X        push    ax
  526. X        mov    ax,0            ;Patch Ourselves into
  527. X        mov    es,ax            ;the INT 21 Vector
  528. X        mov    ax,es:[vect_int_21]    ;Offset
  529. X        mov    word ptr orig_int_21,ax
  530. X        lea    ax,our_int_21
  531. X        mov    es:[vect_int_21],ax
  532. X        mov    ax,es:[vect_int_21+2]    ;Segment
  533. X        mov    word ptr orig_int_21+2,ax
  534. X        mov    ax,cs
  535. X        mov    es:[vect_int_21+2],ax
  536. X        pop    ax
  537. X        pop    es
  538. X        ret
  539. Xpatch_us_in    endp
  540. X
  541. Xour_int_21    proc    far
  542. X        pushf                ;Save entry flags
  543. X        cmp    ah,3Dh            ;Is it an open request?
  544. X        jnz    not_open_req
  545. X        popf                ;Restore entry flags
  546. X;
  547. X; We need to set things up so the 'iret' done by the INT 21
  548. X; code will have some the right stuff on the stack.
  549. X; #1 Flags with interrupts enabled
  550. X; #2 Return Address
  551. X;
  552. X        sti                ;Allow interrupts
  553. X        pushf                ;After the iret
  554. X        cli                ;Shut interrupts off
  555. X        call    cs:orig_int_21        ;While we Pass the request on
  556. X;
  557. X; Upon return, interrupts are enabled, so shut them off while we work
  558. X;
  559. X        pushf
  560. X        cli
  561. X        cmp    cs:opened_flag,FALSE    ;Was it an open for us?
  562. X        jz    not_our_open
  563. X        mov    cs:opened_flag,FALSE    ;Clear for next time
  564. X;
  565. X; We need to forge a call to the ioctl interface
  566. X; to switch DOS to raw mode when it talks to us
  567. X;
  568. X        pusha
  569. X        mov    bx,ax            ;Save the Handle
  570. X        mov    ax,4400h        ;Get Device Information
  571. X        pushf
  572. X        call    cs:orig_int_21
  573. X        mov    dh,0            ;Setup
  574. X        or    dl,20h            ;for RAW Mode
  575. X        mov    ax,4401h        ;Set Device Information
  576. X        pushf
  577. X        call    cs:orig_int_21
  578. X        popa
  579. X
  580. Xnot_our_open:    popf                ;The Original Flags to return
  581. X;
  582. X; When we return, we need to pop the flags that the original INT 21
  583. X; call left on the stack, and return the flags we got back
  584. X;
  585. X        ret    2            ;Return and discard flags
  586. X
  587. Xnot_open_req:    popf                ;Pop the saved flags
  588. X        jmp    cs:orig_int_21        ;Continue with original code
  589. Xour_int_21    endp
  590. SHAR_EOF
  591. chmod 0644 kludge.asm ||
  592. echo 'restore of kludge.asm failed'
  593. Wc_c="`wc -c < 'kludge.asm'`"
  594. test 2417 -eq "$Wc_c" ||
  595.     echo 'kludge.asm: original size 2417, current size' "$Wc_c"
  596. fi
  597. # ============= makefile ==============
  598. if test -f 'makefile' -a X"$1" != X"-c"; then
  599.     echo 'x - skipping makefile (File already exists)'
  600. else
  601. echo 'x - extracting makefile (Text)'
  602. sed 's/^X//' << 'SHAR_EOF' > 'makefile' &&
  603. X#
  604. X# SCSI Stuff
  605. X#
  606. XSRCS = scsi.asm subs.asm ioctl.asm dump.asm units.asm kludge.asm \
  607. X       options.inc equ.inc struct.inc
  608. X
  609. Xall: scsi.sys sformat.exe mt.exe
  610. X
  611. X#
  612. X# SCSI Disk Device Driver
  613. X#
  614. Xscsi.sys: scsi.obj
  615. X    link +scsi.obj, scsi ;
  616. X    exe2bin scsi.exe scsi.sys
  617. X
  618. Xscsi.obj: $(SRCS)
  619. X    masm scsi.asm scsi.obj scsi.lst ;
  620. X
  621. X#
  622. X# SCSI Disk Formatter
  623. X#
  624. Xsformat.exe: sformat.c
  625. X    cl -G2 -Ox -o sformat.exe sformat.c
  626. X
  627. X#
  628. X# SCSI Tape Erase
  629. X#
  630. Xmt.exe: mt.c
  631. X    cl -G2 -Ox -o mt.exe mt.c
  632. X
  633. X#
  634. X# clean
  635. X#
  636. Xclean:
  637. X    rm -f *.exe *.obj *.lst
  638. SHAR_EOF
  639. chmod 0644 makefile ||
  640. echo 'restore of makefile failed'
  641. Wc_c="`wc -c < 'makefile'`"
  642. test 506 -eq "$Wc_c" ||
  643.     echo 'makefile: original size 506, current size' "$Wc_c"
  644. fi
  645. # ============= mt.c ==============
  646. if test -f 'mt.c' -a X"$1" != X"-c"; then
  647.     echo 'x - skipping mt.c (File already exists)'
  648. else
  649. echo 'x - extracting mt.c (Text)'
  650. sed 's/^X//' << 'SHAR_EOF' > 'mt.c' &&
  651. X/*
  652. X** SCSI Tape Control (Low Level)
  653. X**
  654. X** usage: mt [-e|r|l|n|s count|m count]
  655. X**
  656. X** Revision History:
  657. X**
  658. X** Version 1.0  09/09/90 Initial Release
  659. X**
  660. X*/
  661. X#include <stdio.h>
  662. X#include <fcntl.h>
  663. X#include <dos.h>
  664. X
  665. X#define TRUE (1)
  666. X#define FALSE (0)
  667. X#define VERSION "mt Version 1.0 BWA"
  668. X
  669. Xextern int _doserrno;
  670. X
  671. Xstruct cmd {
  672. X    short command;        /* command type */
  673. X    short arg1;            /* command args */
  674. X    short arg2;            /* command args */
  675. X} ioctl_data;
  676. Xunion REGS inregs, outregs;
  677. Xstruct SREGS segregs;
  678. Xint fd;
  679. Xchar *device = "SCSITAPE", *operation = NULL;
  680. Xchar far *cp;
  681. X
  682. Xmain(argc, argv)
  683. Xint argc;
  684. Xchar *argv[];
  685. X{
  686. X    /*
  687. X    ** say hello
  688. X    */
  689. X    puts(VERSION);
  690. X    switch ( argc )
  691. X    {
  692. X        case 3:
  693. X        if (argv[1][0] != '-' || argv[1][2] != 0) usage();
  694. X        switch( argv[1][1] )
  695. X        {
  696. X            case 's':
  697. X            ioctl_data.command = 'S';
  698. X            ioctl_data.arg1 = atoi(argv[2]);
  699. X            ioctl_data.arg2 = 1;        /* space by filemark */
  700. X            if (ioctl_data.arg1 > 0)
  701. X                operation = "space forward";
  702. X            else if (ioctl_data.arg1 < 0)
  703. X                operation = "space backward";
  704. X            else
  705. X            {
  706. X                operation = "space EOD";
  707. X                ioctl_data.arg2 = 3;    /* space to EOD */
  708. X            }
  709. X            break;
  710. X
  711. X            case 'm':
  712. X            ioctl_data.command = 'M';
  713. X            ioctl_data.arg1 = atoi(argv[2]);
  714. X            operation = "filemark";
  715. X            break;
  716. X
  717. X            default:
  718. X            usage();
  719. X            break;
  720. X        }
  721. X        break;
  722. X
  723. X        case 2:
  724. X        if (argv[1][0] != '-' || argv[1][2] != 0) usage();
  725. X        switch( argv[1][1] )
  726. X        {
  727. X            case 'e':
  728. X            /*
  729. X            ** verify that this is what the user really wants to do
  730. X            */
  731. X            printf("Do you really wish to erase the tape\n");
  732. X            printf("contained in the SCSITAPE unit (y,n)? ");
  733. X            fflush(stdout);
  734. X            if ( getchar() != 'y' )
  735. X            {
  736. X                printf("Aborting ....\n");
  737. X                exit(1);
  738. X            }
  739. X            operation = "erase";
  740. X            ioctl_data.command = 'E';
  741. X            break;
  742. X
  743. X            case 'r':
  744. X            operation = "rewind";
  745. X            ioctl_data.command = 'R';
  746. X            break;
  747. X
  748. X            case 'l':
  749. X            operation = "load enable";
  750. X            ioctl_data.command = 'L';
  751. X            break;
  752. X
  753. X            case 'n':
  754. X            operation = "load disable";
  755. X            ioctl_data.command = 'N';
  756. X            break;
  757. X
  758. X            default:
  759. X            usage();
  760. X            break;
  761. X        }
  762. X        break;
  763. X
  764. X        default:
  765. X        usage();
  766. X        break;
  767. X    }
  768. X
  769. X    /*
  770. X    ** put together the command
  771. X    */
  772. X    fd = open(device, O_WRONLY);
  773. X    if ( fd < 0 )
  774. X    {
  775. X        perror(device);
  776. X        exit(1);
  777. X    }
  778. X    inregs.h.ah = 0x44;            /* ioctl */
  779. X    inregs.h.al = 0x03;            /* write */
  780. X    inregs.x.bx = fd;            /* unit */
  781. X    inregs.x.cx = sizeof(struct cmd);
  782. X    cp = (char *) &ioctl_data;
  783. X    inregs.x.dx = FP_OFF(cp);
  784. X    segregs.ds = FP_SEG(cp);
  785. X
  786. X    /*
  787. X    ** start the format
  788. X    */
  789. X    printf("Now performing %s command ....\n", operation);
  790. X    puts("Please wait ....");
  791. X    intdosx(&inregs, &outregs, &segregs);
  792. X
  793. X    /*
  794. X    ** see what happened
  795. X    */
  796. X    if ( outregs.x.cflag )
  797. X        printf("DOS error %d occured during %s.\n", _doserrno, operation);
  798. X    close(fd);
  799. X    exit(0);
  800. X}
  801. X
  802. Xusage()
  803. X{
  804. X    puts("usage: mt [-e|r|l|n|s count|m count]");
  805. X    exit(1);
  806. X}
  807. SHAR_EOF
  808. chmod 0644 mt.c ||
  809. echo 'restore of mt.c failed'
  810. Wc_c="`wc -c < 'mt.c'`"
  811. test 2744 -eq "$Wc_c" ||
  812.     echo 'mt.c: original size 2744, current size' "$Wc_c"
  813. fi
  814. # ============= options.inc ==============
  815. if test -f 'options.inc' -a X"$1" != X"-c"; then
  816.     echo 'x - skipping options.inc (File already exists)'
  817. else
  818. echo 'x - extracting options.inc (Text)'
  819. sed 's/^X//' << 'SHAR_EOF' > 'options.inc' &&
  820. X;
  821. X; Allow multi_sector reads and writes.
  822. X;
  823. X; This means that a read request of less then CHUNK_MAX
  824. X; sectors will be done in one request to the drive rather
  825. X; then multiple single sector requests.
  826. X;
  827. X; The disadvantage here is that the code in receive_data()
  828. X; and send_data() must keep the transfer from exceding the
  829. X; 512 byte buffer on the ST-01 card.
  830. X;
  831. Xmulti_sector    =    1    ;Enable multi_sector support
  832. X
  833. X;
  834. X; Use the extended SCSI commands for reads and writes.
  835. X;
  836. X; This means that we can access drives larger then 1Gb
  837. X; and read/write more then 256 sectors per command.
  838. X;
  839. X; The disadvantage here is that not all devices support
  840. X; the extended command set.
  841. X;
  842. Xextended_io    =    0    ;Disable use of extended io commands
  843. X
  844. X;
  845. X; Use parity on the SCSI bus
  846. X;
  847. Xscsi_parity    =    1    ;Enable use of parity on the SCSI bus
  848. X
  849. X;
  850. X; Reserve SCSI Address 7 for card
  851. X;
  852. Xreserve_addr    =    1    ;Reserve Address for Card Use
  853. X
  854. X;
  855. X; Dump Sense information to the screen
  856. X;
  857. Xdump_sense    =    1    ;Dump Sense Message to the Screen
  858. X
  859. X;
  860. X; Extended Sense or Normal Sense
  861. X;
  862. Xextended_sense    =    1    ;Request Extended Sense
  863. X
  864. X;
  865. X; Include the code to kludge the RAW ioctl call after an open
  866. X;
  867. Xuse_kludge    =    1    ;Enable the ioctl kludge
  868. SHAR_EOF
  869. chmod 0644 options.inc ||
  870. echo 'restore of options.inc failed'
  871. Wc_c="`wc -c < 'options.inc'`"
  872. test 1165 -eq "$Wc_c" ||
  873.     echo 'options.inc: original size 1165, current size' "$Wc_c"
  874. fi
  875. # ============= readme.10 ==============
  876. if test -f 'readme.10' -a X"$1" != X"-c"; then
  877.     echo 'x - skipping readme.10 (File already exists)'
  878. else
  879. echo 'x - extracting readme.10 (Text)'
  880. sed 's/^X//' << 'SHAR_EOF' > 'readme.10' &&
  881. XScsi Version 1.0
  882. X
  883. X     The code you received with this file is a very simple SCSI device
  884. Xdriver that uses the Seagate ST-01 interface card.  As this driver is
  885. Xmy first PC assembler project other then "hello world", please don't
  886. Xsnicker to loudly.
  887. X
  888. X     The package includes the source for a device driver that will scan
  889. Xthe SCSI bus for disk drives and partition any drives found into chunks
  890. Xof 32Meg plus any leftovers.  As soon as I discover a way to get DOS to
  891. Xlet me use > 512 byte sectors, It will just allocate the entire disk to
  892. Xa single logical drive.  It also includes a utility to access the low
  893. Xlevel SCSI format function for any disk found.  You may specify the
  894. Xinterleave when the low level format is done and the version of the
  895. Xdriver here seems to work fine at 1:1 with my 8Mhz NEC.
  896. X
  897. X     Some of the things to look out for are:
  898. X
  899. X#1 The receive_data and send_data functions in subs.asm use polled I/O
  900. X   to transfer data to/from the card.  I would have loved to just use
  901. X   the I/O Channel Ready line that the card is suppose to support, but
  902. X   my NEC does not seem to use that line.  Hence the polling of the REQ
  903. X   bit in the status port.
  904. X
  905. X#2 I did not know how to do clock speed independent timing loops, so there
  906. X   is a wait100us function in subs.asm that is very processor speed
  907. X   dependent :-(
  908. X
  909. X#3 In ioctl.asm there is a commented out call to scsi_verify.  This is
  910. X   used by the DOS format utility to scan for errors.  You may want to
  911. X   enable the call after you get everything setup.  I shut it off while
  912. X   I was testing as I didn't want to wait for the verify everytime I
  913. X   changed the interleave.
  914. X
  915. X     To bring up the driver.  Assemble and link scsi.sys and add it to
  916. Xyour config.sys file.  After rebooting, you may optionaly do a low level
  917. Xformat of each disk found using sformat.exe.  You then use the DOS format
  918. Xutility on each logical drive.  I did figure out just what format needed
  919. Xin the way of ioctl support to get it to do the high level format for me.
  920. XAt this point you should have fully functional DOS drives.  In testing
  921. XI found that with multi_sector support (subs.asm) enabled, the SCSI drives
  922. Xwere just about as fast as the ST-412 C: that came with the machine.  I
  923. Xam sure that the speed problem is basic to the inner loop of the data
  924. Xtransfer routines, but I'm at a loss to figure out how to speed it up.
  925. X
  926. X     Anyway, maybe someone can find some use for the code.  I got the
  927. Xcard for free, so I can't really complain about the speed or cost too
  928. Xmuch :-)
  929. X
  930. X     Also thanks to the people that sent me samples of other device drivers
  931. Xfor the PC.  I lost the names to a disk crash, but here is the result of
  932. Xyour help and my thanks.
  933. X
  934. XBrian Antoine
  935. XAug 29, 1990
  936. SHAR_EOF
  937. chmod 0644 readme.10 ||
  938. echo 'restore of readme.10 failed'
  939. Wc_c="`wc -c < 'readme.10'`"
  940. test 2706 -eq "$Wc_c" ||
  941.     echo 'readme.10: original size 2706, current size' "$Wc_c"
  942. fi
  943. # ============= readme.11 ==============
  944. if test -f 'readme.11' -a X"$1" != X"-c"; then
  945.     echo 'x - skipping readme.11 (File already exists)'
  946. else
  947. echo 'x - extracting readme.11 (Text)'
  948. sed 's/^X//' << 'SHAR_EOF' > 'readme.11' &&
  949. XScsi Version 1.1
  950. X
  951. X     This version of the driver add support for a single tape drive, and
  952. Xcleans up some of the code a little.  It also adds a file that has equates
  953. Xto customize some of the major areas of the driver.
  954. X
  955. X     When the driver is initialized it does a scan of the SCSI bus for
  956. Xdevices.  The FIRST tape device found is assigned to a char device with the
  957. Xname "SCSITAPE".  If no tape drive is found, the char device is still valid
  958. Xbut will generate a "bad unit" error when accessed.
  959. X
  960. X     The SCSITAPE device expects reads and writes to be done in some variation
  961. Xof 512 bytes.  I/O done where (size mod 512) is non-zero will generate an
  962. Xerror.  Tape access must be done in RAW mode, and this is where I had to
  963. Xsome code in the driver that I'm not sure is very pretty.  The problem is
  964. Xthat DOS insists on opening char devices in cooked mode.  It does give you
  965. Xthe ability to switch to RAW mode, but only by using 'intdos()' to access
  966. Xthe ioctl interface.  The MSC 'setmode()' call for binary will not effect
  967. Xchar devices, nor will opening the file with O_BINARY.  So I had two choices.
  968. XI could modify every program that expected to talk to the tape so that it
  969. Xalso issued the ioctl stuff (see binmode.c), or I could kludge the driver
  970. Xto issue the required calls.
  971. X
  972. X     In the end, I punted and did both.  The code in binmode.c is the function
  973. Xthat along with 'setmode()', will make sure that ANYTHING you open is accessed
  974. Xin RAW mode.  Simply check for any call to 'setmode()' that is switching to
  975. XO_BINARY, and add another call to 'binmode()'.  This assumes that you have
  976. Xthe source to the utility in question.  For those who are don't mind a little
  977. Xkludge amount friends.  The file options.inc has an equate called 'use_kludge'
  978. Xthat when enabled turns on some code in kludge.asm.  This code links into the
  979. XINT 21h vector and waits for a DOS open request to go by.  When it sees an
  980. Xopen request, it 'calls' rather then 'jmps' to the normal vector.  This allows
  981. Xthe driver to get the 'handle' returned by DOS.  Because the SCSITAPE device
  982. Xenables the driver_open function, I can tell from the fact that an open is
  983. Xin progress and wether the driver just got an open request, wether any
  984. Xparticular open was for me.  When the open was in fact for the SCSITAPE device,
  985. XI take the 'handle' returned by DOS and forge the required ioctl calls to
  986. Xswitch to RAW mode.
  987. X
  988. X     With the addition of tape support.  I now use GNU Tar to swap tapes with
  989. Xmy normal UN*X system at work.  The driver works well enough that I have yet
  990. Xto have a format problem with the different systems.  It is also a lot faster
  991. Xwhen doing backups on the PC.  Using 'fastback' I would get about 1 Meg a
  992. Xminute thruput on my 8 Mhz AT.  Using GNU Tar and the SCSITAPE device I get
  993. X> 2.5 Meg a minute to the tape and don't have to swap disks quite so often :-)
  994. X
  995. X     Anyway, I hope that someone out there actually gets some use out of this
  996. Xcode.  It has been a real adventure for me.
  997. X
  998. XBrian Antoine
  999. XSept 8, 1990
  1000. SHAR_EOF
  1001. chmod 0644 readme.11 ||
  1002. echo 'restore of readme.11 failed'
  1003. Wc_c="`wc -c < 'readme.11'`"
  1004. test 2983 -eq "$Wc_c" ||
  1005.     echo 'readme.11: original size 2983, current size' "$Wc_c"
  1006. fi
  1007. # ============= readme.12 ==============
  1008. if test -f 'readme.12' -a X"$1" != X"-c"; then
  1009.     echo 'x - skipping readme.12 (File already exists)'
  1010. else
  1011. echo 'x - extracting readme.12 (Text)'
  1012. sed 's/^X//' << 'SHAR_EOF' > 'readme.12' &&
  1013. XScsi Version 1.2
  1014. X
  1015. X     This version of the driver enhances the tape drive support by adding
  1016. Xa program to control the action of the tape drive, and move around within
  1017. Xmultiple containers on the tape.  As I used the Bezerkley 'mt' command for
  1018. Xideas, the program is naturally called 'mt'.  You can tell the driver to:
  1019. X
  1020. X#1 Rewind/No Rewind on close.
  1021. X#2 Erase the tape.
  1022. X#3 Step forwards or backwards X tape marks.
  1023. X   Note: the command 'mt -s 0' steps to End Of Data.
  1024. X
  1025. X     I also did a little more work on the routines that actually transfer
  1026. Xdate to/from the card.  I found that I had left out a check for timeout
  1027. Xin the inner loops of the the data xfer routines.  When the random parity
  1028. Xerror or other glitch occured.  The driver would hang forever.  Not very
  1029. Xfriendly...  The added code does not seem to slow the driver any, or at
  1030. Xleast the disk thru-put tester I use shows no difference.
  1031. X
  1032. X     As the driver seems to be stable now, and it does about everything
  1033. XI started out to do.  I'm going to post this to comp.sources.misc instead
  1034. Xof alt.sources in the hopes that more people will see it.  Hopefully this
  1035. Xwill be usefull to someone else (at least they might get a good chuckle).
  1036. X
  1037. XBrian Antoine
  1038. XSept 25, 1990
  1039. SHAR_EOF
  1040. chmod 0644 readme.12 ||
  1041. echo 'restore of readme.12 failed'
  1042. Wc_c="`wc -c < 'readme.12'`"
  1043. test 1210 -eq "$Wc_c" ||
  1044.     echo 'readme.12: original size 1210, current size' "$Wc_c"
  1045. fi
  1046. # ============= scsi.asm ==============
  1047. if test -f 'scsi.asm' -a X"$1" != X"-c"; then
  1048.     echo 'x - skipping scsi.asm (File already exists)'
  1049. else
  1050. echo 'x - extracting scsi.asm (Text)'
  1051. sed 's/^X//' << 'SHAR_EOF' > 'scsi.asm' &&
  1052. X;
  1053. X; Simple SCSI Device Driver
  1054. X;
  1055. X        .286
  1056. X        PAGE    76,132
  1057. X
  1058. X        INCLUDE    options.inc
  1059. X        INCLUDE    equ.inc
  1060. X        INCLUDE    struct.inc
  1061. X;
  1062. X; Start of Code and Data
  1063. X;
  1064. X_TEXT        segment    word public 'CODE'
  1065. X        assume    cs:_TEXT, ds:_TEXT, es:_TEXT
  1066. X
  1067. X        org    0
  1068. X
  1069. X;
  1070. X; Device Header Required By DOS
  1071. X;
  1072. Xscsi:
  1073. Xtape_link_ofs    dw    disk_link_ofs    ;Forward Link
  1074. Xtape_link_seg    dw    -1
  1075. X        dw    0C800h        ;Char Device
  1076. X        dw    tape_strategy    ;Address of 1st DOS Call
  1077. X        dw    dev_interrupt    ;Address of 2nd DOS Call
  1078. X        db    'SCSITAPE'    ;Device Name
  1079. X
  1080. Xdisk_link_ofs    dw    -1        ;Forward Link
  1081. Xdisk_link_seg    dw    -1
  1082. X        dw    06040h        ;Ioctl R/W, Block Device, Non-IBM, Get/Set
  1083. X        dw    disk_strategy    ;Address of 1st DOS Call
  1084. X        dw    dev_interrupt    ;Address of 2nd DOS Call
  1085. Xdisk_count    db    0        ;Number of Disks Present
  1086. X        db    7 dup(?)
  1087. X
  1088. X;
  1089. X; Work Space For Our Device Driver
  1090. X;
  1091. X        even
  1092. Xrh_off        dw    ?        ;Request Header Offset
  1093. Xrh_seg        dw    ?        ;Request Header Segment
  1094. Xrh_type        db    ?        ;Request Type
  1095. X
  1096. Xwrite_flag    db    FALSE        ;TRUE When Tape Write Seen
  1097. Xload_flag    db    TRUE        ;TRUE When Tape should Load/Unload
  1098. Xcur_drive    db    -1
  1099. Xvol_id        db    'NO NAME    ',0
  1100. X
  1101. X;
  1102. X; Define our own personal Stack
  1103. X;
  1104. X        even
  1105. Xnew_stack    db    STACK_SIZE-2 dup (?)    ;Our Local Stack
  1106. Xnew_stack_top    dw    ?
  1107. X
  1108. Xstack_ptr    dw    ?            ;Old Stack Pointer
  1109. Xstack_seg    dw    ?            ;Old Stack Segment
  1110. X
  1111. X;
  1112. X; Command Table
  1113. X;
  1114. Xcmdtab        label    byte        ;* = Char Only Devices
  1115. X        dw    INITIALIZATION    ;Initialization
  1116. X        dw    MEDIA_CHECK    ;Media Check (Block Only)
  1117. X        dw    GET_BPB        ;Build BPB (Block Only)
  1118. X        dw    unknown        ;IOCTL Read
  1119. X        dw    READ        ;Read Data
  1120. X        dw    done        ;*Non Destructive Read
  1121. X        dw    done        ;*Read Status
  1122. X        dw    done        ;*Flush Read Buffer
  1123. X        dw    WRITE        ;Write Data
  1124. X        dw    WRITE_VERIFY    ;Write With Verify
  1125. X        dw    done        ;*Write Status
  1126. X        dw    done        ;*Flush Write Buffer
  1127. X        dw    WRITE_IOCTL    ;IOCTL Write
  1128. X        dw    OPEN_DEV    ;Device Open
  1129. X        dw    CLOSE_DEV    ;Device Close
  1130. X        dw    done        ;Removable Check
  1131. X        dw    unknown        ;*Write Until Busy
  1132. X        dw    unknown        ;Unknown Call
  1133. X        dw    unknown        ;Unknown Call
  1134. X        dw    IOCTL        ;Generic Ioctl
  1135. X        dw    unknown        ;Unknown Call
  1136. X        dw    unknown        ;Unknown Call
  1137. X        dw    unknown        ;Unknown Call
  1138. X        dw    GET_DEV        ;Get Device
  1139. X        dw    SET_DEV        ;Set Device
  1140. X
  1141. X;
  1142. X; Strategy Procedure
  1143. X;
  1144. Xdisk_strategy    proc    far
  1145. X        mov    cs:rh_seg,es        ;Save Request Header Ptr Segment
  1146. X        mov    cs:rh_off,bx        ;Save Request Header Ptr Offset
  1147. X        mov    cs:rh_type,DISK_REQUEST
  1148. X        ret
  1149. Xdisk_strategy    endp
  1150. X
  1151. Xtape_strategy    proc    far
  1152. X        mov    cs:rh_seg,es        ;Save Request Header Ptr Segment
  1153. X        mov    cs:rh_off,bx        ;Save Request Header Ptr Offset
  1154. X        mov    cs:rh_type,TAPE_REQUEST
  1155. X        ret
  1156. Xtape_strategy    endp
  1157. X
  1158. X;
  1159. X; Interrupt Procedure
  1160. X;
  1161. Xdev_interrupt    proc    far
  1162. X        cli                ;Save Machine State On Entry
  1163. X        push    ds
  1164. X        push    es
  1165. X        push    ax
  1166. X        push    bx
  1167. X        push    cx
  1168. X        push    dx
  1169. X        push    si
  1170. X        push    di
  1171. X        push    bp
  1172. X        pushf
  1173. X
  1174. X        mov    cs:stack_seg,ss        ;Save Old Stack
  1175. X        mov    cs:stack_ptr,sp
  1176. X
  1177. X        mov    ax,cs            ;Save us the Segment Override Crap
  1178. X        mov    ds,ax
  1179. X        mov    es,ax
  1180. X
  1181. X        mov    ss,ax            ;Setup Our Local Stack
  1182. X        lea    ax,new_stack_top
  1183. X        mov    sp,ax
  1184. X        sti                ;We're Safe Now
  1185. X
  1186. X;
  1187. X; Perform branch based on the command passed in the Request Header
  1188. X;
  1189. X        mov    es,rh_seg        ;Point us at the Request Header
  1190. X        mov    bx,rh_off
  1191. X
  1192. X        mov    al,es:[bx].rh_cmd    ;Get Command Code
  1193. X        rol    al,1            ;Get offset into table
  1194. X        lea    di,cmdtab        ;Get address of command table
  1195. X        mov    ah,0            ;Clear hi order byte
  1196. X        add    di,ax            ;Add offset
  1197. X        jmp    word ptr [di]        ;Jump Indirect
  1198. X
  1199. X;
  1200. X; Command Procedures
  1201. X;
  1202. XINITIALIZATION:    cmp    rh_type,TAPE_REQUEST    ;Is this SCSITAPE: Init?
  1203. X        jz    init_skip
  1204. X        mov    al,es:[bx].rh0_drv_ltr    ;Save the starting Drive
  1205. X        add    al,041h
  1206. X        mov    cur_drive,al
  1207. X        call    initial            ;Setup
  1208. X        if use_kludge
  1209. X        call    patch_us_in
  1210. X        endif
  1211. X        mov    bx,rh_off
  1212. X        mov    es,rh_seg
  1213. Xinit_skip:    lea    ax,initial        ;Set The Break Address
  1214. X        mov    es:[bx].rh0_brk_ofs,ax
  1215. X        mov    es:[bx].rh0_brk_seg,cs
  1216. X        mov    al,disk_count        ;Number of Disk Devices Supported
  1217. X        mov    es:[bx].rh0_nunits,al
  1218. X        lea    dx,bpb_array        ;BPB Array
  1219. X        mov    es:[bx].rh0_bpb_tbo,dx
  1220. X        mov    es:[bx].rh0_bpb_tbs,cs
  1221. X        jmp    done
  1222. X
  1223. X;
  1224. X; Has the Media Changed
  1225. X;
  1226. XMEDIA_CHECK:    call    find_unit
  1227. X        jc    mc_jmp_err
  1228. X        mov    di,cur_unit
  1229. X        mov    al,[di].unit_mcheck    ;Get Initial Status
  1230. X        mov    [di].unit_mcheck,1    ;Always OK from then on
  1231. X        mov    es:[bx].rh1_md_stat,al
  1232. X        lea    dx,vol_id        ;Address of Volume ID
  1233. X        mov    es:[bx].rh1_volid_ofs,dx
  1234. X        mov    es:[bx].rh1_volid_seg,cs
  1235. X        jmp    done
  1236. Xmc_jmp_err:    jmp    bad_unit
  1237. X
  1238. X;
  1239. X; Get Disk Parameter Block
  1240. X;
  1241. XGET_BPB:    call    find_unit
  1242. X        jc    get_jmp_err
  1243. X        mov    dx,cur_bpb        ;Address of BPB
  1244. X        mov    es:[bx].rh2_pbpbo,dx
  1245. X        mov    es:[bx].rh2_pbpbs,cs
  1246. X        jmp    done
  1247. Xget_jmp_err:    jmp    bad_unit
  1248. X
  1249. X;
  1250. X; Read some data from the disk/tape
  1251. X;
  1252. XREAD:        cmp    rh_type,DISK_REQUEST
  1253. X        jz    read_a_disk
  1254. X        mov    ax,tape_unit        ;Do We Have a Tape?
  1255. X        cmp    ax,-1
  1256. X        jz    read_jmp_err1
  1257. X        mov    cur_unit,ax
  1258. X        call    tape_read
  1259. X        jc    read_jmp_err2
  1260. X        jmp    done
  1261. Xread_a_disk:    call    find_unit
  1262. X        jc    read_jmp_err1
  1263. X        call    disk_read
  1264. X        jc    read_jmp_err2
  1265. X        jmp    done
  1266. Xread_jmp_err1:    jmp    bad_unit
  1267. Xread_jmp_err2:    jmp    bad_read
  1268. X
  1269. X;
  1270. X; Write some data to the disk/tape
  1271. X;
  1272. XWRITE        equ    $
  1273. XWRITE_VERIFY:    cmp    rh_type,DISK_REQUEST
  1274. X        jz    write_a_disk
  1275. X        mov    ax,tape_unit        ;Do We Have a Tape?
  1276. X        cmp    ax,-1
  1277. X        jz    write_jmp_err1
  1278. X        mov    cur_unit,ax
  1279. X        call    tape_write
  1280. X        jc    write_jmp_err2
  1281. X        jmp    done
  1282. Xwrite_a_disk:    call    find_unit
  1283. X        jc    write_jmp_err1
  1284. X        call    disk_write
  1285. X        jc    write_jmp_err2
  1286. X        jmp    done
  1287. Xwrite_jmp_err1:    jmp    bad_unit
  1288. Xwrite_jmp_err2:    jmp    bad_write
  1289. Xwrite_jmp_err3:    jmp    unknown
  1290. X
  1291. X;
  1292. X; Write Ioctl Packet
  1293. X;
  1294. XWRITE_IOCTL:    cmp    rh_type,DISK_REQUEST
  1295. X        jz    ioctl_a_disk
  1296. X        mov    ax,tape_unit            ;Do we have a SCSITAPE?
  1297. X        cmp    ax,-1
  1298. X        jz    write_jmp_err1
  1299. X        mov    cur_unit,ax
  1300. X        jmp    short ioctl_do
  1301. Xioctl_a_disk:    call    find_unit
  1302. X        jc    write_jmp_err1
  1303. Xioctl_do:    call    scsi_ioctl_write
  1304. X        jc    write_jmp_err3
  1305. X        jmp    done
  1306. X
  1307. X;
  1308. X; Special Control Functions
  1309. X;
  1310. XIOCTL:        call    find_unit
  1311. X        jc    ioctl_jmp_err1
  1312. X        call    scsi_ioctl
  1313. X        jc    ioctl_jmp_err2
  1314. X        jmp    done
  1315. Xioctl_jmp_err1:    jmp    bad_unit
  1316. Xioctl_jmp_err2:    jmp    unknown
  1317. X
  1318. X;
  1319. X; Open Tape Device
  1320. X;
  1321. XOPEN_DEV:    mov    di,tape_unit
  1322. X        cmp    di,-1        ;Do We have a SCSITAPE: Unit?
  1323. X        jz    open_err1
  1324. X        mov    cur_unit,di            ;New Current Unit
  1325. X        lea    bx,[di].unit_sense_buf        ;Buffer Offset
  1326. X        push    ds                ;Buffer Segment
  1327. X        pop    es
  1328. X        mov    cx,size sense            ;Buffer Size
  1329. X        lea    di,cmd_sense            ;Command
  1330. X        call    docmd
  1331. X        jc    open_err2
  1332. X        cmp    load_flag,TRUE            ;Should we LOAD?
  1333. X        jnz    open_ok
  1334. X        lea    di,cmd_load            ;Now Load Tape
  1335. X        mov    [di].load_cmd_type,LOAD_TAPE
  1336. X        call    docmd
  1337. X        jnc    open_ok
  1338. X        call    scsi_sense
  1339. Xopen_err2:    jmp    general
  1340. Xopen_err1:    jmp    bad_unit
  1341. Xopen_ok:    mov    opened_flag,TRUE        ;We are open
  1342. X        mov    write_flag,FALSE        ;No Writes Seen
  1343. X        jmp    done
  1344. X
  1345. X;
  1346. X; Close Tape Device
  1347. X;
  1348. XCLOSE_DEV:    mov    di,tape_unit
  1349. X        cmp    di,-1        ;Do We have a SCSITAPE: Unit?
  1350. X        jz    close_err1
  1351. X        mov    cur_unit,di            ;New Current Unit
  1352. X        cmp    write_flag,TRUE            ;Were We Writing?
  1353. X        jnz    tape_no_write
  1354. X        lea    di,cmd_twritefm            ;End Tape with FM(s)
  1355. X        mov    [di].fm_cmd_cnt_b0,CLOSE_FM_CNT
  1356. X        call    docmd
  1357. X        jnc    tape_no_write
  1358. X        call    scsi_sense
  1359. Xtape_no_write:    cmp    load_flag,TRUE            ;Should we Unload?
  1360. X        jnz    close_ok    
  1361. X        lea    di,cmd_load            ;Now Unload Tape
  1362. X        mov    [di].load_cmd_type,UNLOAD_TAPE
  1363. X        call    docmd
  1364. X        jnc    close_ok
  1365. X        call    scsi_sense
  1366. Xclose_err2:    jmp    general
  1367. Xclose_err1:    jmp    bad_unit
  1368. Xclose_ok:    jmp    done
  1369. X
  1370. X;
  1371. X; Get Device Assignment
  1372. X;
  1373. XGET_DEV:    mov    es:[bx].rh_unit,0
  1374. X        jmp    done
  1375. X
  1376. X;
  1377. X; Set Device Assignment
  1378. X;
  1379. XSET_DEV:    jmp    done
  1380. X
  1381. Xbad_unit:    mov    es,rh_seg        ;Point us at the Request Header
  1382. X        mov    bx,rh_off
  1383. X        or    es:[bx].rh_status,8001h
  1384. X        jmp    short done
  1385. X
  1386. Xunknown:    mov    es,rh_seg        ;Point us at the Request Header
  1387. X        mov    bx,rh_off
  1388. X        or    es:[bx].rh_status,8003h
  1389. X        jmp    short done
  1390. X
  1391. Xbad_write:    mov    es,rh_seg        ;Point us at the Request Header
  1392. X        mov    bx,rh_off
  1393. X        or    es:[bx].rh_status,800Ah
  1394. X        jmp    short done
  1395. X
  1396. Xbad_read:    mov    es,rh_seg        ;Point us at the Request Header
  1397. X        mov    bx,rh_off
  1398. X        or    es:[bx].rh_status,800Bh
  1399. X        jmp    short done
  1400. X
  1401. Xgeneral:    mov    es,rh_seg        ;Point us at the Request Header
  1402. X        mov    bx,rh_off
  1403. X        or    es:[bx].rh_status,800Ch
  1404. X        jmp    short done
  1405. X
  1406. Xbusy:        mov    es,rh_seg        ;Point us at the Request Header
  1407. X        mov    bx,rh_off
  1408. X        or    es:[bx].rh_status,0200h
  1409. X
  1410. Xdone:        mov    es,rh_seg        ;Point us at the Request Header
  1411. X        mov    bx,rh_off
  1412. X        or    es:[bx].rh_status,0100h
  1413. X
  1414. X        cli                ;Make sure we're left alone
  1415. X        mov    ax,cs:stack_seg        ;Restore DOS Stack
  1416. X        mov    ss,ax
  1417. X        mov    ax,cs:stack_ptr
  1418. X        mov    sp,ax
  1419. X
  1420. X        popf                ;Restore All Registers
  1421. X        pop    bp
  1422. X        pop    di
  1423. X        pop    si
  1424. X        pop    dx
  1425. X        pop    cx
  1426. X        pop    bx
  1427. X        pop    ax
  1428. X        pop    es
  1429. X        pop    ds
  1430. X        sti                ;We're Safe Now
  1431. X        ret
  1432. X
  1433. X        INCLUDE    units.asm
  1434. X        INCLUDE    subs.asm
  1435. X        INCLUDE    ioctl.asm
  1436. X        INCLUDE    dump.asm
  1437. X        if use_kludge
  1438. X        INCLUDE    kludge.asm
  1439. X        endif
  1440. X
  1441. X;
  1442. X; End of Program
  1443. X; Stuff Placed Here Gets Handed Back To DOS For Re-use
  1444. X;
  1445. Xinitial        proc    near
  1446. X        lea    dx,hello_msg        ;Tell them the driver version
  1447. X        call    puts
  1448. X        push    cs
  1449. X        pop    dx
  1450. X        lea    bx,seg_msg_value
  1451. X        call    hex2asc4
  1452. X        lea    dx,seg_msg        ;And Were We Loaded
  1453. X        call    puts
  1454. X
  1455. X        call    scsi_reset        ;Reset the bus
  1456. X
  1457. X        mov    cx,0            ;Scan for devices
  1458. Xscan:        mov    ax,cx
  1459. X        add    al,030h
  1460. X        mov    scan_dev,al
  1461. X        mov    ax,1            ;Create Select Bit
  1462. X        shl    ax,cl
  1463. X        if reserve_addr
  1464. X        or    al,80h            ;Add Card Select Bit
  1465. X        endif
  1466. X        mov    di,cur_unit
  1467. X        mov    [di].unit_select,al
  1468. X        mov    [di].unit_num_drv,0    ;No Drives to start with
  1469. X        mov    al,disk_count        ;We will start with
  1470. X        mov    [di].unit_1st_drv,al    ;Drive Number if any
  1471. X
  1472. X        lea    dx,scan_dev        ;Print the device number
  1473. X        call    puts
  1474. X        call    scsi_inquire        ;Inquire as to its type
  1475. X        jnc    scan_inq_ok
  1476. X        jmp    scan_err
  1477. X
  1478. Xscan_inq_ok:    mov    di,cur_unit
  1479. X        lea    dx,[di].unit_inq_buf.inq_manufact
  1480. X        mov    [di].unit_inq_term,'$'
  1481. X        mov    al,[di].unit_inq_buf.inq_dev_type
  1482. X        or    al,al            ;Look at device type
  1483. X        jz    scan_is_drv
  1484. X        cmp    tape_unit,-1        ;Do We Already Have A Tape?
  1485. X        jnz    tape_jmp
  1486. X        call    puts            ;Make this our SCSITAPE: Unit
  1487. X        mov    tape_unit,di
  1488. X        lea    dx,tape_msg
  1489. Xtape_jmp:    jmp    scan_puts
  1490. X
  1491. Xscan_is_drv:    call    puts            ;Output the Device String
  1492. X        call    scsi_capacity        ;Inquire as to its size
  1493. X        lea    dx,err_size
  1494. X        jc    scan_puts        ;Do not use unknown drives
  1495. X        lea    dx,crlf
  1496. X        call    puts
  1497. X
  1498. Xscan_next_drv:    mov    di,cur_unit
  1499. X        mov    al,disk_count        ;Number Of Drives Found
  1500. X        inc    al
  1501. X        mov    disk_count,al
  1502. X        mov    al,[di].unit_num_drv    ;We have a valid Drive
  1503. X        inc    al
  1504. X        mov    [di].unit_num_drv,al
  1505. X        mov    al,cur_drive        ;Get Current Drive Letter
  1506. X        mov    drv_msg_let,al        ;Insert it in message
  1507. X        inc    al            ;Bump Drive Letter
  1508. X        mov    cur_drive,al
  1509. X        call    make_bpb        ;Setup the BPB for this drive
  1510. X        mov    di,cur_bpb        ;Current Working BPB
  1511. X        mov    ax,[di].bpb_ts
  1512. X        shr    ax,11
  1513. X        inc    ax
  1514. X        lea    bx,drv_msg_size
  1515. X        call    bin_ascii
  1516. X        mov    bx,bpb_hw_mark        ;Get the BPB High Water Mark
  1517. X        inc    bx            ;Bump HW Mark for next time
  1518. X        inc    bx
  1519. X        mov    ax,[bx]            ;Get the BPB
  1520. X        mov    cur_bpb,ax        ;Make it the current BPB
  1521. X        mov    bpb_hw_mark,bx
  1522. X        lea    dx,drv_msg
  1523. X        call    puts
  1524. X        mov    bx,cur_unit
  1525. X        mov    ah,0
  1526. X        mov    al,[bx].unit_num_drv    ;Insert Drive Offset
  1527. X        dec    al            ;Into BPB for this Drive
  1528. X        mov    [di].bpb_hs_msw,ax
  1529. X        mov    al,[bx].unit_cap_buf.cap_sectors_b3
  1530. X        or    al,[bx].unit_cap_buf.cap_sectors_b2
  1531. X        or    al,[bx].unit_cap_buf.cap_sectors_b1
  1532. X        or    al,[bx].unit_cap_buf.cap_sectors_b0
  1533. X        jnz    scan_next_drv        ;Room left for another Drive
  1534. X        jmp    short scan_next
  1535. X
  1536. Xscan_err:    lea    dx,no_dev
  1537. X        cmp    al,CNOCONNECT
  1538. X        jz    scan_puts
  1539. X        lea    dx,err_dev
  1540. Xscan_puts:    call    puts
  1541. X        lea    dx,crlf
  1542. X        call    puts
  1543. X
  1544. Xscan_next:    inc    cx
  1545. X        cmp    cx,MAXUNIT    ;End of devices?
  1546. X        jg    scan_exit
  1547. X        mov    bx,cx        ;Bump to next unit
  1548. X        shl    bx,1
  1549. X        mov    ax,word ptr unit_array[bx]
  1550. X        mov    cur_unit,ax
  1551. X        jmp    scan
  1552. X
  1553. Xscan_exit:    ret
  1554. Xinitial        endp
  1555. X
  1556. X;
  1557. X; Data Area Used Only During Initialization
  1558. X;
  1559. Xhello_msg    db    0dh,0ah,'SCSI Device Driver Version 1.2',0Dh,0Ah,'$'
  1560. Xseg_msg        db    'Driver Loaded At Segment '
  1561. Xseg_msg_value    db    '0000',0dh,0ah,'$'
  1562. Xscan_dev    db    'X - ','$'
  1563. Xno_dev        db    '(No Installed Device)$'
  1564. Xerr_dev        db    '(Error On Device)$'
  1565. Xerr_size    db    'unknown size$'
  1566. Xdrv_msg        db    '  - Drive '
  1567. Xdrv_msg_let    db    'X: '
  1568. Xdrv_msg_size    db    'XXXXXX Meg',0dh,0ah,'$'
  1569. Xtape_msg    db    0dh,0ah,'  - Is The SCSITAPE: Device$'
  1570. Xcrlf        db    0dh,0ah,'$'
  1571. X
  1572. Xdev_interrupt    endp
  1573. X_TEXT        ends
  1574. X        end
  1575. SHAR_EOF
  1576. chmod 0644 scsi.asm ||
  1577. echo 'restore of scsi.asm failed'
  1578. Wc_c="`wc -c < 'scsi.asm'`"
  1579. test 11458 -eq "$Wc_c" ||
  1580.     echo 'scsi.asm: original size 11458, current size' "$Wc_c"
  1581. fi
  1582. # ============= scsi.sys ==============
  1583. if test -f 'scsi.sys' -a X"$1" != X"-c"; then
  1584.     echo 'x - skipping scsi.sys (File already exists)'
  1585. else
  1586. echo 'x - extracting scsi.sys (Text)'
  1587. sed 's/^X//' << 'SHAR_EOF' > 'scsi.sys' &&
  1588. XHSCSITAPE@`nNO NAME    L 2IPPPvvPP&Z#PGgo. &.    $.F(K. &.    $.F(KzPSQRVWU. :.    &8 HX@P
  1589. XGP@
  1590. XEFE&G
  1591. Xi)Xr_i    hPrhN
  1592. Xri|ii( >t/    >
  1593. XG
  1594. X@t
  1595. X7:ft
  1596. XFF~F~Hutk     #xkGGbVyaC > GFEGEFEGE
  1597. Xg%
  1598. XG& @t Hg%G&:k
  1599. Xw'FG'2FG(J    UFE
  1600. XxAj
  1601. XB    U GEGEGEGEC
  1602. X
  1603. X %/SCSI Unit: 0xxx, Sense Status: 0xxx, Block Address: 0xxxxxxxxx
  1604. X$`8^@>& G+A&    GCF) {& M A%t&GEyC& ]& E@ CAh FpFc
  1605. XE
  1606. X@t>u h$    >
  1607. XE~@E +"F~@"+h    x > EAh @
  1608. XG~H    E
  1609. XG%
  1610. XG&
  1611. XG'
  1612. XG(uk
  1613. XSCSI Device Driver Version 1.2
  1614. X$Driver Loaded At Segment 0000
  1615. X$X - $(No Installed Device)$(Error On Device)$unknown size$  - Drive X: XXXXXX Meg
  1616. X$
  1617. X  - Is The SCSITAPE: Device$
  1618. X$
  1619. SHAR_EOF
  1620. chmod 0644 scsi.sys ||
  1621. echo 'restore of scsi.sys failed'
  1622. Wc_c="`wc -c < 'scsi.sys'`"
  1623. test 2518 -eq "$Wc_c" ||
  1624.     echo 'scsi.sys: original size 2518, current size' "$Wc_c"
  1625. fi
  1626. # ============= sformat.c ==============
  1627. if test -f 'sformat.c' -a X"$1" != X"-c"; then
  1628.     echo 'x - skipping sformat.c (File already exists)'
  1629. else
  1630. echo 'x - extracting sformat.c (Text)'
  1631. sed 's/^X//' << 'SHAR_EOF' > 'sformat.c' &&
  1632. X/*
  1633. X** SCSI Disk Formatter (Low Level)
  1634. X**
  1635. X** usage: sformat drive: [interleave]
  1636. X**
  1637. X** Revision History:
  1638. X**
  1639. X** Version 1.0  08/03/90 Initial Release
  1640. X**
  1641. X** Version 1.1  08/20/90 Add verification message.
  1642. X**
  1643. X** Version 1.2  09/18/90 Correct ioctl_data struct.
  1644. X*/
  1645. X#include <stdio.h>
  1646. X#include <dos.h>
  1647. X
  1648. X#define TRUE (1)
  1649. X#define FALSE (0)
  1650. X#define VERSION "sformat Version 1.2 BWA"
  1651. X
  1652. Xextern int _doserrno;
  1653. X
  1654. Xstruct cmd {
  1655. X    short command;        /* command type */
  1656. X    short arg1;            /* command args */
  1657. X    short arg2;            /* command args */
  1658. X} ioctl_data;
  1659. Xunion REGS inregs, outregs;
  1660. Xstruct SREGS segregs;
  1661. Xunsigned short interleave = 0;
  1662. Xunsigned char drive;
  1663. Xchar far *cp;
  1664. X
  1665. Xmain(argc, argv)
  1666. Xint argc;
  1667. Xchar *argv[];
  1668. X{
  1669. X    /*
  1670. X    ** say hello
  1671. X    */
  1672. X    puts(VERSION);
  1673. X
  1674. X    /*
  1675. X    ** figure out who to format
  1676. X    */
  1677. X    switch (argc)
  1678. X    {
  1679. X        case 3:
  1680. X        interleave = atoi(argv[2]);
  1681. X        case 2:
  1682. X        if (argv[1][1] != ':') usage();
  1683. X        drive = argv[1][0];
  1684. X        drive = toupper(drive);
  1685. X        drive -= '@';
  1686. X        break;
  1687. X
  1688. X        default:
  1689. X        usage();
  1690. X        break;
  1691. X    }
  1692. X
  1693. X    /*
  1694. X    ** verify that this is what the user really wants to do
  1695. X    */
  1696. X    printf("Do you really wish to format the SCSI\n");
  1697. X    printf("device that contains drive %c: (y,n)? ", argv[1][0]);
  1698. X    fflush(stdout);
  1699. X    if ( getchar() != 'y' )
  1700. X    {
  1701. X        puts("Aborting low level format ....");
  1702. X        exit(1);
  1703. X    }
  1704. X
  1705. X    /*
  1706. X    ** put together the command
  1707. X    */
  1708. X    inregs.h.ah = 0x44;            /* ioctl */
  1709. X    inregs.h.al = 0x05;            /* write */
  1710. X    inregs.h.bl = drive;        /* unit */
  1711. X    inregs.x.cx = sizeof(struct cmd);
  1712. X    cp = (char *) &ioctl_data;
  1713. X    inregs.x.dx = FP_OFF(cp);
  1714. X    segregs.ds = FP_SEG(cp);
  1715. X    ioctl_data.command = 'F';
  1716. X    ioctl_data.arg1 = interleave;
  1717. X
  1718. X    /*
  1719. X    ** start the format
  1720. X    */
  1721. X    puts("Now formating ....");
  1722. X    puts("Please wait ....");
  1723. X    intdosx(&inregs, &outregs, &segregs);
  1724. X
  1725. X    /*
  1726. X    ** see what happened
  1727. X    */
  1728. X    if ( outregs.x.cflag )
  1729. X        printf("DOS error %d occured during format.\n", _doserrno);
  1730. X    else
  1731. X        puts("Formating complete.");
  1732. X    exit(0);
  1733. X}
  1734. X
  1735. Xusage()
  1736. X{
  1737. X    puts("usage: sformat drive: [interleave]");
  1738. X    exit(1);
  1739. X}
  1740. SHAR_EOF
  1741. chmod 0644 sformat.c ||
  1742. echo 'restore of sformat.c failed'
  1743. Wc_c="`wc -c < 'sformat.c'`"
  1744. test 1931 -eq "$Wc_c" ||
  1745.     echo 'sformat.c: original size 1931, current size' "$Wc_c"
  1746. fi
  1747. true || echo 'restore of struct.inc failed'
  1748. echo End of part 1, continue with part 2
  1749. exit 0
  1750.  
  1751.  
  1752.