summaryrefslogtreecommitdiff
path: root/du/scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'du/scsi.c')
-rw-r--r--du/scsi.c214
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;
+}