Imported Upstream version 2.5.1
[debian/amanda] / changer-src / scsi-hpux_new.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-2000 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: scsi-hpux_new.c,v 1.19 2006/05/25 01:47:08 johnfranks Exp $
28  *
29  * Interface to execute SCSI commands on an HP-UX Workstation
30  *
31  * Copyright (c) Thomas Hepper th@ant.han.de
32  */
33
34
35 #include <amanda.h>
36
37 #ifdef HAVE_HPUX_LIKE_SCSI
38
39 # ifdef HAVE_FCNTL_H
40 #include <fcntl.h>
41 #endif
42 /*
43 #ifdef HAVE_STDIO_H
44 */
45 #include <stdio.h>
46 /*
47 #endif
48 */
49 #ifdef HAVE_SYS_IOCTL_H
50 #include <sys/ioctl.h>
51 #endif
52
53 #include <sys/scsi.h>
54 #include <sys/mtio.h>
55
56 #include <scsi-defs.h>
57
58 void SCSI_OS_Version()
59 {
60 #ifndef lint
61     static char rcsid[] = "$Id: scsi-hpux_new.c,v 1.19 2006/05/25 01:47:08 johnfranks Exp $";
62    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
63 #endif
64 }
65
66 int SCSI_OpenDevice(int ip)
67 {
68   extern OpenFiles_T *pDev;
69   int DeviceFD;
70   int i;
71
72   if (pDev[ip].inqdone == 0)
73     {
74       pDev[ip].inqdone = 1;
75       if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
76         {
77           pDev[ip].avail = 1;
78           pDev[ip].fd = DeviceFD;
79           pDev[ip].devopen = 1;
80           pDev[ip].SCSI = 0;
81           pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
82           
83           if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0)
84             {
85               if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER)
86                 {
87                   for (i=0;i < 16;i++)
88                     pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
89                   for (i=15; i >= 0 && !isalnum(pDev[ip].inquiry->prod_ident[i]) ; i--)
90                     {
91                       pDev[ip].inquiry->prod_ident[i] = '\0';
92                     }
93                   pDev[ip].SCSI = 1;
94
95                   if (pDev[ip].inquiry->type == TYPE_TAPE)
96                   {
97                           pDev[ip].type = stralloc("tape");
98                   }
99
100                   if (pDev[ip].inquiry->type == TYPE_CHANGER)
101                   {
102                           pDev[ip].type = stralloc("changer");
103                   }
104
105                   PrintInquiry(pDev[ip].inquiry);
106                   return(1);    
107                 } else {
108                   close(DeviceFD);
109                   free(pDev[ip].inquiry);
110                   return(0);
111               }
112             }
113             close(DeviceFD);
114             free(pDev[ip].inquiry);
115             pDev[ip].inquiry = NULL;
116             return(1);
117         }
118     } else {
119       if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
120         {
121           pDev[ip].fd = DeviceFD;
122           pDev[ip].devopen = 1;
123           return(1);
124         }
125     }
126
127   return(0); 
128 }
129
130 int SCSI_CloseDevice(int DeviceFD)
131 {
132   extern OpenFiles_T *pDev;
133   int ret;
134
135   ret = close(pDev[DeviceFD].fd);
136   pDev[DeviceFD].devopen = 0;
137   return(ret);
138 }
139
140 int SCSI_ExecuteCommand(int DeviceFD,
141                         Direction_T Direction,
142                         CDB_T CDB,
143                         size_t CDB_Length,
144                         void *DataBuffer,
145                         size_t DataBufferLength,
146                         RequestSense_T *RequestSenseBuf,
147                         size_t RequestSenseLength)
148 {
149   extern OpenFiles_T *pDev;
150   struct sctl_io sctl_io;
151   int Retries = 3;
152   int Zero = 0, Result;
153   
154   /* Basic sanity checks */
155   assert(CDB_Length <= UCHAR_MAX);
156   assert(RequestSenseLength <= UCHAR_MAX);
157
158   /* Clear buffer for cases where sense is not returned */
159   memset(RequestSenseBuf, 0, RequestSenseLength);
160
161   if (pDev[DeviceFD].avail == 0)
162     {
163       return(SCSI_ERROR);
164     }
165
166
167   memset(&sctl_io, '\0', SIZEOF(struct sctl_io));
168
169   sctl_io.flags = 0;  
170   sctl_io.max_msecs = 240000;
171   /* Set the cmd */
172   memcpy(sctl_io.cdb, CDB, CDB_Length);
173   sctl_io.cdb_length = CDB_Length;
174   /* Data buffer for results */
175   sctl_io.data = DataBuffer;
176   sctl_io.data_length = (unsigned)DataBufferLength;
177
178   switch (Direction) 
179     {
180     case Input:
181       sctl_io.flags = sctl_io.flags | SCTL_READ;
182       break;
183     case Output:
184       break;
185     }
186
187   while (--Retries > 0) {
188
189     if (pDev[DeviceFD].devopen == 0)
190       {
191         if (SCSI_OpenDevice(DeviceFD) == 0)
192           {
193             dbprintf(("SCSI_ExecuteCommand could not open %s: %s\n",
194                       pDev[DeviceFD].dev,
195                       strerror(errno)));
196             sleep(1); /* Give device a little time befor retry */
197             continue;
198           }
199       }
200
201     DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
202     Result = ioctl(pDev[DeviceFD].fd, SIOC_IO, &sctl_io);
203     SCSI_CloseDevice(DeviceFD);
204     if (Result < 0)
205       {
206         return(SCSI_ERROR);
207       }
208     
209     SCSI_CloseDevice(DeviceFD);
210
211     memcpy(RequestSenseBuf, sctl_io.sense, RequestSenseLength);
212     
213     switch(sctl_io.cdb_status)
214       {
215       case S_GOOD:
216         return(SCSI_OK);
217
218       case S_CHECK_CONDITION:
219         return(SCSI_CHECK);
220
221       default:
222         return(SCSI_ERROR);
223       }
224   }
225   return(SCSI_ERROR);
226 }
227 /*
228  * Send the command to the device with the
229  * ioctl interface
230  */
231 int Tape_Ioctl( int DeviceFD, int command)
232 {
233   extern OpenFiles_T *pDev;
234   struct mtop mtop;
235   int ret = 0;
236
237   if (pDev[DeviceFD].devopen == 0)
238       if (SCSI_OpenDevice(DeviceFD) == 0)
239           return(-1);
240
241   switch (command)
242     {
243     case IOCTL_EJECT:
244       mtop.mt_op = MTOFFL;
245       mtop.mt_count = 1;
246       break;
247
248     default:
249       break;
250     }
251
252   if (ioctl(pDev[DeviceFD].fd , MTIOCTOP, &mtop) != 0)
253     {
254       dbprintf(("Tape_Ioctl error ioctl %s\n", strerror(errno)));
255       SCSI_CloseDevice(DeviceFD);
256       return(-1);
257     }
258
259   SCSI_CloseDevice(DeviceFD);
260   return(ret);  
261 }
262
263
264
265 int Tape_Status( int DeviceFD)
266 {
267   extern OpenFiles_T *pDev;
268   struct mtget mtget;
269   int ret = 0;
270
271   if (pDev[DeviceFD].devopen == 0)
272       if (SCSI_OpenDevice(DeviceFD) == 0)
273           return(-1);
274
275   if (ioctl(pDev[DeviceFD].fd, MTIOCGET, &mtget) != 0)
276   {
277      dbprintf(("Tape_Status error ioctl %s\n", strerror(errno)));
278      SCSI_CloseDevice(DeviceFD);
279      return(-1);
280   }
281
282   dbprintf(("ioctl -> mtget.mt_gstat %X\n",mtget.mt_gstat));
283   if (GMT_ONLINE(mtget.mt_gstat))
284   {
285     ret = TAPE_ONLINE;
286   }
287
288   if (GMT_BOT(mtget.mt_gstat))
289   {
290     ret = ret | TAPE_BOT;
291   }
292
293   if (GMT_EOT(mtget.mt_gstat))
294   {
295     ret = ret | TAPE_EOT;
296   }
297
298   if (GMT_WR_PROT(mtget.mt_gstat))
299   {
300     ret = ret | TAPE_WR_PROT;
301   }
302
303   SCSI_CloseDevice(DeviceFD);
304   return(ret); 
305 }
306
307 int ScanBus(int print)
308 {
309 /*
310   Not yet
311 */
312   return(-1);
313 }
314 #endif
315 /*
316  * Local variables:
317  * indent-tabs-mode: nil
318  * c-file-style: gnu
319  * End:
320  */