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 # include <sys/scsi.h>
42 # include <sys/mtio.h> /* for eject_tape ioctls */
44 char *moddesc = "@(#)" __FILE__
45 ": HP/UX SCSI changer support routines @(#)";
48 * a cache of the robotics information, for use elsewhere
50 static struct element_addresses changer_info;
51 static int changer_info_init = 0;
54 /* Get the number of the first free slot
55 * return > 0 number of empty slot
56 * return = 0 no slot free
59 int GetCurrentSlot(int fd)
64 static int get_changer_info(fd)
68 if (!changer_info_init) {
69 rc = ioctl(fd, SIOC_ELEMENT_ADDRESSES, &changer_info);
75 int get_clean_state(char *dev)
79 This code works for Linux ....
80 maybe someone can do something like this under HPUX
84 unsigned char buffer[255];
87 if ((filenr = open(dev, O_RDWR)) < 0) {
91 memset(buffer, 0, SIZEOF(buffer));
93 *((int *) buffer) = 0; /* length of input data */
94 *(((int *) buffer) + 1) = 100; /* length of output buffer */
96 cmd = (char *) (((int *) buffer) + 2);
98 cmd[0] = 0x4d; /* LOG SENSE */
99 cmd[2] = (1 << 6)|0x33; /* PageControl, PageCode */
100 cmd[7] = 00; /* allocation length hi */
101 cmd[8] = 100; /* allocation length lo */
103 status = ioctl(filenr, 1 /* SCSI_IOCTL_SEND_COMMAND */ , buffer);
108 if ((buffer[16] & 0x1) == 1)
117 void eject_tape(char *tape)
118 /* This function ejects the tape from the drive */
121 This code works for Linux ....
122 This code works for HPUX too, see 'man 7 mt'
127 if ((mtfd = open(tape, O_RDWR)) < 0) {
131 mt_com.mt_op = MTOFFL;
133 if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {
143 * this routine checks a specified slot to see if it is empty
145 int isempty(int fd, int slot)
147 struct element_status es;
151 * fill the cache as required
153 get_changer_info(fd);
155 es.element = changer_info.first_storage + slot;
157 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
159 g_fprintf(stderr, _("%s: element status query failed: 0x%x %s\n"),
160 get_pname(), rc, strerror(errno));
168 * find the first empty slot
170 int find_empty(int fd, int start, int count)
172 struct element_status es;
175 get_changer_info(fd);
177 i = changer_info.first_storage;
180 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
181 } while ( (i <= (changer_info.first_storage + changer_info.num_storages))
185 g_fprintf(stderr,_("%s: element status query failed: 0x%x %s\n"),
186 get_pname(), rc, strerror(errno));
189 return (i - changer_info.first_storage - 1);
193 * returns one if there is a tape loaded in the drive
195 int drive_loaded(int fd, int drivenum)
197 struct element_status es;
200 get_changer_info(fd);
202 es.element = changer_info.first_data_transfer + drivenum;
204 rc = ioctl(fd, SIOC_ELEMENT_STATUS, &es);
206 g_fprintf(stderr,_("%s: drive status quer failed: 0x%x %s\n"),
207 get_pname(), rc, strerror(errno));
216 * unloads the drive, putting the tape in the specified slot
218 int unload(int fd, int drive, int slot)
220 struct move_medium_parms move;
223 get_changer_info(fd);
226 * pick the first transport, just for simplicity
228 move.transport = changer_info.first_transport;
230 move.source = changer_info.first_data_transfer + drive;
231 move.destination = changer_info.first_storage + slot;
234 rc = ioctl(fd, SIOC_MOVE_MEDIUM, &move);
236 g_fprintf(stderr,_("%s: move medium command failed: 0x%x %s\n"),
237 get_pname(), rc, strerror(errno));
245 * moves tape from the specified slot into the drive
247 int load(int fd, int drive, int slot)
249 struct move_medium_parms move;
252 get_changer_info(fd);
255 * use the first transport defined in the changer, for lack of a
258 move.transport = changer_info.first_transport;
260 move.source = changer_info.first_storage + slot;
261 move.destination = changer_info.first_data_transfer + drive;
264 rc = ioctl(fd, SIOC_MOVE_MEDIUM,&move);
266 g_fprintf(stderr,_("%s: drive load failed (MOVE): 0x%x %s\n"),
267 get_pname(), rc, strerror(errno));
273 int get_slot_count(int fd)
277 rc = get_changer_info(fd);
279 g_fprintf(stderr, _("%s: storage size query failed: 0x%x %s\n"), get_pname(),
280 rc, strerror(errno));
284 return(changer_info.num_storages);
288 int get_drive_count(int fd)
292 rc = get_changer_info(fd);
294 g_fprintf(stderr, _("%s: drive count query failed: 0x%x %s\n"), get_pname(),
295 rc, strerror(errno));
299 return changer_info.num_data_transfers;
302 /* This function should ask the drive if it is ready */
303 int Tape_Ready(char *tapedev, char *changerdev, int changerfd, int wait)
308 if (strcmp(tapedev, changerdev) == 0)
314 while ((cnt<wait) && (NULL==(out=fopen(tapedev,"w+")))){
323 int OpenDevice(char * tapedev)
327 DeviceFD = open(tapedev, O_RDWR);
328 dbprintf(_("OpenDevice(%s) returns %d\n"), tapedev, DeviceFD);
332 int CloseDevice(char *device, int DeviceFD)
336 ret = close(DeviceFD);
337 dbprintf(_("CloseDevice(%s) returns %d\n"), device, ret);