Imported Debian patch 1.3.11-1
[debian/mtx] / du / scsi.c
1 /* SCSI.C - Digital Unix-specific SCSI routines.
2 **
3 ** TECSys Development, Inc., April 1998
4 **
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.
10 **
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....
14 */
15
16 /*
17  *   libdi - scsipt SCSI Device Interface Library
18  *
19  *   Copyright (C) 1993-1997  Ti Kan
20  *   E-mail: ti@amb.org
21  *
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.
26  *
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.
31  *
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.
35  */
36
37 /*
38  *   Digital UNIX (OSF/1) and Ultrix support
39  *
40  *   Contributing author: Matt Thomas
41  *   E-Mail: thomas@lkg.dec.com
42  *
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
46  *   purposes only.
47  */
48
49 static int      bus = -1,
50                         target = -1,
51                         lun = -1;
52
53 static int SCSI_OpenDevice(char *DeviceName)
54 {
55         int             fd;
56         struct stat     stbuf;
57         int             saverr;
58
59         /* Check for validity of device node */
60         if (stat(DeviceName, &stbuf) < 0)
61         {
62                 FatalError("cannot stat SCSI device '%s' - %m\n", DeviceName);
63         }
64         if (!S_ISCHR(stbuf.st_mode))
65         {
66                 FatalError("device '%s': not appropriate device type - %m\n", DeviceName);
67         }
68
69         if ((fd = open(DeviceName, O_RDONLY | O_NDELAY, 0)) >= 0)
70         {
71                 struct devget   devget;
72
73                 if (ioctl(fd, DEVIOCGET, &devget) >= 0)
74                 {
75 #ifdef __osf__
76                         lun = devget.slave_num % 8;
77                         devget.slave_num /= 8;
78 #else
79                         lun = 0;
80 #endif
81                         target = devget.slave_num % 8;
82                         devget.slave_num /= 8;
83                         bus = devget.slave_num % 8;
84                         (void) close(fd);
85
86                         if ((fd = open(DEV_CAM, O_RDWR, 0)) >= 0 ||
87                                 (fd = open(DEV_CAM, O_RDONLY, 0)) >= 0)
88                         {
89                                 return (fd);
90                         }
91                         fd = bus = target = lun = -1;
92                         FatalError("error %d opening SCSI device '%s' - %m\n",
93                                          errno, DEV_CAM);
94                 }
95                 else
96                 {
97                         (void) close(fd);
98                         fd = bus = target = lun = -1;
99                         FatalError("error %d on DEVIOCGET ioctl for '%s' - %m\n",
100                                          errno, DeviceName);
101                 }
102         }
103         else
104         {
105                 saverr = errno;
106                 fd = bus = target = lun = -1;
107                 FatalError("cannot open SCSI device '%s', error %d - %m\n",
108                                 DeviceName, saverr);
109         }
110
111         fd = bus = target = lun = -1;
112         return -1;
113 }
114
115
116 static void SCSI_CloseDevice(char *DeviceName, int DeviceFD)
117 {
118         (void) close(DeviceFD);
119         bus = target = lun = -1;
120 }
121
122
123 static int SCSI_ExecuteCommand(int DeviceFD,
124                                                                 Direction_T Direction,
125                                                                 CDB_T *CDB,
126                                                                 int CDB_Length,
127                                                                 void *DataBuffer,
128                                                                 int DataBufferLength,
129                                                                 RequestSense_T *RequestSense)
130 {
131         UAGT_CAM_CCB    uagt;
132         CCB_SCSIIO      ccb;
133
134         if (DeviceFD < 0)
135                 return -1;
136
137         (void) memset(&uagt, 0, sizeof(uagt));
138         (void) memset(&ccb, 0, sizeof(ccb));
139
140         /* Setup the user agent ccb */
141         uagt.uagt_ccb = (CCB_HEADER *) &ccb;
142         uagt.uagt_ccblen = sizeof(CCB_SCSIIO);
143
144         /* Setup the scsi ccb */
145         (void) memcpy((unsigned char  *) ccb.cam_cdb_io.cam_cdb_bytes,
146                                 CDB, CDB_Length);
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;
151
152         if (DataBuffer != NULL && DataBufferLength > 0)
153         {
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;
158         }
159         else
160                 ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
161         
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 */
166
167         ccb.cam_sense_ptr = (u_char *) RequestSense;
168         ccb.cam_sense_len = sizeof(RequestSense_T);
169
170         ccb.cam_ch.cam_path_id = bus;
171         ccb.cam_ch.cam_target_id = target;
172         ccb.cam_ch.cam_target_lun = lun;
173
174         if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
175         {
176                 return -1;
177         }
178
179         /* Check return status */
180         if ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP)
181         {
182                 if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN)
183                 {
184                         (void) memset(&ccb, 0, sizeof(ccb));
185                         (void) memset(&uagt, 0, sizeof(uagt));
186
187                         /* Setup the user agent ccb */
188                         uagt.uagt_ccb = (CCB_HEADER  *) &ccb;
189                         uagt.uagt_ccblen = sizeof(CCB_RELSIM);
190
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;
195
196                         ccb.cam_ch.cam_path_id = bus;
197                         ccb.cam_ch.cam_target_id = target;
198                         ccb.cam_ch.cam_target_lun = lun;
199
200                         if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
201                                 return -1;
202                 }
203
204                 printf( "mtx: %s:\n%s=0x%x %s=0x%x\n",
205                                 "SCSI command fault",
206                                 "Opcode",
207                                 CDB[0],
208                                 "Status",
209                                 ccb.cam_scsi_status);
210                 return -1;
211         }
212
213         return 0;
214 }