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