/*
 * CiderPress
 * Copyright (C) 2007 by faddenSoft, LLC.  All Rights Reserved.
 * See the file LICENSE for distribution terms.
 */
/*
 * Definitions for SCSI (Small Computer System Interface).
 *
 * These structures and defines are passed to the SCSI driver, so they work
 * equally well for ASPI and SPTI
 *
 * Consult the SCSI-2 and MMC-2 specifications for details.
 */
#ifndef __SCSI_DEFS__
#define __SCSI_DEFS__

/*
 * SCSI-2 operation codes.
 */
typedef enum {
	kScsiOpTestUnitReady			= 0x00,
	kScsiOpRezeroUnit				= 0x01,
	kScsiOpRewind					= 0x01,
	kScsiOpRequestBlockAddr			= 0x02,
	kScsiOpRequestSense				= 0x03,
	kScsiOpFormatUnit				= 0x04,
	kScsiOpReadBlockLimits			= 0x05,
	kScsiOpReassignBlocks			= 0x07,
	kScsiOpRead6					= 0x08,
	kScsiOpReceive					= 0x08,
	kScsiOpWrite6					= 0x0a,
	kScsiOpPrint					= 0x0a,
	kScsiOpSend						= 0x0a,
	kScsiOpSeek6					= 0x0b,
	kScsiOpTrackSelect				= 0x0b,
	kScsiOpSlewPrint				= 0x0b,
	kScsiOpSeekBlock				= 0x0c,
	kScsiOpPartition				= 0x0d,
	kScsiOpReadReverse				= 0x0f,
	kScsiOpWriteFilemarks			= 0x10,
	kScsiOpFlushBuffer				= 0x10,
	kScsiOpSpace					= 0x11,
	kScsiOpInquiry					= 0x12,
	kScsiOpVerify6					= 0x13,
	kScsiOpRecoverBufferedData		= 0x14,
	kScsiOpModeSelect				= 0x15,
	kScsiOpReserveUnit				= 0x16,
	kScsiOpReleaseUnit				= 0x17,
	kScsiOpCopy						= 0x18,
	kScsiOpErase					= 0x19,
	kScsiOpModeSense				= 0x1a,
	kScsiOpStartStopUnit			= 0x1b,
	kScsiOpStopPrint				= 0x1b,
	kScsiOpLoadUnload				= 0x1b,
	kScsiOpReceiveDiagnosticResults	= 0x1c,
	kScsiOpSendDiagnostic			= 0x1d,
	kScsiOpMediumRemoval			= 0x1e,
	kScsiOpReadFormattedCapacity	= 0x23,
	kScsiOpReadCapacity				= 0x25,
	kScsiOpRead						= 0x28,	// READ(10)
	kScsiOpWrite					= 0x2a,	// WRITE(10)
	kScsiOpSeek						= 0x2b,
	kScsiOpLocate					= 0x2b,
	kScsiOpPositionToElement		= 0x2b,
	kScsiOpWriteVerify				= 0x2e,
	kScsiOpVerify					= 0x2f,	// VERIFY(10)
	kScsiOpSearchDataHigh			= 0x30,
	kScsiOpSearchDataEqual			= 0x31,
	kScsiOpSearchDataLow			= 0x32,
	kScsiOpSetLimits				= 0x33,
	kScsiOpReadPosition				= 0x34,
	kScsiOpSynchronizeCache			= 0x35,
	kScsiOpCompare					= 0x39,
	kScsiOpCopyAndVerify			= 0x3a,
	kScsiOpWriteBuffer				= 0x3b,
	kScsiOpReadBuffer				= 0x3c,
	kScsiOpChangeDefinition			= 0x40,
	kScsiOpReadSubChannel			= 0x42,
	kScsiOpReadTOC					= 0x43,	// READ TOC/PMA/ATIP
	kScsiOpReadHeader				= 0x44,
	kScsiOpPlayAudio				= 0x45,
	kScsiOpPlayAudioMSF				= 0x47,
	kScsiOpPlayTrackIndex			= 0x48,
	kScsiOpPlayTrackRelative		= 0x49,
	kScsiOpPauseResume				= 0x4b,
	kScsiOpLogSelect				= 0x4c,
	kScsiOpLogSense					= 0x4c,
	kScsiOpStopPlayScan				= 0x4e,
	kScsiOpReadDiscInformation		= 0x51,
	kScsiOpReadTrackInformation		= 0x52,
	kScsiOpSendOPCInformation		= 0x54,
	kScsiOpModeSelect10				= 0x55,
	kScsiOpRepairTrack				= 0x58,
	kScsiOpModeSense10				= 0x5a,
	kScsiOpReportLuns				= 0xa0,
	kScsiOpVerify12					= 0xa2,
	kScsiOpSendKey					= 0xa3,
	kScsiOpReportKey				= 0xa4,
	kScsiOpMoveMedium				= 0xa5,
	kScsiOpLoadUnloadSlot			= 0xa6,
	kScsiOpExchangeMedium			= 0xa6,
	kScsiOpSetReadAhead				= 0xa7,
	kScsiOpReadDVDStructure			= 0xad,
	kScsiOpWriteAndVerify			= 0xae,
	kScsiOpRequestVolElement		= 0xb5,
	kScsiOpSendVolumeTag			= 0xb6,
	kScsiOpReadElementStatus		= 0xb8,
	kScsiOpReadCDMSF				= 0xb9,
	kScsiOpScanCD					= 0xba,
	kScsiOpSetCDSpeed				= 0xbb,
	kScsiOpPlayCD					= 0xbc,
	kScsiOpMechanismStatus			= 0xbd,
	kScsiOpReadCD					= 0xbe,
	kScsiOpInitElementRange			= 0xe7,
} SCSIOperationCode;


/*
 * SCSI status codes.
 */
typedef enum {
	kScsiStatGood					= 0x00,
	kScsiStatCheckCondition			= 0x02,
	kScsiStatConditionMet			= 0x04,
	kScsiStatBusy					= 0x08,
	kScsiStatIntermediate			= 0x10,
	kScsiStatIntermediateCondMet	= 0x14,
	kScsiStatReservationConflict	= 0x18,
	kScsiStatCommandTerminated		= 0x22,
	kScsiStatQueueFull				= 0x28,
} SCSIStatus;

/*
 * SCSI sense codes.
 */
typedef enum {
	kScsiSenseNoSense				= 0x00,
	kScsiSenseRecoveredError		= 0x01,
	kScsiSenseNotReady				= 0x02,
	kScsiSenseMediumError			= 0x03,
	kScsiSenseHardwareError			= 0x04,
	kScsiSenseIllegalRequest		= 0x05,
	kScsiSenseUnitAttention			= 0x06,
	kScsiSenseDataProtect			= 0x07,
	kScsiSenseBlankCheck			= 0x08,
	kScsiSenseUnqiue				= 0x09,
	kScsiSenseCopyAborted			= 0x0a,
	kScsiSenseAbortedCommand		= 0x0b,
	kScsiSenseEqual					= 0x0c,
	kScsiSenseVolOverflow			= 0x0d,
	kScsiSenseMiscompare			= 0x0e,
	kScsiSenseReserved				= 0x0f,
} SCSISenseCode;


/*
 * SCSI additional sense codes.
 */
typedef enum {
	kScsiAdSenseNoSense				= 0x00,
	kScsiAdSenseInvalidMedia		= 0x30,
	kScsiAdSenseNoMediaInDevice		= 0x3a,
} SCSIAdSenseCode;

/*
 * SCSI device types.
 */
typedef enum {
	kScsiDevTypeDASD				= 0x00,		// Disk Device
	kScsiDevTypeSEQD				= 0x01,		// Tape Device
	kScsiDevTypePRNT				= 0x02,		// Printer
	kScsiDevTypePROC				= 0x03,		// Processor
	kScsiDevTypeWORM				= 0x04,		// Write-once read-multiple
	kScsiDevTypeCDROM				= 0x05,		// CD-ROM device
	kScsiDevTypeSCAN				= 0x06,		// Scanner device
	kScsiDevTypeOPTI				= 0x07,		// Optical memory device
	kScsiDevTypeJUKE				= 0x08,		// Medium Changer device
	kScsiDevTypeCOMM				= 0x09,		// Communications device
	kScsiDevTypeRESL				= 0x0a,		// Reserved (low)
	kScsiDevTypeRESH				= 0x1e,		// Reserved (high)
	kScsiDevTypeUNKNOWN				= 0x1f,		// Unknown or no device type
} SCSIDeviceType;

/*
 * Generic 6-byte request block.
 */
typedef struct CDB6 {
	unsigned char	operationCode;
	unsigned char	immediate : 1;
	unsigned char	commandUniqueBits : 4;
	unsigned char	logicalUnitNumber : 3;
	unsigned char	commandUniqueBytes[3];
	unsigned char	link : 1;
	unsigned char	flag : 1;
	unsigned char	reserved : 4;
	unsigned char	vendorUnique : 2;
} CDB6;

/*
 * Generic 10-byte request block.
 *
 * Use for READ(10), READ CAPACITY.
 */
typedef struct CDB10 {
	unsigned char	operationCode;
	unsigned char	relativeAddress : 1;
	unsigned char	reserved1 : 2;
	unsigned char	forceUnitAccess : 1;
	unsigned char	disablePageOut : 1;
	unsigned char	logicalUnitNumber : 3;
	unsigned char	logicalBlockAddr0;	// MSB
	unsigned char	logicalBlockAddr1;
	unsigned char	logicalBlockAddr2;
	unsigned char	logicalBlockAddr3;	// LSB
	unsigned char	reserved2;
	unsigned char	transferLength0;	// MSB
	unsigned char	transferLength1;	// LSB
	unsigned char	control;
} CDB10;

/*
 * INQUIRY request block.
 */
typedef struct CDB6Inquiry {
	unsigned char	operationCode;
	unsigned char	EVPD : 1;
	unsigned char	reserved1 : 4;
	unsigned char	logicalUnitNumber : 3;
	unsigned char	pageCode;
	unsigned char	reserved2;
	unsigned char	allocationLength;
	unsigned char	control;
} CDB6Inquiry;

/*
 * Sense data (ASPI SenseArea).
 */
typedef struct CDB_SenseData {
	unsigned char	errorCode:7;
	unsigned char	valid:1;
	unsigned char	segmentNumber;
	unsigned char	senseKey:4;
	unsigned char	reserved:1;
	unsigned char	incorrectLength:1;
	unsigned char	endOfMedia:1;
	unsigned char	fileMark:1;
	unsigned char	information[4];
	unsigned char	additionalSenseLength;
	unsigned char	commandSpecificInformation[4];
	unsigned char	additionalSenseCode;			// ASC
	unsigned char	additionalSenseCodeQualifier;	// ASCQ
	unsigned char	fieldReplaceableUnitCode;
	unsigned char	senseKeySpecific[3];
} CDB_SenseData;

/*
 * Default sense buffer size.
 */
#define kSenseBufferSize 18


//#define INQUIRYDATABUFFERSIZE 36

/*
 * Result from INQUIRY.
 */
typedef struct CDB_InquiryData {
	unsigned char	deviceType : 5;
	unsigned char	deviceTypeQualifier : 3;
	unsigned char	deviceTypeModifier : 7;
	unsigned char	removableMedia : 1;
	unsigned char	versions;
	unsigned char	responseDataFormat : 4;
	unsigned char	reserved1 : 2;
	unsigned char	trmIOP : 1;
	unsigned char	AENC : 1;
	unsigned char	additionalLength;
	unsigned char	reserved2[2];
	unsigned char	softReset : 1;
	unsigned char	commandQueue : 1;
	unsigned char	reserved3 : 1;
	unsigned char	linkedCommands : 1;
	unsigned char	synchronous : 1;
	unsigned char	wide16Bit : 1;
	unsigned char	wide32Bit : 1;
	unsigned char	relativeAddressing : 1;
	unsigned char	vendorId[8];
	unsigned char	productId[16];
	unsigned char	productRevisionLevel[4];
	unsigned char	vendorSpecific[20];
	unsigned char	reserved4[40];
} CDB_InquiryData;

/*
 * Result from READ CAPACITY.
 */
typedef struct CDB_ReadCapacityData {
	unsigned char	logicalBlockAddr0;	// MSB
	unsigned char	logicalBlockAddr1;
	unsigned char	logicalBlockAddr2;
	unsigned char	logicalBlockAddr3;	// LSB
	unsigned char	bytesPerBlock0;		// MSB
	unsigned char	bytesPerBlock1;
	unsigned char	bytesPerBlock2;
	unsigned char	bytesPerBlock3;		// LSB
} CDB_ReadCapacityData;

#endif /*__SCSI_DEFS__*/
