Imported Upstream version 2.5.1
[debian/amanda] / changer-src / scsi-chio.c
1 /*
2  *      $Id: scsi-chio.c,v 1.14 2006/05/25 01:47:07 johnfranks Exp $
3  *
4  *      scsi-chio.c -- library routines to handle the changer
5  *                      support for chio based systems
6  *
7  *      Author: Eric Schnoebelen, eric@cirr.com
8  *      based on work by: Larry Pyeatt,  pyeatt@cs.colostate.edu 
9  *      Copyright: 1997, 1998 Eric Schnoebelen
10  *              
11  */
12
13 #include "config.h"
14 #include "amanda.h"
15 #include "scsi-defs.h"
16
17 #if (defined(HAVE_CHIO_H) || defined(HAVE_SYS_CHIO_H)) \
18     && !defined(HAVE_CAMLIB_H)
19
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/mtio.h>
23
24 /* This include comes with Gerd Knor's SCSI media changer driver.
25  * If you are porting to another system, this is the file that defines
26  * ioctl calls for the changer.  You will have to track it down yourself
27  * and possibly change all the ioctl() calls in this program.  
28  */
29
30 #if defined(HAVE_CHIO_H)
31 #  include <chio.h>
32 #else /* HAVE_SYS_CHIO_H must be defined */
33 #  include <sys/chio.h>
34 #endif
35
36 char *modname = "@(#)" __FILE__ 
37                 ": SCSI support library for the chio(2) interface @(#)";
38
39 /*
40  * cache the general changer information, for faster access elsewhere
41  */
42 static struct changer_params changer_info;
43 static int changer_info_init = 0;
44
45 static int get_changer_info(fd)
46 {
47 int rc = 0;
48
49     if ( !changer_info_init ) {
50         rc = ioctl(fd, CHIOGPARAMS, &changer_info);
51         changer_info_init++;
52     }
53     return (rc);
54 }
55
56 /* Get the number of the first free slot
57  * return > 0 number of empty slot
58  * return = 0 no slot free
59  * return < 0 error
60  */
61 int GetCurrentSlot(int fd, int drive)
62 {
63     struct changer_element_status  ces;
64     int slot;
65     int i, rc;
66
67     get_changer_info(fd);
68
69     ces.ces_type = CHET_ST;
70     ces.ces_data = malloc(changer_info.cp_nslots);
71
72     rc = ioctl(fd, CHIOGSTATUS, &ces);
73     if (rc) {
74         dbprintf(("%s: changer status query failed: 0x%x %s\n",
75                         get_pname(), rc,strerror(errno)));
76         return -1;
77     }
78     for (slot = 0; slot < changer_info.cp_nslots; slot++)
79     {
80         i = ces.ces_data[slot] & CESTATUS_FULL;
81         dbprintf(("\tGetCurrentSlot slot %d = %d\n", slot, i));
82         if (!i)
83             return(slot);
84     }
85
86
87 }
88
89 int get_clean_state(int changerfd, char *changerdev, char *dev)
90 {
91     return 0;
92
93 }
94 void eject_tape(char *tape)
95 /* This function ejects the tape from the drive */
96 {
97 int mtfd;
98 struct mtop mt_com;
99
100     if ((mtfd = open(tape, O_RDWR)) < 0) {
101         dbprintf(("eject_tape : failed\n"));
102         perror(tape);
103         exit(2);
104     }
105     mt_com.mt_op = MTOFFL;
106     mt_com.mt_count = 1;
107     if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
108 /*
109     If the drive already ejected the tape due an error, or because it
110     was a cleaning tape, threre can be an error, which we should ignore 
111
112        perror(tape);
113        exit(2);
114 */
115     }
116     close(mtfd);
117 }
118
119
120 /* 
121  * this routine checks a specified slot to see if it is empty 
122  */
123 int isempty(int fd, int slot)
124 {
125 struct changer_element_status  ces;
126 int                            i,rc;
127 int type=CHET_ST;
128
129     get_changer_info(fd);
130
131     ces.ces_type = type;
132     ces.ces_data = malloc(changer_info.cp_nslots);
133
134     rc = ioctl(fd, CHIOGSTATUS, &ces);
135     if (rc) {
136         dbprintf(("%s: changer status query failed: 0x%x %s\n",
137                         get_pname(), rc,strerror(errno)));
138         return -1;
139     }
140
141     i = ces.ces_data[slot] & CESTATUS_FULL;
142
143     free(ces.ces_data);
144     return !i;
145 }
146
147 /*
148  * find the first empty slot 
149  */
150 int find_empty(int fd, int start, int count)
151 {
152 struct changer_element_status  ces;
153 int                            i,rc;
154 int type=CHET_ST;
155
156     get_changer_info(fd);
157
158     ces.ces_type = type;
159     ces.ces_data = malloc(changer_info.cp_nslots);
160
161     rc = ioctl(fd,CHIOGSTATUS,&ces);
162     if (rc) {
163         dbprintf(("%s: changer status query failed: 0x%x %s\n",
164                         get_pname(), rc, strerror(errno)));
165         return -1;
166     }
167
168     i = 0; 
169     while ((i < changer_info.cp_nslots)&&(ces.ces_data[i] & CESTATUS_FULL))
170         i++;
171     free(ces.ces_data);
172     return i;
173 }
174
175 /*
176  * returns one if there is a tape loaded in the drive 
177  */
178 int drive_loaded(int fd, int drivenum)
179 {
180 struct changer_element_status  ces;
181 int                            i,rc;
182 int type=CHET_DT;
183
184     get_changer_info(fd);
185
186     ces.ces_type = type;
187     ces.ces_data = malloc(changer_info.cp_ndrives);
188
189     rc = ioctl(fd, CHIOGSTATUS, &ces);
190     if (rc) {
191         dbprintf(("%s: drive status query failed: 0x%x %s\n",
192                         get_pname(), rc, strerror(errno)));
193         return -1;
194     }
195
196     i = (ces.ces_data[drivenum] & CESTATUS_FULL);
197
198     free(ces.ces_data);
199     return i;
200 }
201
202
203 /*
204  * unloads the drive, putting the tape in the specified slot 
205  */
206 int unload(int fd, int drive, int slot)
207 {
208 struct changer_move  move;
209 int rc;
210
211     dbprintf(("unload : fd = %d, drive = %d, slot =%d\n",fd, drive, slot));
212
213     move.cm_fromtype = CHET_DT;
214     move.cm_fromunit = drive;
215     move.cm_totype = CHET_ST;
216     move.cm_tounit = slot;
217     move.cm_flags = 0;
218
219     rc = ioctl(fd, CHIOMOVE, &move);
220     if (rc){
221         dbprintf(("%s: drive unload failed (MOVE): 0x%x %s\n",
222                 get_pname(), rc, strerror(errno)));
223         return(-2);
224     }
225     return 0;
226 }
227
228
229 /*
230  * moves tape from the specified slot into the drive 
231  */
232 int load(int fd, int drive, int slot)
233 {
234 struct changer_move  move;
235 int rc;
236
237     dbprintf(("load : fd = %d, drive = %d, slot =%d\n",fd, drive, slot));
238
239     move.cm_fromtype = CHET_ST;
240     move.cm_fromunit = slot;
241     move.cm_totype = CHET_DT;
242     move.cm_tounit = drive;
243     move.cm_flags = 0;
244
245     rc = ioctl(fd,CHIOMOVE,&move);
246     if (rc){
247         dbprintf(("%s: drive load failed (MOVE): 0x%x %s\n",
248                 get_pname(), rc, strerror(errno)));
249         return(-2);
250     }
251     return(0);
252 }
253
254 int get_slot_count(int fd)
255
256 int rc;
257
258     rc = get_changer_info(fd);
259     if (rc) {
260         dbprintf(("%s: slot count query failed: 0x%x %s\n", 
261                         get_pname(), rc, strerror(errno)));
262         return -1;
263     }
264
265     return changer_info.cp_nslots;
266 }
267
268 int get_drive_count(int fd)
269
270 int rc;
271
272     rc = get_changer_info(fd);
273     if (rc) {
274         dbprintf(("%s: drive count query failed: 0x%x %s\n",
275                         get_pname(), rc, strerror(errno)));
276         return -1;
277     }
278
279     return changer_info.cp_ndrives;
280 }
281
282 /* This function should ask the drive if it is ready */
283 int Tape_Ready ( char *tapedev , int wait)
284 {
285   FILE *out=NULL;
286   int cnt=0;
287   
288   while ((cnt < wait) && (NULL==(out=fopen(tapedev,"w+")))){
289     cnt++;
290     sleep(1);
291   }
292   if (out != NULL)
293     fclose(out);
294   return 0;
295 }
296
297 int OpenDevice (char *tapedev)
298 {
299   int DeviceFD;
300
301   DeviceFD = open(tapedev, O_RDWR);
302   return(DeviceFD);
303 }
304
305 int CloseDevice (char *device, int DeviceFD)
306 {
307    int ret;
308
309    dbprintf(("%s: CloseDevice(%s)\n", device, get_pname()));
310    ret = close(DeviceFD);
311
312    return ret;
313 }
314
315 #endif
316 /*
317  * Local variables:
318  * indent-tabs-mode: nil
319  * c-default-style: gnu
320  * End:
321  */