/*++ Copyright (c) 1993 - Colorado Memory Systems, Inc. All Rights Reserved Module Name: q117.h Abstract: Data structures used only by q117 driver. Contains QIC-40 structures and Context for q117. Revision History: --*/ // // For NTBACKUP to work, an early warning is required to allow the // application to perform tape linking. To achive this, a 5 segment // region at the end of the tape is RESERVED to genterate early warning // status. This value is used in q117WriteTape for this purpose. // #define SEGMENTS_OF_EARLY_WARNING 5 #define FORMAT_BYTE 0x6b #define MAX_BAD_BLOCKS ((1024*27)/sizeof(ULONG)) #define LIST_ENTRY_SIZE 3 #define MAX_BAD_LIST (((1024*27)/LIST_ENTRY_SIZE) - 1) #define MAX_TITLE_SIZE 44 // max volume title entry size in far memory array #define MAX_PASSWORD_SIZE 8 // max volume password size #define MAX_QIC40_FILENAME 13 #define MAX_HEADER_SIZE 256 // maximum QIC-40 header size #define DATA_HEADER_SIG_SIZE 4 // data header signature size #define ECC_BLOCKS_PER_SEGMENT 3 // number of correction sectors ber block #define BLOCKS_PER_SEGMENT 32 // Number of sectors per block on the tape. // number of data sectors per block #define DATA_BLOCKS_PER_SEGMENT (BLOCKS_PER_SEGMENT - ECC_BLOCKS_PER_SEGMENT) #define BYTES_PER_SECTOR 1024 #define BYTES_PER_SEGMENT (BYTES_PER_SECTOR*BLOCKS_PER_SEGMENT) #define TapeHeaderSig 0xaa55aa55l #define VolumeTableSig (((ULONG)'L'<<24) + ((ULONG)'B'<<16) + ('T'<<8) + 'V') #define FileHeaderSig 0x33cc33ccl #define QIC40_VENDOR_UNIQUE_SIZE 106 #define VENDOR_TYPE_NONE 0 #define VENDOR_TYPE_CMS 1 #define MOUNTAIN_SEMISPECED_SPACE 9 #define VU_SIGNATURE_SIZE 4 #define VU_TAPE_NAME_SIZE 11 #define VU_SEGS_PER_TRACK 68 #define VU_SEGS_PER_TRACK_XL 102 #define VU_80SEGS_PER_TRACK 100 #define VU_80SEGS_PER_TRACK_XL 150 #define VU_MAX_FLOPPY_TRACK 169 #define VU_MAX_FLOPPY_TRACK_XL 254 #define VU_80MAX_FLOPPY_TRACK 149 #define VU_80MAX_FLOPPY_TRACK_XL 149 #define VU_TRACKS_PER_CART 20 #define VU_80TRACKS_PER_CART 28 #define VU_MAX_FLOPPY_SIDE 1 #define VU_80MAX_FLOPPY_SIDE 4 #define VU_80MAX_FLOPPY_SIDE_XL 6 #define VU_MAX_FLOPPY_SECT 128 #define NEW_SPEC_TAPE_NAME_SIZE 44 #define FILE_VENDOR_SPECIFIC 0 #define FILE_UNIX_SPECIFIC 1 #define FILE_DATA_BAD 2 #define OP_MS_DOS 0 #define OP_UNIX 1 #define OP_UNIX_PUBLIC 2 #define OP_OS_2 3 #define OP_WINDOWS_NT 4 // Valid values for compression code #define COMP_STAC 0x01 #define COMP_VEND 0x3f // // The following section specifies QIC-40 data structures. // These structures are aligned on byte boundaries. // typedef struct _SEGMENT_BUFFER { PVOID logical; PHYSICAL_ADDRESS physical; } SEGMENT_BUFFER, *PSEGMENT_BUFFER; typedef struct _IO_REQUEST { union { ADIRequestHdr adi_hdr; /* Device Configuration FRB */ struct S_DriveCfgData ioDriveCfgData; /* Generic Device operation FRB */ struct S_DeviceOp ioDeviceOp; /* New Tape configuration FRB */ struct S_LoadTape ioLoadTape; /* Tape length configuration FRB */ struct S_TapeParms ioTapeLength; /* Device I/O FRB */ struct S_DeviceIO ioDeviceIO; /* Format request FRB */ struct S_FormatRequest ioFormatRequest; /* Direct firmware communication FRB */ struct S_DComFirm ioDComFirm; /* Direct firmware communication FRB */ struct S_TapeParms ioTapeParms; /* device info FRB (CMD_REPORT_DEVICE_INFO) */ struct S_ReportDeviceInfo ioDeviceInfo; } x; KEVENT DoneEvent; // Event that IoCompleteReqeust will set IO_STATUS_BLOCK IoStatus; // Status of request PSEGMENT_BUFFER BufferInfo; // Buffer information struct _IO_REQUEST *Next; } *PIO_REQUEST, IO_REQUEST; #pragma pack(1) struct _FAIL_DATE { UWORD Year:7; // year +1970 (1970-2097) UWORD Month:4; // month (1-12) UWORD Day:5; // day (1-31) }; struct _CMS_VENDOR_UNIQUE { UBYTE type; // 0 = none; 1 = CMS CHAR signature[VU_SIGNATURE_SIZE]; // "CMS" , ASCIIZ string ULONG creation_time; // QIC40/QIC113 date/time format CHAR tape_name[VU_TAPE_NAME_SIZE]; // space padded name CHAR checksum; // checksum of UBYTEs 0 - 19 of this struct }; struct _CMS_NEW_TAPE_NAME { CHAR reserved[MOUNTAIN_SEMISPECED_SPACE]; // leave room for Mountain stuff CHAR tape_name[NEW_SPEC_TAPE_NAME_SIZE]; // space padded name ULONG creation_time; // QIC40/QIC113 date/time format }; struct _CMS_CORRECT_TAPE_NAME { UWORD unused2; UWORD TrackSeg; // Tape segments per tape track UBYTE CartTracks; // Tape tracks per cartridge UBYTE MaxFlopSide; // Maximum floppy sides UBYTE MaxFlopTrack; // Maximum floppy tracks UBYTE MaxFlopSect; // Maximum floppy sectors CHAR tape_name[NEW_SPEC_TAPE_NAME_SIZE]; // space padded name ULONG creation_time; // QIC40/QIC113 date/time format }; typedef union _QIC40_VENDOR_UNIQUE { struct _CMS_VENDOR_UNIQUE cms; CHAR vu[QIC40_VENDOR_UNIQUE_SIZE]; struct _CMS_NEW_TAPE_NAME new_name; struct _CMS_CORRECT_TAPE_NAME correct_name; } QIC40_VENDOR_UNIQUE, *PQIC40_VENDOR_UNIQUE; typedef struct S_BadList { UBYTE ListEntry[LIST_ENTRY_SIZE]; } BAD_LIST, *BAD_LIST_PTR; typedef union U_BadMap { ULONG BadSectors[MAX_BAD_BLOCKS]; BAD_LIST BadList[MAX_BAD_LIST]; } BAD_MAP, *BAD_MAP_PTR; // Tape Header (sectors 0-1) and BadSector Array (2-13) typedef struct _TAPE_HEADER { ULONG Signature; // set to 0xaa55aa55l UBYTE FormatCode; // set to 0x01 UBYTE SubFormatCode; // Zero for pre-rev L tapes and // value + 'A' for rev L and above SEGMENT HeaderSegment; // segment number of header SEGMENT DupHeaderSegment; // segment number of duplicate header SEGMENT FirstSegment; // segment number of Data area SEGMENT LastSegment; // segment number of End of Data area ULONG CurrentFormat; // time of most recent format ULONG CurrentUpdate; // time of most recent write to cartridge union _QIC40_VENDOR_UNIQUE VendorUnique; // Vendor unique stuff UBYTE ReformatError; // 0xff if any of remaining data is lost UBYTE unused3; ULONG SegmentsUsed; // incremented every time a segment is used UBYTE unused4[4]; ULONG InitialFormat; // time of initial format UWORD FormatCount; // number of times tape has been formatted UWORD FailedSectors; // the number entries in failed sector log CHAR ManufacturerName[44]; // name of manufacturer that pre-formatted CHAR LotCode[44]; // pre-format lot code UBYTE unused5[22]; struct S_Failed { SEGMENT Segment; // number of segment that failed struct _FAIL_DATE DateFailed; // date of failure } Failed[(1024+768)/4]; // fill out remaining UBYTEs of sector + next BAD_MAP BadMap; } TAPE_HEADER, *PTAPE_HEADER; // // CMS Vendor specific area // typedef struct _CMS_VOLUME_VENDOR { CHAR Signature[4]; // set to "CMS" (null terminated) if it is our backup UWORD FirmwareRevision; // firmware version UWORD SoftwareRevision; // software version CHAR RightsFiles; // if 0xff = novell rights information present UWORD NumFiles; // number of files in volume CHAR OpSysType; // flavor of operating system at creation } CMS_VOLUME_VENDOR, PCMS_VOLUME_VENDOR; // // QIC-40 Volume table structure // typedef struct _VOLUME_TABLE_ENTRY { ULONG Signature; // this entry will be "VTBL" if volume exists SEGMENT StartSegment; // starting segment of volume for this cart SEGMENT EndingSegment; // ending segment of volume for this cart CHAR Description[MAX_TITLE_SIZE]; // user description of volume ULONG CreationTime; // time of creation of the volume UWORD VendorSpecific:1; // set if remainder of volume entry is vend spec UWORD MultiCartridge:1; // set if volume spans another tape UWORD NotVerified:1; // set if volume not verified yet UWORD NoNewName:1; // set if new file names (redirection) disallowed UWORD StacCompress:1; UWORD reserved:3; UWORD SequenceNumber:8; // multi-cartridge sequence number union { CMS_VOLUME_VENDOR cms_QIC40; UBYTE reserved[26]; // vendor extension data } Vendor; CHAR Password[MAX_PASSWORD_SIZE];// password for volume ULONG DirectorySize; // number of UBYTEs reserved for directory ULONG DataSize; // size of data area (includes other cartridges) UWORD OpSysVersion; // operating system version CHAR VolumeLabel[16]; // volume label of source drive UBYTE LogicalDevice; // who knows UBYTE PhysicalDevice; // who knows UWORD CompressCode:6; // type of compression, 3Fh = vendor specific UWORD CompressAlwaysZero:1; // must be 0 UWORD CompressSwitch:1; // compression use flag UWORD reserved1:8; UBYTE reserved2[6]; } VOLUME_TABLE_ENTRY, *PVOLUME_TABLE_ENTRY; #pragma pack() // // The following structure is the context for the q117 driver. It contains // all current "state" information for the tape drive. // typedef struct _Q117_CONTEXT { struct { BOOLEAN VerifyOnlyOnFormat; // Verify only on format. If TRUE // Then do NOT perform LOW-LEVEL // Format BOOLEAN DetectOnly; // If TRUE, allow only the CMS_DETECT // ioctl, and do not allocate memory BOOLEAN FormatDisabled; // If TRUE, Tape API format will be // Disabled. } Parameters; ULONG TapeNumber; // Tape number of this context (used // for DEVICEMAP\tape\Unit {x} and // device \\.\tape{x} BOOLEAN DriverOpened; // Set if q117Create called (this driver opened) BOOLEAN DeviceConfigured; // Set if CMD_REPORT_DEVICE_CFG performed BOOLEAN DeviceSelected; // Set if CMD_SELECT_DEVICE performed, // Reset if CMD_DESELECT_DEVICE performed struct S_DriveCfgData DriveCfg; PVOID PageHandle; VOLUME_TABLE_ENTRY ActiveVolume; // volume currently being saved to (nt volume) USHORT ActiveVolumeNumber; // The sequence number of the current struct VolDir. //TAPE_STATUS TapeStatus; // PVOID DeviceExtension; // Used by the tape thread PDEVICE_OBJECT q117iDeviceObject; PQ117_ADAPTER_INFO AdapterInfo; // Filled in at init time with DMA channel // // Error tracking // ULONG ErrorSequence; UCHAR MajorFunction; // // Queue management globals // SEGMENT_BUFFER SegmentBuffer[UNIX_MAXBFS]; // Array of segment buffers ULONG SegmentBuffersAvailable; ULONG QueueTailIndex; // Index in the IORequest array that indexes the tail. ULONG QueueHeadIndex; // This is the head of the Filer IORequest ring-tail array. PIO_REQUEST IoRequest; // pointer to array of IORequests // // current buffer information // struct { enum { NoOperation, BackupInProgress, RestoreInProgress } Type; // // Information associated with currently active segment // PVOID SegmentPointer; USHORT SegmentBytesRemaining; SEGMENT LastSegmentRead; SEGMENT CurrentSegment; // in backup (active segment) in restore (read-ahead segment) USHORT BytesZeroFilled; // Bytes at end of backup that were zeroed (not part of backup) dStatus SegmentStatus; SEGMENT EndOfUsedTape; SEGMENT LastSegment; // Last segment of volume ULONG BytesOnTape; BOOLEAN UpdateBadMap; // if true then update bad sector map ULONG BytesRead; ULONG Position; // type of last IOCTL_TAPE_SET_POSITION } CurrentOperation; // // current tape information // struct { enum { TapeInfoLoaded, BadTapeInDrive, NeedInfoLoaded } State; dStatus BadTapeError; SEGMENT LastUsedSegment; SEGMENT VolumeSegment; ULONG BadSectors; SEGMENT LastSegment; // Last formatted segment. USHORT MaximumVolumes; // Maximum volumes entries available PTAPE_HEADER TapeHeader; // Header from tape struct _TAPE_GET_MEDIA_PARAMETERS *MediaInfo; BAD_MAP_PTR BadMapPtr; ULONG BadSectorMapSize; USHORT CurBadListIndex; USHORT TapeFormatCode; enum { BadMap3ByteList, BadMap8ByteList, BadMap4ByteArray, BadMapFormatUnknown } BadSectorMapFormat; } CurrentTape; // if this global is set then the tape directory has been loaded PIO_REQUEST tapedir; char drive_type; // QIC40 or QIC80 // // The following pointers are allocated when open is called and // freed at close time. // #ifndef NO_MARKS #define MAX_MARKS 255 ULONG CurrentMark; struct _MARKENTRIES { ULONG TotalMarks; ULONG MarksAllocated; // size of mark entry buffer (in entries not bytes) ULONG MaxMarks; struct _MARKLIST { ULONG Type; ULONG Offset; } *MarkEntry; } MarkArray; #endif } Q117_CONTEXT, *PQ117_CONTEXT; typedef enum _DEQUEUE_TYPE { FlushItem, WaitForItem } DEQUEUE_TYPE; // // Common need: convert block into segment // #define BLOCK_TO_SEGMENT(block) ((SEGMENT)((block) / BLOCKS_PER_SEGMENT)) #define SEGMENT_TO_BLOCK(segment) ((BLOCK)(segment) * BLOCKS_PER_SEGMENT) // // This define is the block size used by position commands // Note: It is 512 to be compatible with the Maynstream backup // that does not do a getmedia parameters // #define BLOCK_SIZE BYTES_PER_SECTOR #define ERROR_DECODE(val) (val >> 16) #define ERR_BAD_TAPE 0x0101 /* BadTape */ #define ERR_BAD_SIGNATURE 0x0102 /* Unformat */ #define ERR_UNKNOWN_FORMAT_CODE 0x0103 /* UnknownFmt */ #define ERR_CORRECTION_FAILED 0x0104 /* error recovery failed */ #define ERR_PROGRAM_FAILURE 0x0105 /* coding error */ #define ERR_WRITE_PROTECTED 0x0106 #define ERR_TAPE_NOT_FORMATED 0x0107 #define ERR_UNRECOGNIZED_FORMAT 0x0108 /* badfmt */ #define ERR_END_OF_VOLUME 0x0109 /*EndOfVol */ #define ERR_UNUSABLE_TAPE 0x010a /* badtape - could not format */ #define ERR_SPLIT_REQUESTS 0x010b /* SplitRequests */ #define ERR_EARLY_WARNING 0x010c #define ERR_SET_MARK 0x010d #define ERR_FILE_MARK 0x010e #define ERR_LONG_FILE_MARK 0x010f #define ERR_SHORT_FILE_MARK 0x0110 #define ERR_NO_VOLUMES 0x0111 #define ERR_NO_MEMORY 0x0112 #define ERR_ECC_FAILED 0x0113 //#define ERR_END_OF_TAPE 0x0114 //#define ERR_TAPE_FULL 0x0115 #define ERR_WRITE_FAILURE 0x0116 #define ERR_BAD_BLOCK_DETECTED 0x0117 #define ERR_OP_PENDING_COMPLETION 0x0118 #define ERR_INVALID_REQUEST 0x0119