1 /* MTX -- SCSI Tape Attached Medium Control Program
3 Copyright 1997-1998 Leonard N. Zubkoff <lnz@dandelion.com>
5 Changes 1999 Eric Lee Green to add support for multi-drive tape changers.
7 $Date: 2001/06/19 21:51:32 $
9 See mtx.c for licensing information.
13 #ifndef MTX_H /* protect against multiple includes... */
16 /* surround all the Unix-stuff w/ifndef VMS */
18 #include "[.vms]defs.h"
19 #else /* all the Unix stuff: */
21 #include "config.h" /* all the autoconf stuff. */
23 /* all the general Unix includes: */
37 # include <sys/types.h>
55 # include <sys/stat.h>
59 # include <sys/ioctl.h>
62 /* Now greately modified to use GNU Autoconf stuff: */
63 /* If we use the 'sg' interface, like Linux, do this: */
65 # include <scsi/scsi.h>
66 # include <scsi/scsi_ioctl.h>
68 typedef int DEVICE_TYPE; /* the sg interface uses this. */
69 # define HAVE_GET_ID_LUN 1 /* signal that we have it... */
72 /* The 'cam' interface, like FreeBSD: */
74 # include <camlib.h> /* easy (?) access to the CAM user library. */
75 # include <cam/cam_ccb.h>
76 # include <cam/scsi/scsi_message.h> /* sigh sigh sigh! */
77 typedef struct cam_device *DEVICE_TYPE;
81 /* the 'uscsi' interface, as used on Solaris: */
82 #if HAVE_SYS_SCSI_IMPL_USCSI_H
83 #include <sys/scsi/impl/uscsi.h>
84 typedef int DEVICE_TYPE;
87 /* the scsi_ctl interface, as used on HP/UX: */
88 #if HAVE_SYS_SCSI_CTL_H
89 # include <sys/wsio.h>
90 # include <sys/spinlock.h>
91 # include <sys/scsi.h>
92 # include <sys/scsi_ctl.h>
93 typedef int DEVICE_TYPE;
95 # define VERSION "1.2.12 hbb"
100 /* The 'tm_buf' interface, as used on AIX. */
101 #ifdef HAVE_SYS_SCSI_H
102 #include <sys/scsi.h>
103 #include <sys/scsi_buf.h>
104 #include <sys/devinfo.h> /* devinfo. */
105 typedef struct tm_device_type {
114 /* the 'dslib' interface, as used on SGI. */
117 typedef dsreq_t *DEVICE_TYPE; /* 64-bit pointers/32bit int on later sgi? */
121 #if ((defined(__alpha) && defined(__osf__)) || \
122 defined(ultrix) || defined(__ultrix))
127 #endif /* VMS protect. */
129 /* Do a test for LITTLE_ENDIAN_BITFIELDS. Use WORDS_BIGENDIAN as set
134 # define BIG_ENDIAN_BITFIELDS
136 # define LITTLE_ENDIAN_BITFIELDS
139 /* Get rid of some Hocky Pux defines: */
143 #ifdef S_RECOVERED_ERROR
144 #undef S_RECOVERED_ERROR
149 #ifdef S_MEDIUM_ERROR
150 #undef S_MEDIUM_ERROR
152 #ifdef S_HARDWARE_ERROR
153 #undef S_HARDWARE_ERROR
155 #ifdef S_UNIT_ATTENTION
156 #undef S_UNIT_ATTENTION
161 #ifdef S_VOLUME_OVERFLOW
162 #undef S_VOLUME_OVERFLOW
165 /* Note: These are only used for defaults for when we don't have
166 * the element assignment mode page to tell us real amount...
168 #define MAX_STORAGE_ELEMENTS 64 /* for the BIG jukeboxes! */
169 #define MAX_TRANSFER_ELEMENTS 2 /* we just do dual-drive for now :-} */
170 #define MAX_TRANSPORT_ELEMENTS 1 /* we just do one arm for now... */
172 /* These are flags used for the READ_ELEMENT_STATUS and MOVE_MEDIUM
175 typedef struct SCSI_Flags_Struct {
177 unsigned char invert;
178 unsigned char no_attached; /* ignore _attached bit */
179 unsigned char no_barcodes; /* don't try to get barcodes. */
187 typedef enum { false, true } boolean;
190 typedef enum { Input, Output } Direction_T;
193 typedef unsigned char CDB_T[12];
196 typedef struct Inquiry
198 #ifdef LITTLE_ENDIAN_BITFIELDS
199 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
200 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
201 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
202 boolean RMB:1; /* Byte 1 Bit 7 */
203 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
204 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
205 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
206 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
207 unsigned char :2; /* Byte 3 Bits 4-5 */
208 boolean TrmIOP:1; /* Byte 3 Bit 6 */
209 boolean AENC:1; /* Byte 3 Bit 7 */
211 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
212 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
213 boolean RMB:1; /* Byte 1 Bit 7 */
214 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
215 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
216 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
217 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
218 boolean AENC:1; /* Byte 3 Bit 7 */
219 boolean TrmIOP:1; /* Byte 3 Bit 6 */
220 unsigned char :2; /* Byte 3 Bits 4-5 */
221 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
223 unsigned char AdditionalLength; /* Byte 4 */
224 unsigned char :8; /* Byte 5 */
225 #ifdef LITTLE_ENDIAN_BITFIELDS
226 boolean ADDR16:1; /* Byte 6 bit 0 */
227 boolean Obs6_1:1; /* Byte 6 bit 1 */
228 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
229 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
230 boolean MultiP:1; /* Byte 6 bit 4 */
231 boolean VS:1; /* Byte 6 bit 5 */
232 boolean EncServ:1; /* Byte 6 bit 6 */
233 boolean BQue:1; /* Byte 6 bit 7 */
235 boolean BQue:1; /* Byte 6 bit 7 */
236 boolean EncServ:1; /* Byte 6 bit 6 */
237 boolean VS:1; /* Byte 6 bit 5 */
238 boolean MultiP:1; /* Byte 6 bit 4 */
239 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
240 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
241 boolean Obs6_1:1; /* Byte 6 bit 1 */
242 boolean ADDR16:1; /* Byte 6 bit 0 */
244 #ifdef LITTLE_ENDIAN_BITFIELDS
245 boolean SftRe:1; /* Byte 7 Bit 0 */
246 boolean CmdQue:1; /* Byte 7 Bit 1 */
247 boolean :1; /* Byte 7 Bit 2 */
248 boolean Linked:1; /* Byte 7 Bit 3 */
249 boolean Sync:1; /* Byte 7 Bit 4 */
250 boolean WBus16:1; /* Byte 7 Bit 5 */
251 boolean WBus32:1; /* Byte 7 Bit 6 */
252 boolean RelAdr:1; /* Byte 7 Bit 7 */
254 boolean RelAdr:1; /* Byte 7 Bit 7 */
255 boolean WBus32:1; /* Byte 7 Bit 6 */
256 boolean WBus16:1; /* Byte 7 Bit 5 */
257 boolean Sync:1; /* Byte 7 Bit 4 */
258 boolean Linked:1; /* Byte 7 Bit 3 */
259 boolean :1; /* Byte 7 Bit 2 */
260 boolean CmdQue:1; /* Byte 7 Bit 1 */
261 boolean SftRe:1; /* Byte 7 Bit 0 */
263 unsigned char VendorIdentification[8]; /* Bytes 8-15 */
264 unsigned char ProductIdentification[16]; /* Bytes 16-31 */
265 unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
266 unsigned char FullProductRevisionLevel[19]; /* bytes 36-54 */
267 unsigned char VendorFlags; /* byte 55 */
271 /* Hockey Pux may define these. If so, *UN*define them. */
280 typedef struct RequestSense
282 #ifdef LITTLE_ENDIAN_BITFIELDS
283 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
284 boolean Valid:1; /* Byte 0 Bit 7 */
286 boolean Valid:1; /* Byte 0 Bit 7 */
287 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
289 unsigned char SegmentNumber; /* Byte 1 */
290 #ifdef LITTLE_ENDIAN_BITFIELDS
291 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
292 unsigned char :1; /* Byte 2 Bit 4 */
293 boolean ILI:1; /* Byte 2 Bit 5 */
294 boolean EOM:1; /* Byte 2 Bit 6 */
295 boolean Filemark:1; /* Byte 2 Bit 7 */
297 boolean Filemark:1; /* Byte 2 Bit 7 */
298 boolean EOM:1; /* Byte 2 Bit 6 */
299 boolean ILI:1; /* Byte 2 Bit 5 */
300 unsigned char :1; /* Byte 2 Bit 4 */
301 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
303 unsigned char Information[4]; /* Bytes 3-6 */
304 unsigned char AdditionalSenseLength; /* Byte 7 */
305 unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */
306 unsigned char AdditionalSenseCode; /* Byte 12 */
307 unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */
308 unsigned char :8; /* Byte 14 */
309 #ifdef LITTLE_ENDIAN_BITFIELDS
310 unsigned char BitPointer:3; /* Byte 15 */
313 boolean CommandData :1;
317 boolean CommandData :1;
320 unsigned char BitPointer:3; /* Byte 15 */
322 unsigned char FieldData[2]; /* Byte 16,17 */
326 /* Okay, now for the element status mode sense page (0x1d): */
328 typedef struct ElementModeSensePageHeader {
329 unsigned char PageCode; /* byte 0 */
330 unsigned char ParameterLengthList; /* byte 1; */
331 unsigned char MediumTransportStartHi; /* byte 2,3 */
332 unsigned char MediumTransportStartLo;
333 unsigned char NumMediumTransportHi; /* byte 4,5 */
334 unsigned char NumMediumTransportLo; /* byte 4,5 */
335 unsigned char StorageStartHi; /* byte 6,7 */
336 unsigned char StorageStartLo; /* byte 6,7 */
337 unsigned char NumStorageHi; /* byte 8,9 */
338 unsigned char NumStorageLo; /* byte 8,9 */
339 unsigned char ImportExportStartHi; /* byte 10,11 */
340 unsigned char ImportExportStartLo; /* byte 10,11 */
341 unsigned char NumImportExportHi; /* byte 12,13 */
342 unsigned char NumImportExportLo; /* byte 12,13 */
343 unsigned char DataTransferStartHi; /* byte 14,15 */
344 unsigned char DataTransferStartLo; /* byte 14,15 */
345 unsigned char NumDataTransferHi; /* byte 16,17 */
346 unsigned char NumDataTransferLo; /* byte 16,17 */
347 unsigned char Reserved1; /* byte 18, 19 */
348 unsigned char Reserved2; /* byte 18, 19 */
349 } ElementModeSensePage_T;
351 typedef struct ElementModeSenseHeader {
352 int MaxReadElementStatusData; /* 'nuff for all of below. */
353 int NumElements; /* total # of elements. */
354 int MediumTransportStart;
355 int NumMediumTransport;
358 int ImportExportStart;
360 int DataTransferStart;
362 } ElementModeSense_T;
365 typedef enum ElementTypeCode
368 MediumTransportElement = 1,
370 ImportExportElement = 3,
371 DataTransferElement = 4
376 typedef struct ElementStatusDataHeader
378 unsigned char FirstElementAddressReported[2]; /* Bytes 0-1 */
379 unsigned char NumberOfElementsAvailable[2]; /* Bytes 2-3 */
380 unsigned char :8; /* Byte 4 */
381 unsigned char ByteCountOfReportAvailable[3]; /* Bytes 5-7 */
383 ElementStatusDataHeader_T;
386 typedef struct ElementStatusPage
388 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
389 #ifdef LITTLE_ENDIAN_BITFIELDS
390 unsigned char :6; /* Byte 1 Bits 0-5 */
391 boolean AVolTag:1; /* Byte 1 Bit 6 */
392 boolean PVolTag:1; /* Byte 1 Bit 7 */
394 boolean PVolTag:1; /* Byte 1 Bit 7 */
395 boolean AVolTag:1; /* Byte 1 Bit 6 */
396 unsigned char :6; /* Byte 1 Bits 0-5 */
398 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
399 unsigned char :8; /* Byte 4 */
400 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
404 typedef struct Element2StatusPage
406 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
407 unsigned char VolBits ; /* byte 1 */
408 #define E2_PVOLTAG 0x80
409 #define E2_AVOLTAG 0x40
410 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
411 unsigned char :8; /* Byte 4 */
412 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
414 Element2StatusPage_T;
418 typedef struct TransportElementDescriptorShort
420 unsigned char ElementAddress[2]; /* Bytes 0-1 */
421 #ifdef LITTLE_ENDIAN_BITFIELDS
422 boolean Full:1; /* Byte 2 Bit 0 */
423 unsigned char :1; /* Byte 2 Bit 1 */
424 boolean Except:1; /* Byte 2 Bit 2 */
425 unsigned char :5; /* Byte 2 Bits 3-7 */
427 unsigned char :5; /* Byte 2 Bits 3-7 */
428 boolean Except:1; /* Byte 2 Bit 2 */
429 unsigned char :1; /* Byte 2 Bit 1 */
430 boolean Full:1; /* Byte 2 Bit 0 */
432 unsigned char :8; /* Byte 3 */
433 unsigned char AdditionalSenseCode; /* Byte 4 */
434 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
435 unsigned char :8; /* Byte 6 */
436 unsigned char :8; /* Byte 7 */
437 unsigned char :8; /* Byte 8 */
438 #ifdef LITTLE_ENDIAN_BITFIELDS
439 unsigned char :6; /* Byte 9 Bits 0-5 */
440 boolean SValid:1; /* Byte 9 Bit 6 */
441 boolean Invert:1; /* Byte 9 Bit 7 */
443 boolean Invert:1; /* Byte 9 Bit 7 */
444 boolean SValid:1; /* Byte 9 Bit 6 */
445 unsigned char :6; /* Byte 9 Bits 0-5 */
447 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
449 TransportElementDescriptorShort_T;
452 typedef struct TransportElementDescriptor
454 unsigned char ElementAddress[2]; /* Bytes 0-1 */
455 #ifdef LITTLE_ENDIAN_BITFIELDS
456 boolean Full:1; /* Byte 2 Bit 0 */
457 unsigned char :1; /* Byte 2 Bit 1 */
458 boolean Except:1; /* Byte 2 Bit 2 */
459 unsigned char :5; /* Byte 2 Bits 3-7 */
461 unsigned char :5; /* Byte 2 Bits 3-7 */
462 boolean Except:1; /* Byte 2 Bit 2 */
463 unsigned char :1; /* Byte 2 Bit 1 */
464 boolean Full:1; /* Byte 2 Bit 0 */
466 unsigned char :8; /* Byte 3 */
467 unsigned char AdditionalSenseCode; /* Byte 4 */
468 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
469 unsigned char :8; /* Byte 6 */
470 unsigned char :8; /* Byte 7 */
471 unsigned char :8; /* Byte 8 */
472 #ifdef LITTLE_ENDIAN_BITFIELDS
473 unsigned char :6; /* Byte 9 Bits 0-5 */
474 boolean SValid:1; /* Byte 9 Bit 6 */
475 boolean Invert:1; /* Byte 9 Bit 7 */
477 boolean Invert:1; /* Byte 9 Bit 7 */
478 boolean SValid:1; /* Byte 9 Bit 6 */
479 unsigned char :6; /* Byte 9 Bits 0-5 */
481 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
482 unsigned char PrimaryVolumeTag[36]; /* barcode */
483 unsigned char AlternateVolumeTag[36];
485 TransportElementDescriptor_T;
489 /* Now for element status data; */
491 typedef unsigned char barcode[37];
493 typedef struct ElementStatus {
495 int StorageElementCount;
496 int ImportExportCount;
497 int DataTransferElementCount;
498 int *DataTransferElementAddress; /* array. */
499 int *DataTransferElementSourceStorageElementNumber; /* array */
500 barcode *DataTransferPrimaryVolumeTag; /* array. */
501 barcode *DataTransferAlternateVolumeTag; /* array. */
502 barcode *PrimaryVolumeTag; /* array */
503 barcode *AlternateVolumeTag; /* array */
504 int *StorageElementAddress; /* array */
505 boolean *StorageElementIsImportExport; /* array */
507 int TransportElementAddress; /* assume only one of those... */
509 boolean *DataTransferElementFull; /* array */
510 boolean *StorageElementFull; /* array */
515 /* Now for the SCSI ID and LUN information: */
516 typedef struct scsi_id {
521 #define MEDIUM_CHANGER_TYPE 8 /* what type bits are set for medium changers. */
523 #endif /* of multi-include protection. */