1 /* Copyright 1996 Grant R. Guenther, based on work of Itai Nahshon
2 * http://www.torque.net/ziptool.html
3 * Copyright 1997-1999,2001,2002,2005,2007,2009 Alain Knaff.
4 * This file is part of mtools.
6 * Mtools is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Mtools is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
20 * Iomega Zip/Jaz drive tool
21 * change protection mode and eject disk
24 /* scis.c by Markus Gyger <mgyger@itr.ch> */
25 /* This code is based on ftp://gear.torque.net/pub/ziptool.c */
26 /* by Grant R. Guenther with the following copyright notice: */
28 /* (c) 1996 Grant R. Guenther, based on work of Itai Nahshon */
29 /* http://www.torque.net/ziptool.html */
32 /* A.K. Moved this from mzip.c to a separate file in order to share with
35 #include "sysincludes.h"
44 #include <sys/scsi/scsi.h>
48 #include <scsi/generic/commands.h>
49 #include <scsi/impl/uscsi.h>
53 #include <sys/dsreq.h>
57 #define SCSI_IOCTL_SEND_COMMAND 1
58 struct scsi_ioctl_command {
66 #include <sys/scsicmd.h>
69 #if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
73 #if defined(OS_netbsd) || defined(OS_netbsdelf)
74 #include <sys/scsiio.h>
77 int scsi_max_length(void)
86 int scsi_open(const char *name, int flag, int mode, void **extra_data)
88 #if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
89 struct cam_device *cam_dev;
90 cam_dev = cam_open_device(name, O_RDWR);
91 *extra_data = (void *) cam_dev;
97 return open(name, O_RDONLY | O_LARGEFILE | O_BINARY
101 /* O_RDONLY | dev->mode*/);
105 int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
106 void *data, size_t len, void *extra_data)
109 struct sctl_io sctl_io;
111 memset(&sctl_io, 0, sizeof sctl_io); /* clear reserved fields */
112 memcpy(sctl_io.cdb, cdb, cmdlen); /* copy command */
113 sctl_io.cdb_length = cmdlen; /* command length */
114 sctl_io.max_msecs = 2000; /* allow 2 seconds for cmd */
118 sctl_io.flags = SCTL_READ;
119 sctl_io.data_length = len;
124 sctl_io.data_length = data ? len : 0;
125 sctl_io.data = len ? data : 0;
129 if (ioctl(fd, SIOC_IO, &sctl_io) == -1) {
134 return sctl_io.cdb_status;
136 #elif defined OS_sunos || defined OS_solaris
137 struct uscsi_cmd uscsi_cmd;
138 memset(&uscsi_cmd, 0, sizeof uscsi_cmd);
139 uscsi_cmd.uscsi_cdb = (char *)cdb;
140 uscsi_cmd.uscsi_cdblen = cmdlen;
142 uscsi_cmd.uscsi_timeout = 20; /* msec? */
145 uscsi_cmd.uscsi_buflen = (u_int)len;
146 uscsi_cmd.uscsi_bufaddr = data;
150 uscsi_cmd.uscsi_flags = USCSI_READ;
153 uscsi_cmd.uscsi_flags = USCSI_WRITE;
157 if (ioctl(fd, USCSICMD, &uscsi_cmd) == -1) {
162 if(uscsi_cmd.uscsi_status) {
164 fprintf(stderr,"scsi status=%x\n",
165 (unsigned short)uscsi_cmd.uscsi_status);
171 #elif defined OS_linux
172 struct scsi_ioctl_command my_scsi_cmd;
175 memcpy(my_scsi_cmd.cmd, cdb, cmdlen); /* copy command */
179 my_scsi_cmd.inlen = 0;
180 my_scsi_cmd.outlen = len;
183 my_scsi_cmd.inlen = len;
184 my_scsi_cmd.outlen = 0;
185 memcpy(my_scsi_cmd.cmd + cmdlen,data,len);
189 if (ioctl(fd, SCSI_IOCTL_SEND_COMMAND, &my_scsi_cmd) < 0) {
196 memcpy(data, &my_scsi_cmd.cmd[0], len);
202 return 0; /* where to get scsi status? */
204 #elif (defined _SCO_DS) && (defined SCSIUSERCMD)
205 struct scsicmd my_scsi_cmd;
207 memset(my_scsi_cmd.cdb, 0, SCSICMDLEN); /* ensure zero pad */
208 memcpy(my_scsi_cmd.cdb, cdb, cmdlen);
209 my_scsi_cmd.cdb_len = cmdlen;
210 my_scsi_cmd.data_len = len;
211 my_scsi_cmd.data_ptr = data;
212 my_scsi_cmd.is_write = mode == SCSI_IO_WRITE;
213 if (ioctl(fd,SCSIUSERCMD,&my_scsi_cmd) == -1) {
214 perror("scsi_io: SCSIUSERCMD");
217 if (my_scsi_cmd.host_sts != 0 || my_scsi_cmd.target_sts != 0) {
218 fprintf(stderr, "scsi_io: scsi status: host=%x; target=%x\n",
219 (unsigned)my_scsi_cmd.host_sts,(unsigned)my_scsi_cmd.target_sts);
224 struct dsreq my_scsi_cmd;
226 my_scsi_cmd.ds_cmdbuf = (char *)cdb;
227 my_scsi_cmd.ds_cmdlen = cmdlen;
228 my_scsi_cmd.ds_databuf = data;
229 my_scsi_cmd.ds_datalen = len;
232 my_scsi_cmd.ds_flags = DSRQ_READ|DSRQ_SENSE;
235 my_scsi_cmd.ds_flags = DSRQ_WRITE|DSRQ_SENSE;
238 my_scsi_cmd.ds_time = 10000;
239 my_scsi_cmd.ds_link = 0;
240 my_scsi_cmd.ds_synch =0;
241 my_scsi_cmd.ds_ret =0;
242 if (ioctl(fd, DS_ENTER, &my_scsi_cmd) == -1) {
247 if(my_scsi_cmd.ds_status) {
249 fprintf(stderr,"scsi status=%x\n",
250 (unsigned short)my_scsi_cmd.ds_status);
255 #elif (defined OS_freebsd) && (__FreeBSD__ >= 2)
256 #define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
260 struct cam_device *cam_dev = (struct cam_device *) extra_data;
263 if (cam_dev==NULL || cam_dev->fd!=fd)
265 fprintf(stderr,"invalid file descriptor\n");
268 ccb = cam_getccb(cam_dev);
270 bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cmdlen);
272 if (mode == SCSI_IO_READ)
274 else if (data && len)
277 flags = CAM_DIR_NONE;
278 cam_fill_csio(&ccb->csio,
282 /* tag_action */ MSG_SIMPLE_Q_TAG,
283 /*data_ptr*/ len ? data : 0,
284 /*data_len */ data ? len : 0,
289 if (cam_send_ccb(cam_dev, ccb) < 0 ||
290 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
294 #elif defined(OS_netbsd) || defined(OS_netbsdelf)
297 memset(&sc, 0, sizeof(sc));
298 memcpy(sc.cmd, cdb, cmdlen);
306 sc.flags = SCCMD_READ;
309 sc.flags = SCCMD_WRITE;
313 if (ioctl(fd, SCIOCCOMMAND, &sc) == -1) {
314 perror("SCIOCCOMMAND ioctl");
320 fprintf(stderr, "SCSI command failed, retsts %d\n",
327 fprintf(stderr, "scsi_io not implemented\n");