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
11 * Patch: Michael Enkelis, michaele@mxim.com)
16 #include "scsi-defs.h"
18 #if (defined(HAVE_CHIO_H) || defined(HAVE_SYS_CHIO_H)) \
19 && !defined(HAVE_CAMLIB_H)
21 #include <sys/types.h>
22 #include <sys/ioctl.h>
25 /* This include comes with Gerd Knor's SCSI media changer driver.
26 * If you are porting to another system, this is the file that defines
27 * ioctl calls for the changer. You will have to track it down yourself
28 * and possibly change all the ioctl() calls in this program.
31 #if defined(HAVE_LINUX_CHIO_H)
32 # include <linux/chio.h>
34 # if defined(HAVE_CHIO_H)
36 # else /* HAVE_SYS_CHIO_H must be defined */
37 # include <sys/chio.h>
38 # endif /* HAVE_CHIO_H */
39 #endif /* HAVE_LINUX_CHIO_H */
41 char *modname = "@(#)" __FILE__
42 ": SCSI support library for the chio(2) interface @(#)";
45 * cache the general changer information, for faster access elsewhere
47 static struct changer_params changer_info;
48 static int changer_info_init = 0;
49 int GetCurrentSlot(int fd, int drive);
50 int GetDeviceStatus (char *tapedev);
51 int OpenDevice (char *tapedev);
52 int CloseDevice (char *device, int DeviceFD);
53 int Tape_Ready1 ( char *tapedev , int wait);
54 int isempty(int fd, int slot);
55 int find_empty(int fd, int start, int count);
56 int get_clean_state(char *tapedev);
57 int get_slot_count(int fd);
58 int get_drive_count(int fd);
59 int eject_tape(char *tapedev);
60 int drive_loaded(int fd, int drivenum);
61 int unload(int fd, int drive, int slot);
62 int load(int fd, int drive, int slot);
64 static int get_changer_info(int fd)
68 if ( !changer_info_init ) {
69 rc = ioctl(fd, CHIOGPARAMS, &changer_info);
75 /* Get the number of the first free slot
76 * return > 0 number of empty slot
77 * return = 0 no slot free
80 int GetCurrentSlot(int fd, int drive)
82 struct changer_element_status ces;
90 ces.ces_type = CHET_ST;
91 ces.ces_data = malloc(changer_info.cp_nslots);
93 rc = ioctl(fd, CHIOGSTATUS, &ces);
95 dbprintf(_("changer status query failed: 0x%x %s\n"), rc, strerror(errno));
98 for (slot = 0; slot < changer_info.cp_nslots; slot++)
100 i = ces.ces_data[slot] & CESTATUS_FULL;
101 dbprintf(_("\tGetCurrentSlot slot %d = %d\n"), slot, i);
108 int get_clean_state(char *tapedev)
114 #define GMT_CLN(x) ((x) & 0x00008000)
115 rc = ( GMT_CLN(GetDeviceStatus(tapedev)) );
120 int eject_tape(char *tapedev)
121 /* This function ejects the tape from the drive */
126 if ( (mtfd = OpenDevice(tapedev) ) < 0) {
127 dbprintf(_("eject_tape : failed\n"));
131 mt_com.mt_op = MTOFFL;
133 if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
135 If the drive already ejected the tape due an error, or because it
136 was a cleaning tape, threre can be an error, which we should ignore
142 return(CloseDevice(tapedev, mtfd));
147 * this routine checks a specified slot to see if it is empty
149 int isempty(int fd, int slot)
151 struct changer_element_status ces;
155 get_changer_info(fd);
158 ces.ces_data = malloc(changer_info.cp_nslots);
160 rc = ioctl(fd, CHIOGSTATUS, &ces);
162 dbprintf(_("changer status query failed: 0x%x %s\n"), rc,strerror(errno));
166 i = ces.ces_data[slot] & CESTATUS_FULL;
173 * find the first empty slot
175 int find_empty(int fd, int start, int count)
177 struct changer_element_status ces;
184 get_changer_info(fd);
187 ces.ces_data = malloc(changer_info.cp_nslots);
189 rc = ioctl(fd,CHIOGSTATUS,&ces);
191 dbprintf(_("changer status query failed: 0x%x %s\n"), rc, strerror(errno));
196 while ((i < changer_info.cp_nslots)&&(ces.ces_data[i] & CESTATUS_FULL))
203 * returns one if there is a tape loaded in the drive
205 int drive_loaded(int fd, int drivenum)
207 struct changer_element_status ces;
211 get_changer_info(fd);
214 ces.ces_data = malloc(changer_info.cp_ndrives);
216 rc = ioctl(fd, CHIOGSTATUS, &ces);
218 dbprintf(_("drive status query failed: 0x%x %s\n"), rc, strerror(errno));
222 i = (ces.ces_data[drivenum] & CESTATUS_FULL);
230 * unloads the drive, putting the tape in the specified slot
232 int unload(int fd, int drive, int slot)
234 struct changer_move move;
237 dbprintf(_("unload : fd = %d, drive = %d, slot =%d\n"),fd, drive, slot);
239 move.cm_fromtype = CHET_DT;
240 move.cm_fromunit = drive;
241 move.cm_totype = CHET_ST;
242 move.cm_tounit = slot;
245 rc = ioctl(fd, CHIOMOVE, &move);
247 dbprintf(_("drive unload failed (MOVE): 0x%x %s\n"), rc, strerror(errno));
255 * moves tape from the specified slot into the drive
257 int load(int fd, int drive, int slot)
259 struct changer_move move;
262 dbprintf(_("load : fd = %d, drive = %d, slot =%d\n"),fd, drive, slot);
264 move.cm_fromtype = CHET_ST;
265 move.cm_fromunit = slot;
266 move.cm_totype = CHET_DT;
267 move.cm_tounit = drive;
270 rc = ioctl(fd,CHIOMOVE,&move);
272 dbprintf(_("drive load failed (MOVE): 0x%x %s\n"), rc, strerror(errno));
278 int get_slot_count(int fd)
282 rc = get_changer_info(fd);
284 dbprintf(_("slot count query failed: 0x%x %s\n"), rc, strerror(errno));
288 return changer_info.cp_nslots;
291 int get_drive_count(int fd)
295 rc = get_changer_info(fd);
297 dbprintf(_("drive count query failed: 0x%x %s\n"), rc, strerror(errno));
301 return changer_info.cp_ndrives;
304 /* This function should ask the drive if it is ready */
305 int Tape_Ready1 ( char *tapedev , int wait)
311 while ((cnt < wait) && (NULL==(out=fopen(tapedev,"w+")))){
324 dbprintf(_("Tape_Ready1 : wait for BOT : max %d seconds\n"),wait);
325 /* loop on status BOT */
326 while ((cnt < wait)) {
327 if ( GMT_BOT(GetDeviceStatus(tapedev)) ) {
330 /* dbprintf(("Tape_Ready1 : cnt %d\n",cnt)); */
335 dbprintf(_("Tape_Ready1 : BOT not found : %d seconds\n"),cnt);
338 dbprintf(_("Tape_Ready1 : BOT : %d seconds\n"),cnt);
344 int GetDeviceStatus (char *tapedev)
349 mtfd = OpenDevice(tapedev);
350 ioctl (mtfd, MTIOCGET, (char *)&status);
351 CloseDevice(tapedev, mtfd);
352 rc = status.mt_gstat;
356 int OpenDevice (char *tapedev)
360 DeviceFD = open(tapedev, O_RDWR);
364 int CloseDevice (char *device, int DeviceFD)
368 dbprintf(_("CloseDevice(%s)\n"), device);
369 rc = close(DeviceFD);
376 * indent-tabs-mode: nil
377 * c-default-style: gnu