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 */
41struct SCSI_6_Byte_Command {                /* Six-byte command         */
42    unsigned char       opcode;             /*  0                       */
43    unsigned char       lbn3;               /*  1 lbn in low 5          */
44    unsigned char       lbn2;               /*  2                       */
45    unsigned char       lbn1;               /*  3                       */
46    unsigned char       len;                /*  4                       */
47    unsigned char       ctrl;               /*  5                       */
48};
49typedef struct SCSI_6_Byte_Command SCSI_6_Byte_Command;
50
51struct SCSI_10_Byte_Command {               /* Ten-byte command         */
52    unsigned char       opcode;             /*  0                       */
53    unsigned char       lun;                /*  1                       */
54    unsigned char       lbn4;               /*  2                       */
55    unsigned char       lbn3;               /*  3                       */
56    unsigned char       lbn2;               /*  4                       */
57    unsigned char       lbn1;               /*  5                       */
58    unsigned char       pad;                /*  6                       */
59    unsigned char       len2;               /*  7                       */
60    unsigned char       len1;               /*  8                       */
61    unsigned char       ctrl;               /*  9                       */
62};
63typedef struct SCSI_10_Byte_Command SCSI_10_Byte_Command;
64
65struct SCSI_12_Byte_Command {               /* Twelve-byte command      */
66    unsigned char       opcode;             /*  0                       */
67    unsigned char       lun;                /*  1                       */
68    unsigned char       lbn4;               /*  2                       */
69    unsigned char       lbn3;               /*  3                       */
70    unsigned char       lbn2;               /*  4                       */
71    unsigned char       lbn1;               /*  5                       */
72    unsigned char       len4;               /*  6                       */
73    unsigned char       len3;               /*  7                       */
74    unsigned char       len2;               /*  8                       */
75    unsigned char       len1;               /*  9                       */
76    unsigned char       pad;                /* 10                       */
77    unsigned char       ctrl;               /* 11                       */
78};
79typedef struct SCSI_12_Byte_Command SCSI_12_Byte_Command;
80
81/*
82 * This union defines all scsi commands.
83 */
84union SCSI_Command {
85    SCSI_6_Byte_Command     scsi6;
86    SCSI_10_Byte_Command    scsi10;
87    SCSI_12_Byte_Command    scsi12;
88    unsigned char           scsi[12];
89};
90typedef union SCSI_Command SCSI_Command, *SCSI_CommandPtr;
91
92/*
93 * Returned by a read-capacity command.
94 */
95struct SCSI_Capacity_Data {
96    unsigned char       lbn4;               /* Number                   */
97    unsigned char       lbn3;               /*  of                      */
98    unsigned char       lbn2;               /*   logical                */
99    unsigned char       lbn1;               /*    blocks                */
100    unsigned char       len4;               /* Length                   */
101    unsigned char       len3;               /*  of each                 */
102    unsigned char       len2;               /*   logical block          */
103    unsigned char       len1;               /*    in bytes              */
104};
105typedef struct SCSI_Capacity_Data SCSI_Capacity_Data;
106
107struct SCSI_Inquiry_Data {                  /* Inquiry returns this     */
108    unsigned char       devType;            /*  0 Device type,          */
109    unsigned char       devTypeMod;         /*  1 Device type modifier  */
110    unsigned char       version;            /*  2 ISO/ECMA/ANSI version */
111    unsigned char       format;             /*  3 Response data format  */
112    unsigned char       length;             /*  4 Additional Length     */
113    unsigned char       reserved5;          /*  5 Reserved              */
114    unsigned char       reserved6;          /*  6 Reserved              */
115    unsigned char       flags;              /*  7 Capability flags      */
116    unsigned char       vendor[8];          /*  8-15 Vendor-specific    */
117    unsigned char       product[16];        /* 16-31 Product id         */
118    unsigned char       revision[4];        /* 32-35 Product revision   */
119    unsigned char       vendorSpecific[20]; /* 36-55 Vendor stuff       */
120    unsigned char       moreReserved[40];   /* 56-95 Reserved           */
121};
122typedef struct SCSI_Inquiry_Data SCSI_Inquiry_Data;
123
124/*
125 * This bit may be set in SCSI_Inquiry_Data.devTypeMod
126 */
127enum {
128    kScsiInquiryRMB = 0x80                  /* Removable medium if set  */
129};
130/*
131 * These bits may be set in SCSI_Inquiry_Data.flags
132 */
133enum {
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 */
147enum {
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 */
168enum {
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 */
188struct SCSI_Sense_Data {                /* Request Sense result         */
189    unsigned char       errorCode;      /*  0   Class code, valid lbn   */
190    unsigned char       segmentNumber;  /*  1   Segment number          */
191    unsigned char       senseKey;       /*  2   Sense key and flags     */
192    unsigned char       info[4];
193    unsigned char       additionalSenseLength;
194    unsigned char       reservedForCopy[4];
195    unsigned char       additionalSenseCode;
196    unsigned char       additionalSenseQualifier;
197    unsigned char       fruCode;        /* Field replacable unit code   */
198    unsigned char       senseKeySpecific[2];
199    unsigned char       additional[101];
200};
201typedef 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 */
241struct SCSI_ModeParamHeader {
242    unsigned char       modeDataLength;
243    unsigned char       mediumType;
244    unsigned char       deviceSpecific;
245    unsigned char       blockDescriptorLength;
246};
247typedef struct SCSI_ModeParamHeader SCSI_ModeParamHeader;
248
249struct SCSI_ModeParamBlockDescriptor {
250    unsigned char       densityCode;
251    unsigned char       numberOfBlocks[3];
252    unsigned char       reserved;
253    unsigned char       blockLength[3];
254};
255typedef struct SCSI_ModeParamBlockDescriptor SCSI_ModeParamBlockDescriptor;
256
257union SCSI_ModeParamPage {
258    unsigned char       data[1];
259    struct {
260	unsigned char   code;
261	unsigned char   length;
262    } page;
263};
264typedef union SCSI_ModeParamPage SCSI_ModeParamPage;
265
266/*
267 * LogSense parameter header
268 */
269struct SCSI_LogSenseParamHeader {
270    unsigned char       pageCode;
271    unsigned char       reserved;
272    unsigned char       pageLength[2];
273};
274typedef struct SCSI_LogSenseParamHeader SCSI_LogSenseParamHeader;
275
276/*
277 * Log parameter pages are variable-length with a fixed length header.
278 */
279union SCSI_LogSenseParamPage {
280    unsigned char       data[1];
281    struct {
282	unsigned char   parameterCode[2];
283	unsigned char   flags;
284	unsigned char   parameterLength;
285    } page;
286};
287typedef 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