2 * $Id: scsi-chio.c,v 1.14 2006/05/25 01:47:07 johnfranks Exp $
4 * scsi-chio.c -- library routines to handle the changer
5 * support for chio based systems
7 * Author: Eric Schnoebelen, eric@cirr.com
8 * based on work by: Larry Pyeatt, pyeatt@cs.colostate.edu
9 * Copyright: 1997, 1998 Eric Schnoebelen
15 #include "scsi-defs.h"
17 #if (defined(HAVE_CHIO_H) || defined(HAVE_SYS_CHIO_H)) \
18 && !defined(HAVE_CAMLIB_H)
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
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.
30 #if defined(HAVE_CHIO_H)
32 #else /* HAVE_SYS_CHIO_H must be defined */
33 # include <sys/chio.h>
36 char *modname = "@(#)" __FILE__
37 ": SCSI support library for the chio(2) interface @(#)";
40 * cache the general changer information, for faster access elsewhere
42 static struct changer_params changer_info;
43 static int changer_info_init = 0;
45 static int get_changer_info(fd)
49 if ( !changer_info_init ) {
50 rc = ioctl(fd, CHIOGPARAMS, &changer_info);
56 /* Get the number of the first free slot
57 * return > 0 number of empty slot
58 * return = 0 no slot free
61 int GetCurrentSlot(int fd, int drive)
63 struct changer_element_status ces;
69 ces.ces_type = CHET_ST;
70 ces.ces_data = malloc(changer_info.cp_nslots);
72 rc = ioctl(fd, CHIOGSTATUS, &ces);
74 dbprintf(("%s: changer status query failed: 0x%x %s\n",
75 get_pname(), rc,strerror(errno)));
78 for (slot = 0; slot < changer_info.cp_nslots; slot++)
80 i = ces.ces_data[slot] & CESTATUS_FULL;
81 dbprintf(("\tGetCurrentSlot slot %d = %d\n", slot, i));
89 int get_clean_state(int changerfd, char *changerdev, char *dev)
94 void eject_tape(char *tape)
95 /* This function ejects the tape from the drive */
100 if ((mtfd = open(tape, O_RDWR)) < 0) {
101 dbprintf(("eject_tape : failed\n"));
105 mt_com.mt_op = MTOFFL;
107 if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
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
121 * this routine checks a specified slot to see if it is empty
123 int isempty(int fd, int slot)
125 struct changer_element_status ces;
129 get_changer_info(fd);
132 ces.ces_data = malloc(changer_info.cp_nslots);
134 rc = ioctl(fd, CHIOGSTATUS, &ces);
136 dbprintf(("%s: changer status query failed: 0x%x %s\n",
137 get_pname(), rc,strerror(errno)));
141 i = ces.ces_data[slot] & CESTATUS_FULL;
148 * find the first empty slot
150 int find_empty(int fd, int start, int count)
152 struct changer_element_status ces;
156 get_changer_info(fd);
159 ces.ces_data = malloc(changer_info.cp_nslots);
161 rc = ioctl(fd,CHIOGSTATUS,&ces);
163 dbprintf(("%s: changer status query failed: 0x%x %s\n",
164 get_pname(), rc, strerror(errno)));
169 while ((i < changer_info.cp_nslots)&&(ces.ces_data[i] & CESTATUS_FULL))
176 * returns one if there is a tape loaded in the drive
178 int drive_loaded(int fd, int drivenum)
180 struct changer_element_status ces;
184 get_changer_info(fd);
187 ces.ces_data = malloc(changer_info.cp_ndrives);
189 rc = ioctl(fd, CHIOGSTATUS, &ces);
191 dbprintf(("%s: drive status query failed: 0x%x %s\n",
192 get_pname(), rc, strerror(errno)));
196 i = (ces.ces_data[drivenum] & CESTATUS_FULL);
204 * unloads the drive, putting the tape in the specified slot
206 int unload(int fd, int drive, int slot)
208 struct changer_move move;
211 dbprintf(("unload : fd = %d, drive = %d, slot =%d\n",fd, drive, slot));
213 move.cm_fromtype = CHET_DT;
214 move.cm_fromunit = drive;
215 move.cm_totype = CHET_ST;
216 move.cm_tounit = slot;
219 rc = ioctl(fd, CHIOMOVE, &move);
221 dbprintf(("%s: drive unload failed (MOVE): 0x%x %s\n",
222 get_pname(), rc, strerror(errno)));
230 * moves tape from the specified slot into the drive
232 int load(int fd, int drive, int slot)
234 struct changer_move move;
237 dbprintf(("load : fd = %d, drive = %d, slot =%d\n",fd, drive, slot));
239 move.cm_fromtype = CHET_ST;
240 move.cm_fromunit = slot;
241 move.cm_totype = CHET_DT;
242 move.cm_tounit = drive;
245 rc = ioctl(fd,CHIOMOVE,&move);
247 dbprintf(("%s: drive load failed (MOVE): 0x%x %s\n",
248 get_pname(), rc, strerror(errno)));
254 int get_slot_count(int fd)
258 rc = get_changer_info(fd);
260 dbprintf(("%s: slot count query failed: 0x%x %s\n",
261 get_pname(), rc, strerror(errno)));
265 return changer_info.cp_nslots;
268 int get_drive_count(int fd)
272 rc = get_changer_info(fd);
274 dbprintf(("%s: drive count query failed: 0x%x %s\n",
275 get_pname(), rc, strerror(errno)));
279 return changer_info.cp_ndrives;
282 /* This function should ask the drive if it is ready */
283 int Tape_Ready ( char *tapedev , int wait)
288 while ((cnt < wait) && (NULL==(out=fopen(tapedev,"w+")))){
297 int OpenDevice (char *tapedev)
301 DeviceFD = open(tapedev, O_RDWR);
305 int CloseDevice (char *device, int DeviceFD)
309 dbprintf(("%s: CloseDevice(%s)\n", device, get_pname()));
310 ret = close(DeviceFD);
318 * indent-tabs-mode: nil
319 * c-default-style: gnu