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