1 | /*
|
---|
2 | * scsi.c
|
---|
3 | * Iomega Zip/Jaz drive tool
|
---|
4 | * change protection mode and eject disk
|
---|
5 | */
|
---|
6 |
|
---|
7 | /* scis.c by Markus Gyger <mgyger@itr.ch> */
|
---|
8 | /* This code is based on ftp://gear.torque.net/pub/ziptool.c */
|
---|
9 | /* by Grant R. Guenther with the following copyright notice: */
|
---|
10 |
|
---|
11 | /* (c) 1996 Grant R. Guenther, based on work of Itai Nahshon */
|
---|
12 | /* http://www.torque.net/ziptool.html */
|
---|
13 |
|
---|
14 |
|
---|
15 | /* A.K. Moved this from mzip.c to a separate file in order to share with
|
---|
16 | * plain_io.c */
|
---|
17 |
|
---|
18 | #include "sysincludes.h"
|
---|
19 | #include "mtools.h"
|
---|
20 | #include "scsi.h"
|
---|
21 |
|
---|
22 | #if defined OS_hpux
|
---|
23 | #include <sys/scsi.h>
|
---|
24 | #endif
|
---|
25 |
|
---|
26 | #ifdef OS_solaris
|
---|
27 | #include <sys/scsi/scsi.h>
|
---|
28 | #endif /* solaris */
|
---|
29 |
|
---|
30 | #ifdef OS_sunos
|
---|
31 | #include <scsi/generic/commands.h>
|
---|
32 | #include <scsi/impl/uscsi.h>
|
---|
33 | #endif /* sunos */
|
---|
34 |
|
---|
35 | #ifdef sgi
|
---|
36 | #include <sys/dsreq.h>
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | #ifdef OS_linux
|
---|
40 | #define SCSI_IOCTL_SEND_COMMAND 1
|
---|
41 | struct scsi_ioctl_command {
|
---|
42 | int inlen;
|
---|
43 | int outlen;
|
---|
44 | char cmd[5008];
|
---|
45 | };
|
---|
46 | #endif
|
---|
47 |
|
---|
48 | #ifdef _SCO_DS
|
---|
49 | #include <sys/scsicmd.h>
|
---|
50 | #endif
|
---|
51 |
|
---|
52 | #if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
|
---|
53 | #include <camlib.h>
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | int scsi_max_length(void)
|
---|
57 | {
|
---|
58 | #ifdef OS_linux
|
---|
59 | return 8;
|
---|
60 | #else
|
---|
61 | return 255;
|
---|
62 | #endif
|
---|
63 | }
|
---|
64 |
|
---|
65 | int scsi_open(const char *name, int flag, int mode, void **extra_data)
|
---|
66 | {
|
---|
67 | #if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
|
---|
68 | struct cam_device *cam_dev;
|
---|
69 | cam_dev = cam_open_device(name, O_RDWR);
|
---|
70 | *extra_data = (void *) cam_dev;
|
---|
71 | if (cam_dev)
|
---|
72 | return cam_dev->fd;
|
---|
73 | else
|
---|
74 | return -1;
|
---|
75 | #else
|
---|
76 | return open(name, O_RDONLY
|
---|
77 | #ifdef O_NDELAY
|
---|
78 | | O_NDELAY
|
---|
79 | #endif
|
---|
80 | /* O_RDONLY | dev->mode*/);
|
---|
81 | #endif
|
---|
82 | }
|
---|
83 |
|
---|
84 | int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
|
---|
85 | void *data, size_t len, void *extra_data)
|
---|
86 | {
|
---|
87 | #if defined OS_hpux
|
---|
88 | struct sctl_io sctl_io;
|
---|
89 |
|
---|
90 | memset(&sctl_io, 0, sizeof sctl_io); /* clear reserved fields */
|
---|
91 | memcpy(sctl_io.cdb, cdb, cmdlen); /* copy command */
|
---|
92 | sctl_io.cdb_length = cmdlen; /* command length */
|
---|
93 | sctl_io.max_msecs = 2000; /* allow 2 seconds for cmd */
|
---|
94 |
|
---|
95 | switch (mode) {
|
---|
96 | case SCSI_IO_READ:
|
---|
97 | sctl_io.flags = SCTL_READ;
|
---|
98 | sctl_io.data_length = len;
|
---|
99 | sctl_io.data = data;
|
---|
100 | break;
|
---|
101 | case SCSI_IO_WRITE:
|
---|
102 | sctl_io.flags = 0;
|
---|
103 | sctl_io.data_length = data ? len : 0;
|
---|
104 | sctl_io.data = len ? data : 0;
|
---|
105 | break;
|
---|
106 | }
|
---|
107 |
|
---|
108 | if (ioctl(fd, SIOC_IO, &sctl_io) == -1) {
|
---|
109 | perror("scsi_io");
|
---|
110 | return -1;
|
---|
111 | }
|
---|
112 |
|
---|
113 | return sctl_io.cdb_status;
|
---|
114 |
|
---|
115 | #elif defined OS_sunos || defined OS_solaris
|
---|
116 | struct uscsi_cmd uscsi_cmd;
|
---|
117 | memset(&uscsi_cmd, 0, sizeof uscsi_cmd);
|
---|
118 | uscsi_cmd.uscsi_cdb = (char *)cdb;
|
---|
119 | uscsi_cmd.uscsi_cdblen = cmdlen;
|
---|
120 | #ifdef OS_solaris
|
---|
121 | uscsi_cmd.uscsi_timeout = 20; /* msec? */
|
---|
122 | #endif /* solaris */
|
---|
123 |
|
---|
124 | uscsi_cmd.uscsi_buflen = (u_int)len;
|
---|
125 | uscsi_cmd.uscsi_bufaddr = data;
|
---|
126 |
|
---|
127 | switch (mode) {
|
---|
128 | case SCSI_IO_READ:
|
---|
129 | uscsi_cmd.uscsi_flags = USCSI_READ;
|
---|
130 | break;
|
---|
131 | case SCSI_IO_WRITE:
|
---|
132 | uscsi_cmd.uscsi_flags = USCSI_WRITE;
|
---|
133 | break;
|
---|
134 | }
|
---|
135 |
|
---|
136 | if (ioctl(fd, USCSICMD, &uscsi_cmd) == -1) {
|
---|
137 | perror("scsi_io");
|
---|
138 | return -1;
|
---|
139 | }
|
---|
140 |
|
---|
141 | if(uscsi_cmd.uscsi_status) {
|
---|
142 | errno = 0;
|
---|
143 | fprintf(stderr,"scsi status=%x\n",
|
---|
144 | (unsigned short)uscsi_cmd.uscsi_status);
|
---|
145 | return -1;
|
---|
146 | }
|
---|
147 |
|
---|
148 | return 0;
|
---|
149 |
|
---|
150 | #elif defined OS_linux
|
---|
151 | struct scsi_ioctl_command scsi_cmd;
|
---|
152 |
|
---|
153 |
|
---|
154 | memcpy(scsi_cmd.cmd, cdb, cmdlen); /* copy command */
|
---|
155 |
|
---|
156 | switch (mode) {
|
---|
157 | case SCSI_IO_READ:
|
---|
158 | scsi_cmd.inlen = 0;
|
---|
159 | scsi_cmd.outlen = len;
|
---|
160 | break;
|
---|
161 | case SCSI_IO_WRITE:
|
---|
162 | scsi_cmd.inlen = len;
|
---|
163 | scsi_cmd.outlen = 0;
|
---|
164 | memcpy(scsi_cmd.cmd + cmdlen,data,len);
|
---|
165 | break;
|
---|
166 | }
|
---|
167 |
|
---|
168 | if (ioctl(fd, SCSI_IOCTL_SEND_COMMAND, &scsi_cmd) < 0) {
|
---|
169 | perror("scsi_io");
|
---|
170 | return -1;
|
---|
171 | }
|
---|
172 |
|
---|
173 | switch (mode) {
|
---|
174 | case SCSI_IO_READ:
|
---|
175 | memcpy(data, &scsi_cmd.cmd[0], len);
|
---|
176 | break;
|
---|
177 | case SCSI_IO_WRITE:
|
---|
178 | break;
|
---|
179 | }
|
---|
180 |
|
---|
181 | return 0; /* where to get scsi status? */
|
---|
182 |
|
---|
183 | #elif defined _SCO_DS
|
---|
184 | struct scsicmd scsi_cmd;
|
---|
185 |
|
---|
186 | memset(scsi_cmd.cdb, 0, SCSICMDLEN); /* ensure zero pad */
|
---|
187 | memcpy(scsi_cmd.cdb, cdb, cmdlen);
|
---|
188 | scsi_cmd.cdb_len = cmdlen;
|
---|
189 | scsi_cmd.data_len = len;
|
---|
190 | scsi_cmd.data_ptr = data;
|
---|
191 | scsi_cmd.is_write = mode == SCSI_IO_WRITE;
|
---|
192 | if (ioctl(fd,SCSIUSERCMD,&scsi_cmd) == -1) {
|
---|
193 | perror("scsi_io");
|
---|
194 | printf("scsi status: host=%x; target=%x\n",
|
---|
195 | (unsigned)scsi_cmd.host_sts,(unsigned)scsi_cmd.target_sts);
|
---|
196 | return -1;
|
---|
197 | }
|
---|
198 | return 0;
|
---|
199 | #elif defined sgi
|
---|
200 | struct dsreq scsi_cmd;
|
---|
201 |
|
---|
202 | scsi_cmd.ds_cmdbuf = (char *)cdb;
|
---|
203 | scsi_cmd.ds_cmdlen = cmdlen;
|
---|
204 | scsi_cmd.ds_databuf = data;
|
---|
205 | scsi_cmd.ds_datalen = len;
|
---|
206 | switch (mode) {
|
---|
207 | case SCSI_IO_READ:
|
---|
208 | scsi_cmd.ds_flags = DSRQ_READ|DSRQ_SENSE;
|
---|
209 | break;
|
---|
210 | case SCSI_IO_WRITE:
|
---|
211 | scsi_cmd.ds_flags = DSRQ_WRITE|DSRQ_SENSE;
|
---|
212 | break;
|
---|
213 | }
|
---|
214 | scsi_cmd.ds_time = 10000;
|
---|
215 | scsi_cmd.ds_link = 0;
|
---|
216 | scsi_cmd.ds_synch =0;
|
---|
217 | scsi_cmd.ds_ret =0;
|
---|
218 | if (ioctl(fd, DS_ENTER, &scsi_cmd) == -1) {
|
---|
219 | perror("scsi_io");
|
---|
220 | return -1;
|
---|
221 | }
|
---|
222 |
|
---|
223 | if(scsi_cmd.ds_status) {
|
---|
224 | errno = 0;
|
---|
225 | fprintf(stderr,"scsi status=%x\n",
|
---|
226 | (unsigned short)scsi_cmd.ds_status);
|
---|
227 | return -1;
|
---|
228 | }
|
---|
229 |
|
---|
230 | return 0;
|
---|
231 | #elif (defined OS_freebsd) && (__FreeBSD__ >= 2)
|
---|
232 | #define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
|
---|
233 | union ccb *ccb;
|
---|
234 | int flags;
|
---|
235 | int r;
|
---|
236 | struct cam_device *cam_dev = (struct cam_device *) extra_data;
|
---|
237 |
|
---|
238 |
|
---|
239 | if (cam_dev==NULL || cam_dev->fd!=fd)
|
---|
240 | {
|
---|
241 | fprintf(stderr,"invalid file descriptor\n");
|
---|
242 | return -1;
|
---|
243 | }
|
---|
244 | ccb = cam_getccb(cam_dev);
|
---|
245 |
|
---|
246 | bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cmdlen);
|
---|
247 |
|
---|
248 | if (mode == SCSI_IO_READ)
|
---|
249 | flags = CAM_DIR_IN;
|
---|
250 | else if (data && len)
|
---|
251 | flags = CAM_DIR_OUT;
|
---|
252 | else
|
---|
253 | flags = CAM_DIR_NONE;
|
---|
254 | cam_fill_csio(&ccb->csio,
|
---|
255 | /* retry */ 1,
|
---|
256 | /* cbfcnp */ NULL,
|
---|
257 | flags,
|
---|
258 | /* tag_action */ MSG_SIMPLE_Q_TAG,
|
---|
259 | /*data_ptr*/ len ? data : 0,
|
---|
260 | /*data_len */ data ? len : 0,
|
---|
261 | 96,
|
---|
262 | cmdlen,
|
---|
263 | 5000);
|
---|
264 |
|
---|
265 | if (cam_send_ccb(cam_dev, ccb) < 0 ||
|
---|
266 | (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
---|
267 | return -1;
|
---|
268 | }
|
---|
269 | return 0;
|
---|
270 | #else
|
---|
271 | fprintf(stderr, "scsi_io not implemented\n");
|
---|
272 | return -1;
|
---|
273 | #endif
|
---|
274 | }
|
---|