2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-2000 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: scsi-bsd.c,v 1.18 2006/05/25 01:47:07 johnfranks Exp $
29 * Interface to execute SCSI commands on an BSD System (FreeBSD)
31 * Copyright (c) Thomes Hepper th@ant.han.de
37 #ifdef HAVE_BSD_LIKE_SCSI
46 #ifdef HAVE_SYS_TYPES_H
47 #include <sys/types.h>
49 #ifdef HAVE_SYS_STAT_H
56 #include <sys/scsiio.h>
59 #include <scsi-defs.h>
61 void SCSI_OS_Version()
64 static char rcsid[] = "$Id: scsi-bsd.c,v 1.18 2006/05/25 01:47:07 johnfranks Exp $";
65 DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
71 * Check if the device is already open,
72 * if no open it and save it in the list
76 * 0 -> device not opened
77 * 1 -> sucess , device open
79 int SCSI_OpenDevice(int ip)
81 extern OpenFiles_T *pDev;
87 * If the SCSI inquiry was not done lets try to get
88 * some infos about the device
90 if (pDev[ip].inqdone == 0) {
91 pDev[ip].inqdone = 1; /* Set it to 1, so the inq is done */
92 pDev[ip].SCSI = 0; /* This will only be set if the inquiry works */
93 pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
95 if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) >= 0) /* We need the device in read/write mode */
97 pDev[ip].devopen = 1; /* The device is open for use */
98 pDev[ip].avail = 1; /* And it is available, it could be opened */
99 if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0) /* Lets try to get the result of an SCSI inquiry */
101 if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER) /* If it worked and we got an type of */
102 /* either tape or changer continue */
104 for (i=0;i < 16 ;i++) /* Copy the product ident to the pDev struct */
105 pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
106 for (i=15; i >= 0 && !isalnum(pDev[ip].ident[i]); i--) /* And terminate it with an \0, remove all white space */
108 pDev[ip].ident[i] = '\0';
110 pDev[ip].SCSI = 1; /* OK, its an SCSI device ... */
112 if (pDev[ip].inquiry->type == TYPE_TAPE)
114 pDev[ip].type = stralloc("tape");
117 if (pDev[ip].inquiry->type == TYPE_CHANGER)
119 pDev[ip].type = stralloc("changer");
122 PrintInquiry(pDev[ip].inquiry); /* Some debug output */
123 return(1); /* All done */
125 free(pDev[ip].inquiry); /* The SCSI was ok, but not an TAPE/CHANGER device ... */
126 pDev[ip].devopen = 0;
129 return(0); /*Might be an ChgExit is better */
131 } else { /* if SCSI_Inquiry */ /* The inquiry failed */
132 free(pDev[ip].inquiry); /* free the allocated memory */
133 pDev[ip].inquiry = NULL;
134 return(1); /* Its not an SCSI device, but can be used for read/write */
137 return(0); /* Open failed .... */
138 } else { /* pDev[ip].inqdone */ /* OK this is the way we go if the device */
139 if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) >= 0) /* was opened successfull before */
141 pDev[ip].devopen = 1;
145 return(0); /* Default, return device not available */
150 * abd set the flags in the device struct
153 int SCSI_CloseDevice(int DeviceFD)
156 extern OpenFiles_T *pDev;
158 ret = close(pDev[DeviceFD].fd) ;
159 pDev[DeviceFD].devopen = 0;
163 int SCSI_ExecuteCommand(int DeviceFD,
164 Direction_T Direction,
168 size_t DataBufferLength,
169 RequestSense_T *pRequestSense,
170 size_t RequestSenseLength)
172 extern OpenFiles_T *pDev;
173 ExtendedRequestSense_T ExtendedRequestSense;
175 int Zero = 0, Result;
179 /* Basic sanity checks */
180 assert(CDB_Length <= UCHAR_MAX);
181 assert(RequestSenseLength <= UCHAR_MAX);
183 /* Clear buffer for cases where sense is not returned */
184 memset(pRequestSense, 0, RequestSenseLength);
186 if (pDev[DeviceFD].avail == 0)
191 memset(&ds, 0, SIZEOF(scsireq_t));
192 memset(pRequestSense, 0, RequestSenseLength);
193 memset(&ExtendedRequestSense, 0 , SIZEOF(ExtendedRequestSense_T));
195 ds.flags = SCCMD_ESCAPE;
199 memcpy(ds.cmd, CDB, CDB_Length);
200 ds.cmdlen = CDB_Length;
201 /* Data buffer for results */
202 if (DataBufferLength > 0)
204 ds.databuf = (caddr_t)DataBuffer;
205 ds.datalen = DataBufferLength;
209 ds.sense = (u_char)pRequestSense;
211 ds.senselen = RequestSenseLength;
216 ds.flags = ds.flags | SCCMD_READ;
219 ds.flags = ds.flags | SCCMD_WRITE;
223 while (--retries > 0) {
225 if (pDev[DeviceFD].devopen == 0)
226 if (SCSI_OpenDevice(DeviceFD) == 0)
228 Result = ioctl(pDev[DeviceFD].fd, SCIOCCOMMAND, &ds);
229 SCSI_CloseDevice(DeviceFD);
231 memcpy(pRequestSense, ds.sense, RequestSenseLength);
234 dbprintf(("errno : %s\n",strerror(errno)));
237 dbprintf(("SCSI_ExecuteCommand(BSD) %02X STATUS(%02X) \n", CDB[0], ds.retsts));
240 case SCCMD_BUSY: /* BUSY */
243 case SCCMD_OK: /* GOOD */
246 case SCCMD_SENSE: /* CHECK CONDITION */
257 * Send the command to the device with the
260 int Tape_Ioctl( int DeviceFD, int command)
262 extern OpenFiles_T *pDev;
266 if (pDev[DeviceFD].devopen == 0)
267 if (SCSI_OpenDevice(DeviceFD) == 0)
280 if (ioctl(pDev[DeviceFD].fd , MTIOCTOP, &mtop) != 0)
282 dbprintf(("Tape_Ioctl error ioctl %s\n",strerror(errno)));
283 SCSI_CloseDevice(DeviceFD);
287 SCSI_CloseDevice(DeviceFD);
291 int Tape_Status( int DeviceFD)
299 int ScanBus(int print)
310 * indent-tabs-mode: nil