Imported Upstream version 3.1.0
[debian/amanda] / changer-src / scsi-irix.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-irix.c,v 1.23 2006/05/25 01:47:08 johnfranks Exp $
28  *
29  * Interface to execute SCSI commands on an SGI Workstation
30  *
31  * Copyright (c) Thomas Hepper th@ant.han.de
32  */
33
34
35 #include "amanda.h"
36
37 #include <sys/scsi.h>
38 #include <sys/dsreq.h>
39 #include <sys/mtio.h>
40
41 #include <scsi-defs.h>
42
43 void SCSI_OS_Version()
44 {
45 #ifndef lint
46    static char rcsid[] = "$Id: scsi-irix.c,v 1.23 2006/05/25 01:47:08 johnfranks Exp $";
47    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
48 #endif
49 }
50
51
52 /*
53  */
54 int SCSI_OpenDevice(int ip)
55 {
56   extern OpenFiles_T *pDev;
57   int DeviceFD;
58   int i;
59   
60   if (pDev[ip].inqdone == 0)
61     {
62       if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) >= 0)
63         {
64           pDev[ip].inqdone = 1;          pDev[ip].SCSI = 0;
65           pDev[ip].avail = 1;
66           pDev[ip].fd = DeviceFD;
67           pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
68           if (SCSI_Inquiry(ip, pDev[ip].inquiry, INQUIRY_SIZE) == 0)
69             {
70               if (pDev[ip].inquiry->type == TYPE_TAPE || pDev[ip].inquiry->type == TYPE_CHANGER)
71                 {
72                   for (i=0;i < 16 ;i++)
73                     pDev[ip].ident[i] = pDev[ip].inquiry->prod_ident[i];
74                   for (i=15; i >= 0 && !isalnum((int)pDev[ip].ident[i]) ; i--)
75                     {
76                       pDev[ip].ident[i] = '\0';
77                     }
78                   pDev[ip].SCSI = 1;
79                   close(DeviceFD);
80
81                   if (pDev[ip].inquiry->type == TYPE_TAPE)
82                   {
83                           pDev[ip].type = stralloc("tape");
84                   }
85
86                   if (pDev[ip].inquiry->type == TYPE_CHANGER)
87                   {
88                           pDev[ip].type = stralloc("changer");
89                   }
90
91                   PrintInquiry(pDev[ip].inquiry);
92                   return(1);
93                 } else { /* ! TYPE_TAPE ! TYPE_CHANGER */
94                   close(DeviceFD);
95                   free(pDev[ip].inquiry);
96                   pDev[ip].inquiry = NULL;
97                   pDev[ip].avail = 0;
98                   return(0);
99                 }
100             }
101             /* inquiry failed or no SCSI communication available */
102             close(DeviceFD);
103             free(pDev[ip].inquiry);
104             pDev[ip].inquiry = NULL;
105             pDev[ip].avail = 0;
106             return(0);
107         }
108     } else {
109       if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) >= 0)
110         {
111           pDev[ip].fd = DeviceFD;
112           pDev[ip].devopen = 1;
113           return(1);
114         } else {
115           pDev[ip].devopen = 0;
116           return(0);
117         }
118     }
119   return(0); 
120 }
121
122 int SCSI_CloseDevice(int DeviceFD)
123 {
124   extern OpenFiles_T *pDev;
125   int ret = 0;
126   
127   if (pDev[DeviceFD].devopen == 1)
128     {
129       pDev[DeviceFD].devopen = 0;
130       ret = close(pDev[DeviceFD].fd);
131     }
132
133   return(ret);
134 }
135
136 int SCSI_ExecuteCommand(int DeviceFD,
137                         Direction_T Direction,
138                         CDB_T CDB,
139                         size_t CDB_Length,
140                         void *DataBuffer,
141                         size_t DataBufferLength,
142                         RequestSense_T *pRequestSense,
143                         size_t RequestSenseLength)
144 {
145   extern OpenFiles_T *pDev;
146   ExtendedRequestSense_T ExtendedRequestSense;
147   struct dsreq ds;
148   int Result;
149   int retries = 5;
150   
151   /* Basic sanity checks */
152   assert(CDB_Length <= UCHAR_MAX);
153   assert(RequestSenseLength <= UCHAR_MAX);
154
155   /* Clear buffer for cases where sense is not returned */
156   memset(pRequestSense, 0, RequestSenseLength);
157
158   if (pDev[DeviceFD].avail == 0)
159     {
160       return(SCSI_ERROR);
161     }
162   
163   memset(&ds, 0, SIZEOF(struct dsreq));
164   memset(pRequestSense, 0, RequestSenseLength);
165   memset(&ExtendedRequestSense, 0 , SIZEOF(ExtendedRequestSense_T)); 
166   
167   ds.ds_flags = DSRQ_SENSE|DSRQ_TRACE|DSRQ_PRINT; 
168   /* Timeout */
169   ds.ds_time = 120000;
170   /* Set the cmd */
171   ds.ds_cmdbuf = (caddr_t)CDB;
172   ds.ds_cmdlen = CDB_Length;
173   /* Data buffer for results */
174   ds.ds_databuf = (caddr_t)DataBuffer;
175   ds.ds_datalen = DataBufferLength;
176   /* Sense Buffer */
177   ds.ds_sensebuf = (caddr_t)pRequestSense;
178   ds.ds_senselen = RequestSenseLength;
179   
180   switch (Direction) 
181     {
182     case Input:
183       ds.ds_flags = ds.ds_flags | DSRQ_READ;
184       break;
185     case Output:
186       ds.ds_flags = ds.ds_flags | DSRQ_WRITE;
187       break;
188     }
189   
190   while (--retries > 0) {
191     if (pDev[DeviceFD].devopen == 0)
192       {
193         if (SCSI_OpenDevice(DeviceFD) == 0)
194           {
195             dbprintf(_("SCSI_ExecuteCommand could not open %s: %s\n"),
196                       pDev[DeviceFD].dev,
197                       strerror(errno));
198             sleep(1); /* Give device a little time befor retry */
199             continue;
200           }
201       }
202     Result = ioctl(pDev[DeviceFD].fd, DS_ENTER, &ds);
203     SCSI_CloseDevice(DeviceFD);
204
205     if (Result < 0)
206       {
207         RET(&ds) = DSRT_DEVSCSI;
208         SCSI_CloseDevice(DeviceFD);
209         return (SCSI_ERROR);
210       }
211     DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
212     dbprintf(_("\t\t\tSTATUS(%02X) RET(%02X)\n"), STATUS(&ds), RET(&ds));
213     switch (STATUS(&ds))
214       {
215       case ST_BUSY:                /*  BUSY */
216         break;
217
218       case STA_RESERV:             /*  RESERV CONFLICT */
219         if (retries > 0)
220           sleep(2);
221         continue;
222
223       case ST_GOOD:                /*  GOOD 0x00 */
224         switch (RET(&ds))
225           {
226           case DSRT_SENSE:
227             return(SCSI_SENSE);
228           }
229           return(SCSI_OK);
230
231       case ST_CHECK:               /*  CHECK CONDITION 0x02 */ 
232         switch (RET(&ds))
233           {
234           case DSRT_SENSE:
235             return(SCSI_SENSE);
236           }
237         return(SCSI_CHECK);
238
239       case ST_COND_MET:            /*  INTERM/GOOD 0x10 */
240       default:
241         continue;
242       }
243   }     
244   return(SCSI_ERROR);
245 }
246
247 int Tape_Ioctl ( int DeviceFD, int command)
248 {
249   extern OpenFiles_T *pDev;
250   struct mtop mtop;
251   
252   if (pDev[DeviceFD].devopen == 0)
253     {
254       if (SCSI_OpenDevice(DeviceFD) == 0)
255           return(-1);
256     }
257   
258   switch (command)
259     {
260     case IOCTL_EJECT:
261       mtop.mt_op = MTUNLOAD;
262       mtop.mt_count = 1;
263       break;
264     default:
265       break;
266     }
267   
268   ioctl(pDev[DeviceFD].fd, MTIOCTOP, &mtop);
269   SCSI_CloseDevice(DeviceFD);
270   return(0);
271 }
272
273 int Tape_Status( int DeviceFD)
274 {
275   extern OpenFiles_T *pDev;
276   struct mtget mtget;
277   int ret = 0;
278
279   if (pDev[DeviceFD].devopen == 0)
280     {
281       if (SCSI_OpenDevice(DeviceFD) == 0)
282           return(-1);
283     }
284
285   if (ioctl(pDev[DeviceFD].fd , MTIOCGET, &mtget) != 0)
286     {
287       dbprintf(_("Tape_Status error ioctl %s\n"),strerror(errno));
288       SCSI_CloseDevice(DeviceFD);
289       return(-1);
290     }
291   
292   switch(mtget.mt_dposn)
293     {
294     case MT_EOT:
295       ret = ret | TAPE_EOT;
296       break;
297     case MT_BOT:
298       ret = ret | TAPE_BOT;
299       break;
300     case MT_WPROT:
301       ret = ret | TAPE_WR_PROT;
302       break;
303     case MT_ONL:
304       ret = TAPE_ONLINE;
305       break;
306     case MT_EOD:
307       break;
308     case MT_FMK:
309       break;
310     default:
311       break;
312     }
313
314   SCSI_CloseDevice(DeviceFD);
315   return(ret); 
316 }
317
318 int ScanBus(int print)
319 {
320   DIR *dir;
321   struct dirent *dirent;
322   extern OpenFiles_T *pDev;
323   extern int errno;
324   int count = 0;
325
326   if ((dir = opendir("/dev/scsi")) == NULL)
327     {
328       dbprintf(_("Can not read /dev/scsi: %s"), strerror(errno));
329       return 0;
330     }
331
332   while ((dirent = readdir(dir)) != NULL)
333     {
334       if (strstr(dirent->d_name, "sc") != NULL)
335       {
336         pDev[count].dev = malloc(10);
337         pDev[count].inqdone = 0;
338         g_sprintf(pDev[count].dev,"/dev/scsi/%s", dirent->d_name);
339         if (OpenDevice(count,pDev[count].dev, "Scan", NULL ))
340           {
341             SCSI_CloseDevice(count);
342             pDev[count].inqdone = 0;
343             
344             if (print)
345               {
346                 g_printf(_("name /dev/scsi/%s "), dirent->d_name);
347                 
348                 switch (pDev[count].inquiry->type)
349                   {
350                   case TYPE_DISK:
351                     g_printf(_("Disk"));
352                     break;
353                   case TYPE_TAPE:
354                     g_printf(_("Tape"));
355                     break;
356                   case TYPE_PRINTER:
357                     g_printf(_("Printer"));
358                     break;
359                   case TYPE_PROCESSOR:
360                     g_printf(_("Processor"));
361                     break;
362                   case TYPE_WORM:
363                     g_printf(_("Worm"));
364                     break;
365                   case TYPE_CDROM:
366                     g_printf(_("Cdrom"));
367                     break;
368                   case TYPE_SCANNER:
369                     g_printf(_("Scanner"));
370                     break;
371                   case TYPE_OPTICAL:
372                     g_printf(_("Optical"));
373                     break;
374                   case TYPE_CHANGER:
375                     g_printf(_("Changer"));
376                     break;
377                   case TYPE_COMM:
378                     g_printf(_("Comm"));
379                     break;
380                   default:
381                     g_printf(_("unknown %d"),pDev[count].inquiry->type);
382                     break;
383                   }
384                 g_printf("\n");
385               }
386             count++;
387             g_printf(_("Count %d\n"),count);
388           } else {
389             free(pDev[count].dev);
390             pDev[count].dev=NULL;
391           }
392       }
393     }
394   return 0;
395 }
396
397 /*
398  * Local variables:
399  * indent-tabs-mode: nil
400  * c-file-style: gnu
401  * End:
402  */