diff options
Diffstat (limited to 'du/scsi.c')
-rw-r--r-- | du/scsi.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/du/scsi.c b/du/scsi.c new file mode 100644 index 0000000..8f11e16 --- /dev/null +++ b/du/scsi.c @@ -0,0 +1,214 @@ +/* SCSI.C - Digital Unix-specific SCSI routines. +** +** TECSys Development, Inc., April 1998 +** +** This module began life as a part of XMCD, an X-windows CD player +** program for many platforms. No real functionality from the original XMCD +** is present in this module, but in the interest of making certain that +** proper credit is given where it may be due, the copyrights and inclusions +** from the XMCD module OS_DEC.C are included below. +** +** The portions of coding in this module ascribable to TECSys Development +** are hereby also released under the terms and conditions of version 2 +** of the GNU General Public License as described below.... +*/ + +/* + * libdi - scsipt SCSI Device Interface Library + * + * Copyright (C) 1993-1997 Ti Kan + * E-mail: ti@amb.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Digital UNIX (OSF/1) and Ultrix support + * + * Contributing author: Matt Thomas + * E-Mail: thomas@lkg.dec.com + * + * This software fragment contains code that interfaces the + * application to the Digital UNIX and Ultrix operating systems. + * The term Digital, Ultrix and OSF/1 are used here for identification + * purposes only. + */ + +static int bus = -1, + target = -1, + lun = -1; + +static int SCSI_OpenDevice(char *DeviceName) +{ + int fd; + struct stat stbuf; + int saverr; + + /* Check for validity of device node */ + if (stat(DeviceName, &stbuf) < 0) + { + FatalError("cannot stat SCSI device '%s' - %m\n", DeviceName); + } + if (!S_ISCHR(stbuf.st_mode)) + { + FatalError("device '%s': not appropriate device type - %m\n", DeviceName); + } + + if ((fd = open(DeviceName, O_RDONLY | O_NDELAY, 0)) >= 0) + { + struct devget devget; + + if (ioctl(fd, DEVIOCGET, &devget) >= 0) + { +#ifdef __osf__ + lun = devget.slave_num % 8; + devget.slave_num /= 8; +#else + lun = 0; +#endif + target = devget.slave_num % 8; + devget.slave_num /= 8; + bus = devget.slave_num % 8; + (void) close(fd); + + if ((fd = open(DEV_CAM, O_RDWR, 0)) >= 0 || + (fd = open(DEV_CAM, O_RDONLY, 0)) >= 0) + { + return (fd); + } + fd = bus = target = lun = -1; + FatalError("error %d opening SCSI device '%s' - %m\n", + errno, DEV_CAM); + } + else + { + (void) close(fd); + fd = bus = target = lun = -1; + FatalError("error %d on DEVIOCGET ioctl for '%s' - %m\n", + errno, DeviceName); + } + } + else + { + saverr = errno; + fd = bus = target = lun = -1; + FatalError("cannot open SCSI device '%s', error %d - %m\n", + DeviceName, saverr); + } + + fd = bus = target = lun = -1; + return -1; +} + + +static void SCSI_CloseDevice(char *DeviceName, int DeviceFD) +{ + (void) close(DeviceFD); + bus = target = lun = -1; +} + + +static int SCSI_ExecuteCommand(int DeviceFD, + Direction_T Direction, + CDB_T *CDB, + int CDB_Length, + void *DataBuffer, + int DataBufferLength, + RequestSense_T *RequestSense) +{ + UAGT_CAM_CCB uagt; + CCB_SCSIIO ccb; + + if (DeviceFD < 0) + return -1; + + (void) memset(&uagt, 0, sizeof(uagt)); + (void) memset(&ccb, 0, sizeof(ccb)); + + /* Setup the user agent ccb */ + uagt.uagt_ccb = (CCB_HEADER *) &ccb; + uagt.uagt_ccblen = sizeof(CCB_SCSIIO); + + /* Setup the scsi ccb */ + (void) memcpy((unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes, + CDB, CDB_Length); + ccb.cam_cdb_len = CDB_Length; + ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb; + ccb.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO); + ccb.cam_ch.cam_func_code = XPT_SCSI_IO; + + if (DataBuffer != NULL && DataBufferLength > 0) + { + ccb.cam_ch.cam_flags |= (Direction == Input) ? + CAM_DIR_IN : CAM_DIR_OUT; + uagt.uagt_buffer = (u_char *) DataBuffer; + uagt.uagt_buflen = DataBufferLength; + } + else + ccb.cam_ch.cam_flags |= CAM_DIR_NONE; + + ccb.cam_ch.cam_flags |= CAM_DIS_AUTOSENSE; + ccb.cam_data_ptr = uagt.uagt_buffer; + ccb.cam_dxfer_len = uagt.uagt_buflen; + ccb.cam_timeout = 300; /* Timeout set to 5 minutes */ + + ccb.cam_sense_ptr = (u_char *) RequestSense; + ccb.cam_sense_len = sizeof(RequestSense_T); + + ccb.cam_ch.cam_path_id = bus; + ccb.cam_ch.cam_target_id = target; + ccb.cam_ch.cam_target_lun = lun; + + if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0) + { + return -1; + } + + /* Check return status */ + if ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP) + { + if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN) + { + (void) memset(&ccb, 0, sizeof(ccb)); + (void) memset(&uagt, 0, sizeof(uagt)); + + /* Setup the user agent ccb */ + uagt.uagt_ccb = (CCB_HEADER *) &ccb; + uagt.uagt_ccblen = sizeof(CCB_RELSIM); + + /* Setup the scsi ccb */ + ccb.cam_ch.my_addr = (struct ccb_header *) &ccb; + ccb.cam_ch.cam_ccb_len = sizeof(CCB_RELSIM); + ccb.cam_ch.cam_func_code = XPT_REL_SIMQ; + + ccb.cam_ch.cam_path_id = bus; + ccb.cam_ch.cam_target_id = target; + ccb.cam_ch.cam_target_lun = lun; + + if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0) + return -1; + } + + printf( "mtx: %s:\n%s=0x%x %s=0x%x\n", + "SCSI command fault", + "Opcode", + CDB[0], + "Status", + ccb.cam_scsi_status); + return -1; + } + + return 0; +} |