Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Src/MacSCSICommand.h
/* MacScsiCommand.h */ |
/* |
* Scsi-specific definitions. |
*/ |
#ifndef __MacSCSICommand__ |
#define __MacSCSICommand__ |
#include <stddef.h> |
/* |
* Include the O.S. files in a specific order to make sure that we have |
* a definition for the _SCSIAtomic trap. |
*/ |
#include <Traps.h> |
#ifndef _SCSIAtomic |
#define _SCSIAtomic 0xA089 |
#endif |
/* |
* This uses the new "common" SCSI.h which is not yet in the public |
* header folders. |
*/ |
#include "SCSI.h" |
#ifndef NULL |
#define NULL 0 |
#endif |
/* |
* 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 devTypeMod |
*/ |
enum { |
kScsiInquiryRMB = 0x80 /* Removable medium if set */ |
}; |
/* |
* These bits may be set in 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 */ |
}; |
enum { |
kScsiDevTypeDirect = 0, |
kScsiDevTypeSequential, |
kScsiDevTypePrinter, |
kScsiDevTypeProcessor, |
kScsiDevTypeWorm, /* Write-once, read multiple */ |
kScsiDevTypeCDROM, |
kScsiDevTypeScanner, |
kScsiDevTypeOptical, |
kScsiDevTypeChanger, |
kScsiDevTypeComm, |
kScsiDevTypeGraphicArts0A, |
kScsiDevTypeGraphicArts0B, |
kScsiDevTypeFirstReserved, /* Start of reserved sequence */ |
kScsiDevTypeUnknownOrMissing = 0x1F, |
kScsiDevTypeMask = 0x1F |
}; |
/* |
* These are device type modifiers. 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 kScsiCmdModeSelect12 0x55 |
#define kScsiCmdModeSelect6 0x15 |
#define kScsiCmdModeSense12 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). The Macintosh |
* SCSI Manager can't really deal with these. |
*/ |
#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 kScsiMsgTwoByte 0x20 |
#define kScsiMsgTwoByteMin 0x20 |
#define kScsiMsgTwoByteMax 0x2f |
/* |
* Default timeout times for SCSI commands. |
*/ |
#define kScsiNormalCompletionTime (30L) /* 1/2 second */ |
/* |
* Dratted DAT tape. |
*/ |
#define kScsiDATCompletionTime (60L * 60L); /* One minute */ |
/* |
* Yes, we do allow 90 seconds for spin-up of those dratted tape drives. |
*/ |
#define kScsiSpinUpCompletionTime (60L * 90L) |
/* |
* The NCR Bits, as returned by ScsiStat are only useful for maintenence |
* and testing. Only the following bits are valid in the current |
* implementation of the SCSI Manager. There is no guarantee that the |
* bits are accessable, or useful, in future SCSI implementations. |
* Note, however, that the Asynchronous SCSI Manager sets these bits to |
* correspond to its current internal state. |
* |
* Using these bits, the following implications can be drawn: |
* kScsiStatBSY Bus is busy. (On systems with multiple busses, |
* there is no indication which bus is busy.) |
* kScsiStatREQ Bus is busy. There is no way to determine whether |
* the target has changed phase or has set REQ. |
* Bus Phase If kScsiStatREQ and kSCSIStatBSY are set, the |
* phase bits will indicate the current bus phase |
* from the point of view of the initiator. It may |
* not necessarily correspond exactly to the hardware |
* bus phase. |
*/ |
#define kScsiStatBSY (1 << 6) /* Bus Busy */ |
#define kScsiStatREQ (1 << 5) /* Set if Bus Busy */ |
#define kScsiStatMSG (1 << 4) /* MSG phase bit */ |
#define kScsiStatCD (1 << 3) /* C/D phase bit */ |
#define kScsiStatIO (1 << 2) /* I/O phase bit */ |
#define kScsiStatSEL (1 << 1) /* Select phase bit */ |
#define kScsiPhaseMask (kScsiStatMSG | kScsiStatCD | kScsiStatIO) |
#define kScsiPhaseShift (2) |
#define ScsiBusPhase(x) (((x) & kScsiPhaseMask) >> kScsiPhaseShift) |
/* |
* The phases are defined by a combination of bus lines. Note: these values |
* have already been shifted. Other values are undefined. This is really |
* only useful for the original SCSI manager. |
*/ |
#define kScsiPhaseDATO 0 /* Data output (host -> device) */ |
#define kScsiPhaseDATI 1 /* Data input (device -> host) */ |
#define kScsiPhaseCMD 2 /* Command */ |
#define kScsiPhaseSTS 3 /* Status */ |
#define kScsiPhaseMSGO 6 /* Message output */ |
#define kScsiPhaseMSGI 7 /* Message input */ |
#endif /* __MacSCSICommand__ */ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14