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