1 /* SCSI.C - Digital Unix-specific SCSI routines.
3 ** TECSys Development, Inc., April 1998
5 ** This module began life as a part of XMCD, an X-windows CD player
6 ** program for many platforms. No real functionality from the original XMCD
7 ** is present in this module, but in the interest of making certain that
8 ** proper credit is given where it may be due, the copyrights and inclusions
9 ** from the XMCD module OS_DEC.C are included below.
11 ** The portions of coding in this module ascribable to TECSys Development
12 ** are hereby also released under the terms and conditions of version 2
13 ** of the GNU General Public License as described below....
17 * libdi - scsipt SCSI Device Interface Library
19 * Copyright (C) 1993-1997 Ti Kan
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Library General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Library General Public License for more details.
32 * You should have received a copy of the GNU Library General Public
33 * License along with this library; if not, write to the Free
34 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 * Digital UNIX (OSF/1) and Ultrix support
40 * Contributing author: Matt Thomas
41 * E-Mail: thomas@lkg.dec.com
43 * This software fragment contains code that interfaces the
44 * application to the Digital UNIX and Ultrix operating systems.
45 * The term Digital, Ultrix and OSF/1 are used here for identification
53 static int SCSI_OpenDevice(char *DeviceName)
59 /* Check for validity of device node */
60 if (stat(DeviceName, &stbuf) < 0)
62 FatalError("cannot stat SCSI device '%s' - %m\n", DeviceName);
64 if (!S_ISCHR(stbuf.st_mode))
66 FatalError("device '%s': not appropriate device type - %m\n", DeviceName);
69 if ((fd = open(DeviceName, O_RDONLY | O_NDELAY, 0)) >= 0)
73 if (ioctl(fd, DEVIOCGET, &devget) >= 0)
76 lun = devget.slave_num % 8;
77 devget.slave_num /= 8;
81 target = devget.slave_num % 8;
82 devget.slave_num /= 8;
83 bus = devget.slave_num % 8;
86 if ((fd = open(DEV_CAM, O_RDWR, 0)) >= 0 ||
87 (fd = open(DEV_CAM, O_RDONLY, 0)) >= 0)
91 fd = bus = target = lun = -1;
92 FatalError("error %d opening SCSI device '%s' - %m\n",
98 fd = bus = target = lun = -1;
99 FatalError("error %d on DEVIOCGET ioctl for '%s' - %m\n",
106 fd = bus = target = lun = -1;
107 FatalError("cannot open SCSI device '%s', error %d - %m\n",
111 fd = bus = target = lun = -1;
116 static void SCSI_CloseDevice(char *DeviceName, int DeviceFD)
118 (void) close(DeviceFD);
119 bus = target = lun = -1;
123 static int SCSI_ExecuteCommand(int DeviceFD,
124 Direction_T Direction,
128 int DataBufferLength,
129 RequestSense_T *RequestSense)
137 (void) memset(&uagt, 0, sizeof(uagt));
138 (void) memset(&ccb, 0, sizeof(ccb));
140 /* Setup the user agent ccb */
141 uagt.uagt_ccb = (CCB_HEADER *) &ccb;
142 uagt.uagt_ccblen = sizeof(CCB_SCSIIO);
144 /* Setup the scsi ccb */
145 (void) memcpy((unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes,
147 ccb.cam_cdb_len = CDB_Length;
148 ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
149 ccb.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO);
150 ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
152 if (DataBuffer != NULL && DataBufferLength > 0)
154 ccb.cam_ch.cam_flags |= (Direction == Input) ?
155 CAM_DIR_IN : CAM_DIR_OUT;
156 uagt.uagt_buffer = (u_char *) DataBuffer;
157 uagt.uagt_buflen = DataBufferLength;
160 ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
162 ccb.cam_ch.cam_flags |= CAM_DIS_AUTOSENSE;
163 ccb.cam_data_ptr = uagt.uagt_buffer;
164 ccb.cam_dxfer_len = uagt.uagt_buflen;
165 ccb.cam_timeout = 300; /* Timeout set to 5 minutes */
167 ccb.cam_sense_ptr = (u_char *) RequestSense;
168 ccb.cam_sense_len = sizeof(RequestSense_T);
170 ccb.cam_ch.cam_path_id = bus;
171 ccb.cam_ch.cam_target_id = target;
172 ccb.cam_ch.cam_target_lun = lun;
174 if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
179 /* Check return status */
180 if ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP)
182 if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN)
184 (void) memset(&ccb, 0, sizeof(ccb));
185 (void) memset(&uagt, 0, sizeof(uagt));
187 /* Setup the user agent ccb */
188 uagt.uagt_ccb = (CCB_HEADER *) &ccb;
189 uagt.uagt_ccblen = sizeof(CCB_RELSIM);
191 /* Setup the scsi ccb */
192 ccb.cam_ch.my_addr = (struct ccb_header *) &ccb;
193 ccb.cam_ch.cam_ccb_len = sizeof(CCB_RELSIM);
194 ccb.cam_ch.cam_func_code = XPT_REL_SIMQ;
196 ccb.cam_ch.cam_path_id = bus;
197 ccb.cam_ch.cam_target_id = target;
198 ccb.cam_ch.cam_target_lun = lun;
200 if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
204 printf( "mtx: %s:\n%s=0x%x %s=0x%x\n",
205 "SCSI command fault",
209 ccb.cam_scsi_status);