1 /*
2    Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU Lesser General Public License as published by
6    the Free Software Foundation; either version 2.1 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public License
15    along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17 #ifndef __scsi_lowlevel_h__
18 #define __scsi_lowlevel_h__
19 
20 #if defined(_WIN32)
21 #define EXTERN __declspec( dllexport )
22 #else
23 #define EXTERN
24 #endif
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 #define SCSI_CDB_MAX_SIZE			16
31 
32 enum scsi_opcode {
33 	SCSI_OPCODE_TESTUNITREADY      = 0x00,
34 	SCSI_OPCODE_READ6              = 0x08,
35 	SCSI_OPCODE_INQUIRY            = 0x12,
36 	SCSI_OPCODE_MODESELECT6        = 0x15,
37 	SCSI_OPCODE_RESERVE6           = 0x16,
38 	SCSI_OPCODE_RELEASE6           = 0x17,
39 	SCSI_OPCODE_MODESENSE6         = 0x1a,
40 	SCSI_OPCODE_STARTSTOPUNIT      = 0x1b,
41 	SCSI_OPCODE_PREVENTALLOW       = 0x1e,
42 	SCSI_OPCODE_READCAPACITY10     = 0x25,
43 	SCSI_OPCODE_READ10             = 0x28,
44 	SCSI_OPCODE_WRITE10            = 0x2A,
45 	SCSI_OPCODE_WRITE_VERIFY10     = 0x2E,
46 	SCSI_OPCODE_VERIFY10           = 0x2F,
47 	SCSI_OPCODE_PREFETCH10         = 0x34,
48 	SCSI_OPCODE_SYNCHRONIZECACHE10 = 0x35,
49 	SCSI_OPCODE_READ_DEFECT_DATA10 = 0x37,
50 	SCSI_OPCODE_WRITE_SAME10       = 0x41,
51 	SCSI_OPCODE_UNMAP              = 0x42,
52 	SCSI_OPCODE_READTOC            = 0x43,
53 	SCSI_OPCODE_SANITIZE           = 0x48,
54 	SCSI_OPCODE_MODESELECT10       = 0x55,
55 	SCSI_OPCODE_MODESENSE10        = 0x5A,
56 	SCSI_OPCODE_PERSISTENT_RESERVE_IN  = 0x5E,
57 	SCSI_OPCODE_PERSISTENT_RESERVE_OUT = 0x5F,
58 	SCSI_OPCODE_EXTENDED_COPY      = 0x83,
59 	SCSI_OPCODE_RECEIVE_COPY_RESULTS = 0x84,
60 	SCSI_OPCODE_READ16             = 0x88,
61 	SCSI_OPCODE_COMPARE_AND_WRITE  = 0x89,
62 	SCSI_OPCODE_WRITE16            = 0x8A,
63 	SCSI_OPCODE_ORWRITE            = 0x8B,
64 	SCSI_OPCODE_WRITE_VERIFY16     = 0x8E,
65 	SCSI_OPCODE_VERIFY16           = 0x8F,
66 	SCSI_OPCODE_PREFETCH16         = 0x90,
67 	SCSI_OPCODE_SYNCHRONIZECACHE16 = 0x91,
68 	SCSI_OPCODE_WRITE_SAME16       = 0x93,
69 	SCSI_OPCODE_WRITE_ATOMIC16     = 0x9C,
70 	SCSI_OPCODE_SERVICE_ACTION_IN  = 0x9E,
71 	SCSI_OPCODE_REPORTLUNS         = 0xA0,
72 	SCSI_OPCODE_MAINTENANCE_IN     = 0xA3,
73 	SCSI_OPCODE_READ12             = 0xA8,
74 	SCSI_OPCODE_WRITE12            = 0xAA,
75 	SCSI_OPCODE_WRITE_VERIFY12     = 0xAE,
76 	SCSI_OPCODE_VERIFY12           = 0xAF,
77 	SCSI_OPCODE_READ_DEFECT_DATA12 = 0xB7
78 };
79 
80 enum scsi_persistent_in_sa {
81 	SCSI_PERSISTENT_RESERVE_READ_KEYS		= 0,
82 	SCSI_PERSISTENT_RESERVE_READ_RESERVATION	= 1,
83 	SCSI_PERSISTENT_RESERVE_REPORT_CAPABILITIES	= 2,
84 	SCSI_PERSISTENT_RESERVE_READ_FULL_STATUS	= 3
85 };
86 
87 enum scsi_service_action_in {
88 	SCSI_READCAPACITY16            = 0x10,
89 	SCSI_GET_LBA_STATUS            = 0x12
90 };
91 
92 enum scsi_persistent_out_sa {
93 	SCSI_PERSISTENT_RESERVE_REGISTER		= 0,
94 	SCSI_PERSISTENT_RESERVE_RESERVE			= 1,
95 	SCSI_PERSISTENT_RESERVE_RELEASE			= 2,
96 	SCSI_PERSISTENT_RESERVE_CLEAR			= 3,
97 	SCSI_PERSISTENT_RESERVE_PREEMPT			= 4,
98 	SCSI_PERSISTENT_RESERVE_PREEMPT_AND_ABORT	= 5,
99 	SCSI_PERSISTENT_RESERVE_REGISTER_AND_IGNORE_EXISTING_KEY = 6,
100 	SCSI_PERSISTENT_RESERVE_REGISTER_AND_MOVE	= 7
101 };
102 
103 enum scsi_persistent_out_scope {
104 	SCSI_PERSISTENT_RESERVE_SCOPE_LU		= 0
105 };
106 
107 enum scsi_persistent_out_type {
108 	SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE			= 1,
109 	SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS			= 3,
110 	SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY	= 5,
111 	SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY	= 6,
112 	SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS	= 7,
113 	SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS	= 8
114 };
115 
116 struct scsi_persistent_reserve_out_basic {
117        uint64_t	reservation_key;
118        uint64_t	service_action_reservation_key;
119        uint8_t  spec_i_pt;
120        uint8_t  all_tg_pt;
121        uint8_t  aptpl;
122 };
123 
124 enum scsi_maintenance_in {
125 	SCSI_REPORT_SUPPORTED_OP_CODES = 0x0c
126 };
127 
128 enum scsi_op_code_reporting_options {
129 	SCSI_REPORT_SUPPORTING_OPS_ALL       = 0x00,
130 	SCSI_REPORT_SUPPORTING_OPCODE        = 0x01,
131 	SCSI_REPORT_SUPPORTING_SERVICEACTION = 0x02
132 };
133 
134 /* sense keys */
135 enum scsi_sense_key {
136 	SCSI_SENSE_NO_SENSE            = 0x00,
137 	SCSI_SENSE_RECOVERED_ERROR     = 0x01,
138 	SCSI_SENSE_NOT_READY           = 0x02,
139 	SCSI_SENSE_MEDIUM_ERROR        = 0x03,
140 	SCSI_SENSE_HARDWARE_ERROR      = 0x04,
141 	SCSI_SENSE_ILLEGAL_REQUEST     = 0x05,
142 	SCSI_SENSE_UNIT_ATTENTION      = 0x06,
143 	SCSI_SENSE_DATA_PROTECTION     = 0x07,
144 	SCSI_SENSE_BLANK_CHECK         = 0x08,
145 	SCSI_SENSE_VENDOR_SPECIFIC     = 0x09,
146 	SCSI_SENSE_COPY_ABORTED        = 0x0a,
147 	SCSI_SENSE_COMMAND_ABORTED     = 0x0b,
148 	SCSI_SENSE_OBSOLETE_ERROR_CODE = 0x0c,
149 	SCSI_SENSE_OVERFLOW_COMMAND    = 0x0d,
150 	SCSI_SENSE_MISCOMPARE          = 0x0e
151 };
152 
153 EXTERN const char *scsi_sense_key_str(int key);
154 
155 /* ascq */
156 #define SCSI_SENSE_ASCQ_NO_ADDL_SENSE			   0x0000
157 #define SCSI_SENSE_ASCQ_SANITIZE_IN_PROGRESS               0x041b
158 #define SCSI_SENSE_ASCQ_UNREACHABLE_COPY_TARGET		   0x0804
159 #define SCSI_SENSE_ASCQ_COPY_TARGET_DEVICE_NOT_REACHABLE   0x0d02
160 #define SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED      0x1115
161 #define SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR        0x1a00
162 #define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY           0x1d00
163 #define SCSI_SENSE_ASCQ_MISCOMPARE_VERIFY_OF_UNMAPPED_LBA  0x1d01
164 #define SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE             0x2000
165 #define SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE                   0x2100
166 #define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB               0x2400
167 #define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED         0x2500
168 #define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST    0x2600
169 #define SCSI_SENSE_ASCQ_TOO_MANY_TARGET_DESCRIPTORS	   0x2606
170 #define SCSI_SENSE_ASCQ_UNSUPPORTED_TARGET_DESCRIPTOR_TYPE_CODE 0x2607
171 #define SCSI_SENSE_ASCQ_TOO_MANY_SEGMENT_DESCRIPTORS	   0x2608
172 #define SCSI_SENSE_ASCQ_UNSUPPORTED_SEGMENT_DESCRIPTOR_TYPE_CODE 0x2609
173 #define SCSI_SENSE_ASCQ_WRITE_PROTECTED                    0x2700
174 #define SCSI_SENSE_ASCQ_HARDWARE_WRITE_PROTECTED           0x2701
175 #define SCSI_SENSE_ASCQ_SOFTWARE_WRITE_PROTECTED           0x2702
176 #define SCSI_SENSE_ASCQ_BUS_RESET                          0x2900
177 #define SCSI_SENSE_ASCQ_POWER_ON_OCCURED                   0x2901
178 #define SCSI_SENSE_ASCQ_SCSI_BUS_RESET_OCCURED             0x2902
179 #define SCSI_SENSE_ASCQ_BUS_DEVICE_RESET_FUNCTION_OCCURED  0x2903
180 #define SCSI_SENSE_ASCQ_DEVICE_INTERNAL_RESET              0x2904
181 #define SCSI_SENSE_ASCQ_TRANSCEIVER_MODE_CHANGED_TO_SINGLE_ENDED 0x2905
182 #define SCSI_SENSE_ASCQ_TRANSCEIVER_MODE_CHANGED_TO_LVD    0x2906
183 #define SCSI_SENSE_ASCQ_NEXUS_LOSS                         0x2907
184 #define SCSI_SENSE_ASCQ_MODE_PARAMETERS_CHANGED            0x2a01
185 #define SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED          0x2a09
186 #define SCSI_SENSE_ASCQ_THIN_PROVISION_SOFT_THRES_REACHED  0x3807
187 #define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT                 0x3a00
188 #define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED     0x3a01
189 #define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN       0x3a02
190 #define SCSI_SENSE_ASCQ_INQUIRY_DATA_HAS_CHANGED           0x3f03
191 #define SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE            0x4400
192 #define SCSI_SENSE_ASCQ_MEDIUM_LOAD_OR_EJECT_FAILED        0x5300
193 #define SCSI_SENSE_ASCQ_MEDIUM_REMOVAL_PREVENTED           0x5302
194 #define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT  0x0e03
195 
196 EXTERN const char *scsi_sense_ascq_str(int ascq);
197 
198 EXTERN const char *scsi_pr_type_str(enum scsi_persistent_out_type pr_type);
199 
200 enum scsi_xfer_dir {
201 	SCSI_XFER_NONE  = 0,
202 	SCSI_XFER_READ  = 1,
203 	SCSI_XFER_WRITE = 2
204 };
205 
206 /*
207  * READTOC
208  */
209 EXTERN struct scsi_task *scsi_cdb_readtoc(int msf, int format, int track_session, uint16_t alloc_len);
210 
211 enum scsi_readtoc_fmt {
212 	SCSI_READ_TOC          = 0,
213 	SCSI_READ_SESSION_INFO = 1,
214 	SCSI_READ_FULL_TOC     = 2,
215 	SCSI_READ_PMA          = 3,
216 	SCSI_READ_ATIP         = 4
217 };
218 struct scsi_readtoc_desc {
219 	union {
220 		struct scsi_toc_desc {
221 			int adr;
222 			int control;
223 			int track;
224 			uint32_t lba;
225 		} toc;
226 		struct scsi_session_desc {
227 			int adr;
228 			int control;
229 			int first_in_last;
230 			uint32_t lba;
231 		} ses;
232 		struct scsi_fulltoc_desc {
233 			int session;
234 			int adr;
235 			int control;
236 			int tno;
237 			int point;
238 			int min;
239 			int sec;
240 			int frame;
241 			int zero;
242 			int pmin;
243 			int psec;
244 			int pframe;
245 		} full;
246 	} desc;
247 };
248 
249 struct scsi_readtoc_list {
250 	int num;
251 	int first;
252 	int last;
253 	struct scsi_readtoc_desc desc[0];
254 };
255 
256 struct scsi_report_supported_params {
257 	int return_timeouts;
258 };
259 
260 #define SCSI_SENSE_FIXED_CURRENT              0x70
261 #define SCSI_SENSE_FIXED_DEFERRED_ERRORS      0x71
262 #define SCSI_SENSE_DESCRIPTOR_CURRENT         0x72
263 #define SCSI_SENSE_DESCRIPTOR_DEFERRED_ERRORS 0x73
264 
265 struct scsi_sense {
266 	unsigned char       error_type;
267 	enum scsi_sense_key key;
268 	int                 ascq;
269 
270 	/*
271 	 * Sense specific descriptor. See also paragraph "Sense key specific
272 	 * sense data descriptor" in SPC.
273 	 */
274 	unsigned            sense_specific:1;
275 	unsigned            ill_param_in_cdb:1;
276 	unsigned            bit_pointer_valid:1;
277 	unsigned char       bit_pointer;
278 	uint16_t            field_pointer;
279 };
280 
281 struct scsi_data {
282 	int            size;
283 	unsigned char *data;
284 };
285 
286 enum scsi_residual {
287 	SCSI_RESIDUAL_NO_RESIDUAL = 0,
288 	SCSI_RESIDUAL_UNDERFLOW,
289 	SCSI_RESIDUAL_OVERFLOW
290 };
291 
292 /* struct scsi_iovec follows the POSIX struct iovec
293    definition and *MUST* never change. */
294 struct scsi_iovec {
295     void *iov_base;
296     size_t iov_len;
297 };
298 
299 struct scsi_iovector {
300 	struct scsi_iovec *iov;
301 	int niov;
302 	int nalloc;
303 	size_t offset;
304 	int consumed;
305 };
306 
307 struct scsi_task {
308 	int status;
309 
310 	int cdb_size;
311 	int xfer_dir;
312 	int expxferlen;
313 	unsigned char cdb[SCSI_CDB_MAX_SIZE];
314 
315 	enum scsi_residual residual_status;
316 	size_t residual;
317 	struct scsi_sense sense;
318 	struct scsi_data datain;
319 	struct scsi_allocated_memory *mem;
320 
321 	void *ptr;
322 
323 	uint32_t itt;
324 	uint32_t cmdsn;
325 	uint32_t lun;
326 
327 	struct scsi_iovector iovector_in;
328 	struct scsi_iovector iovector_out;
329 };
330 
331 
332 /* Create a task using a pre-built CDB which can later be passed to
333    iscsi_scsi_command_[a]sync()
334  */
335 EXTERN struct scsi_task *scsi_create_task(int cdb_size, unsigned char *cdb,
336        int xfer_dir, int expxferlen);
337 
338 /* This function will free a scsi task structure.
339    You may NOT cancel a task until the callback has been invoked
340    and the command has completed on the transport layer.
341 */
342 EXTERN void scsi_free_scsi_task(struct scsi_task *task);
343 
344 EXTERN void scsi_set_task_private_ptr(struct scsi_task *task, void *ptr);
345 EXTERN void *scsi_get_task_private_ptr(struct scsi_task *task);
346 
347 /*
348  * TESTUNITREADY
349  */
350 EXTERN struct scsi_task *scsi_cdb_testunitready(void);
351 
352 /*
353  * SANITIZE
354  */
355 #define SCSI_SANITIZE_OVERWRITE		0x01
356 #define SCSI_SANITIZE_BLOCK_ERASE	0x02
357 #define SCSI_SANITIZE_CRYPTO_ERASE	0x03
358 #define SCSI_SANITIZE_EXIT_FAILURE_MODE	0x1f
359 
360 EXTERN struct scsi_task *scsi_cdb_sanitize(int immed, int ause, int sa,
361        int param_len);
362 
363 /*
364  * REPORTLUNS
365  */
366 #define SCSI_REPORTLUNS_REPORT_ALL_LUNS				0x00
367 #define SCSI_REPORTLUNS_REPORT_WELL_KNOWN_ONLY			0x01
368 #define SCSI_REPORTLUNS_REPORT_AVAILABLE_LUNS_ONLY		0x02
369 
370 struct scsi_reportluns_list {
371 	uint32_t num;
372 	uint16_t luns[0];
373 };
374 
375 EXTERN struct scsi_task *scsi_reportluns_cdb(int report_type, int alloc_len);
376 
377 /*
378  * RESERVE6
379  */
380 EXTERN struct scsi_task *scsi_cdb_reserve6(void);
381 /*
382  * RELEASE6
383  */
384 EXTERN struct scsi_task *scsi_cdb_release6(void);
385 
386 /*
387  * READCAPACITY10
388  */
389 struct scsi_readcapacity10 {
390 	uint32_t lba;
391 	uint32_t block_size;
392 };
393 EXTERN struct scsi_task *scsi_cdb_readcapacity10(int lba, int pmi);
394 
395 
396 /*
397  * INQUIRY
398  */
399 enum scsi_inquiry_peripheral_qualifier {
400 	SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED     = 0x00,
401 	SCSI_INQUIRY_PERIPHERAL_QUALIFIER_DISCONNECTED  = 0x01,
402 	SCSI_INQUIRY_PERIPHERAL_QUALIFIER_NOT_SUPPORTED = 0x03
403 };
404 
405 const char *scsi_devqualifier_to_str(
406 			enum scsi_inquiry_peripheral_qualifier qualifier);
407 
408 enum scsi_inquiry_peripheral_device_type {
409 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS            = 0x00,
410 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SEQUENTIAL_ACCESS        = 0x01,
411 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_PRINTER                  = 0x02,
412 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_PROCESSOR                = 0x03,
413 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_WRITE_ONCE               = 0x04,
414 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_MMC                      = 0x05,
415 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SCANNER                  = 0x06,
416 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_OPTICAL_MEMORY           = 0x07,
417 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_MEDIA_CHANGER            = 0x08,
418 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_COMMUNICATIONS           = 0x09,
419 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_STORAGE_ARRAY_CONTROLLER = 0x0c,
420 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_ENCLOSURE_SERVICES       = 0x0d,
421 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SIMPLIFIED_DIRECT_ACCESS = 0x0e,
422 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_OPTICAL_CARD_READER      = 0x0f,
423 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_BRIDGE_CONTROLLER        = 0x10,
424 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_OSD                      = 0x11,
425 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_AUTOMATION               = 0x12,
426 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SEQURITY_MANAGER         = 0x13,
427 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_WELL_KNOWN_LUN           = 0x1e,
428 	SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_UNKNOWN                  = 0x1f
429 };
430 
431 EXTERN const char *scsi_devtype_to_str(enum scsi_inquiry_peripheral_device_type type);
432 
433 enum scsi_version {
434 	SCSI_VERSION_SPC  = 0x03,
435 	SCSI_VERSION_SPC2 = 0x04,
436 	SCSI_VERSION_SPC3 = 0x05
437 };
438 
439 EXTERN const char *scsi_version_to_str(enum scsi_version version);
440 
441 enum scsi_version_descriptor {
442 	SCSI_VERSION_DESCRIPTOR_ISCSI				= 0x0960,
443 	SCSI_VERSION_DESCRIPTOR_SBC				= 0x0180,
444 	SCSI_VERSION_DESCRIPTOR_SBC_ANSI_INCITS_306_1998	= 0x019C,
445 	SCSI_VERSION_DESCRIPTOR_SBC_T10_0996_D_R08C		= 0x019B,
446 	SCSI_VERSION_DESCRIPTOR_SBC_2				= 0x0320,
447 	SCSI_VERSION_DESCRIPTOR_SBC_2_ISO_IEC_14776_322		= 0x033E,
448 	SCSI_VERSION_DESCRIPTOR_SBC_2_ANSI_INCITS_405_2005	= 0x033D,
449 	SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R16		= 0x033B,
450 	SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R5A		= 0x0322,
451 	SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R15		= 0x0324,
452 	SCSI_VERSION_DESCRIPTOR_SBC_3				= 0x04C0,
453 	SCSI_VERSION_DESCRIPTOR_SPC				= 0x0120,
454 	SCSI_VERSION_DESCRIPTOR_SPC_ANSI_INCITS_301_1997	= 0x013C,
455 	SCSI_VERSION_DESCRIPTOR_SPC_T10_0995_D_R11A		= 0x013B,
456 	SCSI_VERSION_DESCRIPTOR_SPC_2				= 0x0260,
457 	SCSI_VERSION_DESCRIPTOR_SPC_2_ISO_IEC_14776_452		= 0x0278,
458 	SCSI_VERSION_DESCRIPTOR_SPC_2_ANSI_INCITS_351_2001	= 0x0277,
459 	SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R20		= 0x0276,
460 	SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R12		= 0x0267,
461 	SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R18		= 0x0269,
462 	SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R19		= 0x0275,
463 	SCSI_VERSION_DESCRIPTOR_SPC_3				= 0x0300,
464 	SCSI_VERSION_DESCRIPTOR_SPC_3_ISO_IEC_14776_453		= 0x0316,
465 	SCSI_VERSION_DESCRIPTOR_SPC_3_ANSI_INCITS_408_2005	= 0x0314,
466 	SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R7		= 0x0301,
467 	SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R21		= 0x0307,
468 	SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R22		= 0x030F,
469 	SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R23		= 0x0312,
470 	SCSI_VERSION_DESCRIPTOR_SPC_4				= 0x0460,
471 	SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R16		= 0x0461,
472 	SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R18		= 0x0462,
473 	SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R23		= 0x0463,
474 	SCSI_VERSION_DESCRIPTOR_SSC				= 0x0200,
475 	SCSI_VERSION_DESCRIPTOR_UAS_T10_2095D_R04		= 0x1747
476 };
477 
478 EXTERN const char *scsi_version_descriptor_to_str(enum scsi_version_descriptor version_descriptor);
479 
480 enum scsi_inquiry_tpgs {
481 	SCSI_INQUIRY_TPGS_NO_SUPPORT            = 0x00,
482 	SCSI_INQUIRY_TPGS_IMPLICIT              = 0x01,
483 	SCSI_INQUIRY_TPGS_EXPLICIT              = 0x02,
484 	SCSI_INQUIRY_TPGS_IMPLICIT_AND_EXPLICIT = 0x03
485 };
486 
487 /* fix typos, leave old names for backward compatibility */
488 #define periperal_qualifier qualifier
489 #define periperal_device_type device_type
490 
491 struct scsi_inquiry_standard {
492 	enum scsi_inquiry_peripheral_qualifier qualifier;
493 	enum scsi_inquiry_peripheral_device_type device_type;
494 	int rmb;
495 	int version;
496 	int normaca;
497 	int hisup;
498 	int response_data_format;
499 
500 	int additional_length;
501 
502 	int sccs;
503 	int acc;
504 	int tpgs;
505 	int threepc;
506 	int protect;
507 
508 	int encserv;
509 	int multip;
510 	int addr16;
511 	int wbus16;
512 	int sync;
513 	int cmdque;
514 
515 	int clocking;
516 	int qas;
517 	int ius;
518 
519 	char vendor_identification[8+1];
520 	char product_identification[16+1];
521 	char product_revision_level[4+1];
522 
523 	uint16_t version_descriptor[8];
524 };
525 
526 enum scsi_inquiry_pagecode {
527 	SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES          = 0x00,
528 	SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER           = 0x80,
529 	SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION        = 0x83,
530 	SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS                 = 0xB0,
531 	SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS = 0xB1,
532 	SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING   = 0xB2
533 };
534 
535 EXTERN const char *scsi_inquiry_pagecode_to_str(int pagecode);
536 
537 struct scsi_inquiry_supported_pages {
538 	enum scsi_inquiry_peripheral_qualifier qualifier;
539 	enum scsi_inquiry_peripheral_device_type device_type;
540 	enum scsi_inquiry_pagecode pagecode;
541 
542 	int num_pages;
543 	unsigned char *pages;
544 };
545 
546 struct scsi_inquiry_block_limits {
547 	enum scsi_inquiry_peripheral_qualifier qualifier;
548 	enum scsi_inquiry_peripheral_device_type device_type;
549 	enum scsi_inquiry_pagecode pagecode;
550 
551 	int wsnz;		   		/* write same no zero */
552 	uint8_t max_cmp;			/* maximum_compare_and_write_length */
553 	uint16_t opt_gran;			/* optimal_transfer_length_granularity */
554 	uint32_t max_xfer_len;			/* maximum_transfer_length */
555 	uint32_t opt_xfer_len;			/* optimal_transfer_length */
556 	uint32_t max_prefetch;			/* maximum_prefetched_xdread_xdwrite_transfer_length */
557 	uint32_t max_unmap;			/* maximum_unmap_lba_count */
558 	uint32_t max_unmap_bdc;			/* maximum_unmap_block_descriptor_count */
559 	uint32_t opt_unmap_gran;		/* optimal_unmap_granularity */
560 	int ugavalid;
561 	uint32_t unmap_gran_align;		/* unmap_granularity_alignment */
562 	uint64_t max_ws_len;			/* maximum_write_same_length */
563 
564 	/* SBC-4 */
565 	uint32_t max_atomic_xfer_len;
566 	uint32_t atomic_align;
567 	uint32_t atomic_gran;
568 	uint32_t max_atomic_tl_with_atomic_boundary;
569 	uint32_t max_atomic_boundary_size;
570 };
571 
572 struct scsi_inquiry_block_device_characteristics {
573 	enum scsi_inquiry_peripheral_qualifier qualifier;
574 	enum scsi_inquiry_peripheral_device_type device_type;
575 	enum scsi_inquiry_pagecode pagecode;
576 
577 	int medium_rotation_rate;
578 	int product_type;
579 	int wabereq;
580 	int wacereq;
581 	int nominal_form_factor;
582 	int fuab;
583 	int vbuls;
584 };
585 
586 enum scsi_inquiry_provisioning_type {
587 	PROVISIONING_TYPE_NONE     = 0,
588 	PROVISIONING_TYPE_RESOURCE = 1,
589 	PROVISIONING_TYPE_THIN     = 2
590 };
591 
592 struct scsi_inquiry_logical_block_provisioning {
593 	enum scsi_inquiry_peripheral_qualifier qualifier;
594 	enum scsi_inquiry_peripheral_device_type device_type;
595 	enum scsi_inquiry_pagecode pagecode;
596 
597        int threshold_exponent;
598        int lbpu;
599        int lbpws;
600        int lbpws10;
601        int lbprz;
602        int anc_sup;
603        int dp;
604        enum scsi_inquiry_provisioning_type provisioning_type;
605 };
606 
607 EXTERN struct scsi_task *scsi_cdb_inquiry(int evpd, int page_code, int alloc_len);
608 
609 struct scsi_inquiry_unit_serial_number {
610 	enum scsi_inquiry_peripheral_qualifier qualifier;
611 	enum scsi_inquiry_peripheral_device_type device_type;
612 	enum scsi_inquiry_pagecode pagecode;
613 
614 	char *usn;
615 };
616 
617 enum scsi_protocol_identifier {
618 	SCSI_PROTOCOL_IDENTIFIER_FIBRE_CHANNEL = 0x00,
619 	SCSI_PROTOCOL_IDENTIFIER_PARALLEL_SCSI = 0x01,
620 	SCSI_PROTOCOL_IDENTIFIER_SSA           = 0x02,
621 	SCSI_PROTOCOL_IDENTIFIER_IEEE_1394     = 0x03,
622 	SCSI_PROTOCOL_IDENTIFIER_RDMA          = 0x04,
623 	SCSI_PROTOCOL_IDENTIFIER_ISCSI         = 0x05,
624 	SCSI_PROTOCOL_IDENTIFIER_SAS           = 0x06,
625 	SCSI_PROTOCOL_IDENTIFIER_ADT           = 0x07,
626 	SCSI_PROTOCOL_IDENTIFIER_ATA           = 0x08
627 };
628 
629 EXTERN const char *scsi_protocol_identifier_to_str(int identifier);
630 
631 enum scsi_codeset {
632 	SCSI_CODESET_BINARY = 0x01,
633 	SCSI_CODESET_ASCII  = 0x02,
634 	SCSI_CODESET_UTF8   = 0x03
635 };
636 
637 EXTERN const char *scsi_codeset_to_str(int codeset);
638 
639 enum scsi_association {
640 	SCSI_ASSOCIATION_LOGICAL_UNIT  = 0x00,
641 	SCSI_ASSOCIATION_TARGET_PORT   = 0x01,
642 	SCSI_ASSOCIATION_TARGET_DEVICE = 0x02
643 };
644 
645 EXTERN const char *scsi_association_to_str(int association);
646 
647 enum scsi_designator_type {
648 	SCSI_DESIGNATOR_TYPE_VENDOR_SPECIFIC             = 0x00,
649 	SCSI_DESIGNATOR_TYPE_T10_VENDORT_ID              = 0x01,
650 	SCSI_DESIGNATOR_TYPE_EUI_64                      = 0x02,
651 	SCSI_DESIGNATOR_TYPE_NAA                         = 0x03,
652 	SCSI_DESIGNATOR_TYPE_RELATIVE_TARGET_PORT        = 0x04,
653 	SCSI_DESIGNATOR_TYPE_TARGET_PORT_GROUP           = 0x05,
654 	SCSI_DESIGNATOR_TYPE_LOGICAL_UNIT_GROUP          = 0x06,
655 	SCSI_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_IDENTIFIER = 0x07,
656 	SCSI_DESIGNATOR_TYPE_SCSI_NAME_STRING            = 0x08
657 };
658 
659 EXTERN const char *scsi_designator_type_to_str(int association);
660 
661 struct scsi_inquiry_device_designator {
662 	struct scsi_inquiry_device_designator *next;
663 
664 	enum scsi_protocol_identifier protocol_identifier;
665 	enum scsi_codeset code_set;
666 	int piv;
667 	enum scsi_association association;
668 	enum scsi_designator_type designator_type;
669 	int designator_length;
670 	char *designator;
671 };
672 
673 struct scsi_inquiry_device_identification {
674 	enum scsi_inquiry_peripheral_qualifier qualifier;
675 	enum scsi_inquiry_peripheral_device_type device_type;
676 	enum scsi_inquiry_pagecode pagecode;
677 
678 	struct scsi_inquiry_device_designator *designators;
679 };
680 
681 /*
682  * MODESENSE
683  */
684 enum scsi_modesense_page_control {
685 	SCSI_MODESENSE_PC_CURRENT    = 0x00,
686 	SCSI_MODESENSE_PC_CHANGEABLE = 0x01,
687 	SCSI_MODESENSE_PC_DEFAULT    = 0x02,
688 	SCSI_MODESENSE_PC_SAVED      = 0x03
689 };
690 
691 struct scsi_mode_page_caching {
692 	int ic;
693 	int abpf;
694 	int cap;
695 	int disc;
696 	int size;
697 	int wce;
698 	int mf;
699 	int rcd;
700 
701 	int demand_read_retention_priority;
702 	int write_retention_priority;
703 
704 	int disable_prefetch_transfer_length;
705 	int minimum_prefetch;
706 	int maximum_prefetch;
707 	int maximum_prefetch_ceiling;
708 
709 	int fsw;
710 	int lbcss;
711 	int dra;
712 	int nv_dis;
713 
714 	int number_of_cache_segments;
715 	int cache_segment_size;
716 };
717 
718 struct scsi_mode_page_power_condition {
719        int pm_bg_precedence;
720        int standby_y;
721 
722        int idle_c;
723        int idle_b;
724        int idle_a;
725        int standby_z;
726 
727        uint32_t idle_a_condition_timer;
728        uint32_t standby_z_condition_timer;
729        uint32_t idle_b_condition_timer;
730        uint32_t idle_c_condition_timer;
731        uint32_t standby_y_condition_timer;
732 
733        int ccf_idle;
734        int ccf_standby;
735        int ccf_stopped;
736 };
737 
738 struct scsi_mode_page_control {
739 	int tst;
740 	int tmf_only;
741 	int dpicz;
742 	int d_sense;
743 	int gltsd;
744 	int rlec;
745 
746 	int queue_algorithm_modifier;
747 	int nuar;
748 	int qerr;
749 
750 	int vs;
751 	int rac;
752 	int ua_intlck_ctrl;
753 	int swp;
754 
755 	int ato;
756 	int tas;
757 	int atmpe;
758 	int rwwp;
759 	int autoload_mode;
760 
761 	int busy_timeout_period;
762 	int extended_selftest_completion_time;
763 };
764 
765 struct scsi_mode_page_disconnect_reconnect {
766 	int buffer_full_ratio;
767 	int buffer_empty_ratio;
768 	int bus_inactivity_limit;
769 	int disconnect_time_limit;
770 	int connect_time_limit;
771 	int maximum_burst_size;
772 	int emdp;
773 	int fair_arbitration;
774 	int dimm;
775 	int dtdc;
776 	int first_burst_size;
777 };
778 
779 struct scsi_mode_page_informational_exceptions_control {
780 	int perf;
781 	int ebf;
782 	int ewasc;
783 	int dexcpt;
784 	int test;
785 	int ebackerr;
786 	int logerr;
787 	int mrie;
788 	int interval_timer;
789 	int report_count;
790 };
791 
792 enum scsi_modesense_page_code {
793 	SCSI_MODEPAGE_READ_WRITE_ERROR_RECOVERY = 0x01,
794 	SCSI_MODEPAGE_DISCONNECT_RECONNECT      = 0x02,
795 	SCSI_MODEPAGE_VERIFY_ERROR_RECOVERY     = 0x07,
796 	SCSI_MODEPAGE_CACHING                   = 0x08,
797 	SCSI_MODEPAGE_XOR_CONTROL               = 0x10,
798 	SCSI_MODEPAGE_CONTROL                   = 0x0a,
799 	SCSI_MODEPAGE_POWER_CONDITION           = 0x1a,
800 	SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL        = 0x1c,
801 	SCSI_MODEPAGE_RETURN_ALL_PAGES          = 0x3f
802 };
803 
804 
805 /* Do not use in new code.
806  * Backward compatibility macros
807  */
808 #define SCSI_MODESENSE_PAGECODE_READ_WRITE_ERROR_RECOVERY SCSI_MODEPAGE_READ_WRITE_ERROR_RECOVERY
809 #define SCSI_MODESENSE_PAGECODE_DISCONNECT_RECONNECT SCSI_MODEPAGE_DISCONNECT_RECONNECT
810 #define SCSI_MODESENSE_PAGECODE_VERIFY_ERROR_RECOVERY SCSI_MODEPAGE_VERIFY_ERROR_RECOVERY
811 #define SCSI_MODESENSE_PAGECODE_CACHING SCSI_MODEPAGE_CACHING
812 #define SCSI_MODESENSE_PAGECODE_XOR_CONTROL SCSI_MODEPAGE_XOR_CONTROL
813 #define SCSI_MODESENSE_PAGECODE_CONTROL SCSI_MODEPAGE_CONTROL
814 #define SCSI_MODESENSE_PAGECODE_INFORMATIONAL_EXCEPTIONS_CONTROL SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL
815 #define SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES SCSI_MODEPAGE_RETURN_ALL_PAGES
816 
817 struct scsi_mode_page {
818        struct scsi_mode_page *next;
819        int ps;
820        int spf;
821        enum scsi_modesense_page_code page_code;
822        int subpage_code;
823        int len;
824        union {
825               struct scsi_mode_page_caching caching;
826               struct scsi_mode_page_control control;
827               struct scsi_mode_page_disconnect_reconnect disconnect_reconnect;
828 	      struct scsi_mode_page_informational_exceptions_control iec;
829               struct scsi_mode_page_power_condition power_condition;
830        };
831 };
832 
833 struct scsi_mode_sense {
834        uint16_t mode_data_length;
835        uint8_t medium_type;
836        uint8_t device_specific_parameter;
837        uint8_t longlba;
838        uint8_t block_descriptor_length;
839        struct scsi_mode_page *pages;
840 };
841 
842 EXTERN struct scsi_mode_page *
843 scsi_modesense_get_page(struct scsi_mode_sense *ms,
844 			enum scsi_modesense_page_code page_code,
845 			int subpage_code);
846 
847 EXTERN struct scsi_task *scsi_cdb_modesense6(int dbd,
848 			enum scsi_modesense_page_control pc,
849 			enum scsi_modesense_page_code page_code,
850 			int sub_page_code,
851 			unsigned char alloc_len);
852 
853 EXTERN struct scsi_task *scsi_cdb_modesense10(int llbaa, int dbd,
854 			enum scsi_modesense_page_control pc,
855 			enum scsi_modesense_page_code page_code,
856 			int sub_page_code,
857 			unsigned char alloc_len);
858 
859 
860 EXTERN struct scsi_task *scsi_cdb_modeselect6(int pf, int sp, int param_len);
861 
862 EXTERN struct scsi_task *scsi_cdb_modeselect10(int pf, int sp, int param_len);
863 
864 EXTERN struct scsi_data *
865 scsi_modesense_dataout_marshall(struct scsi_task *task,
866 				struct scsi_mode_page *mp,
867 				int is_modeselect6);
868 
869 
870 struct scsi_readcapacity16 {
871        uint64_t returned_lba;
872        uint32_t block_length;
873        uint8_t  p_type;
874        uint8_t  prot_en;
875        uint8_t  p_i_exp;
876        uint8_t  lbppbe;
877        uint8_t  lbpme;
878        uint8_t  lbprz;
879        uint16_t lalba;
880 };
881 
882 enum scsi_provisioning_type {
883      SCSI_PROVISIONING_TYPE_MAPPED	= 0x00,
884      SCSI_PROVISIONING_TYPE_DEALLOCATED	= 0x01,
885      SCSI_PROVISIONING_TYPE_ANCHORED	= 0x02
886 };
887 
888 struct scsi_lba_status_descriptor {
889        uint64_t	lba;
890        uint32_t num_blocks;
891        enum scsi_provisioning_type provisioning;
892 };
893 
894 struct scsi_get_lba_status {
895        uint32_t num_descriptors;
896        struct scsi_lba_status_descriptor *descriptors;
897 };
898 
899 
900 struct scsi_op_timeout_descriptor {
901 	uint16_t descriptor_length;
902 	uint8_t command_specific;
903 	uint32_t nominal_processing_timeout;
904 	uint32_t recommended_timeout;
905 
906 };
907 struct scsi_command_descriptor {
908 	uint8_t opcode;
909 	uint16_t sa;
910 	uint8_t ctdp;
911 	uint8_t servactv;
912 	uint16_t cdb_len;
913 
914 	/* only present if CTDP==1 */
915 	struct scsi_op_timeout_descriptor to;
916 };
917 
918 struct scsi_report_supported_op_codes {
919 	int num_descriptors;
920 	struct scsi_command_descriptor descriptors[0];
921 };
922 
923 struct scsi_report_supported_op_codes_one_command {
924 	uint8_t ctdp;
925 	uint8_t support;
926 	uint8_t cdb_length;
927 	uint8_t cdb_usage_data[16];
928 
929 	/* only present if CTDP==1 */
930 	struct scsi_op_timeout_descriptor to;
931 };
932 
933 struct scsi_persistent_reserve_in_read_keys {
934        uint32_t prgeneration;
935        uint32_t additional_length;
936 
937        int      num_keys;
938        uint64_t keys[0];
939 };
940 
941 struct scsi_persistent_reserve_in_read_reservation {
942        uint32_t prgeneration;
943        uint32_t additional_length;
944 
945        int reserved;
946 
947        uint64_t reservation_key;
948        unsigned char pr_scope;
949        unsigned char pr_type;
950 };
951 
952 enum scsi_persistent_reservation_type_mask {
953      SCSI_PR_TYPE_MASK_EX_AC_AR	= (1 << 0),
954      SCSI_PR_TYPE_MASK_WR_EX   	= (1 << 9),
955      SCSI_PR_TYPE_MASK_EX_AC   	= (1 << 11),
956      SCSI_PR_TYPE_MASK_WR_EX_RO	= (1 << 13),
957      SCSI_PR_TYPE_MASK_EX_AC_RO	= (1 << 14),
958      SCSI_PR_TYPE_MASK_WR_EX_AR	= (1 << 15),
959 
960      SCSI_PR_TYPE_MASK_ALL	= (SCSI_PR_TYPE_MASK_EX_AC_AR
961 				 | SCSI_PR_TYPE_MASK_WR_EX
962 				 | SCSI_PR_TYPE_MASK_EX_AC
963 				 | SCSI_PR_TYPE_MASK_WR_EX_RO
964 				 | SCSI_PR_TYPE_MASK_EX_AC_RO
965 				 | SCSI_PR_TYPE_MASK_WR_EX_AR)
966 };
967 
968 struct scsi_persistent_reserve_in_report_capabilities {
969        uint16_t length;
970        uint8_t  crh;
971        uint8_t  sip_c;
972        uint8_t  atp_c;
973        uint8_t  ptpl_c;
974        uint8_t  tmv;
975        uint8_t  allow_commands;
976        uint8_t  ptpl_a;
977        uint16_t persistent_reservation_type_mask;
978 };
979 
980 struct scsi_read6_cdb {
981 	enum scsi_opcode opcode;
982 	uint32_t lba;
983 	uint16_t transfer_length;
984 	uint8_t  control;
985 };
986 
987 struct scsi_read10_cdb {
988 	enum scsi_opcode opcode;
989 	uint8_t  rdprotect;
990 	uint8_t  dpo;
991 	uint8_t  fua;
992 	uint8_t  fua_nv;
993 	uint32_t lba;
994 	uint8_t  group;
995 	uint16_t transfer_length;
996 	uint8_t  control;
997 };
998 
999 struct scsi_read12_cdb {
1000 	enum scsi_opcode opcode;
1001 	uint8_t  rdprotect;
1002 	uint8_t  dpo;
1003 	uint8_t  fua;
1004 	uint8_t	 rarc;
1005 	uint8_t  fua_nv;
1006 	uint32_t lba;
1007 	uint32_t transfer_length;
1008 	uint8_t  group;
1009 	uint8_t  control;
1010 };
1011 
1012 struct scsi_read16_cdb {
1013 	enum scsi_opcode opcode;
1014 	uint8_t  rdprotect;
1015 	uint8_t  dpo;
1016 	uint8_t  fua;
1017 	uint8_t	 rarc;
1018 	uint8_t  fua_nv;
1019 	uint64_t lba;
1020 	uint32_t transfer_length;
1021 	uint8_t  group;
1022 	uint8_t  control;
1023 };
1024 
1025 struct scsi_verify10_cdb {
1026 	enum scsi_opcode opcode;
1027 	uint8_t  vrprotect;
1028 	uint8_t  dpo;
1029 	uint8_t  bytchk;
1030 	uint32_t lba;
1031 	uint8_t  group;
1032 	uint16_t verification_length;
1033 	uint8_t  control;
1034 };
1035 
1036 struct scsi_verify12_cdb {
1037 	enum scsi_opcode opcode;
1038 	uint8_t  vrprotect;
1039 	uint8_t  dpo;
1040 	uint8_t  bytchk;
1041 	uint32_t lba;
1042 	uint32_t verification_length;
1043 	uint8_t  group;
1044 	uint8_t  control;
1045 };
1046 
1047 struct scsi_verify16_cdb {
1048 	enum scsi_opcode opcode;
1049 	uint8_t  vrprotect;
1050 	uint8_t  dpo;
1051 	uint8_t  bytchk;
1052 	uint64_t lba;
1053 	uint32_t verification_length;
1054 	uint8_t  group;
1055 	uint8_t  control;
1056 };
1057 
1058 struct scsi_write10_cdb {
1059 	enum scsi_opcode opcode;
1060 	uint8_t  wrprotect;
1061 	uint8_t  dpo;
1062 	uint8_t  fua;
1063 	uint8_t  fua_nv;
1064 	uint32_t lba;
1065 	uint8_t  group;
1066 	uint16_t transfer_length;
1067 	uint8_t  control;
1068 };
1069 
1070 struct scsi_write12_cdb {
1071 	enum scsi_opcode opcode;
1072 	uint8_t  wrprotect;
1073 	uint8_t  dpo;
1074 	uint8_t  fua;
1075 	uint8_t  fua_nv;
1076 	uint32_t lba;
1077 	uint32_t transfer_length;
1078 	uint8_t  group;
1079 	uint8_t  control;
1080 };
1081 
1082 struct scsi_write16_cdb {
1083 	enum scsi_opcode opcode;
1084 	uint8_t  wrprotect;
1085 	uint8_t  dpo;
1086 	uint8_t  fua;
1087 	uint8_t  fua_nv;
1088 	uint32_t lba;
1089 	uint32_t transfer_length;
1090 	uint8_t  group;
1091 	uint8_t  control;
1092 };
1093 
1094 struct scsi_writeatomic16_cdb {
1095 	enum scsi_opcode opcode;
1096 	uint8_t  wrprotect;
1097 	uint8_t  dpo;
1098 	uint8_t  fua;
1099 	uint32_t lba;
1100 	uint16_t transfer_length;
1101 	uint8_t  group;
1102 	uint8_t  control;
1103 };
1104 
1105 EXTERN int scsi_datain_getfullsize(struct scsi_task *task);
1106 EXTERN void *scsi_datain_unmarshall(struct scsi_task *task);
1107 EXTERN void *scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode);
1108 
1109 EXTERN void scsi_parse_sense_data(struct scsi_sense *sense, const uint8_t *sb);
1110 
1111 EXTERN struct scsi_task *scsi_cdb_compareandwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
1112 EXTERN struct scsi_task *scsi_cdb_get_lba_status(uint64_t starting_lba, uint32_t alloc_len);
1113 EXTERN struct scsi_task *scsi_cdb_orwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
1114 EXTERN struct scsi_task *scsi_cdb_persistent_reserve_in(enum scsi_persistent_in_sa sa, uint16_t xferlen);
1115 EXTERN struct scsi_task *scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persistent_out_scope scope, enum scsi_persistent_out_type type, void *params);
1116 EXTERN struct scsi_task *scsi_cdb_prefetch10(uint32_t lba, int num_blocks, int immed, int group);
1117 EXTERN struct scsi_task *scsi_cdb_prefetch16(uint64_t lba, int num_blocks, int immed, int group);
1118 EXTERN struct scsi_task *scsi_cdb_preventallow(int prevent);
1119 EXTERN struct scsi_task *scsi_cdb_read6(uint32_t lba, uint32_t xferlen, int blocksize);
1120 EXTERN struct scsi_task *scsi_cdb_read10(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
1121 EXTERN struct scsi_task *scsi_cdb_read12(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
1122 EXTERN struct scsi_task *scsi_cdb_read16(uint64_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
1123 EXTERN struct scsi_task *scsi_cdb_readcapacity16(void);
1124 EXTERN struct scsi_task *scsi_cdb_readdefectdata10(int req_plist, int req_glist, int defect_list_format, uint16_t alloc_len);
1125 EXTERN struct scsi_task *scsi_cdb_readdefectdata12(int req_plist, int req_glist, int defect_list_format, uint32_t address_descriptor_index, uint32_t alloc_len);
1126 EXTERN struct scsi_task *scsi_cdb_report_supported_opcodes(int rctd, int options, enum scsi_opcode opcode, int sa, uint32_t alloc_len);
1127 EXTERN struct scsi_task *scsi_cdb_serviceactionin16(enum scsi_service_action_in sa, uint32_t xferlen);
1128 EXTERN struct scsi_task *scsi_cdb_startstopunit(int immed, int pcm, int pc, int no_flush, int loej, int start);
1129 EXTERN struct scsi_task *scsi_cdb_synchronizecache10(int lba, int num_blocks, int syncnv, int immed);
1130 EXTERN struct scsi_task *scsi_cdb_synchronizecache16(uint64_t lba, uint32_t num_blocks, int syncnv, int immed);
1131 EXTERN struct scsi_task *scsi_cdb_unmap(int anchor, int group, uint16_t xferlen);
1132 EXTERN struct scsi_task *scsi_cdb_verify10(uint32_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
1133 EXTERN struct scsi_task *scsi_cdb_verify12(uint32_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
1134 EXTERN struct scsi_task *scsi_cdb_verify16(uint64_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
1135 EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
1136 EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
1137 EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
1138 EXTERN struct scsi_task *scsi_cdb_writeatomic16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int group_number);
1139 EXTERN struct scsi_task *scsi_cdb_writesame10(int wrprotect, int anchor, int unmap, uint32_t lba, int group, uint16_t num_blocks, uint32_t datalen);
1140 EXTERN struct scsi_task *scsi_cdb_writesame16(int wrprotect, int anchor, int unmap, uint64_t lba, int group, uint32_t num_blocks, uint32_t datalen);
1141 EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
1142 EXTERN struct scsi_task *scsi_cdb_writeverify12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
1143 EXTERN struct scsi_task *scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
1144 
1145 
1146 /*
1147  * EXTENDED COPY
1148  */
1149 #define XCOPY_DESC_OFFSET 16
1150 #define SEG_DESC_SRC_INDEX_OFFSET 4
1151 enum list_id_usage {
1152 	LIST_ID_USAGE_HOLD = 0,
1153 	LIST_ID_USAGE_DISCARD = 2,
1154 	LIST_ID_USAGE_DISABLE = 3
1155 };
1156 
1157 enum ec_descr_type_code {
1158 	/* Segment descriptors : 0x00 to 0xBF */
1159 	BLK_TO_STRM_SEG_DESCR	= 0x00,
1160 	STRM_TO_BLK_SEG_DESCR	= 0x01,
1161 	BLK_TO_BLK_SEG_DESCR	= 0x02,
1162 	STRM_TO_STRM_SEG_DESCR	= 0x03,
1163 
1164 	/* Target descriptors : 0xEO to 0xFE */
1165 	IDENT_DESCR_TGT_DESCR	= 0xE4,
1166 	IPV4_TGT_DESCR		= 0xE5,
1167 	IPV6_TGT_DESCR		= 0xEA,
1168 	IP_COPY_SVC_TGT_DESCR	= 0xEB
1169 };
1170 
1171 enum lu_id_type {
1172 	LU_ID_TYPE_LUN		= 0x00,
1173 	LU_ID_TYPE_PROXY_TOKEN 	= 0x01,
1174 	LU_ID_TYPE_RSVD		= 0x02,
1175 	LU_ID_TYPE_RSVD1	= 0x03
1176 };
1177 
1178 EXTERN struct scsi_task *scsi_cdb_extended_copy(int immed);
1179 
1180 /*
1181  * RECEIVE COPY RESULTS
1182  */
1183 enum scsi_copy_results_sa {
1184         SCSI_COPY_RESULTS_COPY_STATUS 		= 0,
1185         SCSI_COPY_RESULTS_RECEIVE_DATA  	= 1,
1186         SCSI_COPY_RESULTS_OP_PARAMS   		= 3,
1187         SCSI_COPY_RESULTS_FAILED_SEGMENT	= 4,
1188 };
1189 
1190 EXTERN struct scsi_task *scsi_cdb_receive_copy_results(enum scsi_copy_results_sa sa, int list_id, int xferlen);
1191 
1192 struct scsi_copy_results_copy_status {
1193 	uint32_t available_data;
1194 	uint8_t copy_manager_status;
1195 	uint8_t hdd;
1196 	uint16_t segments_processed;
1197 	uint8_t transfer_count_units;
1198 	uint32_t transfer_count;
1199 };
1200 
1201 struct scsi_copy_results_op_params {
1202 	uint32_t available_data;
1203 	uint16_t max_target_desc_count;
1204 	uint16_t max_segment_desc_count;
1205 	uint32_t max_desc_list_length;
1206 	uint32_t max_segment_length;
1207 	uint32_t max_inline_data_length;
1208 	uint32_t held_data_limit;
1209 	uint32_t max_stream_device_transfer_size;
1210 	uint16_t total_concurrent_copies;
1211 	uint8_t max_concurrent_copies;
1212 	uint8_t data_segment_granularity;
1213 	uint8_t inline_data_granularity;
1214 	uint8_t held_data_granularity;
1215 	uint8_t impl_desc_list_length;
1216 	uint8_t imp_desc_type_codes[0];
1217 };
1218 void *scsi_malloc(struct scsi_task *task, size_t size);
1219 
1220 uint64_t scsi_get_uint64(const unsigned char *c);
1221 uint32_t scsi_get_uint32(const unsigned char *c);
1222 uint16_t scsi_get_uint16(const unsigned char *c);
1223 void scsi_set_uint64(unsigned char *c, uint64_t val);
1224 void scsi_set_uint32(unsigned char *c, uint32_t val);
1225 void scsi_set_uint16(unsigned char *c, uint16_t val);
1226 
1227 #ifdef __cplusplus
1228 }
1229 #endif
1230 
1231 #endif /* __scsi_lowlevel_h__ */
1232