2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-2000 University of Maryland at College Park
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.
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.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: scsi-hpux.c,v 1.15 2006/05/25 01:47:07 johnfranks Exp $
29 * scsi-chio.c -- library routines to handle the changer
30 * support for chio based systems
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
36 * Michael C. Povel 03.06.98 added dummy for eject_tape
41 #if defined(HAVE_HPUX_SCSI_CHIO)
42 # include <sys/scsi.h>
43 # include <sys/mtio.h> /* for eject_tape ioctls */
45 char *moddesc = "@(#)" __FILE__
46 ": HP/UX SCSI changer support routines @(#)";
49 * a cache of the robotics information, for use elsewhere
51 static struct element_addresses changer_info;
52 static int changer_info_init = 0;
55 /* Get the number of the first free slot
56 * return > 0 number of empty slot
57 * return = 0 no slot free
60 int GetCurrentSlot(int fd)
65 static int get_changer_info(fd)
69 if (!changer_info_init) {
70 rc = ioctl(fd, SIOC_ELEMENT_ADDRESSES, &changer_info);
76 int get_clean_state(char *dev)
80 This code works for Linux ....
81 maybe someone can do something like this under HPUX
85 unsigned char buffer[255];
88 if ((filenr = open(dev, O_RDWR)) < 0) {
92 memset(buffer, 0, SIZEOF(buffer));
94 *((int *) buffer) = 0; /* length of input data */
95 *(((int *) buffer) + 1) = 100; /* length of output buffer */
97 cmd = (char *) (((int *) buffer) + 2);
99 cmd[0] = 0x4d; /* LOG SENSE */
100 cmd[2] = (1 << 6)|0x33; /* PageControl, PageCode */
101 cmd[7] = 00; /* allocation length hi */
102 cmd[8] = 100; /* allocation length lo */
104 status = ioctl(filenr, 1 /* SCSI_IOCTL_SEND_COMMAND */ , buffer);
109 if ((buffer[16] & 0x1) == 1)
118 void eject_tape(char *tape)
119 /* This function ejects the tape from the drive */
122 This code works for Linux ....
123 This code works for HPUX too, see 'man 7 mt'
128 if ((mtfd = open(tape, O_RDWR)) < 0) {
132 mt_com.mt_op = MTOFFL;
134 if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
144 * this routine checks a specified slot to see if it is empty
146 int isempty(int fd, int slot)
148 struct element_status es;
152 * fill the cache as required
154 get_changer_info(fd);
156 es.element = changer_info.first_storage + slot;
158 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
160 fprintf(stderr, "%s: element status query failed: 0x%x %s\n",
161 get_pname(), rc, strerror(errno));
169 * find the first empty slot
171 int find_empty(int fd, int start, int count)
173 struct element_status es;
176 get_changer_info(fd);
178 i = changer_info.first_storage;
181 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
182 } while ( (i <= (changer_info.first_storage + changer_info.num_storages))
186 fprintf(stderr,"%s: element status query failed: 0x%x %s\n",
187 get_pname(), rc, strerror(errno));
190 return (i - changer_info.first_storage - 1);
194 * returns one if there is a tape loaded in the drive
196 int drive_loaded(int fd, int drivenum)
198 struct element_status es;
201 get_changer_info(fd);
203 es.element = changer_info.first_data_transfer + drivenum;
205 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
207 fprintf(stderr,"%s: drive status quer failed: 0x%x %s\n",
208 get_pname(), rc, strerror(errno));
217 * unloads the drive, putting the tape in the specified slot
219 int unload(int fd, int drive, int slot)
221 struct move_medium_parms move;
224 get_changer_info(fd);
227 * pick the first transport, just for simplicity
229 move.transport = changer_info.first_transport;
231 move.source = changer_info.first_data_transfer + drive;
232 move.destination = changer_info.first_storage + slot;
235 rc = ioctl(fd, SIOC_MOVE_MEDIUM, &move);
237 fprintf(stderr,"%s: move medium command failed: 0x%x %s\n",
238 get_pname(), rc, strerror(errno));
246 * moves tape from the specified slot into the drive
248 int load(int fd, int drive, int slot)
250 struct move_medium_parms move;
253 get_changer_info(fd);
256 * use the first transport defined in the changer, for lack of a
259 move.transport = changer_info.first_transport;
261 move.source = changer_info.first_storage + slot;
262 move.destination = changer_info.first_data_transfer + drive;
265 rc = ioctl(fd, SIOC_MOVE_MEDIUM,&move);
267 fprintf(stderr,"%s: drive load failed (MOVE): 0x%x %s\n",
268 get_pname(), rc, strerror(errno));
274 int get_slot_count(int fd)
278 rc = get_changer_info(fd);
280 fprintf(stderr, "%s: storage size query failed: 0x%x %s\n", get_pname(),
281 rc, strerror(errno));
285 return(changer_info.num_storages);
289 int get_drive_count(int fd)
293 rc = get_changer_info(fd);
295 fprintf(stderr, "%s: drive count query failed: 0x%x %s\n", get_pname(),
296 rc, strerror(errno));
300 return changer_info.num_data_transfers;
303 /* This function should ask the drive if it is ready */
304 int Tape_Ready(char *tapedev, char *changerdev, int changerfd, int wait)
309 if (strcmp(tapedev, changerdev) == 0)
315 while ((cnt<wait) && (NULL==(out=fopen(tapedev,"w+")))){
324 int OpenDevice(char * tapedev)
328 DeviceFD = open(tapedev, O_RDWR);
329 dbprintf(("%s: OpenDevice(%s) returns %d\n", get_pname(), tapedev, DeviceFD));
333 int CloseDevice(char *device, int DeviceFD)
337 ret = close(DeviceFD);
338 dbprintf(("%s: CloseDevice(%s) returns %d\n", get_pname(), device, ret));