c046734b8dc5f63e8a05f6a7078bc4e2b5fc3f07
[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.18 2005/10/15 13:20:47 martinea 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 #ifdef HAVE_SYS_SCSI_H
53 #include <sys/scsi.h>
54 #endif
55
56 #include <sys/mtio.h>
57
58 #include <scsi-defs.h>
59
60 void SCSI_OS_Version()
61 {
62 #ifndef lint
63     static char rcsid[] = "$Id: scsi-hpux_new.c,v 1.18 2005/10/15 13:20:47 martinea Exp $";
64    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
65 #endif
66 }
67
68 int SCSI_OpenDevice(int ip)
69 {
70   extern OpenFiles_T *pDev;
71   int DeviceFD;
72   int i;
73
74   if (pDev[ip].inqdone == 0)
75     {
76       pDev[ip].inqdone = 1;
77       if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
78         {
79           pDev[ip].avail = 1;
80           pDev[ip].fd = DeviceFD;
81           pDev[ip].devopen = 1;
82           pDev[ip].SCSI = 0;
83           pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
84           
85           if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0)
86             {
87               if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER)
88                 {
89                   for (i=0;i < 16;i++)
90                     pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
91                   for (i=15; i >= 0 && !isalnum(pDev[ip].inquiry->prod_ident[i]) ; i--)
92                     {
93                       pDev[ip].inquiry->prod_ident[i] = '\0';
94                     }
95                   pDev[ip].SCSI = 1;
96
97                   if (pDev[ip].inquiry->type == TYPE_TAPE)
98                   {
99                           pDev[ip].type = stralloc("tape");
100                   }
101
102                   if (pDev[ip].inquiry->type == TYPE_CHANGER)
103                   {
104                           pDev[ip].type = stralloc("changer");
105                   }
106
107                   PrintInquiry(pDev[ip].inquiry);
108                   return(1);    
109                 } else {
110                   close(DeviceFD);
111                   free(pDev[ip].inquiry);
112                   return(0);
113               }
114             } else {
115               close(DeviceFD);
116               free(pDev[ip].inquiry);
117               pDev[ip].inquiry = NULL;
118               return(1);
119             }
120           return(1);
121         }
122     } else {
123       if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
124         {
125           pDev[ip].fd = DeviceFD;
126           pDev[ip].devopen = 1;
127           return(1);
128         }
129     }
130
131   return(0); 
132 }
133
134 int SCSI_CloseDevice(int DeviceFD)
135 {
136   extern OpenFiles_T *pDev;
137   int ret;
138
139   ret = close(pDev[DeviceFD].fd);
140   pDev[DeviceFD].devopen = 0;
141   return(ret);
142 }
143
144 int SCSI_ExecuteCommand(int DeviceFD,
145                         Direction_T Direction,
146                         CDB_T CDB,
147                         int CDB_Length,
148                         void *DataBuffer,
149                         int DataBufferLength,
150                         char *RequestSense,
151                         int RequestSenseLength)
152 {
153   extern OpenFiles_T *pDev;
154   struct sctl_io sctl_io;
155   extern int errno;
156   int Retries = 3;
157   int Zero = 0, Result;
158   
159   if (pDev[DeviceFD].avail == 0)
160     {
161       return(SCSI_ERROR);
162     }
163
164
165   memset(&sctl_io, '\0', sizeof(struct sctl_io));
166
167   sctl_io.flags = 0;  
168   sctl_io.max_msecs = 240000;
169   /* Set the cmd */
170   memcpy(sctl_io.cdb, CDB, CDB_Length);
171   sctl_io.cdb_length = CDB_Length;
172   /* Data buffer for results */
173   sctl_io.data = DataBuffer;
174   sctl_io.data_length = (unsigned)DataBufferLength;
175
176   switch (Direction) 
177     {
178     case Input:
179       sctl_io.flags = sctl_io.flags | SCTL_READ;
180       break;
181     case Output:
182       break;
183     }
184
185   while (--Retries > 0) {
186
187     if (pDev[DeviceFD].devopen == 0)
188       {
189         if (SCSI_OpenDevice(DeviceFD) == 0)
190           {
191             dbprintf(("SCSI_ExecuteCommand could not open %s: %s\n",
192                       pDev[DeviceFD].dev,
193                       strerror(errno)));
194             sleep(1); /* Give device a little time befor retry */
195             continue;
196           }
197       }
198
199     DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
200     Result = ioctl(pDev[DeviceFD].fd, SIOC_IO, &sctl_io);
201     SCSI_CloseDevice(DeviceFD);
202     if (Result < 0)
203       {
204         return(SCSI_ERROR);
205       }
206     
207     SCSI_CloseDevice(DeviceFD);
208
209     memcpy(RequestSense, sctl_io.sense, RequestSenseLength);
210     
211     switch(sctl_io.cdb_status)
212       {
213       case S_GOOD:
214         return(SCSI_OK);
215       case S_CHECK_CONDITION:
216         return(SCSI_CHECK);
217         break;
218       default:
219         return(SCSI_ERROR);
220         break;
221       }
222   }
223   return(SCSI_ERROR);
224 }
225 /*
226  * Send the command to the device with the
227  * ioctl interface
228  */
229 int Tape_Ioctl( int DeviceFD, int command)
230 {
231   extern OpenFiles_T *pDev;
232   struct mtop mtop;
233   int ret = 0;
234
235   if (pDev[DeviceFD].devopen == 0)
236       if (SCSI_OpenDevice(DeviceFD) == 0)
237           return(-1);
238
239   switch (command)
240     {
241     case IOCTL_EJECT:
242       mtop.mt_op = MTOFFL;
243       mtop.mt_count = 1;
244       break;
245     default:
246       break;
247     }
248
249   if (ioctl(pDev[DeviceFD].fd , MTIOCTOP, &mtop) != 0)
250     {
251       dbprintf(("Tape_Ioctl error ioctl %d\n",errno));
252       SCSI_CloseDevice(DeviceFD);
253       return(-1);
254     }
255
256   SCSI_CloseDevice(DeviceFD);
257   return(ret);  
258 }
259
260
261
262 int Tape_Status( int DeviceFD)
263 {
264   extern OpenFiles_T *pDev;
265   struct mtget mtget;
266   int ret = 0;
267
268   if (pDev[DeviceFD].devopen == 0)
269       if (SCSI_OpenDevice(DeviceFD) == 0)
270           return(-1);
271
272   if (ioctl(pDev[DeviceFD].fd, MTIOCGET, &mtget) != 0)
273   {
274      dbprintf(("Tape_Status error ioctl %d\n",errno));
275      SCSI_CloseDevice(DeviceFD);
276      return(-1);
277   }
278
279   dbprintf(("ioctl -> mtget.mt_gstat %X\n",mtget.mt_gstat));
280   if (GMT_ONLINE(mtget.mt_gstat))
281   {
282     ret = TAPE_ONLINE;
283   }
284
285   if (GMT_BOT(mtget.mt_gstat))
286   {
287     ret = ret | TAPE_BOT;
288   }
289
290   if (GMT_EOT(mtget.mt_gstat))
291   {
292     ret = ret | TAPE_EOT;
293   }
294
295   if (GMT_WR_PROT(mtget.mt_gstat))
296   {
297     ret = ret | TAPE_WR_PROT;
298   }
299
300   SCSI_CloseDevice(DeviceFD);
301   return(ret); 
302 }
303
304 int ScanBus(int print)
305 {
306 /*
307   Not yet
308 */
309   return(-1);
310 }
311 #endif
312 /*
313  * Local variables:
314  * indent-tabs-mode: nil
315  * c-file-style: gnu
316  * End:
317  */