421 lines
17 KiB
C
421 lines
17 KiB
C
|
/*
|
||
|
File: MacSCSICommand.h
|
||
|
|
||
|
Contains: SCSI specific definitions.
|
||
|
|
||
|
Written by: Martin Minow
|
||
|
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Copyright 1995, 1997 by Apple Computer, Inc.
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
* Permission to use, copy, modify, and distribute this software and
|
||
|
* its documentation for any purpose and without fee is hereby granted,
|
||
|
* provided that the above copyright notice appears in all copies and
|
||
|
* that both the copyright notice and this permission notice appear in
|
||
|
* supporting documentation.
|
||
|
*
|
||
|
* APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
|
||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
* FOR A PARTICULAR PURPOSE.
|
||
|
*
|
||
|
* IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
|
||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
|
||
|
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Scsi-specific definitions.
|
||
|
*/
|
||
|
#ifndef __MacSCSICommand__
|
||
|
#define __MacSCSICommand__
|
||
|
|
||
|
/*
|
||
|
* The 6-byte commands are used for most simple
|
||
|
* I/O requests.
|
||
|
*/
|
||
|
struct SCSI_6_Byte_Command { /* Six-byte command */
|
||
|
unsigned char opcode; /* 0 */
|
||
|
unsigned char lbn3; /* 1 lbn in low 5 */
|
||
|
unsigned char lbn2; /* 2 */
|
||
|
unsigned char lbn1; /* 3 */
|
||
|
unsigned char len; /* 4 */
|
||
|
unsigned char ctrl; /* 5 */
|
||
|
};
|
||
|
typedef struct SCSI_6_Byte_Command SCSI_6_Byte_Command;
|
||
|
|
||
|
struct SCSI_10_Byte_Command { /* Ten-byte command */
|
||
|
unsigned char opcode; /* 0 */
|
||
|
unsigned char lun; /* 1 */
|
||
|
unsigned char lbn4; /* 2 */
|
||
|
unsigned char lbn3; /* 3 */
|
||
|
unsigned char lbn2; /* 4 */
|
||
|
unsigned char lbn1; /* 5 */
|
||
|
unsigned char pad; /* 6 */
|
||
|
unsigned char len2; /* 7 */
|
||
|
unsigned char len1; /* 8 */
|
||
|
unsigned char ctrl; /* 9 */
|
||
|
};
|
||
|
typedef struct SCSI_10_Byte_Command SCSI_10_Byte_Command;
|
||
|
|
||
|
struct SCSI_12_Byte_Command { /* Twelve-byte command */
|
||
|
unsigned char opcode; /* 0 */
|
||
|
unsigned char lun; /* 1 */
|
||
|
unsigned char lbn4; /* 2 */
|
||
|
unsigned char lbn3; /* 3 */
|
||
|
unsigned char lbn2; /* 4 */
|
||
|
unsigned char lbn1; /* 5 */
|
||
|
unsigned char len4; /* 6 */
|
||
|
unsigned char len3; /* 7 */
|
||
|
unsigned char len2; /* 8 */
|
||
|
unsigned char len1; /* 9 */
|
||
|
unsigned char pad; /* 10 */
|
||
|
unsigned char ctrl; /* 11 */
|
||
|
};
|
||
|
typedef struct SCSI_12_Byte_Command SCSI_12_Byte_Command;
|
||
|
|
||
|
/*
|
||
|
* This union defines all scsi commands.
|
||
|
*/
|
||
|
union SCSI_Command {
|
||
|
SCSI_6_Byte_Command scsi6;
|
||
|
SCSI_10_Byte_Command scsi10;
|
||
|
SCSI_12_Byte_Command scsi12;
|
||
|
unsigned char scsi[12];
|
||
|
};
|
||
|
typedef union SCSI_Command SCSI_Command, *SCSI_CommandPtr;
|
||
|
|
||
|
/*
|
||
|
* Returned by a read-capacity command.
|
||
|
*/
|
||
|
struct SCSI_Capacity_Data {
|
||
|
unsigned char lbn4; /* Number */
|
||
|
unsigned char lbn3; /* of */
|
||
|
unsigned char lbn2; /* logical */
|
||
|
unsigned char lbn1; /* blocks */
|
||
|
unsigned char len4; /* Length */
|
||
|
unsigned char len3; /* of each */
|
||
|
unsigned char len2; /* logical block */
|
||
|
unsigned char len1; /* in bytes */
|
||
|
};
|
||
|
typedef struct SCSI_Capacity_Data SCSI_Capacity_Data;
|
||
|
|
||
|
struct SCSI_Inquiry_Data { /* Inquiry returns this */
|
||
|
unsigned char devType; /* 0 Device type, */
|
||
|
unsigned char devTypeMod; /* 1 Device type modifier */
|
||
|
unsigned char version; /* 2 ISO/ECMA/ANSI version */
|
||
|
unsigned char format; /* 3 Response data format */
|
||
|
unsigned char length; /* 4 Additional Length */
|
||
|
unsigned char reserved5; /* 5 Reserved */
|
||
|
unsigned char reserved6; /* 6 Reserved */
|
||
|
unsigned char flags; /* 7 Capability flags */
|
||
|
unsigned char vendor[8]; /* 8-15 Vendor-specific */
|
||
|
unsigned char product[16]; /* 16-31 Product id */
|
||
|
unsigned char revision[4]; /* 32-35 Product revision */
|
||
|
unsigned char vendorSpecific[20]; /* 36-55 Vendor stuff */
|
||
|
unsigned char moreReserved[40]; /* 56-95 Reserved */
|
||
|
};
|
||
|
typedef struct SCSI_Inquiry_Data SCSI_Inquiry_Data;
|
||
|
|
||
|
/*
|
||
|
* This bit may be set in SCSI_Inquiry_Data.devTypeMod
|
||
|
*/
|
||
|
enum {
|
||
|
kScsiInquiryRMB = 0x80 /* Removable medium if set */
|
||
|
};
|
||
|
/*
|
||
|
* These bits may be set in SCSI_Inquiry_Data.flags
|
||
|
*/
|
||
|
enum {
|
||
|
kScsiInquiryRelAdr = 0x80, /* Has relative addressing */
|
||
|
kScsiInquiryWBus32 = 0x40, /* Wide (32-bit) transfers */
|
||
|
kScsiInquiryWBus16 = 0x20, /* Wide (16-bit) transfers */
|
||
|
kScsiInquirySync = 0x10, /* Synchronous transfers */
|
||
|
kScsiInquiryLinked = 0x08, /* Linked commands ok */
|
||
|
kScsiInquiryReserved = 0x04,
|
||
|
kScsiInquiryCmdQue = 0x02, /* Tagged cmd queuing ok */
|
||
|
kScsiInquirySftRe = 0x01 /* Soft reset alternative */
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* These bits may be set in SCSI_Inquiry_Data.devType
|
||
|
*/
|
||
|
enum {
|
||
|
kScsiDevTypeDirect = 0,
|
||
|
kScsiDevTypeSequential,
|
||
|
kScsiDevTypePrinter,
|
||
|
kScsiDevTypeProcessor,
|
||
|
kScsiDevTypeWorm, /* Write-once, read mult */
|
||
|
kScsiDevTypeCDROM,
|
||
|
kScsiDevTypeScanner,
|
||
|
kScsiDevTypeOptical,
|
||
|
kScsiDevTypeChanger,
|
||
|
kScsiDevTypeComm,
|
||
|
kScsiDevTypeGraphicArts0A,
|
||
|
kScsiDevTypeGraphicArts0B,
|
||
|
kScsiDevTypeFirstReserved, /* Reserved sequence start */
|
||
|
kScsiDevTypeUnknownOrMissing = 0x1F,
|
||
|
kScsiDevTypeMask = 0x1F
|
||
|
};
|
||
|
/*
|
||
|
* These are device type qualifiers. We need them to distinguish between "unknown"
|
||
|
* and "missing" devices.
|
||
|
*/
|
||
|
enum {
|
||
|
kScsiDevTypeQualifierConnected = 0x00, /* Exists and is connected */
|
||
|
kScsiDevTypeQualifierNotConnected = 0x20, /* Logical unit exists */
|
||
|
kScsiDevTypeQualifierReserved = 0x40,
|
||
|
kScsiDevTypeQualifierMissing = 0x60, /* No such logical unit */
|
||
|
kScsiDevTypeQualifierVendorSpecific = 0x80, /* Other bits are unspecified */
|
||
|
kScsiDevTypeQualifierMask = 0xE0
|
||
|
};
|
||
|
#define kScsiDevTypeMissing \
|
||
|
(kScsiDevTypeUnknownOrMissing | kScsiDevTypeQualifierMissing)
|
||
|
|
||
|
/*
|
||
|
* This is the data that is returned after a GetExtendedStatus
|
||
|
* request. The errorCode gives a general indication of the error,
|
||
|
* which may be qualified by the additionalSenseCode and
|
||
|
* additionalSenseQualifier fields. These may be device (vendor)
|
||
|
* specific values, however. The info[] field contains additional
|
||
|
* information. For a media error, it contains the failing
|
||
|
* logical block number (most-significant byte first).
|
||
|
*/
|
||
|
struct SCSI_Sense_Data { /* Request Sense result */
|
||
|
unsigned char errorCode; /* 0 Class code, valid lbn */
|
||
|
unsigned char segmentNumber; /* 1 Segment number */
|
||
|
unsigned char senseKey; /* 2 Sense key and flags */
|
||
|
unsigned char info[4];
|
||
|
unsigned char additionalSenseLength;
|
||
|
unsigned char reservedForCopy[4];
|
||
|
unsigned char additionalSenseCode;
|
||
|
unsigned char additionalSenseQualifier;
|
||
|
unsigned char fruCode; /* Field replacable unit code */
|
||
|
unsigned char senseKeySpecific[2];
|
||
|
unsigned char additional[101];
|
||
|
};
|
||
|
typedef struct SCSI_Sense_Data SCSI_Sense_Data;
|
||
|
/*
|
||
|
* The high-bit of errorCode signals whether there is a logical
|
||
|
* block. The low value signals whether there is a valid sense
|
||
|
*/
|
||
|
#define kScsiSenseHasLBN 0x80 /* Logical block number set */
|
||
|
#define kScsiSenseInfoValid 0x70 /* Is sense key valid? */
|
||
|
#define kScsiSenseInfoMask 0x70 /* Mask for sense info */
|
||
|
/*
|
||
|
* These bits may be set in the sense key
|
||
|
*/
|
||
|
#define kScsiSenseKeyMask 0x0F
|
||
|
#define kScsiSenseILI 0x20 /* Illegal logical Length */
|
||
|
#define kScsiSenseEOM 0x40 /* End of media */
|
||
|
#define kScsiSenseFileMark 0x80 /* End of file mark */
|
||
|
|
||
|
/*
|
||
|
* SCSI sense codes. (Returned after request sense).
|
||
|
*/
|
||
|
#define kScsiSenseNone 0x00 /* No error */
|
||
|
#define kScsiSenseRecoveredErr 0x01 /* Warning */
|
||
|
#define kScsiSenseNotReady 0x02 /* Device not ready */
|
||
|
#define kScsiSenseMediumErr 0x03 /* Device medium error */
|
||
|
#define kScsiSenseHardwareErr 0x04 /* Device hardware error */
|
||
|
#define kScsiSenseIllegalReq 0x05 /* Illegal request for dev. */
|
||
|
#define kScsiSenseUnitAtn 0x06 /* Unit attention (not err) */
|
||
|
#define kScsiSenseDataProtect 0x07 /* Data protection */
|
||
|
#define kScsiSenseBlankCheck 0x08 /* Tape-specific error */
|
||
|
#define kScsiSenseVendorSpecific 0x09 /* Vendor-specific error */
|
||
|
#define kScsiSenseCopyAborted 0x0a /* Copy request cancelled */
|
||
|
#define kScsiSenseAbortedCmd 0x0b /* Initiator aborted cmd. */
|
||
|
#define kScsiSenseEqual 0x0c /* Comparison equal */
|
||
|
#define kScsiSenseVolumeOverflow 0x0d /* Write past end mark */
|
||
|
#define kScsiSenseMiscompare 0x0e /* Comparison failed */
|
||
|
#define kScsiSenseCurrentErr 0x70
|
||
|
#define kScsiSenseDeferredErr 0x71
|
||
|
|
||
|
/*
|
||
|
* Mode sense parameter header
|
||
|
*/
|
||
|
struct SCSI_ModeParamHeader {
|
||
|
unsigned char modeDataLength;
|
||
|
unsigned char mediumType;
|
||
|
unsigned char deviceSpecific;
|
||
|
unsigned char blockDescriptorLength;
|
||
|
};
|
||
|
typedef struct SCSI_ModeParamHeader SCSI_ModeParamHeader;
|
||
|
|
||
|
struct SCSI_ModeParamBlockDescriptor {
|
||
|
unsigned char densityCode;
|
||
|
unsigned char numberOfBlocks[3];
|
||
|
unsigned char reserved;
|
||
|
unsigned char blockLength[3];
|
||
|
};
|
||
|
typedef struct SCSI_ModeParamBlockDescriptor SCSI_ModeParamBlockDescriptor;
|
||
|
|
||
|
union SCSI_ModeParamPage {
|
||
|
unsigned char data[1];
|
||
|
struct {
|
||
|
unsigned char code;
|
||
|
unsigned char length;
|
||
|
} page;
|
||
|
};
|
||
|
typedef union SCSI_ModeParamPage SCSI_ModeParamPage;
|
||
|
|
||
|
/*
|
||
|
* LogSense parameter header
|
||
|
*/
|
||
|
struct SCSI_LogSenseParamHeader {
|
||
|
unsigned char pageCode;
|
||
|
unsigned char reserved;
|
||
|
unsigned char pageLength[2];
|
||
|
};
|
||
|
typedef struct SCSI_LogSenseParamHeader SCSI_LogSenseParamHeader;
|
||
|
|
||
|
/*
|
||
|
* Log parameter pages are variable-length with a fixed length header.
|
||
|
*/
|
||
|
union SCSI_LogSenseParamPage {
|
||
|
unsigned char data[1];
|
||
|
struct {
|
||
|
unsigned char parameterCode[2];
|
||
|
unsigned char flags;
|
||
|
unsigned char parameterLength;
|
||
|
} page;
|
||
|
};
|
||
|
typedef union SCSI_LogSenseParamPage SCSI_LogSenseParamPage;
|
||
|
|
||
|
/*
|
||
|
* SCSI command status (from status phase)
|
||
|
*/
|
||
|
#define kScsiStatusGood 0x00 /* Normal completion */
|
||
|
#define kScsiStatusCheckCondition 0x02 /* Need GetExtendedStatus */
|
||
|
#define kScsiStatusConditionMet 0x04
|
||
|
#define kScsiStatusBusy 0x08 /* Device busy (self-test?) */
|
||
|
#define kScsiStatusIntermediate 0x10 /* Intermediate status */
|
||
|
#define kScsiStatusResConflict 0x18 /* Reservation conflict */
|
||
|
#define kScsiStatusQueueFull 0x28 /* Target can't do command */
|
||
|
#define kScsiStatusReservedMask 0x3e /* Vendor specific? */
|
||
|
|
||
|
/*
|
||
|
* SCSI command codes. Commands defined as ...6, ...10, ...12, are
|
||
|
* six-byte, ten-byte, and twelve-byte variants of the indicated command.
|
||
|
*/
|
||
|
/*
|
||
|
* These commands are supported for all devices.
|
||
|
*/
|
||
|
#define kScsiCmdChangeDefinition 0x40
|
||
|
#define kScsiCmdCompare 0x39
|
||
|
#define kScsiCmdCopy 0x18
|
||
|
#define kScsiCmdCopyAndVerify 0x3a
|
||
|
#define kScsiCmdInquiry 0x12
|
||
|
#define kScsiCmdLogSelect 0x4c
|
||
|
#define kScsiCmdLogSense 0x4d
|
||
|
#define kScsiCmdModeSelect10 0x55
|
||
|
#define kScsiCmdModeSelect6 0x15
|
||
|
#define kScsiCmdModeSense10 0x5a
|
||
|
#define kScsiCmdModeSense6 0x1a
|
||
|
#define kScsiCmdReadBuffer 0x3c
|
||
|
#define kScsiCmdRecvDiagResult 0x1c
|
||
|
#define kScsiCmdRequestSense 0x03
|
||
|
#define kScsiCmdSendDiagnostic 0x1d
|
||
|
#define kScsiCmdTestUnitReady 0x00
|
||
|
#define kScsiCmdWriteBuffer 0x3b
|
||
|
|
||
|
/*
|
||
|
* These commands are supported by direct-access devices only.
|
||
|
*/
|
||
|
#define kScsiCmdFormatUnit 0x04
|
||
|
#define kSCSICmdCopy 0x18
|
||
|
#define kSCSICmdCopyAndVerify 0x3a
|
||
|
#define kScsiCmdLockUnlockCache 0x36
|
||
|
#define kScsiCmdPrefetch 0x34
|
||
|
#define kScsiCmdPreventAllowRemoval 0x1e
|
||
|
#define kScsiCmdRead6 0x08
|
||
|
#define kScsiCmdRead10 0x28
|
||
|
#define kScsiCmdReadCapacity 0x25
|
||
|
#define kScsiCmdReadDefectData 0x37
|
||
|
#define kScsiCmdReadLong 0x3e
|
||
|
#define kScsiCmdReassignBlocks 0x07
|
||
|
#define kScsiCmdRelease 0x17
|
||
|
#define kScsiCmdReserve 0x16
|
||
|
#define kScsiCmdRezeroUnit 0x01
|
||
|
#define kScsiCmdSearchDataEql 0x31
|
||
|
#define kScsiCmdSearchDataHigh 0x30
|
||
|
#define kScsiCmdSearchDataLow 0x32
|
||
|
#define kScsiCmdSeek6 0x0b
|
||
|
#define kScsiCmdSeek10 0x2b
|
||
|
#define kScsiCmdSetLimits 0x33
|
||
|
#define kScsiCmdStartStopUnit 0x1b
|
||
|
#define kScsiCmdSynchronizeCache 0x35
|
||
|
#define kScsiCmdVerify 0x2f
|
||
|
#define kScsiCmdWrite6 0x0a
|
||
|
#define kScsiCmdWrite10 0x2a
|
||
|
#define kScsiCmdWriteAndVerify 0x2e
|
||
|
#define kScsiCmdWriteLong 0x3f
|
||
|
#define kScsiCmdWriteSame 0x41
|
||
|
|
||
|
/*
|
||
|
* These commands are supported by sequential devices.
|
||
|
*/
|
||
|
#define kScsiCmdRewind 0x01
|
||
|
#define kScsiCmdWriteFilemarks 0x10
|
||
|
#define kScsiCmdSpace 0x11
|
||
|
#define kScsiCmdLoadUnload 0x1B
|
||
|
/*
|
||
|
* ANSI SCSI-II for CD-ROM devices.
|
||
|
*/
|
||
|
#define kScsiCmdReadCDTableOfContents 0x43
|
||
|
|
||
|
/*
|
||
|
* Message codes (for Msg In and Msg Out phases).
|
||
|
*/
|
||
|
#define kScsiMsgAbort 0x06
|
||
|
#define kScsiMsgAbortTag 0x0d
|
||
|
#define kScsiMsgBusDeviceReset 0x0c
|
||
|
#define kScsiMsgClearQueue 0x0e
|
||
|
#define kScsiMsgCmdComplete 0x00
|
||
|
#define kScsiMsgDisconnect 0x04
|
||
|
#define kScsiMsgIdentify 0x80
|
||
|
#define kScsiMsgIgnoreWideResdue 0x23
|
||
|
#define kScsiMsgInitiateRecovery 0x0f
|
||
|
#define kScsiMsgInitiatorDetectedErr 0x05
|
||
|
#define kScsiMsgLinkedCmdComplete 0x0a
|
||
|
#define kScsiMsgLinkedCmdCompleteFlag 0x0b
|
||
|
#define kScsiMsgParityErr 0x09
|
||
|
#define kScsiMsgRejectMsg 0x07
|
||
|
#define kScsiMsgModifyDataPtr 0x00 /* Extended msg */
|
||
|
#define kScsiMsgNop 0x08
|
||
|
#define kScsiMsgHeadOfQueueTag 0x21 /* Two byte msg */
|
||
|
#define kScsiMsgOrderedQueueTag 0x22 /* Two byte msg */
|
||
|
#define kScsiMsgSimpleQueueTag 0x20 /* Two byte msg */
|
||
|
#define kScsiMsgReleaseRecovery 0x10
|
||
|
#define kScsiMsgRestorePointers 0x03
|
||
|
#define kScsiMsgSaveDataPointers 0x02
|
||
|
#define kScsiMsgSyncXferReq 0x01 /* Extended msg */
|
||
|
#define kScsiMsgWideDataXferReq 0x03 /* Extended msg */
|
||
|
#define kScsiMsgTerminateIOP 0x11
|
||
|
#define kScsiMsgExtended 0x01
|
||
|
#define kScsiMsgEnableDisconnectMask 0x40
|
||
|
|
||
|
#define kScsiMsgTwoByte 0x20
|
||
|
#define kScsiMsgTwoByteMin 0x20
|
||
|
#define kScsiMsgTwoByteMax 0x2f
|
||
|
|
||
|
/*
|
||
|
* Default timeout times for SCSI commands (times are in Msec).
|
||
|
*/
|
||
|
#define kScsiNormalCompletionTime (500L) /* 1/2 second */
|
||
|
/*
|
||
|
* Dratted DAT tape.
|
||
|
*/
|
||
|
#define kScsiDATCompletionTime (60L * 1000L); /* One minute */
|
||
|
/*
|
||
|
* Yes, we do allow 90 seconds for spin-up of those dratted tape drives.
|
||
|
*/
|
||
|
#define kScsiSpinUpCompletionTime (90L * 1000L)
|
||
|
|
||
|
|
||
|
#endif /* __MacSCSICommand__ */
|