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.
6 Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
8 $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
10 See mtx.c for licensing information.
14 #ifndef MTX_H /* protect against multiple includes... */
17 /* surround all the Unix-stuff w/ifndef VMS */
19 #include "[.vms]defs.h"
20 #else /* all the Unix stuff: */
23 #include "msvc/config.h" /* all the autoconf stuff. */
25 #include "config.h" /* all the autoconf stuff. */
28 /* all the general Unix includes: */
42 # include <sys/types.h>
60 # include <sys/stat.h>
64 # include <sys/ioctl.h>
68 # include <sys/param.h>
71 /* Now greatly modified to use GNU Autoconf stuff: */
72 /* If we use the 'sg' interface, like Linux, do this: */
74 # include <scsi/scsi.h>
75 # include <scsi/scsi_ioctl.h>
77 typedef int DEVICE_TYPE; /* the sg interface uses this. */
78 # define HAVE_GET_ID_LUN 1 /* signal that we have it... */
81 /* Windows Native programs built using MinGW */
82 #if HAVE_DDK_NTDDSCSI_H
83 # define WIN32_LEAN_AND_MEAN
85 # include <ddk/ntddscsi.h>
88 typedef int DEVICE_TYPE;
91 /* Windows Native programs built using Microsoft Visual C */
93 # define WIN32_LEAN_AND_MEAN
95 # include <winioctl.h>
96 # include <ntddscsi.h>
99 typedef int DEVICE_TYPE;
102 /* The 'cam' interface, like FreeBSD: */
104 # include <camlib.h> /* easy (?) access to the CAM user library. */
105 # include <cam/cam_ccb.h>
106 # include <cam/scsi/scsi_message.h> /* sigh sigh sigh! */
107 typedef struct cam_device *DEVICE_TYPE;
111 /* the 'uscsi' interface, as used on Solaris: */
112 #if HAVE_SYS_SCSI_IMPL_USCSI_H
113 #include <sys/scsi/impl/uscsi.h>
114 typedef int DEVICE_TYPE;
117 /* the scsi_ctl interface, as used on HP/UX: */
118 #if HAVE_SYS_SCSI_CTL_H
119 # include <sys/wsio.h>
120 # include <sys/spinlock.h>
121 # include <sys/scsi.h>
122 # include <sys/scsi_ctl.h>
123 typedef int DEVICE_TYPE;
125 # define VERSION "1.2.12 hbb"
129 /* the 'gsc' interface, as used on AIX: */
130 #if HAVE_SYS_GSCDDS_H
131 # include <sys/gscdds.h>
132 typedef int DEVICE_TYPE;
135 /* the 'dslib' interface, as used on SGI. */
138 typedef dsreq_t *DEVICE_TYPE; /* 64-bit pointers/32bit int on later sgi? */
142 #if ((defined(__alpha) && defined(__osf__)) || \
143 defined(ultrix) || defined(__ultrix))
148 #endif /* VMS protect. */
150 /* Do a test for LITTLE_ENDIAN_BITFIELDS. Use WORDS_BIGENDIAN as set
155 # define BIG_ENDIAN_BITFIELDS
157 # define LITTLE_ENDIAN_BITFIELDS
160 /* Get rid of some Hocky Pux defines: */
164 #ifdef S_RECOVERED_ERROR
165 #undef S_RECOVERED_ERROR
170 #ifdef S_MEDIUM_ERROR
171 #undef S_MEDIUM_ERROR
173 #ifdef S_HARDWARE_ERROR
174 #undef S_HARDWARE_ERROR
176 #ifdef S_UNIT_ATTENTION
177 #undef S_UNIT_ATTENTION
182 #ifdef S_VOLUME_OVERFLOW
183 #undef S_VOLUME_OVERFLOW
186 /* Note: These are only used for defaults for when we don't have
187 * the element assignment mode page to tell us real amount...
189 #define MAX_STORAGE_ELEMENTS 64 /* for the BIG jukeboxes! */
190 #define MAX_TRANSFER_ELEMENTS 2 /* we just do dual-drive for now :-} */
191 #define MAX_TRANSPORT_ELEMENTS 1 /* we just do one arm for now... */
193 #define MTX_ELEMENTSTATUS_ORIGINAL 0
194 #define MTX_ELEMENTSTATUS_READALL 1
196 /* These are flags used for the READ_ELEMENT_STATUS and MOVE_MEDIUM
199 typedef struct SCSI_Flags_Struct
202 unsigned char invert;
203 unsigned char no_attached; /* ignore _attached bit */
204 unsigned char no_barcodes; /* don't try to get barcodes. */
210 int querytype; //MTX_ELEMENTSTATUS
211 unsigned char invert2; /* used for EXCHANGE command, sigh. */
215 typedef unsigned char boolean;
220 typedef unsigned char Direction_T;
225 typedef enum { false, true } boolean;
227 typedef enum { Input, Output } Direction_T;
231 typedef unsigned char CDB_T[12];
234 typedef struct Inquiry
236 #ifdef LITTLE_ENDIAN_BITFIELDS
237 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
238 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
239 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
240 boolean RMB:1; /* Byte 1 Bit 7 */
241 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
242 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
243 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
244 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
245 unsigned char :2; /* Byte 3 Bits 4-5 */
246 boolean TrmIOP:1; /* Byte 3 Bit 6 */
247 boolean AENC:1; /* Byte 3 Bit 7 */
249 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
250 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
251 boolean RMB:1; /* Byte 1 Bit 7 */
252 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
253 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
254 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
255 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
256 boolean AENC:1; /* Byte 3 Bit 7 */
257 boolean TrmIOP:1; /* Byte 3 Bit 6 */
258 unsigned char :2; /* Byte 3 Bits 4-5 */
259 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
261 unsigned char AdditionalLength; /* Byte 4 */
262 unsigned char :8; /* Byte 5 */
263 #ifdef LITTLE_ENDIAN_BITFIELDS
264 boolean ADDR16:1; /* Byte 6 bit 0 */
265 boolean Obs6_1:1; /* Byte 6 bit 1 */
266 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
267 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
268 boolean MultiP:1; /* Byte 6 bit 4 */
269 boolean VS:1; /* Byte 6 bit 5 */
270 boolean EncServ:1; /* Byte 6 bit 6 */
271 boolean BQue:1; /* Byte 6 bit 7 */
273 boolean BQue:1; /* Byte 6 bit 7 */
274 boolean EncServ:1; /* Byte 6 bit 6 */
275 boolean VS:1; /* Byte 6 bit 5 */
276 boolean MultiP:1; /* Byte 6 bit 4 */
277 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
278 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
279 boolean Obs6_1:1; /* Byte 6 bit 1 */
280 boolean ADDR16:1; /* Byte 6 bit 0 */
282 #ifdef LITTLE_ENDIAN_BITFIELDS
283 boolean SftRe:1; /* Byte 7 Bit 0 */
284 boolean CmdQue:1; /* Byte 7 Bit 1 */
285 boolean :1; /* Byte 7 Bit 2 */
286 boolean Linked:1; /* Byte 7 Bit 3 */
287 boolean Sync:1; /* Byte 7 Bit 4 */
288 boolean WBus16:1; /* Byte 7 Bit 5 */
289 boolean WBus32:1; /* Byte 7 Bit 6 */
290 boolean RelAdr:1; /* Byte 7 Bit 7 */
292 boolean RelAdr:1; /* Byte 7 Bit 7 */
293 boolean WBus32:1; /* Byte 7 Bit 6 */
294 boolean WBus16:1; /* Byte 7 Bit 5 */
295 boolean Sync:1; /* Byte 7 Bit 4 */
296 boolean Linked:1; /* Byte 7 Bit 3 */
297 boolean :1; /* Byte 7 Bit 2 */
298 boolean CmdQue:1; /* Byte 7 Bit 1 */
299 boolean SftRe:1; /* Byte 7 Bit 0 */
301 unsigned char VendorIdentification[8]; /* Bytes 8-15 */
302 unsigned char ProductIdentification[16]; /* Bytes 16-31 */
303 unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
304 unsigned char FullProductRevisionLevel[19]; /* bytes 36-54 */
305 unsigned char VendorFlags; /* byte 55 */
309 /* Hockey Pux may define these. If so, *UN*define them. */
318 typedef struct RequestSense
320 #ifdef LITTLE_ENDIAN_BITFIELDS
321 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
322 boolean Valid:1; /* Byte 0 Bit 7 */
324 boolean Valid:1; /* Byte 0 Bit 7 */
325 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
327 unsigned char SegmentNumber; /* Byte 1 */
328 #ifdef LITTLE_ENDIAN_BITFIELDS
329 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
330 unsigned char :1; /* Byte 2 Bit 4 */
331 boolean ILI:1; /* Byte 2 Bit 5 */
332 boolean EOM:1; /* Byte 2 Bit 6 */
333 boolean Filemark:1; /* Byte 2 Bit 7 */
335 boolean Filemark:1; /* Byte 2 Bit 7 */
336 boolean EOM:1; /* Byte 2 Bit 6 */
337 boolean ILI:1; /* Byte 2 Bit 5 */
338 unsigned char :1; /* Byte 2 Bit 4 */
339 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
341 unsigned char Information[4]; /* Bytes 3-6 */
342 unsigned char AdditionalSenseLength; /* Byte 7 */
343 unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */
344 unsigned char AdditionalSenseCode; /* Byte 12 */
345 unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */
346 unsigned char :8; /* Byte 14 */
347 #ifdef LITTLE_ENDIAN_BITFIELDS
348 unsigned char BitPointer:3; /* Byte 15 */
351 boolean CommandData :1;
355 boolean CommandData :1;
358 unsigned char BitPointer:3; /* Byte 15 */
360 unsigned char FieldData[2]; /* Byte 16,17 */
364 /* Okay, now for the element status mode sense page (0x1d): */
366 typedef struct ElementModeSensePageHeader {
367 unsigned char PageCode; /* byte 0 */
368 unsigned char ParameterLengthList; /* byte 1; */
369 unsigned char MediumTransportStartHi; /* byte 2,3 */
370 unsigned char MediumTransportStartLo;
371 unsigned char NumMediumTransportHi; /* byte 4,5 */
372 unsigned char NumMediumTransportLo; /* byte 4,5 */
373 unsigned char StorageStartHi; /* byte 6,7 */
374 unsigned char StorageStartLo; /* byte 6,7 */
375 unsigned char NumStorageHi; /* byte 8,9 */
376 unsigned char NumStorageLo; /* byte 8,9 */
377 unsigned char ImportExportStartHi; /* byte 10,11 */
378 unsigned char ImportExportStartLo; /* byte 10,11 */
379 unsigned char NumImportExportHi; /* byte 12,13 */
380 unsigned char NumImportExportLo; /* byte 12,13 */
381 unsigned char DataTransferStartHi; /* byte 14,15 */
382 unsigned char DataTransferStartLo; /* byte 14,15 */
383 unsigned char NumDataTransferHi; /* byte 16,17 */
384 unsigned char NumDataTransferLo; /* byte 16,17 */
385 unsigned char Reserved1; /* byte 18, 19 */
386 unsigned char Reserved2; /* byte 18, 19 */
387 } ElementModeSensePage_T;
389 typedef struct ElementModeSenseHeader {
390 int MaxReadElementStatusData; /* 'nuff for all of below. */
391 int NumElements; /* total # of elements. */
392 int MediumTransportStart;
393 int NumMediumTransport;
396 int ImportExportStart;
398 int DataTransferStart;
400 } ElementModeSense_T;
404 typedef char ElementTypeCode_T;
406 #define AllElementTypes 0
407 #define MediumTransportElement 1
408 #define StorageElement 2
409 #define ImportExportElement 3
410 #define DataTransferElement 4
412 typedef enum ElementTypeCode
415 MediumTransportElement = 1,
417 ImportExportElement = 3,
418 DataTransferElement = 4
424 typedef struct ElementStatusDataHeader
426 unsigned char FirstElementAddressReported[2]; /* Bytes 0-1 */
427 unsigned char NumberOfElementsAvailable[2]; /* Bytes 2-3 */
428 unsigned char :8; /* Byte 4 */
429 unsigned char ByteCountOfReportAvailable[3]; /* Bytes 5-7 */
431 ElementStatusDataHeader_T;
434 typedef struct ElementStatusPage
436 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
437 #ifdef LITTLE_ENDIAN_BITFIELDS
438 unsigned char :6; /* Byte 1 Bits 0-5 */
439 boolean AVolTag:1; /* Byte 1 Bit 6 */
440 boolean PVolTag:1; /* Byte 1 Bit 7 */
442 boolean PVolTag:1; /* Byte 1 Bit 7 */
443 boolean AVolTag:1; /* Byte 1 Bit 6 */
444 unsigned char :6; /* Byte 1 Bits 0-5 */
446 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
447 unsigned char :8; /* Byte 4 */
448 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
452 typedef struct Element2StatusPage
454 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
455 unsigned char VolBits ; /* byte 1 */
456 #define E2_PVOLTAG 0x80
457 #define E2_AVOLTAG 0x40
458 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
459 unsigned char :8; /* Byte 4 */
460 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
462 Element2StatusPage_T;
466 typedef struct TransportElementDescriptorShort
468 unsigned char ElementAddress[2]; /* Bytes 0-1 */
469 #ifdef LITTLE_ENDIAN_BITFIELDS
470 boolean Full:1; /* Byte 2 Bit 0 */
471 unsigned char :1; /* Byte 2 Bit 1 */
472 boolean Except:1; /* Byte 2 Bit 2 */
473 unsigned char :5; /* Byte 2 Bits 3-7 */
475 unsigned char :5; /* Byte 2 Bits 3-7 */
476 boolean Except:1; /* Byte 2 Bit 2 */
477 unsigned char :1; /* Byte 2 Bit 1 */
478 boolean Full:1; /* Byte 2 Bit 0 */
480 unsigned char :8; /* Byte 3 */
481 unsigned char AdditionalSenseCode; /* Byte 4 */
482 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
483 unsigned char :8; /* Byte 6 */
484 unsigned char :8; /* Byte 7 */
485 unsigned char :8; /* Byte 8 */
486 #ifdef LITTLE_ENDIAN_BITFIELDS
487 unsigned char :6; /* Byte 9 Bits 0-5 */
488 boolean SValid:1; /* Byte 9 Bit 6 */
489 boolean Invert:1; /* Byte 9 Bit 7 */
491 boolean Invert:1; /* Byte 9 Bit 7 */
492 boolean SValid:1; /* Byte 9 Bit 6 */
493 unsigned char :6; /* Byte 9 Bits 0-5 */
495 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
496 #ifdef HAS_LONG_DESCRIPTORS
497 unsigned char Reserved[4]; /* Bytes 12-15 */
500 TransportElementDescriptorShort_T;
503 typedef struct TransportElementDescriptor
505 unsigned char ElementAddress[2]; /* Bytes 0-1 */
506 #ifdef LITTLE_ENDIAN_BITFIELDS
507 boolean Full:1; /* Byte 2 Bit 0 */
508 unsigned char :1; /* Byte 2 Bit 1 */
509 boolean Except:1; /* Byte 2 Bit 2 */
510 unsigned char :5; /* Byte 2 Bits 3-7 */
512 unsigned char :5; /* Byte 2 Bits 3-7 */
513 boolean Except:1; /* Byte 2 Bit 2 */
514 unsigned char :1; /* Byte 2 Bit 1 */
515 boolean Full:1; /* Byte 2 Bit 0 */
517 unsigned char :8; /* Byte 3 */
518 unsigned char AdditionalSenseCode; /* Byte 4 */
519 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
520 unsigned char :8; /* Byte 6 */
521 unsigned char :8; /* Byte 7 */
522 unsigned char :8; /* Byte 8 */
523 #ifdef LITTLE_ENDIAN_BITFIELDS
524 unsigned char :6; /* Byte 9 Bits 0-5 */
525 boolean SValid:1; /* Byte 9 Bit 6 */
526 boolean Invert:1; /* Byte 9 Bit 7 */
528 boolean Invert:1; /* Byte 9 Bit 7 */
529 boolean SValid:1; /* Byte 9 Bit 6 */
530 unsigned char :6; /* Byte 9 Bits 0-5 */
532 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
533 unsigned char PrimaryVolumeTag[36]; /* barcode */
534 unsigned char AlternateVolumeTag[36];
535 #ifdef HAS_LONG_DESCRIPTORS
536 unsigned char Reserved[4]; /* 4 extra bytes? */
540 TransportElementDescriptor_T;
545 /* Now for element status data; */
547 typedef unsigned char barcode[37];
549 typedef struct ElementStatus {
551 int StorageElementCount;
552 int ImportExportCount;
553 int DataTransferElementCount;
554 int *DataTransferElementAddress; /* array. */
555 int *DataTransferElementSourceStorageElementNumber; /* array */
556 barcode *DataTransferPrimaryVolumeTag; /* array. */
557 barcode *DataTransferAlternateVolumeTag; /* array. */
558 barcode *PrimaryVolumeTag; /* array */
559 barcode *AlternateVolumeTag; /* array */
560 int *StorageElementAddress; /* array */
561 boolean *StorageElementIsImportExport; /* array */
563 int TransportElementAddress; /* assume only one of those... */
565 boolean *DataTransferElementFull; /* array */
566 boolean *StorageElementFull; /* array */
571 /* Now for the SCSI ID and LUN information: */
572 typedef struct scsi_id {
577 #define MEDIUM_CHANGER_TYPE 8 /* what type bits are set for medium changers. */
579 /* The following two structs are used for the brain-dead functions of the
583 typedef struct NSM_Param {
584 unsigned char page_code;
585 unsigned char reserved;
586 unsigned char page_len_msb;
587 unsigned char page_len_lsb;
588 unsigned char allocation_msb;
589 unsigned char allocation_lsb;
590 unsigned char reserved2[2];
591 unsigned char command_code[4];
592 unsigned char command_params[2048]; /* egregious overkill. */
595 extern RequestSense_T scsi_error_sense;
597 typedef struct NSM_Result {
598 unsigned char page_code;
599 unsigned char reserved;
600 unsigned char page_len_msb;
601 unsigned char page_len_lsb;
602 unsigned char command_code[4];
603 unsigned char ces_code[2];
604 unsigned char return_data[0xffff]; /* egregioius overkill */
607 #endif /* of multi-include protection. */