aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/HAL/DUE/usb/spc_protocol.h
blob: d67cc5c78803e6f1d01092961265a4c9506295ed (plain) (blame)
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
/**
 * \file
 *
 * \brief SCSI Primary Commands
 *
 * This file contains definitions of some of the commands found in the
 * SPC-2 standard.
 *
 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
 *
 * \asf_license_start
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel microcontroller product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \asf_license_stop
 *
 */

/*
 * Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
 */
#ifndef _SPC_PROTOCOL_H_
#define _SPC_PROTOCOL_H_

/**
 * \ingroup usb_msc_protocol
 * \defgroup usb_spc_protocol SCSI Primary Commands protocol definitions
 *
 * @{
 */

//! \name SCSI commands defined by SPC-2
//@{
#define  SPC_TEST_UNIT_READY              0x00
#define  SPC_REQUEST_SENSE                0x03
#define  SPC_INQUIRY                      0x12
#define  SPC_MODE_SELECT6                 0x15
#define  SPC_MODE_SENSE6                  0x1A
#define  SPC_SEND_DIAGNOSTIC              0x1D
#define  SPC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define  SPC_MODE_SENSE10                 0x5A
#define  SPC_REPORT_LUNS                  0xA0
//@}

//! \brief May be set in byte 0 of the INQUIRY CDB
//@{
//! Enable Vital Product Data
#define  SCSI_INQ_REQ_EVPD    0x01
//! Command Support Data specified by the PAGE OR OPERATION CODE field
#define  SCSI_INQ_REQ_CMDT    0x02
//@}

COMPILER_PACK_SET(1)

/**
 * \brief SCSI Standard Inquiry data structure
 */
struct scsi_inquiry_data {
	uint8_t pq_pdt; //!< Peripheral Qual / Peripheral Dev Type
#define  SCSI_INQ_PQ_CONNECTED   0x00   //!< Peripheral connected
#define  SCSI_INQ_PQ_NOT_CONN    0x20   //!< Peripheral not connected
#define  SCSI_INQ_PQ_NOT_SUPP    0x60   //!< Peripheral not supported
#define  SCSI_INQ_DT_DIR_ACCESS  0x00   //!< Direct Access (SBC)
#define  SCSI_INQ_DT_SEQ_ACCESS  0x01   //!< Sequential Access
#define  SCSI_INQ_DT_PRINTER     0x02   //!< Printer
#define  SCSI_INQ_DT_PROCESSOR   0x03   //!< Processor device
#define  SCSI_INQ_DT_WRITE_ONCE  0x04   //!< Write-once device
#define  SCSI_INQ_DT_CD_DVD      0x05   //!< CD/DVD device
#define  SCSI_INQ_DT_OPTICAL     0x07   //!< Optical Memory
#define  SCSI_INQ_DT_MC          0x08   //!< Medium Changer
#define  SCSI_INQ_DT_ARRAY       0x0C   //!< Storage Array Controller
#define  SCSI_INQ_DT_ENCLOSURE   0x0D   //!< Enclosure Services
#define  SCSI_INQ_DT_RBC         0x0E   //!< Simplified Direct Access
#define  SCSI_INQ_DT_OCRW        0x0F   //!< Optical card reader/writer
#define  SCSI_INQ_DT_BCC         0x10   //!< Bridge Controller Commands
#define  SCSI_INQ_DT_OSD         0x11   //!< Object-based Storage
#define  SCSI_INQ_DT_NONE        0x1F   //!< No Peripheral
	uint8_t flags1; //!< Flags (byte 1)
#define  SCSI_INQ_RMB            0x80   //!< Removable Medium
	uint8_t version; //!< Version
#define  SCSI_INQ_VER_NONE       0x00   //!< No standards conformance
#define  SCSI_INQ_VER_SPC        0x03   //!< SCSI Primary Commands     (link to SBC)
#define  SCSI_INQ_VER_SPC2       0x04   //!< SCSI Primary Commands - 2 (link to SBC-2)
#define  SCSI_INQ_VER_SPC3       0x05   //!< SCSI Primary Commands - 3 (link to SBC-2)
#define  SCSI_INQ_VER_SPC4       0x06   //!< SCSI Primary Commands - 4 (link to SBC-3)
	uint8_t flags3; //!< Flags (byte 3)
#define  SCSI_INQ_NORMACA        0x20   //!< Normal ACA Supported
#define  SCSI_INQ_HISUP          0x10   //!< Hierarchal LUN addressing
#define  SCSI_INQ_RSP_SPC2       0x02   //!< SPC-2 / SPC-3 response format
	uint8_t addl_len; //!< Additional Length (n-4)
#define  SCSI_INQ_ADDL_LEN(tot)  ((tot)-5) //!< Total length is \a tot
	uint8_t flags5; //!< Flags (byte 5)
#define  SCSI_INQ_SCCS           0x80
	uint8_t flags6; //!< Flags (byte 6)
#define  SCSI_INQ_BQUE           0x80
#define  SCSI_INQ_ENCSERV        0x40
#define  SCSI_INQ_MULTIP         0x10
#define  SCSI_INQ_MCHGR          0x08
#define  SCSI_INQ_ADDR16         0x01
	uint8_t flags7; //!< Flags (byte 7)
#define  SCSI_INQ_WBUS16         0x20
#define  SCSI_INQ_SYNC           0x10
#define  SCSI_INQ_LINKED         0x08
#define  SCSI_INQ_CMDQUE         0x02
	uint8_t vendor_id[8];   //!< T10 Vendor Identification
	uint8_t product_id[16]; //!< Product Identification
	uint8_t product_rev[4]; //!< Product Revision Level
};

/**
 * \brief SCSI Standard Request sense data structure
 */
struct scsi_request_sense_data {
	/* 1st byte: REQUEST SENSE response flags*/
	uint8_t valid_reponse_code;
#define  SCSI_SENSE_VALID              0x80 //!< Indicates the INFORMATION field contains valid information
#define  SCSI_SENSE_RESPONSE_CODE_MASK 0x7F
#define  SCSI_SENSE_CURRENT            0x70 //!< Response code 70h (current errors)
#define  SCSI_SENSE_DEFERRED           0x71

	/* 2nd byte */
	uint8_t obsolete;

	/* 3rd byte */
	uint8_t sense_flag_key;
#define  SCSI_SENSE_FILEMARK        0x80 //!< Indicates that the current command has read a filemark or setmark.
#define  SCSI_SENSE_EOM             0x40 //!< Indicates that an end-of-medium condition exists.
#define  SCSI_SENSE_ILI             0x20 //!< Indicates that the requested logical block length did not match the logical block length of the data on the medium.
#define  SCSI_SENSE_RESERVED        0x10 //!< Reserved
#define  SCSI_SENSE_KEY(x)          (x&0x0F) //!< Sense Key

	/* 4th to 7th bytes - INFORMATION field */
	uint8_t information[4];

	/* 8th byte  - ADDITIONAL SENSE LENGTH field */
	uint8_t AddSenseLen;
#define  SCSI_SENSE_ADDL_LEN(total_len)   ((total_len) - 8)

	/* 9th to 12th byte  - COMMAND-SPECIFIC INFORMATION field */
	uint8_t CmdSpecINFO[4];

	/* 13th byte  - ADDITIONAL SENSE CODE field */
	uint8_t AddSenseCode;

	/* 14th byte  - ADDITIONAL SENSE CODE QUALIFIER field */
	uint8_t AddSnsCodeQlfr;

	/* 15th byte  - FIELD REPLACEABLE UNIT CODE field */
	uint8_t FldReplUnitCode;

	/* 16th byte */
	uint8_t SenseKeySpec[3];
#define  SCSI_SENSE_SKSV            0x80 //!< Indicates the SENSE-KEY SPECIFIC field contains valid information
};

COMPILER_PACK_RESET()

/* Vital Product Data page codes */
enum scsi_vpd_page_code {
	SCSI_VPD_SUPPORTED_PAGES = 0x00,
	SCSI_VPD_UNIT_SERIAL_NUMBER = 0x80,
	SCSI_VPD_DEVICE_IDENTIFICATION = 0x83,
};
#define  SCSI_VPD_HEADER_SIZE       4

/* Constants associated with the Device Identification VPD page */
#define  SCSI_VPD_ID_HEADER_SIZE    4

#define  SCSI_VPD_CODE_SET_BINARY   1
#define  SCSI_VPD_CODE_SET_ASCII    2
#define  SCSI_VPD_CODE_SET_UTF8     3

#define  SCSI_VPD_ID_TYPE_T10       1


/* Sense keys */
enum scsi_sense_key {
	SCSI_SK_NO_SENSE = 0x0,
	SCSI_SK_RECOVERED_ERROR = 0x1,
	SCSI_SK_NOT_READY = 0x2,
	SCSI_SK_MEDIUM_ERROR = 0x3,
	SCSI_SK_HARDWARE_ERROR = 0x4,
	SCSI_SK_ILLEGAL_REQUEST = 0x5,
	SCSI_SK_UNIT_ATTENTION = 0x6,
	SCSI_SK_DATA_PROTECT = 0x7,
	SCSI_SK_BLANK_CHECK = 0x8,
	SCSI_SK_VENDOR_SPECIFIC = 0x9,
	SCSI_SK_COPY_ABORTED = 0xA,
	SCSI_SK_ABORTED_COMMAND = 0xB,
	SCSI_SK_VOLUME_OVERFLOW = 0xD,
	SCSI_SK_MISCOMPARE = 0xE,
};

/* Additional Sense Code / Additional Sense Code Qualifier pairs */
enum scsi_asc_ascq {
	SCSI_ASC_NO_ADDITIONAL_SENSE_INFO = 0x0000,
	SCSI_ASC_LU_NOT_READY_REBUILD_IN_PROGRESS = 0x0405,
	SCSI_ASC_WRITE_ERROR = 0x0C00,
	SCSI_ASC_UNRECOVERED_READ_ERROR = 0x1100,
	SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x2000,
	SCSI_ASC_INVALID_FIELD_IN_CDB = 0x2400,
	SCSI_ASC_WRITE_PROTECTED = 0x2700,
	SCSI_ASC_NOT_READY_TO_READY_CHANGE = 0x2800,
	SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A00,
	SCSI_ASC_INTERNAL_TARGET_FAILURE = 0x4400,
};

/**
 * \brief SPC-2 Mode parameter
 * This subclause describes the block descriptors and the pages
 * used with MODE SELECT and MODE SENSE commands
 * that are applicable to all SCSI devices.
 */
enum scsi_spc_mode {
	SCSI_MS_MODE_VENDOR_SPEC = 0x00,
	SCSI_MS_MODE_INFEXP = 0x1C,    // Informational exceptions control page
	SCSI_MS_MODE_ALL = 0x3F,
};

/**
 * \brief SPC-2 Informational exceptions control page
 * See chapter 8.3.8
 */
struct spc_control_page_info_execpt {
	uint8_t page_code;
	uint8_t page_length;
#define  SPC_MP_INFEXP_PAGE_LENGTH     0x0A
	uint8_t flags1;
#define  SPC_MP_INFEXP_PERF            (1<<7)   //!< Initiator Control
#define  SPC_MP_INFEXP_EBF             (1<<5)   //!< Caching Analysis Permitted
#define  SPC_MP_INFEXP_EWASC           (1<<4)   //!< Discontinuity
#define  SPC_MP_INFEXP_DEXCPT          (1<<3)   //!< Size enable
#define  SPC_MP_INFEXP_TEST            (1<<2)   //!< Writeback Cache Enable
#define  SPC_MP_INFEXP_LOGERR          (1<<0)   //!< Log errors bit
	uint8_t mrie;
#define  SPC_MP_INFEXP_MRIE_NO_REPORT           0x00
#define  SPC_MP_INFEXP_MRIE_ASYNC_EVENT         0x01
#define  SPC_MP_INFEXP_MRIE_GEN_UNIT            0x02
#define  SPC_MP_INFEXP_MRIE_COND_RECOV_ERROR    0x03
#define  SPC_MP_INFEXP_MRIE_UNCOND_RECOV_ERROR  0x04
#define  SPC_MP_INFEXP_MRIE_NO_SENSE            0x05
#define  SPC_MP_INFEXP_MRIE_ONLY_REPORT         0x06
	be32_t interval_timer;
	be32_t report_count;
};


enum scsi_spc_mode_sense_pc {
	SCSI_MS_SENSE_PC_CURRENT = 0,
	SCSI_MS_SENSE_PC_CHANGEABLE = 1,
	SCSI_MS_SENSE_PC_DEFAULT = 2,
	SCSI_MS_SENSE_PC_SAVED = 3,
};



static inline bool scsi_mode_sense_dbd_is_set(const uint8_t * cdb)
{
	return (cdb[1] >> 3) & 1;
}

static inline uint8_t scsi_mode_sense_get_page_code(const uint8_t * cdb)
{
	return cdb[2] & 0x3F;
}

static inline uint8_t scsi_mode_sense_get_pc(const uint8_t * cdb)
{
	return cdb[2] >> 6;
}

/**
 * \brief SCSI Mode Parameter Header used by MODE SELECT(6) and MODE
 * SENSE(6)
 */
struct scsi_mode_param_header6 {
	uint8_t mode_data_length;	//!< Number of bytes after this
	uint8_t medium_type;	//!< Medium Type
	uint8_t device_specific_parameter;	//!< Defined by command set
	uint8_t block_descriptor_length;	//!< Length of block descriptors
};

/**
 * \brief SCSI Mode Parameter Header used by MODE SELECT(10) and MODE
 * SENSE(10)
 */
struct scsi_mode_param_header10 {
	be16_t mode_data_length;	//!< Number of bytes after this
	uint8_t medium_type;	//!< Medium Type
	uint8_t device_specific_parameter;	//!< Defined by command set
	uint8_t flags4;	//!< LONGLBA in bit 0
	uint8_t reserved;
	be16_t block_descriptor_length;	//!< Length of block descriptors
};

/**
 * \brief SCSI Page_0 Mode Page header (SPF not set)
 */
struct scsi_mode_page_0_header {
	uint8_t page_code;
#define  SCSI_PAGE_CODE_PS          (1 << 7)	//!< Parameters Saveable
#define  SCSI_PAGE_CODE_SPF         (1 << 6)	//!< SubPage Format
	uint8_t page_length;	//!< Number of bytes after this
#define  SCSI_MS_PAGE_LEN(total)   ((total) - 2)
};

//@}

#endif // SPC_PROTOCOL_H_