summaryrefslogtreecommitdiffstats
path: root/include/VBox/scsi.h
blob: 1acf1f3cc82e96f2fe47fe36927fcb7afdf21ae0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/** @file
 * VirtualBox - SCSI declarations. (DEV,+)
 */

/*
 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef VBOX_INCLUDED_scsi_h
#define VBOX_INCLUDED_scsi_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <iprt/assert.h>

/**
 * @todo: Remove when the splitting code was removed from DevATA.
 *        The limit doesn't belong here but is specific for each host platform.
 */
#ifdef RT_OS_FREEBSD
/* The cam subsystem doesn't allow more */
# define SCSI_MAX_BUFFER_SIZE (64  * _1K)
#else
# define SCSI_MAX_BUFFER_SIZE (100 * _1K)
#endif

/**
 * SCSI command opcode identifiers.
 *
 * SCSI-3, so far for CD/DVD Logical Units, from Table 49 of the MMC-3 draft standard.
 */
typedef enum SCSICMD
{
    SCSI_BLANK                          = 0xa1,
    SCSI_CLOSE_TRACK_SESSION            = 0x5b,
    SCSI_ERASE_10                       = 0x2c,
    SCSI_FORMAT_UNIT                    = 0x04,
    SCSI_GET_CONFIGURATION              = 0x46,
    SCSI_GET_EVENT_STATUS_NOTIFICATION  = 0x4a,
    SCSI_GET_PERFORMANCE                = 0xac,
    /** Inquiry command. */
    SCSI_INQUIRY                        = 0x12,
    SCSI_LOAD_UNLOAD_MEDIUM             = 0xa6,
    SCSI_MECHANISM_STATUS               = 0xbd,
    SCSI_MODE_SELECT_10                 = 0x55,
    SCSI_MODE_SENSE_10                  = 0x5a,
    SCSI_PAUSE_RESUME                   = 0x4b,
    SCSI_PLAY_AUDIO_10                  = 0x45,
    SCSI_PLAY_AUDIO_12                  = 0xa5,
    SCSI_PLAY_AUDIO_MSF                 = 0x47,
    SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL   = 0x1e,
    /** Read(10) command. */
    SCSI_READ_10                        = 0x28,
    SCSI_READ_12                        = 0xa8,
    SCSI_READ_BUFFER                    = 0x3c,
    SCSI_READ_BUFFER_CAPACITY           = 0x5c,
    /** Read Capacity(6) command. */
    SCSI_READ_CAPACITY                  = 0x25,
    SCSI_READ_CD                        = 0xbe,
    SCSI_READ_CD_MSF                    = 0xb9,
    SCSI_READ_DISC_INFORMATION          = 0x51,
    SCSI_READ_DVD_STRUCTURE             = 0xad,
    SCSI_READ_FORMAT_CAPACITIES         = 0x23,
    SCSI_READ_SUBCHANNEL                = 0x42,
    SCSI_READ_TOC_PMA_ATIP              = 0x43,
    SCSI_READ_TRACK_INFORMATION         = 0x52,
    SCSI_REPAIR_TRACK                   = 0x58,
    SCSI_REPORT_KEY                     = 0xa4,
    SCSI_REQUEST_SENSE                  = 0x03,
    SCSI_RESERVE_TRACK                  = 0x53,
    SCSI_SCAN                           = 0xba,
    SCSI_SEEK_10                        = 0x2b,
    SCSI_SEND_CUE_SHEET                 = 0x5d,
    SCSI_SEND_DVD_STRUCTURE             = 0xbf,
    SCSI_SEND_EVENT                     = 0xa2,
    SCSI_SEND_KEY                       = 0xa3,
    SCSI_SEND_OPC_INFORMATION           = 0x54,
    SCSI_SET_CD_SPEED                   = 0xbb,
    SCSI_SET_READ_AHEAD                 = 0xa7,
    SCSI_SET_STREAMING                  = 0xb6,
    SCSI_START_STOP_UNIT                = 0x1b,
    SCSI_LOAD_UNLOAD                    = 0x1b,
    SCSI_STOP_PLAY_SCAN                 = 0x4e,
    /** Synchronize Cache command. */
    SCSI_SYNCHRONIZE_CACHE              = 0x35,
    SCSI_TEST_UNIT_READY                = 0x00,
    SCSI_VERIFY_10                      = 0x2f,
    /** Write(10) command. */
    SCSI_WRITE_10                       = 0x2a,
    SCSI_WRITE_12                       = 0xaa,
    SCSI_WRITE_AND_VERIFY_10            = 0x2e,
    SCSI_WRITE_BUFFER                   = 0x3b,

    /** Mode Select(6) command */
    SCSI_MODE_SELECT_6                  = 0x15,
    /** Mode Sense(6) command */
    SCSI_MODE_SENSE_6                   = 0x1a,
    /** Report LUNs command. */
    SCSI_REPORT_LUNS                    = 0xa0,
    SCSI_REPORT_DENSITY                 = 0x44,
    /** Rezero Unit command. Obsolete for ages now, but used by cdrecord. */
    SCSI_REZERO_UNIT                    = 0x01,
    SCSI_REWIND                         = 0x01,
    SCSI_SERVICE_ACTION_IN_16           = 0x9e,
    SCSI_READ_16                        = 0x88,
    SCSI_WRITE_16                       = 0x8a,
    SCSI_READ_6                         = 0x08,
    SCSI_WRITE_6                        = 0x0a,
    SCSI_LOG_SENSE                      = 0x4d,
    SCSI_UNMAP                          = 0x42,
    SCSI_RESERVE_6                      = 0x16,
    SCSI_RELEASE_6                      = 0x17,
    SCSI_RESERVE_10                     = 0x56,
    SCSI_RELEASE_10                     = 0x57,
    SCSI_READ_BLOCK_LIMITS              = 0x05,
    SCSI_MAINTENANCE_IN                 = 0xa3
} SCSICMD;

/**
 * Service action in opcode identifiers
 */
typedef enum SCSISVCACTIONIN
{
    SCSI_SVC_ACTION_IN_READ_CAPACITY_16 = 0x10
} SCSISVCACTIONIN;

/**
 * Maintenance in opcode identifiers
 */
typedef enum SCSIMAINTENANCEIN
{
    SCSI_MAINTENANCE_IN_REPORT_SUPP_OPC = 0x0c
} SCSIMAINTENANCEIN;

/* Mode page codes for mode sense/select commands. */
#define SCSI_MODEPAGE_ERROR_RECOVERY   0x01
#define SCSI_MODEPAGE_WRITE_PARAMETER  0x05
#define SCSI_MODEPAGE_CD_STATUS        0x2a


/* Page control codes. */
#define SCSI_PAGECONTROL_CURRENT        0x00
#define SCSI_PAGECONTROL_CHANGEABLE     0x01
#define SCSI_PAGECONTROL_DEFAULT        0x02
#define SCSI_PAGECONTROL_SAVED          0x03


/* Status codes */
#define SCSI_STATUS_OK                          0x00
#define SCSI_STATUS_CHECK_CONDITION             0x02
#define SCSI_STATUS_CONDITION_MET               0x04
#define SCSI_STATUS_BUSY                        0x08
#define SCSI_STATUS_INTERMEDIATE                0x10
#define SCSI_STATUS_DATA_UNDEROVER_RUN          0x12
#define SCSI_STATUS_INTERMEDIATE_CONDITION_MET  0x14
#define SCSI_STATUS_RESERVATION_CONFLICT        0x18
#define SCSI_STATUS_COMMAND_TERMINATED          0x22
#define SCSI_STATUS_QUEUE_FULL                  0x28
#define SCSI_STATUS_ACA_ACTIVE                  0x30
#define SCSI_STATUS_TASK_ABORTED                0x40

/* Sense data response codes - This is the first byte in the sense data */
#define SCSI_SENSE_RESPONSE_CODE_CURR_FIXED     0x70
#define SCSI_SENSE_RESPONSE_CODE_DEFERRED_FIXED 0x71
#define SCSI_SENSE_RESPONSE_CODE_CURR_DESC      0x72
#define SCSI_SENSE_RESPONSE_CODE_DEFERRED_DESC  0x73

/* Sense keys */
#define SCSI_SENSE_NONE             0
#define SCSI_SENSE_RECOVERED_ERROR  1
#define SCSI_SENSE_NOT_READY        2
#define SCSI_SENSE_MEDIUM_ERROR     3
#define SCSI_SENSE_HARDWARE_ERROR   4
#define SCSI_SENSE_ILLEGAL_REQUEST  5
#define SCSI_SENSE_UNIT_ATTENTION   6
#define SCSI_SENSE_DATA_PROTECT     7
#define SCSI_SENSE_BLANK_CHECK      8
#define SCSI_SENSE_VENDOR_SPECIFIC  9
#define SCSI_SENSE_COPY_ABORTED     10
#define SCSI_SENSE_ABORTED_COMMAND  11
#define SCSI_SENSE_VOLUME_OVERFLOW  13
#define SCSI_SENSE_MISCOMPARE       14

/* Additional sense bit flags (to be ORed with sense key). */
#define SCSI_SENSE_FLAG_FILEMARK    0x80
#define SCSI_SENSE_FLAG_EOM         0x40
#define SCSI_SENSE_FLAG_ILI         0x20

/* Additional sense keys */
#define SCSI_ASC_NONE                                       0x00
#define SCSI_ASC_WRITE_ERROR                                0x0c
#define SCSI_ASC_READ_ERROR                                 0x11
#define SCSI_ASC_ILLEGAL_OPCODE                             0x20
#define SCSI_ASC_LOGICAL_BLOCK_OOR                          0x21
#define SCSI_ASC_INV_FIELD_IN_CMD_PACKET                    0x24
#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED                 0x25
#define SCSI_ASC_WRITE_PROTECTED                            0x27
#define SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED                    0x28
#define SCSI_ASC_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED   0x29
#define SCSI_ASC_CANNOT_READ_MEDIUM                         0x30
#define SCSI_ASC_MEDIUM_NOT_PRESENT                         0x3a
#define SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED            0x39
#define SCSI_ASC_INTERNAL_TARGET_FAILURE                    0x44
#define SCSI_ASC_INVALID_MESSAGE                            0x49
#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED                 0x53
#define SCSI_ASC_LOGICAL_UNIT_DOES_NOT_RESPOND_TO_SELECTION 0x00
#define SCSI_ASC_SYSTEM_RESOURCE_FAILURE                    0x55
#define SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK                0x64
#define SCSI_ASC_COMMAND_TO_LOGICAL_UNIT_FAILED             0x6E

/** Additional sense code qualifiers (ASCQ). */
/* NB: The ASC/ASCQ combination determines the full meaning. */
#define SCSI_ASCQ_SYSTEM_BUFFER_FULL                        0x01
#define SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED  0x00
#define SCSI_ASCQ_END_OF_DATA_DETECTED                      0x05
#define SCSI_ASCQ_FILEMARK_DETECTED                         0x01
#define SCSI_ASCQ_EOP_EOM_DETECTED                          0x02
#define SCSI_ASCQ_SETMARK_DETECTED                          0x03
#define SCSI_ASCQ_BOP_BOM_DETECTED                          0x04
#define SCSI_ASCQ_UNKNOWN_FORMAT                            0x01
#define SCSI_ASCQ_INCOMPATIBLE_FORMAT                       0x02
#define SCSI_ASCQ_COPY_TARGET_DEVICE_DATA_OVERRUN           0x0d

/** @name SCSI_INQUIRY
 * @{
 */

/** Length of the SCSI INQUIRY vendor identifier (without termination). */
#define SCSI_INQUIRY_VENDOR_ID_LENGTH   8
/** Length of the SCSI INQUIRY product identifier (without termination). */
#define SCSI_INQUIRY_PRODUCT_ID_LENGTH 16
/** Length of the SCSI INQUIRY revision identifier (without termination). */
#define SCSI_INQUIRY_REVISION_LENGTH    4

#pragma pack(1)
typedef struct SCSIINQUIRYCDB
{
    unsigned u8Cmd : 8;
    unsigned fEVPD : 1;
    unsigned u4Reserved : 4;
    unsigned u3LUN : 3;
    unsigned u8PageCode : 8;
    unsigned u8Reserved : 8;
    uint8_t cbAlloc;
    uint8_t u8Control;
} SCSIINQUIRYCDB;
#pragma pack()
AssertCompileSize(SCSIINQUIRYCDB, 6);
typedef SCSIINQUIRYCDB *PSCSIINQUIRYCDB;
typedef const SCSIINQUIRYCDB *PCSCSIINQUIRYCDB;

#pragma pack(1)
typedef struct SCSIINQUIRYDATA
{
    unsigned u5PeripheralDeviceType : 5;                    /**< 0x00 / 00 */
    unsigned u3PeripheralQualifier : 3;
    unsigned u6DeviceTypeModifier : 7;                      /**< 0x01 */
    unsigned fRMB : 1;
    unsigned u3AnsiVersion : 3;                             /**< 0x02 */
    unsigned u3EcmaVersion : 3;
    unsigned u2IsoVersion : 2;
    unsigned u4ResponseDataFormat : 4;                      /**< 0x03 */
    unsigned u2Reserved0 : 2;
    unsigned fTrmlOP : 1;
    unsigned fAEC : 1;
    unsigned cbAdditional : 8;                              /**< 0x04 */
    unsigned u8Reserved1 : 8;                               /**< 0x05 */
    unsigned u8Reserved2 : 8;                               /**< 0x06 */
    unsigned fSftRe : 1;                                    /**< 0x07 */
    unsigned fCmdQue : 1;
    unsigned fReserved3 : 1;
    unsigned fLinked : 1;
    unsigned fSync : 1;
    unsigned fWBus16 : 1;
    unsigned fWBus32 : 1;
    unsigned fRelAdr : 1;
    int8_t   achVendorId[SCSI_INQUIRY_VENDOR_ID_LENGTH];    /**< 0x08 */
    int8_t   achProductId[SCSI_INQUIRY_PRODUCT_ID_LENGTH];  /**< 0x10 */
    int8_t   achProductLevel[SCSI_INQUIRY_REVISION_LENGTH]; /**< 0x20 */
    uint8_t  abVendorSpecific[20];                          /**< 0x24/36 - Optional it seems. */
    uint8_t  abReserved4[40];
    uint8_t  abVendorSpecificParameters[1];                 /**< 0x60/96 - Variable size. */
} SCSIINQUIRYDATA;
#pragma pack()
AssertCompileSize(SCSIINQUIRYDATA, 97);
typedef SCSIINQUIRYDATA *PSCSIINQUIRYDATA;
typedef const SCSIINQUIRYDATA *PCSCSIINQUIRYDATA;

#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED                   0x00
#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_BUT_SUPPORTED 0x01
#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED 0x03

#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS     0x00
#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_SEQUENTIAL_ACCESS 0x01
#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD            0x05
#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN           0x1f

/** @} */

#if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(RT_STRICT))
const char * SCSICmdText(uint8_t uCmd);
const char * SCSIStatusText(uint8_t uStatus);
const char * SCSISenseText(uint8_t uSense);
const char * SCSISenseExtText(uint8_t uASC, uint8_t uASCQ);
int SCSILogModePage(char *pszBuf, size_t cchBuffer, uint8_t *pbModePage,
                    size_t cbModePage);
int SCSILogCueSheet(char *pszBuf, size_t cchBuffer, uint8_t *pbCueSheet,
                    size_t cbCueSheet);
#endif

#endif /* !VBOX_INCLUDED_scsi_h */