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 #include <scsi-defs.h>
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
58 #include <sys/scarray.h>
61 #include <scsi-defs.h>
64 void SCSI_OS_Version(void)
67 static char rcsid[] = "$Id: scsi-aix.c,v 1.23 2006/05/25 01:47:07 johnfranks Exp $";
68 DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
73 int SCSI_OpenDevice(int ip)
77 extern OpenFiles_T *pDev;
79 if (pDev[ip].inqdone == 0)
83 * Check if it is an gsc (generic SCSI device)
85 if (strncmp("/dev/gsc", pDev[ip].dev, 8) == 0)
87 pDev[ip].flags = AIX_USE_GSC;
88 DeviceFD = open(pDev[ip].dev, 0);
90 DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC);
95 pDev[ip].fd = DeviceFD;
98 pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
100 if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0)
102 if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER)
105 pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
106 for (i=15; i >= 0 && !isalnum(pDev[ip].ident[i]) ; i--)
108 pDev[ip].ident[i] = '\0';
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);
126 free(pDev[ip].inquiry);
130 free(pDev[ip].inquiry);
131 pDev[ip].inquiry = NULL;
134 dbprintf(_("SCSI_OpenDevice %s failed\n"), pDev[ip].dev);
138 if ((DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC)) >= 0)
140 pDev[ip].fd = DeviceFD;
141 pDev[ip].devopen = 1;
148 int SCSI_CloseDevice(int DeviceFD)
151 extern OpenFiles_T *pDev;
153 ret = close(pDev[DeviceFD].fd);
154 pDev[DeviceFD].devopen = 0;
159 int SCSI_ExecuteCommand(int DeviceFD,
160 Direction_T Direction,
164 size_t DataBufferLength,
165 RequestSense_T *RequestSenseBuf,
166 size_t RequestSenseLength)
168 extern OpenFiles_T *pDev;
169 extern FILE * debug_file;
172 ExtendedRequestSense_T ExtendedRequestSense;
180 /* Basic sanity checks */
181 assert(CDB_Length <= UCHAR_MAX);
182 assert(RequestSenseLength <= UCHAR_MAX);
184 /* Clear buffer for cases where sense is not returned */
185 memset(RequestSenseBuf, 0, RequestSenseLength);
187 if (pDev[DeviceFD].avail == 0)
193 if (pDev[DeviceFD].flags == AIX_USE_GSC)
196 scmd.cdblen = CDB_Length;
197 scmd.data_buf = DataBuffer;
198 scmd.datalen = DataBufferLength;
199 scmd.sense_buf = (unsigned char *)RequestSenseBuf;
200 scmd.senselen = RequestSenseLength;
201 scmd.statusp = &sbyte;
213 if (ioctl(pDev[DeviceFD].fd, GSC_CMD, (caddr_t) &scmd) < 0) {
219 bzero(&ds, SIZEOF(struct sc_iocmd));
220 bzero(RequestSenseBuf, RequestSenseLength);
221 bzero(&ExtendedRequestSense, SIZEOF(ExtendedRequestSense_T));
225 ds.timeout_value = 60;
226 bcopy(CDB, ds.scsi_cdb, CDB_Length);
227 ds.command_length = CDB_Length;
229 * Data buffer for results
230 * If the size of the buffer is 0
231 * then keep this fields untouched
233 if (DataBufferLength > 0)
235 ds.buffer = DataBuffer;
236 ds.data_length = DataBufferLength;
239 /* Sense Buffer is not available on AIX ?*/
241 ds.req_sense_length = 255;
242 ds.request_sense_ptr = (unsigned char *)RequestSense;
247 ds.flags = ds.flags | B_READ;
250 ds.flags = ds.flags | B_WRITE;
253 DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
255 if (pDev[DeviceFD].devopen == 0)
256 if (SCSI_OpenDevice(DeviceFD) == 0)
258 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
259 SCSI_CloseDevice(DeviceFD);
263 switch (ds.scsi_bus_status)
266 SINQ[0] = SC_COM_REQUEST_SENSE;
272 bcopy(SINQ, ds.scsi_cdb, 6);
273 ds.command_length = 6;
274 ds.buffer = (unsigned char *)RequestSenseBuf;
275 ds.data_length = RequestSenseLength;
277 if (pDev[DeviceFD].devopen == 0)
278 if (SCSI_OpenDevice(DeviceFD) == 0)
280 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
281 SCSI_CloseDevice(DeviceFD);
287 case SC_CHECK_CONDITION:
288 SINQ[0] = SC_COM_REQUEST_SENSE;
294 bcopy(SINQ, ds.scsi_cdb, 6);
295 ds.command_length = 6;
296 ds.buffer = (unsigned char *)RequestSenseBuf;
297 ds.data_length = (unsigned char)RequestSenseLength;
299 if (pDev[DeviceFD].devopen == 0)
300 if (SCSI_OpenDevice(DeviceFD) == 0)
302 Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
303 SCSI_CloseDevice(DeviceFD);
308 * Makes no sense yet, may result in an endless loop
310 RequestSense(DeviceFD, &ExtendedRequestSense, 0);
311 DecodeExtSense(&ExtendedRequestSense, "SCSI_ExecuteCommand:", debug_file);
312 bcopy(&ExtendedRequestSense, RequestSenseBuf, RequestSenseLength);
314 dbprintf(_("ioctl on %d return %d\n"), pDev[DeviceFD].fd, Result);
315 dbprintf(_("ret: %d errno: %d (%s)\n"), Result, errno, "");
316 dbprintf(_("data_length: %d\n"), ds.data_length);
317 dbprintf(_("buffer: 0x%X\n"), ds.buffer);
318 dbprintf(_("timeout_value: %d\n"), ds.timeout_value);
319 dbprintf(_("status_validity: %d\n"), ds.status_validity);
320 dbprintf(_("scsi_bus_status: 0x%X\n"), ds.scsi_bus_status);
321 dbprintf(_("adapter_status: 0x%X\n"), ds.adapter_status);
322 dbprintf(_("adap_q_status: 0x%X\n"), ds.adap_q_status);
323 dbprintf(_("q_tag_msg: 0x%X\n"), ds.q_tag_msg);
324 dbprintf(_("flags: 0X%X\n"), ds.flags);
335 struct sc_inquiry si;
341 char bus[] = "/dev/scsi0";
343 if ((fd = open(bus, O_RDWR)) == -1)
346 for (target = 0; target < 7; target++)
348 for (lun = 0; lun < 7; lun++)
350 g_printf(_("Target:Lun %d:%d\n"), target,lun);
351 if (ioctl(fd, SCIOSTART, IDLUN(target, lun)) == -1) {
352 if (errno == EINVAL) {
353 g_printf(_("is in use\n"));
362 bzero(&si, SIZEOF(si));
365 si.inquiry_len = 255;
366 si.inquiry_ptr = (char *)&buf;
367 if (ioctl(fd, SCIOINQU, &si) == -1)
369 g_printf("SCIOINQU: %s\n", strerror(errno));
371 dump_hex(&buf, 255, DEBUG_INFO, SECTION_SCSI);
372 type = buf[0] & 0x1lf;
374 g_printf(_("%-28s|Device Type %d\n"),buf[8], type);
376 if (!isbusy && ioctl(fd, SCIOSTOP, IDLUN(target, lun)) == -1)
382 int Tape_Ioctl(int DeviceFD, int command)
384 extern OpenFiles_T *pDev;
389 int Tape_Status( int DeviceFD)
397 int ScanBus(int print)
408 * indent-tabs-mode: nil