/* MTX -- SCSI Tape Attached Medium Control Program Copyright 1997-1998 Leonard N. Zubkoff Changes 1999 Eric Lee Green to add support for multi-drive tape changers. Copyright 2007-2008 by Robert Nelson $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $ $Revision: 193 $ See mtx.c for licensing information. */ #ifndef MTX_H /* protect against multiple includes... */ #define MTX_H 1 /* surround all the Unix-stuff w/ifndef VMS */ #ifdef VMS #include "[.vms]defs.h" #else /* all the Unix stuff: */ #ifdef _MSC_VER #include "msvc/config.h" /* all the autoconf stuff. */ #else #include "config.h" /* all the autoconf stuff. */ #endif /* all the general Unix includes: */ #include #include #if HAVE_STDLIB_H # include #endif #if HAVE_FCNTL_H # include #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_STRING_H # include #else # include #endif #if HAVE_UNISTD_H # include #endif #if HAVE_STDARG_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if HAVE_SYS_IOCTL_H # include #endif #if HAVE_SYS_PARAM_H # include #endif /* Now greatly modified to use GNU Autoconf stuff: */ /* If we use the 'sg' interface, like Linux, do this: */ #if HAVE_SCSI_SG_H # include # include # include typedef int DEVICE_TYPE; /* the sg interface uses this. */ # define HAVE_GET_ID_LUN 1 /* signal that we have it... */ #endif /* Windows Native programs built using MinGW */ #if HAVE_DDK_NTDDSCSI_H # define WIN32_LEAN_AND_MEAN # include # include # undef DEVICE_TYPE typedef int DEVICE_TYPE; #endif /* Windows Native programs built using Microsoft Visual C */ #ifdef _MSC_VER # define WIN32_LEAN_AND_MEAN # include # include # include # undef DEVICE_TYPE typedef int DEVICE_TYPE; #endif /* The 'cam' interface, like FreeBSD: */ #if HAVE_CAMLIB_H # include /* easy (?) access to the CAM user library. */ # include # include /* sigh sigh sigh! */ typedef struct cam_device *DEVICE_TYPE; #endif /* the 'uscsi' interface, as used on Solaris: */ #if HAVE_SYS_SCSI_IMPL_USCSI_H #include typedef int DEVICE_TYPE; #endif /* the scsi_ctl interface, as used on HP/UX: */ #if HAVE_SYS_SCSI_CTL_H # include # include # include # include typedef int DEVICE_TYPE; # ifndef VERSION # define VERSION "1.2.12 hbb" # endif #endif /* the 'gsc' interface, as used on AIX: */ #if HAVE_SYS_GSCDDS_H # include typedef int DEVICE_TYPE; #endif /* the 'dslib' interface, as used on SGI. */ #if HAVE_DSLIB_H #include typedef dsreq_t *DEVICE_TYPE; /* 64-bit pointers/32bit int on later sgi? */ #endif #if ((defined(__alpha) && defined(__osf__)) || \ defined(ultrix) || defined(__ultrix)) #include "du/defs.h" #endif #endif /* VMS protect. */ /* Do a test for LITTLE_ENDIAN_BITFIELDS. Use WORDS_BIGENDIAN as set * by configure: */ #if WORDS_BIGENDIAN # define BIG_ENDIAN_BITFIELDS #else # define LITTLE_ENDIAN_BITFIELDS #endif /* Get rid of some Hocky Pux defines: */ #ifdef S_NO_SENSE #undef S_NO_SENSE #endif #ifdef S_RECOVERED_ERROR #undef S_RECOVERED_ERROR #endif #ifdef S_NOT_READY #undef S_NOT_READY #endif #ifdef S_MEDIUM_ERROR #undef S_MEDIUM_ERROR #endif #ifdef S_HARDWARE_ERROR #undef S_HARDWARE_ERROR #endif #ifdef S_UNIT_ATTENTION #undef S_UNIT_ATTENTION #endif #ifdef S_BLANK_CHECK #undef S_BLANK_CHECK #endif #ifdef S_VOLUME_OVERFLOW #undef S_VOLUME_OVERFLOW #endif /* Note: These are only used for defaults for when we don't have * the element assignment mode page to tell us real amount... */ #define MAX_STORAGE_ELEMENTS 64 /* for the BIG jukeboxes! */ #define MAX_TRANSFER_ELEMENTS 2 /* we just do dual-drive for now :-} */ #define MAX_TRANSPORT_ELEMENTS 1 /* we just do one arm for now... */ #define MTX_ELEMENTSTATUS_ORIGINAL 0 #define MTX_ELEMENTSTATUS_READALL 1 /* These are flags used for the READ_ELEMENT_STATUS and MOVE_MEDIUM * commands: */ typedef struct SCSI_Flags_Struct { unsigned char eepos; unsigned char invert; unsigned char no_attached; /* ignore _attached bit */ unsigned char no_barcodes; /* don't try to get barcodes. */ int numbytes; int elementtype; int numelements; int attached; int has_barcodes; int querytype; //MTX_ELEMENTSTATUS unsigned char invert2; /* used for EXCHANGE command, sigh. */ } SCSI_Flags_T; #ifdef _MSC_VER typedef unsigned char boolean; #define false 0 #define true 1 typedef unsigned char Direction_T; #define Input 0 #define Output 1 #else typedef enum { false, true } boolean; typedef enum { Input, Output } Direction_T; #endif typedef unsigned char CDB_T[12]; typedef struct Inquiry { #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ boolean RMB:1; /* Byte 1 Bit 7 */ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ unsigned char :2; /* Byte 3 Bits 4-5 */ boolean TrmIOP:1; /* Byte 3 Bit 6 */ boolean AENC:1; /* Byte 3 Bit 7 */ #else unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ boolean RMB:1; /* Byte 1 Bit 7 */ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ boolean AENC:1; /* Byte 3 Bit 7 */ boolean TrmIOP:1; /* Byte 3 Bit 6 */ unsigned char :2; /* Byte 3 Bits 4-5 */ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ #endif unsigned char AdditionalLength; /* Byte 4 */ unsigned char :8; /* Byte 5 */ #ifdef LITTLE_ENDIAN_BITFIELDS boolean ADDR16:1; /* Byte 6 bit 0 */ boolean Obs6_1:1; /* Byte 6 bit 1 */ boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */ boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */ boolean MultiP:1; /* Byte 6 bit 4 */ boolean VS:1; /* Byte 6 bit 5 */ boolean EncServ:1; /* Byte 6 bit 6 */ boolean BQue:1; /* Byte 6 bit 7 */ #else boolean BQue:1; /* Byte 6 bit 7 */ boolean EncServ:1; /* Byte 6 bit 6 */ boolean VS:1; /* Byte 6 bit 5 */ boolean MultiP:1; /* Byte 6 bit 4 */ boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */ boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */ boolean Obs6_1:1; /* Byte 6 bit 1 */ boolean ADDR16:1; /* Byte 6 bit 0 */ #endif #ifdef LITTLE_ENDIAN_BITFIELDS boolean SftRe:1; /* Byte 7 Bit 0 */ boolean CmdQue:1; /* Byte 7 Bit 1 */ boolean :1; /* Byte 7 Bit 2 */ boolean Linked:1; /* Byte 7 Bit 3 */ boolean Sync:1; /* Byte 7 Bit 4 */ boolean WBus16:1; /* Byte 7 Bit 5 */ boolean WBus32:1; /* Byte 7 Bit 6 */ boolean RelAdr:1; /* Byte 7 Bit 7 */ #else boolean RelAdr:1; /* Byte 7 Bit 7 */ boolean WBus32:1; /* Byte 7 Bit 6 */ boolean WBus16:1; /* Byte 7 Bit 5 */ boolean Sync:1; /* Byte 7 Bit 4 */ boolean Linked:1; /* Byte 7 Bit 3 */ boolean :1; /* Byte 7 Bit 2 */ boolean CmdQue:1; /* Byte 7 Bit 1 */ boolean SftRe:1; /* Byte 7 Bit 0 */ #endif unsigned char VendorIdentification[8]; /* Bytes 8-15 */ unsigned char ProductIdentification[16]; /* Bytes 16-31 */ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ unsigned char FullProductRevisionLevel[19]; /* bytes 36-54 */ unsigned char VendorFlags; /* byte 55 */ } Inquiry_T; /* Hockey Pux may define these. If so, *UN*define them. */ #ifdef ILI #undef ILI #endif #ifdef EOM #undef EOM #endif typedef struct RequestSense { #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */ boolean Valid:1; /* Byte 0 Bit 7 */ #else boolean Valid:1; /* Byte 0 Bit 7 */ unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */ #endif unsigned char SegmentNumber; /* Byte 1 */ #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */ unsigned char :1; /* Byte 2 Bit 4 */ boolean ILI:1; /* Byte 2 Bit 5 */ boolean EOM:1; /* Byte 2 Bit 6 */ boolean Filemark:1; /* Byte 2 Bit 7 */ #else boolean Filemark:1; /* Byte 2 Bit 7 */ boolean EOM:1; /* Byte 2 Bit 6 */ boolean ILI:1; /* Byte 2 Bit 5 */ unsigned char :1; /* Byte 2 Bit 4 */ unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */ #endif unsigned char Information[4]; /* Bytes 3-6 */ unsigned char AdditionalSenseLength; /* Byte 7 */ unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */ unsigned char AdditionalSenseCode; /* Byte 12 */ unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */ unsigned char :8; /* Byte 14 */ #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char BitPointer:3; /* Byte 15 */ boolean BPV:1; unsigned char :2; boolean CommandData :1; boolean SKSV:1; #else boolean SKSV:1; boolean CommandData :1; unsigned char :2; boolean BPV:1; unsigned char BitPointer:3; /* Byte 15 */ #endif unsigned char FieldData[2]; /* Byte 16,17 */ } RequestSense_T; /* Okay, now for the element status mode sense page (0x1d): */ typedef struct ElementModeSensePageHeader { unsigned char PageCode; /* byte 0 */ unsigned char ParameterLengthList; /* byte 1; */ unsigned char MediumTransportStartHi; /* byte 2,3 */ unsigned char MediumTransportStartLo; unsigned char NumMediumTransportHi; /* byte 4,5 */ unsigned char NumMediumTransportLo; /* byte 4,5 */ unsigned char StorageStartHi; /* byte 6,7 */ unsigned char StorageStartLo; /* byte 6,7 */ unsigned char NumStorageHi; /* byte 8,9 */ unsigned char NumStorageLo; /* byte 8,9 */ unsigned char ImportExportStartHi; /* byte 10,11 */ unsigned char ImportExportStartLo; /* byte 10,11 */ unsigned char NumImportExportHi; /* byte 12,13 */ unsigned char NumImportExportLo; /* byte 12,13 */ unsigned char DataTransferStartHi; /* byte 14,15 */ unsigned char DataTransferStartLo; /* byte 14,15 */ unsigned char NumDataTransferHi; /* byte 16,17 */ unsigned char NumDataTransferLo; /* byte 16,17 */ unsigned char Reserved1; /* byte 18, 19 */ unsigned char Reserved2; /* byte 18, 19 */ } ElementModeSensePage_T; typedef struct ElementModeSenseHeader { int MaxReadElementStatusData; /* 'nuff for all of below. */ int NumElements; /* total # of elements. */ int MediumTransportStart; int NumMediumTransport; int StorageStart; int NumStorage; int ImportExportStart; int NumImportExport; int DataTransferStart; int NumDataTransfer; } ElementModeSense_T; #ifdef _MSC_VER typedef char ElementTypeCode_T; #define AllElementTypes 0 #define MediumTransportElement 1 #define StorageElement 2 #define ImportExportElement 3 #define DataTransferElement 4 #else typedef enum ElementTypeCode { AllElementTypes = 0, MediumTransportElement = 1, StorageElement = 2, ImportExportElement = 3, DataTransferElement = 4 } ElementTypeCode_T; #endif typedef struct ElementStatusDataHeader { unsigned char FirstElementAddressReported[2]; /* Bytes 0-1 */ unsigned char NumberOfElementsAvailable[2]; /* Bytes 2-3 */ unsigned char :8; /* Byte 4 */ unsigned char ByteCountOfReportAvailable[3]; /* Bytes 5-7 */ } ElementStatusDataHeader_T; typedef struct ElementStatusPage { ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */ #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char :6; /* Byte 1 Bits 0-5 */ boolean AVolTag:1; /* Byte 1 Bit 6 */ boolean PVolTag:1; /* Byte 1 Bit 7 */ #else boolean PVolTag:1; /* Byte 1 Bit 7 */ boolean AVolTag:1; /* Byte 1 Bit 6 */ unsigned char :6; /* Byte 1 Bits 0-5 */ #endif unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */ unsigned char :8; /* Byte 4 */ unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */ } ElementStatusPage_T; typedef struct Element2StatusPage { ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */ unsigned char VolBits ; /* byte 1 */ #define E2_PVOLTAG 0x80 #define E2_AVOLTAG 0x40 unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */ unsigned char :8; /* Byte 4 */ unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */ } Element2StatusPage_T; typedef struct TransportElementDescriptorShort { unsigned char ElementAddress[2]; /* Bytes 0-1 */ #ifdef LITTLE_ENDIAN_BITFIELDS boolean Full:1; /* Byte 2 Bit 0 */ unsigned char :1; /* Byte 2 Bit 1 */ boolean Except:1; /* Byte 2 Bit 2 */ unsigned char :5; /* Byte 2 Bits 3-7 */ #else unsigned char :5; /* Byte 2 Bits 3-7 */ boolean Except:1; /* Byte 2 Bit 2 */ unsigned char :1; /* Byte 2 Bit 1 */ boolean Full:1; /* Byte 2 Bit 0 */ #endif unsigned char :8; /* Byte 3 */ unsigned char AdditionalSenseCode; /* Byte 4 */ unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */ unsigned char :8; /* Byte 6 */ unsigned char :8; /* Byte 7 */ unsigned char :8; /* Byte 8 */ #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char :6; /* Byte 9 Bits 0-5 */ boolean SValid:1; /* Byte 9 Bit 6 */ boolean Invert:1; /* Byte 9 Bit 7 */ #else boolean Invert:1; /* Byte 9 Bit 7 */ boolean SValid:1; /* Byte 9 Bit 6 */ unsigned char :6; /* Byte 9 Bits 0-5 */ #endif unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */ #ifdef HAS_LONG_DESCRIPTORS unsigned char Reserved[4]; /* Bytes 12-15 */ #endif } TransportElementDescriptorShort_T; typedef struct TransportElementDescriptor { unsigned char ElementAddress[2]; /* Bytes 0-1 */ #ifdef LITTLE_ENDIAN_BITFIELDS boolean Full:1; /* Byte 2 Bit 0 */ unsigned char :1; /* Byte 2 Bit 1 */ boolean Except:1; /* Byte 2 Bit 2 */ unsigned char :5; /* Byte 2 Bits 3-7 */ #else unsigned char :5; /* Byte 2 Bits 3-7 */ boolean Except:1; /* Byte 2 Bit 2 */ unsigned char :1; /* Byte 2 Bit 1 */ boolean Full:1; /* Byte 2 Bit 0 */ #endif unsigned char :8; /* Byte 3 */ unsigned char AdditionalSenseCode; /* Byte 4 */ unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */ unsigned char :8; /* Byte 6 */ unsigned char :8; /* Byte 7 */ unsigned char :8; /* Byte 8 */ #ifdef LITTLE_ENDIAN_BITFIELDS unsigned char :6; /* Byte 9 Bits 0-5 */ boolean SValid:1; /* Byte 9 Bit 6 */ boolean Invert:1; /* Byte 9 Bit 7 */ #else boolean Invert:1; /* Byte 9 Bit 7 */ boolean SValid:1; /* Byte 9 Bit 6 */ unsigned char :6; /* Byte 9 Bits 0-5 */ #endif unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */ unsigned char PrimaryVolumeTag[36]; /* barcode */ unsigned char AlternateVolumeTag[36]; #ifdef HAS_LONG_DESCRIPTORS unsigned char Reserved[4]; /* 4 extra bytes? */ #endif } TransportElementDescriptor_T; /* Now for element status data; */ typedef unsigned char barcode[37]; typedef struct ElementStatus { int StorageElementCount; int ImportExportCount; int DataTransferElementCount; int *DataTransferElementAddress; /* array. */ int *DataTransferElementSourceStorageElementNumber; /* array */ barcode *DataTransferPrimaryVolumeTag; /* array. */ barcode *DataTransferAlternateVolumeTag; /* array. */ barcode *PrimaryVolumeTag; /* array */ barcode *AlternateVolumeTag; /* array */ int *StorageElementAddress; /* array */ boolean *StorageElementIsImportExport; /* array */ int TransportElementAddress; /* assume only one of those... */ boolean *DataTransferElementFull; /* array */ boolean *StorageElementFull; /* array */ } ElementStatus_T; /* Now for the SCSI ID and LUN information: */ typedef struct scsi_id { int id; int lun; } scsi_id_t; #define MEDIUM_CHANGER_TYPE 8 /* what type bits are set for medium changers. */ /* The following two structs are used for the brain-dead functions of the * NSM jukebox. */ typedef struct NSM_Param { unsigned char page_code; unsigned char reserved; unsigned char page_len_msb; unsigned char page_len_lsb; unsigned char allocation_msb; unsigned char allocation_lsb; unsigned char reserved2[2]; unsigned char command_code[4]; unsigned char command_params[2048]; /* egregious overkill. */ } NSM_Param_T; extern RequestSense_T scsi_error_sense; typedef struct NSM_Result { unsigned char page_code; unsigned char reserved; unsigned char page_len_msb; unsigned char page_len_lsb; unsigned char command_code[4]; unsigned char ces_code[2]; unsigned char return_data[0xffff]; /* egregioius overkill */ } NSM_Result_T; #endif /* of multi-include protection. */