NT4/private/ntos/dd/qic117/q117.h
2020-09-30 17:12:29 +02:00

487 lines
16 KiB
C

/*++
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