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: 2007-03-04 15:27:11 -0800 (Sun, 04 Mar 2007) $
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: */
22 #include "msvc/config.h" /* all the autoconf stuff. */
24 #include "config.h" /* all the autoconf stuff. */
27 /* all the general Unix includes: */
41 # include <sys/types.h>
59 # include <sys/stat.h>
63 # include <sys/ioctl.h>
67 # include <sys/param.h>
70 /* Now greatly modified to use GNU Autoconf stuff: */
71 /* If we use the 'sg' interface, like Linux, do this: */
73 # include <scsi/scsi.h>
74 # include <scsi/scsi_ioctl.h>
76 typedef int DEVICE_TYPE; /* the sg interface uses this. */
77 # define HAVE_GET_ID_LUN 1 /* signal that we have it... */
80 /* Windows Native programs built using MinGW */
81 #if HAVE_DDK_NTDDSCSI_H
83 # include <ddk/ntddscsi.h>
86 typedef int DEVICE_TYPE;
89 /* Windows Native programs built using Microsoft Visual C */
92 # include <winioctl.h>
93 # include <ntddscsi.h>
96 typedef int DEVICE_TYPE;
99 /* The 'cam' interface, like FreeBSD: */
101 # include <camlib.h> /* easy (?) access to the CAM user library. */
102 # include <cam/cam_ccb.h>
103 # include <cam/scsi/scsi_message.h> /* sigh sigh sigh! */
104 typedef struct cam_device *DEVICE_TYPE;
108 /* the 'uscsi' interface, as used on Solaris: */
109 #if HAVE_SYS_SCSI_IMPL_USCSI_H
110 #include <sys/scsi/impl/uscsi.h>
111 typedef int DEVICE_TYPE;
114 /* the scsi_ctl interface, as used on HP/UX: */
115 #if HAVE_SYS_SCSI_CTL_H
116 # include <sys/wsio.h>
117 # include <sys/spinlock.h>
118 # include <sys/scsi.h>
119 # include <sys/scsi_ctl.h>
120 typedef int DEVICE_TYPE;
122 # define VERSION "1.2.12 hbb"
126 /* the 'gsc' interface, as used on AIX: */
127 #if HAVE_SYS_GSCDDS_H
128 # include <sys/gscdds.h>
129 typedef int DEVICE_TYPE;
132 /* the 'dslib' interface, as used on SGI. */
135 typedef dsreq_t *DEVICE_TYPE; /* 64-bit pointers/32bit int on later sgi? */
139 #if ((defined(__alpha) && defined(__osf__)) || \
140 defined(ultrix) || defined(__ultrix))
145 #endif /* VMS protect. */
147 /* Do a test for LITTLE_ENDIAN_BITFIELDS. Use WORDS_BIGENDIAN as set
152 # define BIG_ENDIAN_BITFIELDS
154 # define LITTLE_ENDIAN_BITFIELDS
157 /* Get rid of some Hocky Pux defines: */
161 #ifdef S_RECOVERED_ERROR
162 #undef S_RECOVERED_ERROR
167 #ifdef S_MEDIUM_ERROR
168 #undef S_MEDIUM_ERROR
170 #ifdef S_HARDWARE_ERROR
171 #undef S_HARDWARE_ERROR
173 #ifdef S_UNIT_ATTENTION
174 #undef S_UNIT_ATTENTION
179 #ifdef S_VOLUME_OVERFLOW
180 #undef S_VOLUME_OVERFLOW
183 /* Note: These are only used for defaults for when we don't have
184 * the element assignment mode page to tell us real amount...
186 #define MAX_STORAGE_ELEMENTS 64 /* for the BIG jukeboxes! */
187 #define MAX_TRANSFER_ELEMENTS 2 /* we just do dual-drive for now :-} */
188 #define MAX_TRANSPORT_ELEMENTS 1 /* we just do one arm for now... */
190 #define MTX_ELEMENTSTATUS_ORIGINAL 0
191 #define MTX_ELEMENTSTATUS_READALL 1
193 /* These are flags used for the READ_ELEMENT_STATUS and MOVE_MEDIUM
196 typedef struct SCSI_Flags_Struct
199 unsigned char invert;
200 unsigned char no_attached; /* ignore _attached bit */
201 unsigned char no_barcodes; /* don't try to get barcodes. */
207 int querytype; //MTX_ELEMENTSTATUS
208 unsigned char invert2; /* used for EXCHANGE command, sigh. */
212 typedef unsigned char boolean;
217 typedef unsigned char Direction_T;
222 typedef enum { false, true } boolean;
224 typedef enum { Input, Output } Direction_T;
228 typedef unsigned char CDB_T[12];
231 typedef struct Inquiry
233 #ifdef LITTLE_ENDIAN_BITFIELDS
234 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
235 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
236 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
237 boolean RMB:1; /* Byte 1 Bit 7 */
238 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
239 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
240 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
241 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
242 unsigned char :2; /* Byte 3 Bits 4-5 */
243 boolean TrmIOP:1; /* Byte 3 Bit 6 */
244 boolean AENC:1; /* Byte 3 Bit 7 */
246 unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
247 unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
248 boolean RMB:1; /* Byte 1 Bit 7 */
249 unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
250 unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
251 unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
252 unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
253 boolean AENC:1; /* Byte 3 Bit 7 */
254 boolean TrmIOP:1; /* Byte 3 Bit 6 */
255 unsigned char :2; /* Byte 3 Bits 4-5 */
256 unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
258 unsigned char AdditionalLength; /* Byte 4 */
259 unsigned char :8; /* Byte 5 */
260 #ifdef LITTLE_ENDIAN_BITFIELDS
261 boolean ADDR16:1; /* Byte 6 bit 0 */
262 boolean Obs6_1:1; /* Byte 6 bit 1 */
263 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
264 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
265 boolean MultiP:1; /* Byte 6 bit 4 */
266 boolean VS:1; /* Byte 6 bit 5 */
267 boolean EncServ:1; /* Byte 6 bit 6 */
268 boolean BQue:1; /* Byte 6 bit 7 */
270 boolean BQue:1; /* Byte 6 bit 7 */
271 boolean EncServ:1; /* Byte 6 bit 6 */
272 boolean VS:1; /* Byte 6 bit 5 */
273 boolean MultiP:1; /* Byte 6 bit 4 */
274 boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
275 boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
276 boolean Obs6_1:1; /* Byte 6 bit 1 */
277 boolean ADDR16:1; /* Byte 6 bit 0 */
279 #ifdef LITTLE_ENDIAN_BITFIELDS
280 boolean SftRe:1; /* Byte 7 Bit 0 */
281 boolean CmdQue:1; /* Byte 7 Bit 1 */
282 boolean :1; /* Byte 7 Bit 2 */
283 boolean Linked:1; /* Byte 7 Bit 3 */
284 boolean Sync:1; /* Byte 7 Bit 4 */
285 boolean WBus16:1; /* Byte 7 Bit 5 */
286 boolean WBus32:1; /* Byte 7 Bit 6 */
287 boolean RelAdr:1; /* Byte 7 Bit 7 */
289 boolean RelAdr:1; /* Byte 7 Bit 7 */
290 boolean WBus32:1; /* Byte 7 Bit 6 */
291 boolean WBus16:1; /* Byte 7 Bit 5 */
292 boolean Sync:1; /* Byte 7 Bit 4 */
293 boolean Linked:1; /* Byte 7 Bit 3 */
294 boolean :1; /* Byte 7 Bit 2 */
295 boolean CmdQue:1; /* Byte 7 Bit 1 */
296 boolean SftRe:1; /* Byte 7 Bit 0 */
298 unsigned char VendorIdentification[8]; /* Bytes 8-15 */
299 unsigned char ProductIdentification[16]; /* Bytes 16-31 */
300 unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
301 unsigned char FullProductRevisionLevel[19]; /* bytes 36-54 */
302 unsigned char VendorFlags; /* byte 55 */
306 /* Hockey Pux may define these. If so, *UN*define them. */
315 typedef struct RequestSense
317 #ifdef LITTLE_ENDIAN_BITFIELDS
318 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
319 boolean Valid:1; /* Byte 0 Bit 7 */
321 boolean Valid:1; /* Byte 0 Bit 7 */
322 unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
324 unsigned char SegmentNumber; /* Byte 1 */
325 #ifdef LITTLE_ENDIAN_BITFIELDS
326 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
327 unsigned char :1; /* Byte 2 Bit 4 */
328 boolean ILI:1; /* Byte 2 Bit 5 */
329 boolean EOM:1; /* Byte 2 Bit 6 */
330 boolean Filemark:1; /* Byte 2 Bit 7 */
332 boolean Filemark:1; /* Byte 2 Bit 7 */
333 boolean EOM:1; /* Byte 2 Bit 6 */
334 boolean ILI:1; /* Byte 2 Bit 5 */
335 unsigned char :1; /* Byte 2 Bit 4 */
336 unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
338 unsigned char Information[4]; /* Bytes 3-6 */
339 unsigned char AdditionalSenseLength; /* Byte 7 */
340 unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */
341 unsigned char AdditionalSenseCode; /* Byte 12 */
342 unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */
343 unsigned char :8; /* Byte 14 */
344 #ifdef LITTLE_ENDIAN_BITFIELDS
345 unsigned char BitPointer:3; /* Byte 15 */
348 boolean CommandData :1;
352 boolean CommandData :1;
355 unsigned char BitPointer:3; /* Byte 15 */
357 unsigned char FieldData[2]; /* Byte 16,17 */
361 /* Okay, now for the element status mode sense page (0x1d): */
363 typedef struct ElementModeSensePageHeader {
364 unsigned char PageCode; /* byte 0 */
365 unsigned char ParameterLengthList; /* byte 1; */
366 unsigned char MediumTransportStartHi; /* byte 2,3 */
367 unsigned char MediumTransportStartLo;
368 unsigned char NumMediumTransportHi; /* byte 4,5 */
369 unsigned char NumMediumTransportLo; /* byte 4,5 */
370 unsigned char StorageStartHi; /* byte 6,7 */
371 unsigned char StorageStartLo; /* byte 6,7 */
372 unsigned char NumStorageHi; /* byte 8,9 */
373 unsigned char NumStorageLo; /* byte 8,9 */
374 unsigned char ImportExportStartHi; /* byte 10,11 */
375 unsigned char ImportExportStartLo; /* byte 10,11 */
376 unsigned char NumImportExportHi; /* byte 12,13 */
377 unsigned char NumImportExportLo; /* byte 12,13 */
378 unsigned char DataTransferStartHi; /* byte 14,15 */
379 unsigned char DataTransferStartLo; /* byte 14,15 */
380 unsigned char NumDataTransferHi; /* byte 16,17 */
381 unsigned char NumDataTransferLo; /* byte 16,17 */
382 unsigned char Reserved1; /* byte 18, 19 */
383 unsigned char Reserved2; /* byte 18, 19 */
384 } ElementModeSensePage_T;
386 typedef struct ElementModeSenseHeader {
387 int MaxReadElementStatusData; /* 'nuff for all of below. */
388 int NumElements; /* total # of elements. */
389 int MediumTransportStart;
390 int NumMediumTransport;
393 int ImportExportStart;
395 int DataTransferStart;
397 } ElementModeSense_T;
401 typedef char ElementTypeCode_T;
403 #define AllElementTypes 0
404 #define MediumTransportElement 1
405 #define StorageElement 2
406 #define ImportExportElement 3
407 #define DataTransferElement 4
409 typedef enum ElementTypeCode
412 MediumTransportElement = 1,
414 ImportExportElement = 3,
415 DataTransferElement = 4
421 typedef struct ElementStatusDataHeader
423 unsigned char FirstElementAddressReported[2]; /* Bytes 0-1 */
424 unsigned char NumberOfElementsAvailable[2]; /* Bytes 2-3 */
425 unsigned char :8; /* Byte 4 */
426 unsigned char ByteCountOfReportAvailable[3]; /* Bytes 5-7 */
428 ElementStatusDataHeader_T;
431 typedef struct ElementStatusPage
433 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
434 #ifdef LITTLE_ENDIAN_BITFIELDS
435 unsigned char :6; /* Byte 1 Bits 0-5 */
436 boolean AVolTag:1; /* Byte 1 Bit 6 */
437 boolean PVolTag:1; /* Byte 1 Bit 7 */
439 boolean PVolTag:1; /* Byte 1 Bit 7 */
440 boolean AVolTag:1; /* Byte 1 Bit 6 */
441 unsigned char :6; /* Byte 1 Bits 0-5 */
443 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
444 unsigned char :8; /* Byte 4 */
445 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
449 typedef struct Element2StatusPage
451 ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
452 unsigned char VolBits ; /* byte 1 */
453 #define E2_PVOLTAG 0x80
454 #define E2_AVOLTAG 0x40
455 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
456 unsigned char :8; /* Byte 4 */
457 unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
459 Element2StatusPage_T;
463 typedef struct TransportElementDescriptorShort
465 unsigned char ElementAddress[2]; /* Bytes 0-1 */
466 #ifdef LITTLE_ENDIAN_BITFIELDS
467 boolean Full:1; /* Byte 2 Bit 0 */
468 unsigned char :1; /* Byte 2 Bit 1 */
469 boolean Except:1; /* Byte 2 Bit 2 */
470 unsigned char :5; /* Byte 2 Bits 3-7 */
472 unsigned char :5; /* Byte 2 Bits 3-7 */
473 boolean Except:1; /* Byte 2 Bit 2 */
474 unsigned char :1; /* Byte 2 Bit 1 */
475 boolean Full:1; /* Byte 2 Bit 0 */
477 unsigned char :8; /* Byte 3 */
478 unsigned char AdditionalSenseCode; /* Byte 4 */
479 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
480 unsigned char :8; /* Byte 6 */
481 unsigned char :8; /* Byte 7 */
482 unsigned char :8; /* Byte 8 */
483 #ifdef LITTLE_ENDIAN_BITFIELDS
484 unsigned char :6; /* Byte 9 Bits 0-5 */
485 boolean SValid:1; /* Byte 9 Bit 6 */
486 boolean Invert:1; /* Byte 9 Bit 7 */
488 boolean Invert:1; /* Byte 9 Bit 7 */
489 boolean SValid:1; /* Byte 9 Bit 6 */
490 unsigned char :6; /* Byte 9 Bits 0-5 */
492 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
493 #ifdef HAS_LONG_DESCRIPTORS
494 unsigned char Reserved[4]; /* Bytes 12-15 */
497 TransportElementDescriptorShort_T;
500 typedef struct TransportElementDescriptor
502 unsigned char ElementAddress[2]; /* Bytes 0-1 */
503 #ifdef LITTLE_ENDIAN_BITFIELDS
504 boolean Full:1; /* Byte 2 Bit 0 */
505 unsigned char :1; /* Byte 2 Bit 1 */
506 boolean Except:1; /* Byte 2 Bit 2 */
507 unsigned char :5; /* Byte 2 Bits 3-7 */
509 unsigned char :5; /* Byte 2 Bits 3-7 */
510 boolean Except:1; /* Byte 2 Bit 2 */
511 unsigned char :1; /* Byte 2 Bit 1 */
512 boolean Full:1; /* Byte 2 Bit 0 */
514 unsigned char :8; /* Byte 3 */
515 unsigned char AdditionalSenseCode; /* Byte 4 */
516 unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
517 unsigned char :8; /* Byte 6 */
518 unsigned char :8; /* Byte 7 */
519 unsigned char :8; /* Byte 8 */
520 #ifdef LITTLE_ENDIAN_BITFIELDS
521 unsigned char :6; /* Byte 9 Bits 0-5 */
522 boolean SValid:1; /* Byte 9 Bit 6 */
523 boolean Invert:1; /* Byte 9 Bit 7 */
525 boolean Invert:1; /* Byte 9 Bit 7 */
526 boolean SValid:1; /* Byte 9 Bit 6 */
527 unsigned char :6; /* Byte 9 Bits 0-5 */
529 unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
530 unsigned char PrimaryVolumeTag[36]; /* barcode */
531 unsigned char AlternateVolumeTag[36];
532 #ifdef HAS_LONG_DESCRIPTORS
533 unsigned char Reserved[4]; /* 4 extra bytes? */
537 TransportElementDescriptor_T;
542 /* Now for element status data; */
544 typedef unsigned char barcode[37];
546 typedef struct ElementStatus {
548 int StorageElementCount;
549 int ImportExportCount;
550 int DataTransferElementCount;
551 int *DataTransferElementAddress; /* array. */
552 int *DataTransferElementSourceStorageElementNumber; /* array */
553 barcode *DataTransferPrimaryVolumeTag; /* array. */
554 barcode *DataTransferAlternateVolumeTag; /* array. */
555 barcode *PrimaryVolumeTag; /* array */
556 barcode *AlternateVolumeTag; /* array */
557 int *StorageElementAddress; /* array */
558 boolean *StorageElementIsImportExport; /* array */
560 int TransportElementAddress; /* assume only one of those... */
562 boolean *DataTransferElementFull; /* array */
563 boolean *StorageElementFull; /* array */
568 /* Now for the SCSI ID and LUN information: */
569 typedef struct scsi_id {
574 #define MEDIUM_CHANGER_TYPE 8 /* what type bits are set for medium changers. */
576 /* The following two structs are used for the brain-dead functions of the
580 typedef struct NSM_Param {
581 unsigned char page_code;
582 unsigned char reserved;
583 unsigned char page_len_msb;
584 unsigned char page_len_lsb;
585 unsigned char allocation_msb;
586 unsigned char allocation_lsb;
587 unsigned char reserved2[2];
588 unsigned char command_code[4];
589 unsigned char command_params[2048]; /* egregious overkill. */
592 extern RequestSense_T scsi_error_sense;
594 typedef struct NSM_Result {
595 unsigned char page_code;
596 unsigned char reserved;
597 unsigned char page_len_msb;
598 unsigned char page_len_lsb;
599 unsigned char command_code[4];
600 unsigned char ces_code[2];
601 unsigned char return_data[0xffff]; /* egregioius overkill */
604 #endif /* of multi-include protection. */