home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume15 / st-01_scsi / part01 next >
Encoding:
Text File  |  1990-10-05  |  45.1 KB  |  1,772 lines

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