📄 scsi-aix.c
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-2000 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team. Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: scsi-aix.c,v 1.23 2006/05/25 01:47:07 johnfranks Exp $ * * Interface to execute SCSI commands on an AIX System * * Copyright (c) Thomas Hepper th@ant.han.de */#include <amanda.h>#include <scsi-defs.h>#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_STAT_H#include <sys/stat.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#include <sys/scarray.h>#include <sys/tape.h>#include <scsi-defs.h>#include <gscdds.h>void SCSI_OS_Version(void){#ifndef lint static char rcsid[] = "$Id: scsi-aix.c,v 1.23 2006/05/25 01:47:07 johnfranks Exp $"; DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);#endif}int SCSI_OpenDevice(int ip){ int DeviceFD; int i; extern OpenFiles_T *pDev; if (pDev[ip].inqdone == 0) { pDev[ip].inqdone = 1; /* * Check if it is an gsc (generic SCSI device) */ if (strncmp("/dev/gsc", pDev[ip].dev, 8) == 0) { pDev[ip].flags = AIX_USE_GSC; DeviceFD = open(pDev[ip].dev, 0); } else { DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC); } if (DeviceFD >= 0) { pDev[ip].avail = 1; pDev[ip].fd = DeviceFD; pDev[ip].SCSI = 0; pDev[ip].devopen = 1; pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE); if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0) { if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER) { for (i=0;i < 16;i++) pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i]; for (i=15; i >= 0 && !isalnum(pDev[ip].ident[i]) ; i--) { pDev[ip].ident[i] = '\0'; } pDev[ip].SCSI = 1; if (pDev[ip].inquiry->type == TYPE_TAPE) { pDev[ip].type = stralloc("tape"); } if (pDev[ip].inquiry->type == TYPE_CHANGER) { pDev[ip].type = stralloc("changer"); } PrintInquiry(pDev[ip].inquiry); return(1); } else { close(DeviceFD); free(pDev[ip].inquiry); return(0); } } free(pDev[ip].inquiry); pDev[ip].inquiry = NULL; return(1); } else { dbprintf(_("SCSI_OpenDevice %s failed\n"), pDev[ip].dev); return(0); } } else { if ((DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC)) >= 0) { pDev[ip].fd = DeviceFD; pDev[ip].devopen = 1; return(1); } } return(0);}int SCSI_CloseDevice(int DeviceFD){ int ret; extern OpenFiles_T *pDev; ret = close(pDev[DeviceFD].fd); pDev[DeviceFD].devopen = 0; return(ret);}int SCSI_ExecuteCommand(int DeviceFD, Direction_T Direction, CDB_T CDB, size_t CDB_Length, void *DataBuffer, size_t DataBufferLength, RequestSense_T *RequestSenseBuf, size_t RequestSenseLength){ extern OpenFiles_T *pDev; extern FILE * debug_file; CDB_T CDBSENSE; CDB_T SINQ; ExtendedRequestSense_T ExtendedRequestSense; struct sc_iocmd ds; scmd_t scmd; char sbyte; int Result; int isbusy = 0; int target = 3; /* Basic sanity checks */ assert(CDB_Length <= UCHAR_MAX); assert(RequestSenseLength <= UCHAR_MAX); /* Clear buffer for cases where sense is not returned */ memset(RequestSenseBuf, 0, RequestSenseLength); if (pDev[DeviceFD].avail == 0) { return(SCSI_ERROR); } if (pDev[DeviceFD].flags == AIX_USE_GSC) { scmd.cdb = CDB; scmd.cdblen = CDB_Length; scmd.data_buf = DataBuffer; scmd.datalen = DataBufferLength; scmd.sense_buf = (unsigned char *)RequestSenseBuf; scmd.senselen = RequestSenseLength; scmd.statusp = &sbyte; scmd.timeval = 60; switch (Direction) { case Input: scmd.rw = 0; break; case Output: scmd.rw = 1; break; } if (ioctl(pDev[DeviceFD].fd, GSC_CMD, (caddr_t) &scmd) < 0) { return(SCSI_ERROR); } return(SCSI_OK); } else { bzero(&ds, SIZEOF(struct sc_iocmd)); bzero(RequestSenseBuf, RequestSenseLength); bzero(&ExtendedRequestSense, SIZEOF(ExtendedRequestSense_T)); ds.flags = SC_ASYNC; /* Timeout */ ds.timeout_value = 60; bcopy(CDB, ds.scsi_cdb, CDB_Length); ds.command_length = CDB_Length; /* * Data buffer for results * If the size of the buffer is 0 * then keep this fields untouched */ if (DataBufferLength > 0) { ds.buffer = DataBuffer; ds.data_length = DataBufferLength; } /* Sense Buffer is not available on AIX ?*/ /* ds.req_sense_length = 255; ds.request_sense_ptr = (unsigned char *)RequestSense; */ switch (Direction) { case Input: ds.flags = ds.flags | B_READ; break; case Output: ds.flags = ds.flags | B_WRITE; break; } DecodeSCSI(CDB, "SCSI_ExecuteCommand : "); if (pDev[DeviceFD].devopen == 0) if (SCSI_OpenDevice(DeviceFD) == 0) return(SCSI_ERROR); Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds); SCSI_CloseDevice(DeviceFD); if ( Result < 0) { switch (ds.scsi_bus_status) { case SC_GOOD_STATUS: SINQ[0] = SC_COM_REQUEST_SENSE; SINQ[1] = 0; SINQ[2] = 0; SINQ[3] = 0; SINQ[4] = 0x1D; SINQ[5] = 0x80; bcopy(SINQ, ds.scsi_cdb, 6); ds.command_length = 6; ds.buffer = (unsigned char *)RequestSenseBuf; ds.data_length = RequestSenseLength; if (pDev[DeviceFD].devopen == 0) if (SCSI_OpenDevice(DeviceFD) == 0) return(SCSI_ERROR); Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds); SCSI_CloseDevice(DeviceFD); return(SCSI_OK); case SC_BUSY_STATUS: return(SCSI_BUSY); case SC_CHECK_CONDITION: SINQ[0] = SC_COM_REQUEST_SENSE; SINQ[1] = 0; SINQ[2] = 0; SINQ[3] = 0; SINQ[4] = 0x1D; SINQ[5] = 0x80; bcopy(SINQ, ds.scsi_cdb, 6); ds.command_length = 6; ds.buffer = (unsigned char *)RequestSenseBuf; ds.data_length = (unsigned char)RequestSenseLength; if (pDev[DeviceFD].devopen == 0) if (SCSI_OpenDevice(DeviceFD) == 0) return(SCSI_ERROR); Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds); SCSI_CloseDevice(DeviceFD); return(SCSI_CHECK); default: /* * Makes no sense yet, may result in an endless loop * RequestSense(DeviceFD, &ExtendedRequestSense, 0); DecodeExtSense(&ExtendedRequestSense, "SCSI_ExecuteCommand:", debug_file); bcopy(&ExtendedRequestSense, RequestSenseBuf, RequestSenseLength); */ dbprintf(_("ioctl on %d return %d\n"), pDev[DeviceFD].fd, Result); dbprintf(_("ret: %d errno: %d (%s)\n"), Result, errno, ""); dbprintf(_("data_length: %d\n"), ds.data_length); dbprintf(_("buffer: 0x%X\n"), ds.buffer); dbprintf(_("timeout_value: %d\n"), ds.timeout_value); dbprintf(_("status_validity: %d\n"), ds.status_validity); dbprintf(_("scsi_bus_status: 0x%X\n"), ds.scsi_bus_status); dbprintf(_("adapter_status: 0x%X\n"), ds.adapter_status); dbprintf(_("adap_q_status: 0x%X\n"), ds.adap_q_status); dbprintf(_("q_tag_msg: 0x%X\n"), ds.q_tag_msg); dbprintf(_("flags: 0X%X\n"), ds.flags); return(SCSI_ERROR); } } return(SCSI_OK); }}int SCSI_Scan(void){ int fd; struct sc_inquiry si; u_char buf[255]; int target; int lun; int isbusy; char type; char bus[] = "/dev/scsi0"; if ((fd = open(bus, O_RDWR)) == -1) return(1); for (target = 0; target < 7; target++) { for (lun = 0; lun < 7; lun++) { g_printf(_("Target:Lun %d:%d\n"), target,lun); if (ioctl(fd, SCIOSTART, IDLUN(target, lun)) == -1) { if (errno == EINVAL) { g_printf(_("is in use\n")); isbusy = 1; } else { return(1); } } else { isbusy = 0; } bzero(&si, SIZEOF(si)); si.scsi_id = target; si.lun_id = lun; si.inquiry_len = 255; si.inquiry_ptr = (char *)&buf; if (ioctl(fd, SCIOINQU, &si) == -1) { g_printf("SCIOINQU: %s\n", strerror(errno)); } else { dump_hex(&buf, 255, DEBUG_INFO, SECTION_SCSI); type = buf[0] & 0x1lf; buf[8+28] = 0; g_printf(_("%-28s|Device Type %d\n"),buf[8], type); } if (!isbusy && ioctl(fd, SCIOSTOP, IDLUN(target, lun)) == -1) return(1); } }}int Tape_Ioctl(int DeviceFD, int command){ extern OpenFiles_T *pDev; int ret = -1; return(ret);}int Tape_Status( int DeviceFD){/* Not yet*/ return(-1);}int ScanBus(int print){/* Not yet*/ SCSI_Scan(); return(-1);}/* * Local variables: * indent-tabs-mode: nil * c-file-style: gnu * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -