xref: /freebsd/sys/cam/ctl/ctl_util.c (revision 6f308bcf572467c0884db833e169d9f14b7b49b2)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003 Silicon Graphics International Corp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification.
13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14  *    substantially similar to the "NO WARRANTY" disclaimer below
15  *    ("Disclaimer") and any redistribution must be conditioned upon
16  *    including a substantially similar Disclaimer requirement for further
17  *    binary redistribution.
18  *
19  * NO WARRANTY
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGES.
31  *
32  * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_util.c#2 $
33  */
34 /*
35  * CAM Target Layer SCSI library
36  *
37  * Author: Ken Merry <ken@FreeBSD.org>
38  */
39 
40 #ifdef _KERNEL
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/types.h>
45 #include <sys/malloc.h>
46 #else /* __KERNEL__ */
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <stdint.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #endif /* __KERNEL__ */
54 #include <sys/sbuf.h>
55 #include <sys/queue.h>
56 #include <sys/callout.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/ctl/ctl_io.h>
59 #include <cam/ctl/ctl_nvme_all.h>
60 #include <cam/ctl/ctl_scsi_all.h>
61 #include <cam/ctl/ctl_util.h>
62 
63 struct ctl_status_desc {
64 	ctl_io_status status;
65 	const char *description;
66 };
67 
68 struct ctl_task_desc {
69 	ctl_task_type	task_action;
70 	const char	*description;
71 };
72 static struct ctl_status_desc ctl_status_table[] = {
73 	{CTL_STATUS_NONE, "No Status"},
74 	{CTL_SUCCESS, "Command Completed Successfully"},
75 	{CTL_CMD_TIMEOUT, "Command Timed Out"},
76 	{CTL_SEL_TIMEOUT, "Selection Timeout"},
77 	{CTL_ERROR, "Command Failed"},
78 	{CTL_SCSI_ERROR, "SCSI Error"},
79 	{CTL_CMD_ABORTED, "Command Aborted"},
80 };
81 
82 static struct ctl_task_desc ctl_task_table[] = {
83 	{CTL_TASK_ABORT_TASK, "Abort Task"},
84 	{CTL_TASK_ABORT_TASK_SET, "Abort Task Set"},
85 	{CTL_TASK_CLEAR_ACA, "Clear ACA"},
86 	{CTL_TASK_CLEAR_TASK_SET, "Clear Task Set"},
87 	{CTL_TASK_I_T_NEXUS_RESET, "I_T Nexus Reset"},
88 	{CTL_TASK_LUN_RESET, "LUN Reset"},
89 	{CTL_TASK_TARGET_RESET, "Target Reset"},
90 	{CTL_TASK_BUS_RESET, "Bus Reset"},
91 	{CTL_TASK_PORT_LOGIN, "Port Login"},
92 	{CTL_TASK_PORT_LOGOUT, "Port Logout"},
93 	{CTL_TASK_QUERY_TASK, "Query Task"},
94 	{CTL_TASK_QUERY_TASK_SET, "Query Task Set"},
95 	{CTL_TASK_QUERY_ASYNC_EVENT, "Query Async Event"}
96 };
97 
98 void
99 ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control)
100 {
101 	struct ctl_scsiio *ctsio;
102 	struct scsi_test_unit_ready *cdb;
103 
104 	ctl_scsi_zero_io(io);
105 
106 	io->io_hdr.io_type = CTL_IO_SCSI;
107 	ctsio = &io->scsiio;
108 	cdb = (struct scsi_test_unit_ready *)ctsio->cdb;
109 
110 	cdb->opcode = TEST_UNIT_READY;
111 	cdb->control = control;
112 	io->io_hdr.flags = CTL_FLAG_DATA_NONE;
113 	ctsio->tag_type = tag_type;
114 	ctsio->cdb_len = sizeof(*cdb);
115 	ctsio->ext_data_len = 0;
116 	ctsio->ext_data_ptr = NULL;
117 	ctsio->ext_sg_entries = 0;
118 	ctsio->ext_data_filled = 0;
119 	ctsio->sense_len = SSD_FULL_SIZE;
120 }
121 
122 void
123 ctl_scsi_inquiry(union ctl_io *io, uint8_t *data_ptr, int32_t data_len,
124 		 uint8_t byte2, uint8_t page_code, ctl_tag_type tag_type,
125 		 uint8_t control)
126 {
127 	struct ctl_scsiio *ctsio;
128 	struct scsi_inquiry *cdb;
129 
130 	ctl_scsi_zero_io(io);
131 
132 	io->io_hdr.io_type = CTL_IO_SCSI;
133 	ctsio = &io->scsiio;
134 	cdb = (struct scsi_inquiry *)ctsio->cdb;
135 
136 	cdb->opcode = INQUIRY;
137 	cdb->byte2 = byte2;
138 	cdb->page_code = page_code;
139 	cdb->control = control;
140 	scsi_ulto2b(data_len, cdb->length);
141 	io->io_hdr.io_type = CTL_IO_SCSI;
142 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
143 	ctsio->tag_type = tag_type;
144 	ctsio->cdb_len = sizeof(*cdb);
145 	ctsio->ext_data_len = data_len;
146 	ctsio->ext_data_ptr = data_ptr;
147 	ctsio->ext_sg_entries = 0;
148 	ctsio->ext_data_filled = 0;
149 	ctsio->sense_len = SSD_FULL_SIZE;
150 }
151 
152 void
153 ctl_scsi_request_sense(union ctl_io *io, uint8_t *data_ptr,
154 		       int32_t data_len, uint8_t byte2, ctl_tag_type tag_type,
155 		       uint8_t control)
156 {
157 	struct ctl_scsiio *ctsio;
158 	struct scsi_request_sense *cdb;
159 
160 	ctl_scsi_zero_io(io);
161 
162 	io->io_hdr.io_type = CTL_IO_SCSI;
163 	ctsio = &io->scsiio;
164 	cdb = (struct scsi_request_sense *)ctsio->cdb;
165 
166 	cdb->opcode = REQUEST_SENSE;
167 	cdb->byte2 = byte2;
168 	cdb->control = control;
169 	cdb->length = data_len;
170 	io->io_hdr.io_type = CTL_IO_SCSI;
171 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
172 	ctsio->tag_type = tag_type;
173 	ctsio->cdb_len = sizeof(*cdb);
174 	ctsio->ext_data_ptr = data_ptr;
175 	ctsio->ext_data_len = data_len;
176 	ctsio->ext_sg_entries = 0;
177 	ctsio->ext_data_filled = 0;
178 	ctsio->sense_len = SSD_FULL_SIZE;
179 }
180 
181 void
182 ctl_scsi_report_luns(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
183 		     uint8_t select_report, ctl_tag_type tag_type,
184 		     uint8_t control)
185 {
186 	struct ctl_scsiio *ctsio;
187 	struct scsi_report_luns *cdb;
188 
189 	ctl_scsi_zero_io(io);
190 
191 	io->io_hdr.io_type = CTL_IO_SCSI;
192 	ctsio = &io->scsiio;
193 	cdb = (struct scsi_report_luns *)ctsio->cdb;
194 
195 	cdb->opcode = REPORT_LUNS;
196 	cdb->select_report = select_report;
197 	scsi_ulto4b(data_len, cdb->length);
198 	cdb->control = control;
199 	io->io_hdr.io_type = CTL_IO_SCSI;
200 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
201 	ctsio->tag_type = tag_type;
202 	ctsio->cdb_len = sizeof(*cdb);
203 	ctsio->ext_data_ptr = data_ptr;
204 	ctsio->ext_data_len = data_len;
205 	ctsio->ext_sg_entries = 0;
206 	ctsio->ext_data_filled = 0;
207 	ctsio->sense_len = SSD_FULL_SIZE;
208 }
209 
210 void
211 ctl_scsi_read_write_buffer(union ctl_io *io, uint8_t *data_ptr,
212 			   uint32_t data_len, int read_buffer, uint8_t mode,
213 			   uint8_t buffer_id, uint32_t buffer_offset,
214 			   ctl_tag_type tag_type, uint8_t control)
215 {
216 	struct ctl_scsiio *ctsio;
217 	struct scsi_write_buffer *cdb;
218 
219 	ctl_scsi_zero_io(io);
220 
221 	io->io_hdr.io_type = CTL_IO_SCSI;
222 	ctsio = &io->scsiio;
223 	cdb = (struct scsi_write_buffer *)ctsio->cdb;
224 
225 	if (read_buffer != 0)
226 		cdb->opcode = READ_BUFFER;
227 	else
228 		cdb->opcode = WRITE_BUFFER;
229 
230 	cdb->byte2 = mode & RWB_MODE;
231 	cdb->buffer_id = buffer_id;
232 	scsi_ulto3b(buffer_offset, cdb->offset);
233 	scsi_ulto3b(data_len, cdb->length);
234 	cdb->control = control;
235 	io->io_hdr.io_type = CTL_IO_SCSI;
236 	if (read_buffer != 0)
237 		io->io_hdr.flags = CTL_FLAG_DATA_IN;
238 	else
239 		io->io_hdr.flags = CTL_FLAG_DATA_OUT;
240 	ctsio->tag_type = tag_type;
241 	ctsio->cdb_len = sizeof(*cdb);
242 	ctsio->ext_data_ptr = data_ptr;
243 	ctsio->ext_data_len = data_len;
244 	ctsio->ext_sg_entries = 0;
245 	ctsio->ext_data_filled = 0;
246 	ctsio->sense_len = SSD_FULL_SIZE;
247 }
248 
249 void
250 ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
251 		    int read_op, uint8_t byte2, int minimum_cdb_size,
252 		    uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type,
253 		    uint8_t control)
254 {
255 	struct ctl_scsiio *ctsio;
256 
257 	ctl_scsi_zero_io(io);
258 
259 	io->io_hdr.io_type = CTL_IO_SCSI;
260 	ctsio = &io->scsiio;
261 
262 	/*
263 	 * Pick out the smallest CDB that will hold the user's request.
264 	 * minimum_cdb_size allows cranking the CDB size up, even for
265 	 * requests that would not normally need a large CDB.  This can be
266 	 * useful for testing (e.g. to make sure READ_16 support works without
267 	 * having an array larger than 2TB) and for compatibility -- e.g.
268 	 * if your device doesn't support READ_6.  (ATAPI drives don't.)
269 	 */
270 	if ((minimum_cdb_size < 10)
271 	 && ((lba & 0x1fffff) == lba)
272 	 && ((num_blocks & 0xff) == num_blocks)
273 	 && (byte2 == 0)) {
274 		struct scsi_rw_6 *cdb;
275 
276 		/*
277 		 * Note that according to SBC-2, the target should return 256
278 		 * blocks if the transfer length in a READ(6) or WRITE(6) CDB
279 		 * is set to 0.  Since it's possible that some targets
280 		 * won't do the right thing, we only send a READ(6) or
281 		 * WRITE(6) for transfer sizes up to and including 255 blocks.
282 		 */
283 		cdb = (struct scsi_rw_6 *)ctsio->cdb;
284 
285 		cdb->opcode = (read_op) ? READ_6 : WRITE_6;
286 		scsi_ulto3b(lba, cdb->addr);
287 		cdb->length = num_blocks & 0xff;
288 		cdb->control = control;
289 
290 		ctsio->cdb_len = sizeof(*cdb);
291 
292 	} else if ((minimum_cdb_size < 12)
293 		&& ((num_blocks & 0xffff) == num_blocks)
294 		&& ((lba & 0xffffffff) == lba)) {
295 		struct scsi_rw_10 *cdb;
296 
297 		cdb = (struct scsi_rw_10 *)ctsio->cdb;
298 
299 		cdb->opcode = (read_op) ? READ_10 : WRITE_10;
300 		cdb->byte2 = byte2;
301 		scsi_ulto4b(lba, cdb->addr);
302 		cdb->reserved = 0;
303 		scsi_ulto2b(num_blocks, cdb->length);
304 		cdb->control = control;
305 
306 		ctsio->cdb_len = sizeof(*cdb);
307 	} else if ((minimum_cdb_size < 16)
308 		&& ((num_blocks & 0xffffffff) == num_blocks)
309 		&& ((lba & 0xffffffff) == lba)) {
310 		struct scsi_rw_12 *cdb;
311 
312 		cdb = (struct scsi_rw_12 *)ctsio->cdb;
313 
314 		cdb->opcode = (read_op) ? READ_12 : WRITE_12;
315 		cdb->byte2 = byte2;
316 		scsi_ulto4b(lba, cdb->addr);
317 		scsi_ulto4b(num_blocks, cdb->length);
318 		cdb->reserved = 0;
319 		cdb->control = control;
320 
321 		ctsio->cdb_len = sizeof(*cdb);
322 	} else {
323 		struct scsi_rw_16 *cdb;
324 
325 		cdb = (struct scsi_rw_16 *)ctsio->cdb;
326 
327 		cdb->opcode = (read_op) ? READ_16 : WRITE_16;
328 		cdb->byte2 = byte2;
329 		scsi_u64to8b(lba, cdb->addr);
330 		scsi_ulto4b(num_blocks, cdb->length);
331 		cdb->reserved = 0;
332 		cdb->control = control;
333 
334 		ctsio->cdb_len = sizeof(*cdb);
335 	}
336 
337 	io->io_hdr.io_type = CTL_IO_SCSI;
338 	if (read_op != 0)
339 		io->io_hdr.flags = CTL_FLAG_DATA_IN;
340 	else
341 		io->io_hdr.flags = CTL_FLAG_DATA_OUT;
342 	ctsio->tag_type = tag_type;
343 	ctsio->ext_data_ptr = data_ptr;
344 	ctsio->ext_data_len = data_len;
345 	ctsio->ext_sg_entries = 0;
346 	ctsio->ext_data_filled = 0;
347 	ctsio->sense_len = SSD_FULL_SIZE;
348 }
349 
350 void
351 ctl_scsi_write_same(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
352 		    uint8_t byte2, uint64_t lba, uint32_t num_blocks,
353 		    ctl_tag_type tag_type, uint8_t control)
354 {
355 	struct ctl_scsiio *ctsio;
356 	struct scsi_write_same_16 *cdb;
357 
358 	ctl_scsi_zero_io(io);
359 
360 	io->io_hdr.io_type = CTL_IO_SCSI;
361 	ctsio = &io->scsiio;
362 	ctsio->cdb_len = sizeof(*cdb);
363 	cdb = (struct scsi_write_same_16 *)ctsio->cdb;
364 	cdb->opcode = WRITE_SAME_16;
365 	cdb->byte2 = byte2;
366 	scsi_u64to8b(lba, cdb->addr);
367 	scsi_ulto4b(num_blocks, cdb->length);
368 	cdb->group = 0;
369 	cdb->control = control;
370 
371 	io->io_hdr.io_type = CTL_IO_SCSI;
372 	io->io_hdr.flags = CTL_FLAG_DATA_OUT;
373 	ctsio->tag_type = tag_type;
374 	ctsio->ext_data_ptr = data_ptr;
375 	ctsio->ext_data_len = data_len;
376 	ctsio->ext_sg_entries = 0;
377 	ctsio->ext_data_filled = 0;
378 	ctsio->sense_len = SSD_FULL_SIZE;
379 }
380 
381 void
382 ctl_scsi_read_capacity(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
383 		       uint32_t addr, int reladr, int pmi,
384 		       ctl_tag_type tag_type, uint8_t control)
385 {
386 	struct scsi_read_capacity *cdb;
387 
388 	ctl_scsi_zero_io(io);
389 
390 	io->io_hdr.io_type = CTL_IO_SCSI;
391 	cdb = (struct scsi_read_capacity *)io->scsiio.cdb;
392 
393 	cdb->opcode = READ_CAPACITY;
394 	if (reladr)
395 		cdb->byte2 = SRC_RELADR;
396 	if (pmi)
397 		cdb->pmi = SRC_PMI;
398 	scsi_ulto4b(addr, cdb->addr);
399 	cdb->control = control;
400 	io->io_hdr.io_type = CTL_IO_SCSI;
401 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
402 	io->scsiio.tag_type = tag_type;
403 	io->scsiio.ext_data_ptr = data_ptr;
404 	io->scsiio.ext_data_len = data_len;
405 	io->scsiio.ext_sg_entries = 0;
406 	io->scsiio.ext_data_filled = 0;
407 	io->scsiio.sense_len = SSD_FULL_SIZE;
408 }
409 
410 void
411 ctl_scsi_read_capacity_16(union ctl_io *io, uint8_t *data_ptr,
412 			  uint32_t data_len, uint64_t addr, int reladr,
413 			  int pmi, ctl_tag_type tag_type, uint8_t control)
414 {
415 	struct scsi_read_capacity_16 *cdb;
416 
417 	ctl_scsi_zero_io(io);
418 
419 	io->io_hdr.io_type = CTL_IO_SCSI;
420 	cdb = (struct scsi_read_capacity_16 *)io->scsiio.cdb;
421 
422 	cdb->opcode = SERVICE_ACTION_IN;
423 	cdb->service_action = SRC16_SERVICE_ACTION;
424 	if (reladr)
425 		cdb->reladr |= SRC16_RELADR;
426 	if (pmi)
427 		cdb->reladr |= SRC16_PMI;
428 	scsi_u64to8b(addr, cdb->addr);
429 	scsi_ulto4b(data_len, cdb->alloc_len);
430 	cdb->control = control;
431 
432 	io->io_hdr.io_type = CTL_IO_SCSI;
433 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
434 	io->scsiio.tag_type = tag_type;
435 	io->scsiio.ext_data_ptr = data_ptr;
436 	io->scsiio.ext_data_len = data_len;
437 	io->scsiio.ext_sg_entries = 0;
438 	io->scsiio.ext_data_filled = 0;
439 	io->scsiio.sense_len = SSD_FULL_SIZE;
440 }
441 
442 void
443 ctl_scsi_mode_sense(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
444 		    int dbd, int llbaa, uint8_t page_code, uint8_t pc,
445 		    uint8_t subpage, int minimum_cdb_size,
446 		    ctl_tag_type tag_type, uint8_t control)
447 {
448 	ctl_scsi_zero_io(io);
449 
450 	if ((minimum_cdb_size < 10)
451 	 && (llbaa == 0)
452 	 && (data_len < 256)) {
453 		struct scsi_mode_sense_6 *cdb;
454 
455 		cdb = (struct scsi_mode_sense_6 *)io->scsiio.cdb;
456 
457 		cdb->opcode = MODE_SENSE_6;
458 		if (dbd)
459 			cdb->byte2 |= SMS_DBD;
460 		cdb->page = page_code | pc;
461 		cdb->subpage = subpage;
462 		cdb->length = data_len;
463 		cdb->control = control;
464 	} else {
465 		struct scsi_mode_sense_10 *cdb;
466 
467 		cdb = (struct scsi_mode_sense_10 *)io->scsiio.cdb;
468 
469 		cdb->opcode = MODE_SENSE_10;
470 		if (dbd)
471 			cdb->byte2 |= SMS_DBD;
472 		if (llbaa)
473 			cdb->byte2 |= SMS10_LLBAA;
474 		cdb->page = page_code | pc;
475 		cdb->subpage = subpage;
476 		scsi_ulto2b(data_len, cdb->length);
477 		cdb->control = control;
478 	}
479 
480 	io->io_hdr.io_type = CTL_IO_SCSI;
481 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
482 	io->scsiio.tag_type = tag_type;
483 	io->scsiio.ext_data_ptr = data_ptr;
484 	io->scsiio.ext_data_len = data_len;
485 	io->scsiio.ext_sg_entries = 0;
486 	io->scsiio.ext_data_filled = 0;
487 	io->scsiio.sense_len = SSD_FULL_SIZE;
488 }
489 
490 void
491 ctl_scsi_start_stop(union ctl_io *io, int start, int load_eject, int immediate,
492     int power_conditions, ctl_tag_type tag_type, uint8_t control)
493 {
494 	struct scsi_start_stop_unit *cdb;
495 
496 	cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
497 
498 	ctl_scsi_zero_io(io);
499 
500 	cdb->opcode = START_STOP_UNIT;
501 	if (immediate)
502 		cdb->byte2 |= SSS_IMMED;
503 	cdb->how = power_conditions;
504 	if (load_eject)
505 		cdb->how |= SSS_LOEJ;
506 	if (start)
507 		cdb->how |= SSS_START;
508 	cdb->control = control;
509 	io->io_hdr.io_type = CTL_IO_SCSI;
510 	io->io_hdr.flags = CTL_FLAG_DATA_NONE;
511 	io->scsiio.tag_type = tag_type;
512 	io->scsiio.ext_data_ptr = NULL;
513 	io->scsiio.ext_data_len = 0;
514 	io->scsiio.ext_sg_entries = 0;
515 	io->scsiio.ext_data_filled = 0;
516 	io->scsiio.sense_len = SSD_FULL_SIZE;
517 }
518 
519 void
520 ctl_scsi_sync_cache(union ctl_io *io, int immed, int reladr,
521 		    int minimum_cdb_size, uint64_t starting_lba,
522 		    uint32_t block_count, ctl_tag_type tag_type,
523 		    uint8_t control)
524 {
525 	ctl_scsi_zero_io(io);
526 
527 	if ((minimum_cdb_size < 16)
528 	 && ((block_count & 0xffff) == block_count)
529 	 && ((starting_lba & 0xffffffff) == starting_lba)) {
530 		struct scsi_sync_cache *cdb;
531 
532 		cdb = (struct scsi_sync_cache *)io->scsiio.cdb;
533 
534 		cdb->opcode = SYNCHRONIZE_CACHE;
535 		if (reladr)
536 			cdb->byte2 |= SSC_RELADR;
537 
538 		if (immed)
539 			cdb->byte2 |= SSC_IMMED;
540 
541 		scsi_ulto4b(starting_lba, cdb->begin_lba);
542 		scsi_ulto2b(block_count, cdb->lb_count);
543 		cdb->control = control;
544 	} else {
545 		struct scsi_sync_cache_16 *cdb;
546 
547 		cdb = (struct scsi_sync_cache_16 *)io->scsiio.cdb;
548 
549 		cdb->opcode = SYNCHRONIZE_CACHE_16;
550 		if (reladr)
551 			cdb->byte2 |= SSC_RELADR;
552 
553 		if (immed)
554 			cdb->byte2 |= SSC_IMMED;
555 
556 		scsi_u64to8b(starting_lba, cdb->begin_lba);
557 		scsi_ulto4b(block_count, cdb->lb_count);
558 		cdb->control = control;
559 	}
560 	io->io_hdr.io_type = CTL_IO_SCSI;
561 	io->io_hdr.flags = CTL_FLAG_DATA_NONE;
562 	io->scsiio.tag_type = tag_type;
563 	io->scsiio.ext_data_ptr = NULL;
564 	io->scsiio.ext_data_len = 0;
565 	io->scsiio.ext_sg_entries = 0;
566 	io->scsiio.ext_data_filled = 0;
567 	io->scsiio.sense_len = SSD_FULL_SIZE;
568 }
569 
570 void
571 ctl_scsi_persistent_res_in(union ctl_io *io, uint8_t *data_ptr,
572 			   uint32_t data_len, int action,
573 			   ctl_tag_type tag_type, uint8_t control)
574 {
575 
576 	struct scsi_per_res_in *cdb;
577 
578 	ctl_scsi_zero_io(io);
579 
580 	cdb = (struct scsi_per_res_in *)io->scsiio.cdb;
581 	cdb->opcode = PERSISTENT_RES_IN;
582 	cdb->action = action;
583 	scsi_ulto2b(data_len, cdb->length);
584 	cdb->control = control;
585 
586 	io->io_hdr.io_type = CTL_IO_SCSI;
587 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
588 	io->scsiio.tag_type = tag_type;
589 	io->scsiio.ext_data_ptr = data_ptr;
590 	io->scsiio.ext_data_len = data_len;
591 	io->scsiio.ext_sg_entries = 0;
592 	io->scsiio.ext_data_filled = 0;
593 	io->scsiio.sense_len = SSD_FULL_SIZE;
594 }
595 
596 void
597 ctl_scsi_persistent_res_out(union ctl_io *io, uint8_t *data_ptr,
598 			    uint32_t data_len, int action, int type,
599 			    uint64_t key, uint64_t sa_key,
600 			    ctl_tag_type tag_type, uint8_t control)
601 {
602 
603 	struct scsi_per_res_out *cdb;
604 	struct scsi_per_res_out_parms *params;
605 
606 	ctl_scsi_zero_io(io);
607 
608 	cdb = (struct scsi_per_res_out *)io->scsiio.cdb;
609 	params = (struct scsi_per_res_out_parms *)data_ptr;
610 
611 	cdb->opcode = PERSISTENT_RES_OUT;
612 	if (action == 5)
613 	    cdb->action = 6;
614 	else
615 	    cdb->action = action;
616 	switch(type)
617 	{
618 	    case 0:
619 		    cdb->scope_type = 1;
620 			break;
621 	    case 1:
622 		    cdb->scope_type = 3;
623 			break;
624 	    case 2:
625 		    cdb->scope_type = 5;
626 			break;
627 	    case 3:
628 		    cdb->scope_type = 6;
629 			break;
630 	    case 4:
631 		    cdb->scope_type = 7;
632 			break;
633 	    case 5:
634 		    cdb->scope_type = 8;
635 			break;
636 	}
637 	scsi_ulto4b(data_len, cdb->length);
638 	cdb->control = control;
639 
640 	scsi_u64to8b(key, params->res_key.key);
641 	scsi_u64to8b(sa_key, params->serv_act_res_key);
642 
643 	io->io_hdr.io_type = CTL_IO_SCSI;
644 	io->io_hdr.flags = CTL_FLAG_DATA_OUT;
645 	io->scsiio.tag_type = tag_type;
646 	io->scsiio.ext_data_ptr = data_ptr;
647 	io->scsiio.ext_data_len = data_len;
648 	io->scsiio.ext_sg_entries = 0;
649 	io->scsiio.ext_data_filled = 0;
650 	io->scsiio.sense_len = SSD_FULL_SIZE;
651 
652 }
653 
654 void
655 ctl_scsi_maintenance_in(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
656 			uint8_t action, ctl_tag_type tag_type, uint8_t control)
657 {
658 	struct scsi_maintenance_in *cdb;
659 
660 	ctl_scsi_zero_io(io);
661 
662 	cdb = (struct scsi_maintenance_in *)io->scsiio.cdb;
663 	cdb->opcode = MAINTENANCE_IN;
664 	cdb->byte2 = action;
665 	scsi_ulto4b(data_len, cdb->length);
666 	cdb->control = control;
667 
668 	io->io_hdr.io_type = CTL_IO_SCSI;
669 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
670 	io->scsiio.tag_type = tag_type;
671 	io->scsiio.ext_data_ptr = data_ptr;
672 	io->scsiio.ext_data_len = data_len;
673 	io->scsiio.ext_sg_entries = 0;
674 	io->scsiio.ext_data_filled = 0;
675 	io->scsiio.sense_len = SSD_FULL_SIZE;
676 }
677 
678 #ifndef _KERNEL
679 union ctl_io *
680 ctl_scsi_alloc_io(uint32_t initid)
681 {
682 	union ctl_io *io;
683 
684 	io = (union ctl_io *)malloc(sizeof(*io));
685 	if (io == NULL)
686 		goto bailout;
687 
688 	io->io_hdr.nexus.initid = initid;
689 
690 bailout:
691 	return (io);
692 }
693 
694 void
695 ctl_scsi_free_io(union ctl_io *io)
696 {
697 	free(io);
698 }
699 
700 void
701 ctl_scsi_zero_io(union ctl_io *io)
702 {
703 	void *pool_ref;
704 
705 	if (io == NULL)
706 		return;
707 
708 	pool_ref = io->io_hdr.pool;
709 	memset(io, 0, sizeof(*io));
710 	io->io_hdr.pool = pool_ref;
711 }
712 #endif /* !_KERNEL */
713 
714 const char *
715 ctl_scsi_task_string(struct ctl_taskio *taskio)
716 {
717 	unsigned int i;
718 
719 	for (i = 0; i < (sizeof(ctl_task_table)/sizeof(ctl_task_table[0]));
720 	     i++) {
721 		if (taskio->task_action == ctl_task_table[i].task_action) {
722 			return (ctl_task_table[i].description);
723 		}
724 	}
725 
726 	return (NULL);
727 }
728 
729 void
730 ctl_io_sbuf(union ctl_io *io, struct sbuf *sb)
731 {
732 	const char *task_desc;
733 	char path_str[64];
734 
735 	ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
736 
737 	switch (io->io_hdr.io_type) {
738 	case CTL_IO_SCSI:
739 		sbuf_cat(sb, path_str);
740 		ctl_scsi_command_string(&io->scsiio, NULL, sb);
741 		sbuf_printf(sb, " Tag: %#jx/%d, Prio: %d\n",
742 			    io->scsiio.tag_num, io->scsiio.tag_type,
743 			    io->scsiio.priority);
744 		break;
745 	case CTL_IO_TASK:
746 		sbuf_cat(sb, path_str);
747 		task_desc = ctl_scsi_task_string(&io->taskio);
748 		if (task_desc == NULL)
749 			sbuf_printf(sb, "Unknown Task Action %d (%#x)",
750 			    io->taskio.task_action, io->taskio.task_action);
751 		else
752 			sbuf_printf(sb, "Task Action: %s", task_desc);
753 		switch (io->taskio.task_action) {
754 		case CTL_TASK_ABORT_TASK:
755 			sbuf_printf(sb, " Tag: %#jx/%d\n",
756 			    io->taskio.tag_num, io->taskio.tag_type);
757 			break;
758 		default:
759 			sbuf_putc(sb, '\n');
760 			break;
761 		}
762 		break;
763 	case CTL_IO_NVME:
764 	case CTL_IO_NVME_ADMIN:
765 		sbuf_cat(sb, path_str);
766 		ctl_nvme_command_string(&io->nvmeio, sb);
767 		sbuf_printf(sb, " CID: 0x%x\n", le16toh(io->nvmeio.cmd.cid));
768 		break;
769 	default:
770 		break;
771 	}
772 }
773 
774 void
775 ctl_io_error_sbuf(union ctl_io *io, struct scsi_inquiry_data *inq_data,
776 		  struct sbuf *sb)
777 {
778 	struct ctl_status_desc *status_desc;
779 	char path_str[64];
780 	unsigned int i;
781 
782 	ctl_io_sbuf(io, sb);
783 
784 	status_desc = NULL;
785 	for (i = 0; i < (sizeof(ctl_status_table)/sizeof(ctl_status_table[0]));
786 	     i++) {
787 		if ((io->io_hdr.status & CTL_STATUS_MASK) ==
788 		     ctl_status_table[i].status) {
789 			status_desc = &ctl_status_table[i];
790 			break;
791 		}
792 	}
793 
794 	ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
795 
796 	sbuf_cat(sb, path_str);
797 	if (status_desc == NULL)
798 		sbuf_printf(sb, "CTL Status: Unknown status %#x\n",
799 			    io->io_hdr.status);
800 	else
801 		sbuf_printf(sb, "CTL Status: %s\n", status_desc->description);
802 
803 	switch (io->io_hdr.io_type) {
804 	case CTL_IO_SCSI:
805 		if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR) {
806 			sbuf_cat(sb, path_str);
807 			sbuf_printf(sb, "SCSI Status: %s\n",
808 			    ctl_scsi_status_string(&io->scsiio));
809 
810 			if (io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND)
811 				ctl_scsi_sense_sbuf(&io->scsiio, inq_data,
812 				    sb, SSS_FLAG_NONE);
813 		}
814 		break;
815 	case CTL_IO_NVME:
816 	case CTL_IO_NVME_ADMIN:
817 		if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_NVME_ERROR) {
818 			sbuf_cat(sb, path_str);
819 			sbuf_printf(sb, "NVMe Status: ");
820 			ctl_nvme_status_string(&io->nvmeio, sb);
821 			sbuf_printf(sb, "\n");
822 		}
823 		break;
824 	default:
825 		break;
826 	}
827 }
828 
829 char *
830 ctl_io_string(union ctl_io *io, char *str, int str_len)
831 {
832 	struct sbuf sb;
833 
834 	sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
835 	ctl_io_sbuf(io, &sb);
836 	sbuf_finish(&sb);
837 	return (sbuf_data(&sb));
838 }
839 
840 char *
841 ctl_io_error_string(union ctl_io *io, struct scsi_inquiry_data *inq_data,
842 		    char *str, int str_len)
843 {
844 	struct sbuf sb;
845 
846 	sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
847 	ctl_io_error_sbuf(io, inq_data, &sb);
848 	sbuf_finish(&sb);
849 	return (sbuf_data(&sb));
850 }
851 
852 #ifdef _KERNEL
853 
854 void
855 ctl_io_print(union ctl_io *io)
856 {
857 	char str[512];
858 
859 	printf("%s", ctl_io_string(io, str, sizeof(str)));
860 }
861 
862 void
863 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data)
864 {
865 	char str[512];
866 
867 	printf("%s", ctl_io_error_string(io, inq_data, str, sizeof(str)));
868 
869 }
870 
871 void
872 ctl_data_print(union ctl_io *io)
873 {
874 	char str[128];
875 	char path_str[64];
876 	struct sbuf sb;
877 	uintmax_t tag_num;
878 	int i, j, len;
879 
880 	switch (io->io_hdr.io_type) {
881 	case CTL_IO_SCSI:
882 		tag_num = io->scsiio.tag_num;
883 		break;
884 	case CTL_IO_NVME:
885 	case CTL_IO_NVME_ADMIN:
886 		tag_num = le16toh(io->nvmeio.cmd.cid);
887 		break;
888 	default:
889 		return;
890 	}
891 	if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
892 		return;
893 	if (ctl_kern_sg_entries(io) > 0)	/* XXX: Implement */
894 		return;
895 	ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
896 	len = min(ctl_kern_data_len(io), 4096);
897 	for (i = 0; i < len; ) {
898 		sbuf_new(&sb, str, sizeof(str), SBUF_FIXEDLEN);
899 		sbuf_cat(&sb, path_str);
900 		sbuf_printf(&sb, " %#jx:%04x:", tag_num, i);
901 		for (j = 0; j < 16 && i < len; i++, j++) {
902 			if (j == 8)
903 				sbuf_cat(&sb, " ");
904 			sbuf_printf(&sb, " %02x", ctl_kern_data_ptr(io)[i]);
905 		}
906 		sbuf_cat(&sb, "\n");
907 		sbuf_finish(&sb);
908 		printf("%s", sbuf_data(&sb));
909 	}
910 }
911 
912 #else /* _KERNEL */
913 
914 void
915 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data,
916 		   FILE *ofile)
917 {
918 	char str[512];
919 
920 	fprintf(ofile, "%s", ctl_io_error_string(io, inq_data, str,
921 		sizeof(str)));
922 }
923 
924 #endif /* _KERNEL */
925 
926 /*
927  * vim: ts=8
928  */
929