1 /* 2 File: MacSCSICommand.h 3 4 Contains: SCSI specific definitions. 5 6 Written by: Martin Minow 7 8 */ 9 10 /* 11 * Copyright 1995, 1997 by Apple Computer, Inc. 12 * All Rights Reserved 13 * 14 * Permission to use, copy, modify, and distribute this software and 15 * its documentation for any purpose and without fee is hereby granted, 16 * provided that the above copyright notice appears in all copies and 17 * that both the copyright notice and this permission notice appear in 18 * supporting documentation. 19 * 20 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE. 23 * 24 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 25 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 26 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 27 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 28 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 */ 30 31 /* 32 * Scsi-specific definitions. 33 */ 34 #ifndef __MacSCSICommand__ 35 #define __MacSCSICommand__ 36 37 /* 38 * The 6-byte commands are used for most simple 39 * I/O requests. 40 */ 41 struct SCSI_6_Byte_Command { /* Six-byte command */ 42 uint8_t opcode; /* 0 */ 43 uint8_t lbn3; /* 1 lbn in low 5 */ 44 uint8_t lbn2; /* 2 */ 45 uint8_t lbn1; /* 3 */ 46 uint8_t len; /* 4 */ 47 uint8_t ctrl; /* 5 */ 48 }; 49 typedef struct SCSI_6_Byte_Command SCSI_6_Byte_Command; 50 51 struct SCSI_10_Byte_Command { /* Ten-byte command */ 52 uint8_t opcode; /* 0 */ 53 uint8_t lun; /* 1 */ 54 uint8_t lbn4; /* 2 */ 55 uint8_t lbn3; /* 3 */ 56 uint8_t lbn2; /* 4 */ 57 uint8_t lbn1; /* 5 */ 58 uint8_t pad; /* 6 */ 59 uint8_t len2; /* 7 */ 60 uint8_t len1; /* 8 */ 61 uint8_t ctrl; /* 9 */ 62 }; 63 typedef struct SCSI_10_Byte_Command SCSI_10_Byte_Command; 64 65 struct SCSI_12_Byte_Command { /* Twelve-byte command */ 66 uint8_t opcode; /* 0 */ 67 uint8_t lun; /* 1 */ 68 uint8_t lbn4; /* 2 */ 69 uint8_t lbn3; /* 3 */ 70 uint8_t lbn2; /* 4 */ 71 uint8_t lbn1; /* 5 */ 72 uint8_t len4; /* 6 */ 73 uint8_t len3; /* 7 */ 74 uint8_t len2; /* 8 */ 75 uint8_t len1; /* 9 */ 76 uint8_t pad; /* 10 */ 77 uint8_t ctrl; /* 11 */ 78 }; 79 typedef struct SCSI_12_Byte_Command SCSI_12_Byte_Command; 80 81 /* 82 * This union defines all scsi commands. 83 */ 84 union SCSI_Command { 85 SCSI_6_Byte_Command scsi6; 86 SCSI_10_Byte_Command scsi10; 87 SCSI_12_Byte_Command scsi12; 88 uint8_t scsi[12]; 89 }; 90 typedef union SCSI_Command SCSI_Command, *SCSI_CommandPtr; 91 92 /* 93 * Returned by a read-capacity command. 94 */ 95 struct SCSI_Capacity_Data { 96 uint8_t lbn4; /* Number */ 97 uint8_t lbn3; /* of */ 98 uint8_t lbn2; /* logical */ 99 uint8_t lbn1; /* blocks */ 100 uint8_t len4; /* Length */ 101 uint8_t len3; /* of each */ 102 uint8_t len2; /* logical block */ 103 uint8_t len1; /* in bytes */ 104 }; 105 typedef struct SCSI_Capacity_Data SCSI_Capacity_Data; 106 107 struct SCSI_Inquiry_Data { /* Inquiry returns this */ 108 uint8_t devType; /* 0 Device type, */ 109 uint8_t devTypeMod; /* 1 Device type modifier */ 110 uint8_t version; /* 2 ISO/ECMA/ANSI version */ 111 uint8_t format; /* 3 Response data format */ 112 uint8_t length; /* 4 Additional Length */ 113 uint8_t reserved5; /* 5 Reserved */ 114 uint8_t reserved6; /* 6 Reserved */ 115 uint8_t flags; /* 7 Capability flags */ 116 uint8_t vendor[8]; /* 8-15 Vendor-specific */ 117 uint8_t product[16]; /* 16-31 Product id */ 118 uint8_t revision[4]; /* 32-35 Product revision */ 119 uint8_t vendorSpecific[20]; /* 36-55 Vendor stuff */ 120 uint8_t moreReserved[40]; /* 56-95 Reserved */ 121 }; 122 typedef struct SCSI_Inquiry_Data SCSI_Inquiry_Data; 123 124 /* 125 * This bit may be set in SCSI_Inquiry_Data.devTypeMod 126 */ 127 enum { 128 kScsiInquiryRMB = 0x80 /* Removable medium if set */ 129 }; 130 /* 131 * These bits may be set in SCSI_Inquiry_Data.flags 132 */ 133 enum { 134 kScsiInquiryRelAdr = 0x80, /* Has relative addressing */ 135 kScsiInquiryWBus32 = 0x40, /* Wide (32-bit) transfers */ 136 kScsiInquiryWBus16 = 0x20, /* Wide (16-bit) transfers */ 137 kScsiInquirySync = 0x10, /* Synchronous transfers */ 138 kScsiInquiryLinked = 0x08, /* Linked commands ok */ 139 kScsiInquiryReserved = 0x04, 140 kScsiInquiryCmdQue = 0x02, /* Tagged cmd queuing ok */ 141 kScsiInquirySftRe = 0x01 /* Soft reset alternative */ 142 }; 143 144 /* 145 * These bits may be set in SCSI_Inquiry_Data.devType 146 */ 147 enum { 148 kScsiDevTypeDirect = 0, 149 kScsiDevTypeSequential, 150 kScsiDevTypePrinter, 151 kScsiDevTypeProcessor, 152 kScsiDevTypeWorm, /* Write-once, read mult */ 153 kScsiDevTypeCDROM, 154 kScsiDevTypeScanner, 155 kScsiDevTypeOptical, 156 kScsiDevTypeChanger, 157 kScsiDevTypeComm, 158 kScsiDevTypeGraphicArts0A, 159 kScsiDevTypeGraphicArts0B, 160 kScsiDevTypeFirstReserved, /* Reserved sequence start */ 161 kScsiDevTypeUnknownOrMissing = 0x1F, 162 kScsiDevTypeMask = 0x1F 163 }; 164 /* 165 * These are device type qualifiers. We need them to distinguish between "unknown" 166 * and "missing" devices. 167 */ 168 enum { 169 kScsiDevTypeQualifierConnected = 0x00, /* Exists and is connected */ 170 kScsiDevTypeQualifierNotConnected = 0x20, /* Logical unit exists */ 171 kScsiDevTypeQualifierReserved = 0x40, 172 kScsiDevTypeQualifierMissing = 0x60, /* No such logical unit */ 173 kScsiDevTypeQualifierVendorSpecific = 0x80, /* Other bits are unspecified */ 174 kScsiDevTypeQualifierMask = 0xE0 175 }; 176 #define kScsiDevTypeMissing \ 177 (kScsiDevTypeUnknownOrMissing | kScsiDevTypeQualifierMissing) 178 179 /* 180 * This is the data that is returned after a GetExtendedStatus 181 * request. The errorCode gives a general indication of the error, 182 * which may be qualified by the additionalSenseCode and 183 * additionalSenseQualifier fields. These may be device (vendor) 184 * specific values, however. The info[] field contains additional 185 * information. For a media error, it contains the failing 186 * logical block number (most-significant byte first). 187 */ 188 struct SCSI_Sense_Data { /* Request Sense result */ 189 uint8_t errorCode; /* 0 Class code, valid lbn */ 190 uint8_t segmentNumber; /* 1 Segment number */ 191 uint8_t senseKey; /* 2 Sense key and flags */ 192 uint8_t info[4]; 193 uint8_t additionalSenseLength; 194 uint8_t reservedForCopy[4]; 195 uint8_t additionalSenseCode; 196 uint8_t additionalSenseQualifier; 197 uint8_t fruCode; /* Field replacable unit code */ 198 uint8_t senseKeySpecific[2]; 199 uint8_t additional[101]; 200 }; 201 typedef struct SCSI_Sense_Data SCSI_Sense_Data; 202 /* 203 * The high-bit of errorCode signals whether there is a logical 204 * block. The low value signals whether there is a valid sense 205 */ 206 #define kScsiSenseHasLBN 0x80 /* Logical block number set */ 207 #define kScsiSenseInfoValid 0x70 /* Is sense key valid? */ 208 #define kScsiSenseInfoMask 0x70 /* Mask for sense info */ 209 /* 210 * These bits may be set in the sense key 211 */ 212 #define kScsiSenseKeyMask 0x0F 213 #define kScsiSenseILI 0x20 /* Illegal logical Length */ 214 #define kScsiSenseEOM 0x40 /* End of media */ 215 #define kScsiSenseFileMark 0x80 /* End of file mark */ 216 217 /* 218 * SCSI sense codes. (Returned after request sense). 219 */ 220 #define kScsiSenseNone 0x00 /* No error */ 221 #define kScsiSenseRecoveredErr 0x01 /* Warning */ 222 #define kScsiSenseNotReady 0x02 /* Device not ready */ 223 #define kScsiSenseMediumErr 0x03 /* Device medium error */ 224 #define kScsiSenseHardwareErr 0x04 /* Device hardware error */ 225 #define kScsiSenseIllegalReq 0x05 /* Illegal request for dev. */ 226 #define kScsiSenseUnitAtn 0x06 /* Unit attention (not err) */ 227 #define kScsiSenseDataProtect 0x07 /* Data protection */ 228 #define kScsiSenseBlankCheck 0x08 /* Tape-specific error */ 229 #define kScsiSenseVendorSpecific 0x09 /* Vendor-specific error */ 230 #define kScsiSenseCopyAborted 0x0a /* Copy request cancelled */ 231 #define kScsiSenseAbortedCmd 0x0b /* Initiator aborted cmd. */ 232 #define kScsiSenseEqual 0x0c /* Comparison equal */ 233 #define kScsiSenseVolumeOverflow 0x0d /* Write past end mark */ 234 #define kScsiSenseMiscompare 0x0e /* Comparison failed */ 235 #define kScsiSenseCurrentErr 0x70 236 #define kScsiSenseDeferredErr 0x71 237 238 /* 239 * Mode sense parameter header 240 */ 241 struct SCSI_ModeParamHeader { 242 uint8_t modeDataLength; 243 uint8_t mediumType; 244 uint8_t deviceSpecific; 245 uint8_t blockDescriptorLength; 246 }; 247 typedef struct SCSI_ModeParamHeader SCSI_ModeParamHeader; 248 249 struct SCSI_ModeParamBlockDescriptor { 250 uint8_t densityCode; 251 uint8_t numberOfBlocks[3]; 252 uint8_t reserved; 253 uint8_t blockLength[3]; 254 }; 255 typedef struct SCSI_ModeParamBlockDescriptor SCSI_ModeParamBlockDescriptor; 256 257 union SCSI_ModeParamPage { 258 uint8_t data[1]; 259 struct { 260 uint8_t code; 261 uint8_t length; 262 } page; 263 }; 264 typedef union SCSI_ModeParamPage SCSI_ModeParamPage; 265 266 /* 267 * LogSense parameter header 268 */ 269 struct SCSI_LogSenseParamHeader { 270 uint8_t pageCode; 271 uint8_t reserved; 272 uint8_t pageLength[2]; 273 }; 274 typedef struct SCSI_LogSenseParamHeader SCSI_LogSenseParamHeader; 275 276 /* 277 * Log parameter pages are variable-length with a fixed length header. 278 */ 279 union SCSI_LogSenseParamPage { 280 uint8_t data[1]; 281 struct { 282 uint8_t parameterCode[2]; 283 uint8_t flags; 284 uint8_t parameterLength; 285 } page; 286 }; 287 typedef union SCSI_LogSenseParamPage SCSI_LogSenseParamPage; 288 289 /* 290 * SCSI command status (from status phase) 291 */ 292 #define kScsiStatusGood 0x00 /* Normal completion */ 293 #define kScsiStatusCheckCondition 0x02 /* Need GetExtendedStatus */ 294 #define kScsiStatusConditionMet 0x04 295 #define kScsiStatusBusy 0x08 /* Device busy (self-test?) */ 296 #define kScsiStatusIntermediate 0x10 /* Intermediate status */ 297 #define kScsiStatusResConflict 0x18 /* Reservation conflict */ 298 #define kScsiStatusQueueFull 0x28 /* Target can't do command */ 299 #define kScsiStatusReservedMask 0x3e /* Vendor specific? */ 300 301 /* 302 * SCSI command codes. Commands defined as ...6, ...10, ...12, are 303 * six-byte, ten-byte, and twelve-byte variants of the indicated command. 304 */ 305 /* 306 * These commands are supported for all devices. 307 */ 308 #define kScsiCmdChangeDefinition 0x40 309 #define kScsiCmdCompare 0x39 310 #define kScsiCmdCopy 0x18 311 #define kScsiCmdCopyAndVerify 0x3a 312 #define kScsiCmdInquiry 0x12 313 #define kScsiCmdLogSelect 0x4c 314 #define kScsiCmdLogSense 0x4d 315 #define kScsiCmdModeSelect10 0x55 316 #define kScsiCmdModeSelect6 0x15 317 #define kScsiCmdModeSense10 0x5a 318 #define kScsiCmdModeSense6 0x1a 319 #define kScsiCmdReadBuffer 0x3c 320 #define kScsiCmdRecvDiagResult 0x1c 321 #define kScsiCmdRequestSense 0x03 322 #define kScsiCmdSendDiagnostic 0x1d 323 #define kScsiCmdTestUnitReady 0x00 324 #define kScsiCmdWriteBuffer 0x3b 325 326 /* 327 * These commands are supported by direct-access devices only. 328 */ 329 #define kScsiCmdFormatUnit 0x04 330 #define kSCSICmdCopy 0x18 331 #define kSCSICmdCopyAndVerify 0x3a 332 #define kScsiCmdLockUnlockCache 0x36 333 #define kScsiCmdPrefetch 0x34 334 #define kScsiCmdPreventAllowRemoval 0x1e 335 #define kScsiCmdRead6 0x08 336 #define kScsiCmdRead10 0x28 337 #define kScsiCmdReadCapacity 0x25 338 #define kScsiCmdReadDefectData 0x37 339 #define kScsiCmdReadLong 0x3e 340 #define kScsiCmdReassignBlocks 0x07 341 #define kScsiCmdRelease 0x17 342 #define kScsiCmdReserve 0x16 343 #define kScsiCmdRezeroUnit 0x01 344 #define kScsiCmdSearchDataEql 0x31 345 #define kScsiCmdSearchDataHigh 0x30 346 #define kScsiCmdSearchDataLow 0x32 347 #define kScsiCmdSeek6 0x0b 348 #define kScsiCmdSeek10 0x2b 349 #define kScsiCmdSetLimits 0x33 350 #define kScsiCmdStartStopUnit 0x1b 351 #define kScsiCmdSynchronizeCache 0x35 352 #define kScsiCmdVerify 0x2f 353 #define kScsiCmdWrite6 0x0a 354 #define kScsiCmdWrite10 0x2a 355 #define kScsiCmdWriteAndVerify 0x2e 356 #define kScsiCmdWriteLong 0x3f 357 #define kScsiCmdWriteSame 0x41 358 359 /* 360 * These commands are supported by sequential devices. 361 */ 362 #define kScsiCmdRewind 0x01 363 #define kScsiCmdWriteFilemarks 0x10 364 #define kScsiCmdSpace 0x11 365 #define kScsiCmdLoadUnload 0x1B 366 /* 367 * ANSI SCSI-II for CD-ROM devices. 368 */ 369 #define kScsiCmdReadCDTableOfContents 0x43 370 371 /* 372 * Message codes (for Msg In and Msg Out phases). 373 */ 374 #define kScsiMsgAbort 0x06 375 #define kScsiMsgAbortTag 0x0d 376 #define kScsiMsgBusDeviceReset 0x0c 377 #define kScsiMsgClearQueue 0x0e 378 #define kScsiMsgCmdComplete 0x00 379 #define kScsiMsgDisconnect 0x04 380 #define kScsiMsgIdentify 0x80 381 #define kScsiMsgIgnoreWideResdue 0x23 382 #define kScsiMsgInitiateRecovery 0x0f 383 #define kScsiMsgInitiatorDetectedErr 0x05 384 #define kScsiMsgLinkedCmdComplete 0x0a 385 #define kScsiMsgLinkedCmdCompleteFlag 0x0b 386 #define kScsiMsgParityErr 0x09 387 #define kScsiMsgRejectMsg 0x07 388 #define kScsiMsgModifyDataPtr 0x00 /* Extended msg */ 389 #define kScsiMsgNop 0x08 390 #define kScsiMsgHeadOfQueueTag 0x21 /* Two byte msg */ 391 #define kScsiMsgOrderedQueueTag 0x22 /* Two byte msg */ 392 #define kScsiMsgSimpleQueueTag 0x20 /* Two byte msg */ 393 #define kScsiMsgReleaseRecovery 0x10 394 #define kScsiMsgRestorePointers 0x03 395 #define kScsiMsgSaveDataPointers 0x02 396 #define kScsiMsgSyncXferReq 0x01 /* Extended msg */ 397 #define kScsiMsgWideDataXferReq 0x03 /* Extended msg */ 398 #define kScsiMsgTerminateIOP 0x11 399 #define kScsiMsgExtended 0x01 400 #define kScsiMsgEnableDisconnectMask 0x40 401 402 #define kScsiMsgTwoByte 0x20 403 #define kScsiMsgTwoByteMin 0x20 404 #define kScsiMsgTwoByteMax 0x2f 405 406 /* 407 * Default timeout times for SCSI commands (times are in Msec). 408 */ 409 #define kScsiNormalCompletionTime (500L) /* 1/2 second */ 410 /* 411 * Dratted DAT tape. 412 */ 413 #define kScsiDATCompletionTime (60L * 1000L); /* One minute */ 414 /* 415 * Yes, we do allow 90 seconds for spin-up of those dratted tape drives. 416 */ 417 #define kScsiSpinUpCompletionTime (90L * 1000L) 418 419 420 #endif /* __MacSCSICommand__ */ 421