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-aix.c,v 1.23 2006/05/25 01:47:07 johnfranks Exp $
29 * Interface to execute SCSI commands on an AIX System
31 * Copyright (c) Thomas Hepper th@ant.han.de
37 #ifdef HAVE_AIX_LIKE_SCSI
39 #include <scsi-defs.h>
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
60 #include <sys/scarray.h>
63 #include <scsi-defs.h>
66 void SCSI_OS_Version(void)
69 static char rcsid[] = "$Id: scsi-aix.c,v 1.23 2006/05/25 01:47:07 johnfranks Exp $";
70 DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
75 int SCSI_OpenDevice(int ip)
79 extern OpenFiles_T *pDev;
81 if (pDev[ip].inqdone == 0)
85 * Check if it is an gsc (generic SCSI device)
87 if (strncmp("/dev/gsc", pDev[ip].dev, 8) == 0)
89 pDev[ip].flags = AIX_USE_GSC;
90 DeviceFD = open(pDev[ip].dev, 0);
92 DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC);
97 pDev[ip].fd = DeviceFD;
100 pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
102 if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0)
104 if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER)
107 pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
108 for (i=15; i >= 0 && !isalnum(pDev[ip].ident[i]) ; i--)
110 pDev[ip].ident[i] = '\0';
114 if (pDev[ip].inquiry->type == TYPE_TAPE)
116 pDev[ip].type = stralloc("tape");
119 if (pDev[ip].inquiry->type == TYPE_CHANGER)
121 pDev[ip].type = stralloc("changer");
124 PrintInquiry(pDev[ip].inquiry);
128 free(pDev[ip].inquiry);
132 free(pDev[ip].inquiry);
133 pDev[ip].inquiry = NULL;
136 dbprintf(("SCSI_OpenDevice %s failed\n", pDev[ip].dev));
140 if ((DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC)) >= 0)
142 pDev[ip].fd = DeviceFD;
143 pDev[ip].devopen = 1;
150 int SCSI_CloseDevice(int DeviceFD)
153 extern OpenFiles_T *pDev;
155 ret = close(pDev[DeviceFD].fd);
156 pDev[DeviceFD].devopen = 0;
161 int SCSI_ExecuteCommand(int DeviceFD,
162 Direction_T Direction,
166 size_t DataBufferLength,
167 RequestSense_T *RequestSenseBuf,
168 size_t RequestSenseLength)
170 extern OpenFiles_T *pDev;
171 extern FILE * debug_file;
174 ExtendedRequestSense_T ExtendedRequestSense;
182 /* Basic sanity checks */
183 assert(CDB_Length <= UCHAR_MAX);
184 assert(RequestSenseLength <= UCHAR_MAX);
186 /* Clear buffer for cases where sense is not returned */
187 memset(RequestSenseBuf, 0, RequestSenseLength);
189 if (pDev[DeviceFD].avail == 0)
195 if (pDev[DeviceFD].flags == AIX_USE_GSC)
198 scmd.cdblen = CDB_Length;
199 scmd.data_buf = DataBuffer;
200 scmd.datalen = DataBufferLength;
201 scmd.sense_buf = (unsigned char *)RequestSenseBuf;
202 scmd.senselen = RequestSenseLength;
203 scmd.statusp = &sbyte;
215 if (ioctl(pDev[DeviceFD].fd, GSC_CMD, (caddr_t) &scmd) < 0) {
221 bzero(&ds, SIZEOF(struct sc_iocmd));
222 bzero(RequestSenseBuf, RequestSenseLength);
223 bzero(&ExtendedRequestSense, SIZEOF(ExtendedRequestSense_T));
227 ds.timeout_value = 60;
228 bcopy(CDB, ds.scsi_cdb, CDB_Length);
229 ds.command_length = CDB_Length;
231 * Data buffer for results
232 * If the size of the buffer is 0
233 * then keep this fields untouched
235 if (DataBufferLength > 0)
237 ds.buffer = DataBuffer;
238 ds.data_length = DataBufferLength;
241 /* Sense Buffer is not available on AIX ?*/
243 ds.req_sense_length = 255;
244 ds.request_sense_ptr = (unsigned char *)RequestSense;
249 ds.flags = ds.flags | B_READ;
252 ds.flags = ds.flags | B_WRITE;
255 DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
257 if (pDev[DeviceFD].devopen == 0)
258 if (SCSI_OpenDevice(DeviceFD) == 0)
260 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
261 SCSI_CloseDevice(DeviceFD);
265 switch (ds.scsi_bus_status)
268 SINQ[0] = SC_COM_REQUEST_SENSE;
274 bcopy(SINQ, ds.scsi_cdb, 6);
275 ds.command_length = 6;
276 ds.buffer = (unsigned char *)RequestSenseBuf;
277 ds.data_length = RequestSenseLength;
279 if (pDev[DeviceFD].devopen == 0)
280 if (SCSI_OpenDevice(DeviceFD) == 0)
282 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
283 SCSI_CloseDevice(DeviceFD);
289 case SC_CHECK_CONDITION:
290 SINQ[0] = SC_COM_REQUEST_SENSE;
296 bcopy(SINQ, ds.scsi_cdb, 6);
297 ds.command_length = 6;
298 ds.buffer = (unsigned char *)RequestSenseBuf;
299 ds.data_length = (unsigned char)RequestSenseLength;
301 if (pDev[DeviceFD].devopen == 0)
302 if (SCSI_OpenDevice(DeviceFD) == 0)
304 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
305 SCSI_CloseDevice(DeviceFD);
310 * Makes no sense yet, may result in an endless loop
312 RequestSense(DeviceFD, &ExtendedRequestSense, 0);
313 DecodeExtSense(&ExtendedRequestSense, "SCSI_ExecuteCommand:", debug_file);
314 bcopy(&ExtendedRequestSense, RequestSenseBuf, RequestSenseLength);
316 dbprintf(("ioctl on %d return %d\n", pDev[DeviceFD].fd, Result));
317 dbprintf(("ret: %d errno: %d (%s)\n", Result, errno, ""));
318 dbprintf(("data_length: %d\n", ds.data_length));
319 dbprintf(("buffer: 0x%X\n", ds.buffer));
320 dbprintf(("timeout_value: %d\n", ds.timeout_value));
321 dbprintf(("status_validity: %d\n", ds.status_validity));
322 dbprintf(("scsi_bus_status: 0x%X\n", ds.scsi_bus_status));
323 dbprintf(("adapter_status: 0x%X\n", ds.adapter_status));
324 dbprintf(("adap_q_status: 0x%X\n", ds.adap_q_status));
325 dbprintf(("q_tag_msg: 0x%X\n", ds.q_tag_msg));
326 dbprintf(("flags: 0X%X\n", ds.flags));
337 struct sc_inquiry si;
343 char bus[] = "/dev/scsi0";
345 if ((fd = open(bus, O_RDWR)) == -1)
348 for (target = 0; target < 7; target++)
350 for (lun = 0; lun < 7; lun++)
352 printf("Target:Lun %d:%d\n", target,lun);
353 if (ioctl(fd, SCIOSTART, IDLUN(target, lun)) == -1) {
354 if (errno == EINVAL) {
355 printf("is in use\n");
364 bzero(&si, SIZEOF(si));
367 si.inquiry_len = 255;
368 si.inquiry_ptr = (char *)&buf;
369 if (ioctl(fd, SCIOINQU, &si) == -1)
371 printf("SCIOINQU: %s\n", strerror(errno));
373 dump_hex(&buf, 255, DEBUG_INFO, SECTION_SCSI);
374 type = buf[0] & 0x1lf;
376 printf("%-28s|Device Type %d\n",buf[8], type);
378 if (!isbusy && ioctl(fd, SCIOSTOP, IDLUN(target, lun)) == -1)
384 int Tape_Ioctl(int DeviceFD, int command)
386 extern OpenFiles_T *pDev;
391 int Tape_Status( int DeviceFD)
399 int ScanBus(int print)
411 * indent-tabs-mode: nil