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