d7ae82fb24a53bb209ea8d333fe3d4cc2530d920
[debian/amanda] / changer-src / scsi-hpux.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.c,v 1.14 2001/02/08 19:19:08 ant Exp $
28  *
29  *      scsi-chio.c -- library routines to handle the changer
30  *                      support for chio based systems
31  *
32  *      Author: Eric Schnoebelen, eric@cirr.com
33  *      interface based on work by: Larry Pyeatt, pyeatt@cs.colostate.edu 
34  *      Copyright: 1997, 1998 Eric Schnoebelen
35  *              
36  *      Michael C. Povel 03.06.98 added dummy for eject_tape
37  */
38
39 #include "amanda.h"
40
41 #if defined(HAVE_HPUX_SCSI_CHIO)
42 # include <sys/scsi.h>
43 # include <sys/mtio.h>  /* for eject_tape ioctls */
44
45 char *moddesc = "@(#)" __FILE__
46                 ": HP/UX SCSI changer support routines @(#)";
47
48 /* 
49  * a cache of the robotics information, for use elsewhere
50  */
51 static struct element_addresses changer_info;
52 static int changer_info_init = 0;
53
54
55 /* Get the number of the first free slot
56  * return > 0 number of empty slot
57  * return = 0 no slot free
58  * return < 0 error
59  */
60 int GetCurrentSlot(int fd)
61 {
62
63 }
64
65 static int get_changer_info(fd)
66 {
67 int rc = 0;
68
69     if (!changer_info_init) {
70         rc = ioctl(fd, SIOC_ELEMENT_ADDRESSES, &changer_info);
71         changer_info_init++;
72     }
73     return (rc);
74 }
75
76 int get_clean_state(char *dev)
77 {
78 #if 0
79 /*
80   This code works for Linux .... 
81   maybe someone can do something like this under HPUX
82 */
83     int status;
84     unsigned char *cmd;
85     unsigned char buffer[255];
86     int filenr;
87
88     if ((filenr = open(dev, O_RDWR)) < 0) {
89         perror(dev);
90         return 0;
91     }
92     memset(buffer, 0, sizeof(buffer));
93
94     *((int *) buffer) = 0;      /* length of input data */
95     *(((int *) buffer) + 1) = 100;     /* length of output buffer */
96
97     cmd = (char *) (((int *) buffer) + 2);
98
99     cmd[0] = 0x4d;         /* LOG SENSE  */
100     cmd[2] = (1 << 6)|0x33;     /* PageControl, PageCode */
101     cmd[7] = 00;                 /* allocation length hi */
102     cmd[8] = 100;                 /* allocation length lo */
103
104     status = ioctl(filenr, 1 /* SCSI_IOCTL_SEND_COMMAND */ , buffer);
105
106     if (status)
107         return 0;
108
109     if ((buffer[16] & 0x1) == 1)
110           return 1;
111
112 #endif
113     return 0;
114
115 }
116
117
118 void eject_tape(char *tape)
119      /* This function ejects the tape from the drive */
120 {
121 /*
122   This code works for Linux .... 
123   This code works for HPUX too, see 'man 7 mt'
124 */
125     int mtfd;
126     struct mtop mt_com;
127
128     if ((mtfd = open(tape, O_RDWR)) < 0) {
129         perror(tape);
130         exit(2);
131     }
132     mt_com.mt_op = MTOFFL;
133     mt_com.mt_count = 1;
134     if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
135 /* Ignore the error
136        perror(tape);
137        exit(2);
138 */
139     }
140     close(mtfd);
141 }
142
143 /* 
144  * this routine checks a specified slot to see if it is empty 
145  */
146 int isempty(int fd, int slot)
147 {
148 struct element_status es;
149 int rc;
150
151     /*
152      * fill the cache as required
153      */
154     get_changer_info(fd);
155
156     es.element = changer_info.first_storage + slot;
157
158     rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
159     if (rc) {
160         fprintf(stderr, "%s: element status query failed: 0x%x %s\n",
161                                 get_pname(), rc, strerror(errno));
162         return(-1);
163     }
164
165     return !es.full;
166 }
167
168 /*
169  * find the first empty slot 
170  */
171 int find_empty(int fd)
172 {
173 struct element_status  es;
174 int i, rc;
175
176     get_changer_info(fd);
177
178     i = changer_info.first_storage;
179     do {
180         es.element = i++;
181         rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
182     } while ( (i <= (changer_info.first_storage + changer_info.num_storages))
183                 && !rc && es.full);
184
185     if (rc) {
186         fprintf(stderr,"%s: element status query failed: 0x%x %s\n",
187                                 get_pname(), rc, strerror(errno));
188         return -1;
189     }
190     return (i - changer_info.first_storage - 1);
191 }
192
193 /*
194  * returns one if there is a tape loaded in the drive 
195  */
196 int drive_loaded(int fd, int drivenum)
197 {
198 struct element_status  es;
199 int                            i,rc;
200
201     get_changer_info(fd);
202
203     es.element = changer_info.first_data_transfer + drivenum;
204
205     rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
206     if (rc) {
207         fprintf(stderr,"%s: drive status quer failed: 0x%x %s\n",
208                                 get_pname(), rc, strerror(errno));
209         return(-1);
210     }
211
212     return es.full;
213 }
214
215
216 /*
217  * unloads the drive, putting the tape in the specified slot 
218  */
219 int unload(int fd, int drive, int slot)
220 {
221 struct move_medium_parms  move;
222 int rc;
223
224     get_changer_info(fd);
225
226     /*
227      * pick the first transport, just for simplicity
228      */
229     move.transport = changer_info.first_transport;
230
231     move.source = changer_info.first_data_transfer + drive;
232     move.destination = changer_info.first_storage + slot;
233     move.invert = 0;
234
235     rc = ioctl(fd, SIOC_MOVE_MEDIUM, &move);
236     if (rc){
237         fprintf(stderr,"%s: move medium command failed: 0x%x %s\n",
238                 get_pname(), rc, strerror(errno));
239         return(-2);
240     }
241     return 0;
242 }
243
244
245 /*
246  * moves tape from the specified slot into the drive 
247  */
248 int load(int fd, int drive, int slot)
249 {
250 struct move_medium_parms  move;
251 int rc;
252
253     get_changer_info(fd);
254
255     /*
256      * use the first transport defined in the changer, for lack of a
257      * better choice..
258      */
259     move.transport = changer_info.first_transport;
260
261     move.source = changer_info.first_storage + slot;
262     move.destination = changer_info.first_data_transfer + drive;
263     move.invert = 0;
264
265     rc = ioctl(fd, SIOC_MOVE_MEDIUM,&move);
266     if (rc){
267         fprintf(stderr,"%s: drive load failed (MOVE): 0x%x %s\n",
268                 get_pname(), rc, strerror(errno));
269         return(-2);
270     }
271     return (rc);
272 }
273
274 int get_slot_count(int fd)
275
276 int rc;
277
278     rc = get_changer_info(fd);
279     if (rc) {
280         fprintf(stderr, "%s: storage size query failed: 0x%x %s\n", get_pname(),
281                                                 rc, strerror(errno));
282         return -1;
283     }
284
285     return(changer_info.num_storages);
286
287 }
288
289 int get_drive_count(int fd)
290
291     int rc;
292
293     rc = get_changer_info(fd);
294     if (rc) {
295         fprintf(stderr, "%s: drive count query failed: 0x%x %s\n", get_pname(),
296                                                 rc, strerror(errno));
297         return -1;
298     }
299
300     return changer_info.num_data_transfers;
301 }
302
303 /* This function should ask the drive if it is ready */
304 int Tape_Ready(char *tapedev, char *changerdev, int changerfd, int wait)
305 {
306   FILE *out=NULL;
307   int cnt=0;
308
309   if (strcmp(tapedev, changerdev) == 0)
310     {
311       sleep(wait);
312       return(0);
313     }
314
315   while ((cnt<wait) && (NULL==(out=fopen(tapedev,"w+")))){
316     cnt++;
317     sleep(1);
318   }
319   if (out != NULL)
320     fclose(out);
321   return 0;
322 }
323
324 int OpenDevice(char * tapedev)
325 {
326   int DeviceFD;
327
328   DeviceFD = open(tapedev, O_RDWR);
329   return(DeviceFD);
330 }
331
332 int CloseDevice(int DeviceFD)
333 {
334   int ret;
335
336   ret = close(DeviceFD);
337   return(ret);
338 }
339
340 #endif