xref: /freebsd/sys/cam/ctl/ctl_util.c (revision fcb560670601b2a4d87bb31d7531c8dcc37ee71b)
1 /*-
2  * Copyright (c) 2003 Silicon Graphics International Corp.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    substantially similar to the "NO WARRANTY" disclaimer below
13  *    ("Disclaimer") and any redistribution must be conditioned upon
14  *    including a substantially similar Disclaimer requirement for further
15  *    binary redistribution.
16  *
17  * NO WARRANTY
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGES.
29  *
30  * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_util.c#2 $
31  */
32 /*
33  * CAM Target Layer SCSI library
34  *
35  * Author: Ken Merry <ken@FreeBSD.org>
36  */
37 
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #ifdef _KERNEL
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/types.h>
46 #include <sys/malloc.h>
47 #else /* __KERNEL__ */
48 #include <sys/types.h>
49 #include <sys/time.h>
50 #include <stdint.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #endif /* __KERNEL__ */
55 #include <sys/sbuf.h>
56 #include <sys/queue.h>
57 #include <sys/callout.h>
58 #include <cam/scsi/scsi_all.h>
59 #include <cam/ctl/ctl_io.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 };
94 
95 void
96 ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control)
97 {
98 	struct ctl_scsiio *ctsio;
99 	struct scsi_test_unit_ready *cdb;
100 
101 	ctl_scsi_zero_io(io);
102 
103 	io->io_hdr.io_type = CTL_IO_SCSI;
104 	ctsio = &io->scsiio;
105 	cdb = (struct scsi_test_unit_ready *)ctsio->cdb;
106 
107 	cdb->opcode = TEST_UNIT_READY;
108 	cdb->control = control;
109 	io->io_hdr.flags = CTL_FLAG_DATA_NONE;
110 	ctsio->tag_type = tag_type;
111 	ctsio->cdb_len = sizeof(*cdb);
112 	ctsio->ext_data_len = 0;
113 	ctsio->ext_data_ptr = NULL;
114 	ctsio->ext_sg_entries = 0;
115 	ctsio->ext_data_filled = 0;
116 	ctsio->sense_len = SSD_FULL_SIZE;
117 }
118 
119 void
120 ctl_scsi_inquiry(union ctl_io *io, uint8_t *data_ptr, int32_t data_len,
121 		 uint8_t byte2, uint8_t page_code, ctl_tag_type tag_type,
122 		 uint8_t control)
123 {
124 	struct ctl_scsiio *ctsio;
125 	struct scsi_inquiry *cdb;
126 
127 	ctl_scsi_zero_io(io);
128 
129 	io->io_hdr.io_type = CTL_IO_SCSI;
130 	ctsio = &io->scsiio;
131 	cdb = (struct scsi_inquiry *)ctsio->cdb;
132 
133 	cdb->opcode = INQUIRY;
134 	cdb->byte2 = byte2;
135 	cdb->page_code = page_code;
136 	cdb->control = control;
137 	scsi_ulto2b(data_len, cdb->length);
138 	io->io_hdr.io_type = CTL_IO_SCSI;
139 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
140 	ctsio->tag_type = tag_type;
141 	ctsio->cdb_len = sizeof(*cdb);
142 	ctsio->ext_data_len = data_len;
143 	ctsio->ext_data_ptr = data_ptr;
144 	ctsio->ext_sg_entries = 0;
145 	ctsio->ext_data_filled = 0;
146 	ctsio->sense_len = SSD_FULL_SIZE;
147 }
148 
149 void
150 ctl_scsi_request_sense(union ctl_io *io, uint8_t *data_ptr,
151 		       int32_t data_len, uint8_t byte2, ctl_tag_type tag_type,
152 		       uint8_t control)
153 {
154 	struct ctl_scsiio *ctsio;
155 	struct scsi_request_sense *cdb;
156 
157 	ctl_scsi_zero_io(io);
158 
159 	io->io_hdr.io_type = CTL_IO_SCSI;
160 	ctsio = &io->scsiio;
161 	cdb = (struct scsi_request_sense *)ctsio->cdb;
162 
163 	cdb->opcode = REQUEST_SENSE;
164 	cdb->byte2 = byte2;
165 	cdb->control = control;
166 	cdb->length = data_len;
167 	io->io_hdr.io_type = CTL_IO_SCSI;
168 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
169 	ctsio->tag_type = tag_type;
170 	ctsio->cdb_len = sizeof(*cdb);
171 	ctsio->ext_data_ptr = data_ptr;
172 	ctsio->ext_data_len = data_len;
173 	ctsio->ext_sg_entries = 0;
174 	ctsio->ext_data_filled = 0;
175 	ctsio->sense_len = SSD_FULL_SIZE;
176 }
177 
178 void
179 ctl_scsi_report_luns(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
180 		     uint8_t select_report, ctl_tag_type tag_type,
181 		     uint8_t control)
182 {
183 	struct ctl_scsiio *ctsio;
184 	struct scsi_report_luns *cdb;
185 
186 	ctl_scsi_zero_io(io);
187 
188 	io->io_hdr.io_type = CTL_IO_SCSI;
189 	ctsio = &io->scsiio;
190 	cdb = (struct scsi_report_luns *)ctsio->cdb;
191 
192 	cdb->opcode = REPORT_LUNS;
193 	cdb->select_report = select_report;
194 	scsi_ulto4b(data_len, cdb->length);
195 	cdb->control = control;
196 	io->io_hdr.io_type = CTL_IO_SCSI;
197 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
198 	ctsio->tag_type = tag_type;
199 	ctsio->cdb_len = sizeof(*cdb);
200 	ctsio->ext_data_ptr = data_ptr;
201 	ctsio->ext_data_len = data_len;
202 	ctsio->ext_sg_entries = 0;
203 	ctsio->ext_data_filled = 0;
204 	ctsio->sense_len = SSD_FULL_SIZE;
205 }
206 
207 void
208 ctl_scsi_read_write_buffer(union ctl_io *io, uint8_t *data_ptr,
209 			   uint32_t data_len, int read_buffer, uint8_t mode,
210 			   uint8_t buffer_id, uint32_t buffer_offset,
211 			   ctl_tag_type tag_type, uint8_t control)
212 {
213 	struct ctl_scsiio *ctsio;
214 	struct scsi_write_buffer *cdb;
215 
216 	ctl_scsi_zero_io(io);
217 
218 	io->io_hdr.io_type = CTL_IO_SCSI;
219 	ctsio = &io->scsiio;
220 	cdb = (struct scsi_write_buffer *)ctsio->cdb;
221 
222 	if (read_buffer != 0)
223 		cdb->opcode = READ_BUFFER;
224 	else
225 		cdb->opcode = WRITE_BUFFER;
226 
227 	cdb->byte2 = mode & RWB_MODE;
228 	cdb->buffer_id = buffer_id;
229 	scsi_ulto3b(buffer_offset, cdb->offset);
230 	scsi_ulto3b(data_len, cdb->length);
231 	cdb->control = control;
232 	io->io_hdr.io_type = CTL_IO_SCSI;
233 	if (read_buffer != 0)
234 		io->io_hdr.flags = CTL_FLAG_DATA_IN;
235 	else
236 		io->io_hdr.flags = CTL_FLAG_DATA_OUT;
237 	ctsio->tag_type = tag_type;
238 	ctsio->cdb_len = sizeof(*cdb);
239 	ctsio->ext_data_ptr = data_ptr;
240 	ctsio->ext_data_len = data_len;
241 	ctsio->ext_sg_entries = 0;
242 	ctsio->ext_data_filled = 0;
243 	ctsio->sense_len = SSD_FULL_SIZE;
244 }
245 
246 void
247 ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
248 		    int read_op, uint8_t byte2, int minimum_cdb_size,
249 		    uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type,
250 		    uint8_t control)
251 {
252 	struct ctl_scsiio *ctsio;
253 
254 	ctl_scsi_zero_io(io);
255 
256 	io->io_hdr.io_type = CTL_IO_SCSI;
257 	ctsio = &io->scsiio;
258 
259 	/*
260 	 * Pick out the smallest CDB that will hold the user's request.
261 	 * minimum_cdb_size allows cranking the CDB size up, even for
262 	 * requests that would not normally need a large CDB.  This can be
263 	 * useful for testing (e.g. to make sure READ_16 support works without
264 	 * having an array larger than 2TB) and for compatibility -- e.g.
265 	 * if your device doesn't support READ_6.  (ATAPI drives don't.)
266 	 */
267 	if ((minimum_cdb_size < 10)
268 	 && ((lba & 0x1fffff) == lba)
269 	 && ((num_blocks & 0xff) == num_blocks)
270 	 && (byte2 == 0)) {
271 		struct scsi_rw_6 *cdb;
272 
273 		/*
274 		 * Note that according to SBC-2, the target should return 256
275 		 * blocks if the transfer length in a READ(6) or WRITE(6) CDB
276 		 * is set to 0.  Since it's possible that some targets
277 		 * won't do the right thing, we only send a READ(6) or
278 		 * WRITE(6) for transfer sizes up to and including 255 blocks.
279 		 */
280 		cdb = (struct scsi_rw_6 *)ctsio->cdb;
281 
282 		cdb->opcode = (read_op) ? READ_6 : WRITE_6;
283 		scsi_ulto3b(lba, cdb->addr);
284 		cdb->length = num_blocks & 0xff;
285 		cdb->control = control;
286 
287 		ctsio->cdb_len = sizeof(*cdb);
288 
289 	} else if ((minimum_cdb_size < 12)
290 		&& ((num_blocks & 0xffff) == num_blocks)
291 		&& ((lba & 0xffffffff) == lba)) {
292 		struct scsi_rw_10 *cdb;
293 
294 		cdb = (struct scsi_rw_10 *)ctsio->cdb;
295 
296 		cdb->opcode = (read_op) ? READ_10 : WRITE_10;
297 		cdb->byte2 = byte2;
298 		scsi_ulto4b(lba, cdb->addr);
299 		cdb->reserved = 0;
300 		scsi_ulto2b(num_blocks, cdb->length);
301 		cdb->control = control;
302 
303 		ctsio->cdb_len = sizeof(*cdb);
304 	} else if ((minimum_cdb_size < 16)
305 		&& ((num_blocks & 0xffffffff) == num_blocks)
306 		&& ((lba & 0xffffffff) == lba)) {
307 		struct scsi_rw_12 *cdb;
308 
309 		cdb = (struct scsi_rw_12 *)ctsio->cdb;
310 
311 		cdb->opcode = (read_op) ? READ_12 : WRITE_12;
312 		cdb->byte2 = byte2;
313 		scsi_ulto4b(lba, cdb->addr);
314 		scsi_ulto4b(num_blocks, cdb->length);
315 		cdb->reserved = 0;
316 		cdb->control = control;
317 
318 		ctsio->cdb_len = sizeof(*cdb);
319 	} else {
320 		struct scsi_rw_16 *cdb;
321 
322 		cdb = (struct scsi_rw_16 *)ctsio->cdb;
323 
324 		cdb->opcode = (read_op) ? READ_16 : WRITE_16;
325 		cdb->byte2 = byte2;
326 		scsi_u64to8b(lba, cdb->addr);
327 		scsi_ulto4b(num_blocks, cdb->length);
328 		cdb->reserved = 0;
329 		cdb->control = control;
330 
331 		ctsio->cdb_len = sizeof(*cdb);
332 	}
333 
334 	io->io_hdr.io_type = CTL_IO_SCSI;
335 	if (read_op != 0)
336 		io->io_hdr.flags = CTL_FLAG_DATA_IN;
337 	else
338 		io->io_hdr.flags = CTL_FLAG_DATA_OUT;
339 	ctsio->tag_type = tag_type;
340 	ctsio->ext_data_ptr = data_ptr;
341 	ctsio->ext_data_len = data_len;
342 	ctsio->ext_sg_entries = 0;
343 	ctsio->ext_data_filled = 0;
344 	ctsio->sense_len = SSD_FULL_SIZE;
345 }
346 
347 void
348 ctl_scsi_write_same(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
349 		    uint8_t byte2, uint64_t lba, uint32_t num_blocks,
350 		    ctl_tag_type tag_type, uint8_t control)
351 {
352 	struct ctl_scsiio *ctsio;
353 	struct scsi_write_same_16 *cdb;
354 
355 	ctl_scsi_zero_io(io);
356 
357 	io->io_hdr.io_type = CTL_IO_SCSI;
358 	ctsio = &io->scsiio;
359 	ctsio->cdb_len = sizeof(*cdb);
360 	cdb = (struct scsi_write_same_16 *)ctsio->cdb;
361 	cdb->opcode = WRITE_SAME_16;
362 	cdb->byte2 = byte2;
363 	scsi_u64to8b(lba, cdb->addr);
364 	scsi_ulto4b(num_blocks, cdb->length);
365 	cdb->group = 0;
366 	cdb->control = control;
367 
368 	io->io_hdr.io_type = CTL_IO_SCSI;
369 	io->io_hdr.flags = CTL_FLAG_DATA_OUT;
370 	ctsio->tag_type = tag_type;
371 	ctsio->ext_data_ptr = data_ptr;
372 	ctsio->ext_data_len = data_len;
373 	ctsio->ext_sg_entries = 0;
374 	ctsio->ext_data_filled = 0;
375 	ctsio->sense_len = SSD_FULL_SIZE;
376 }
377 
378 void
379 ctl_scsi_read_capacity(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
380 		       uint32_t addr, int reladr, int pmi,
381 		       ctl_tag_type tag_type, uint8_t control)
382 {
383 	struct scsi_read_capacity *cdb;
384 
385 	ctl_scsi_zero_io(io);
386 
387 	io->io_hdr.io_type = CTL_IO_SCSI;
388 	cdb = (struct scsi_read_capacity *)io->scsiio.cdb;
389 
390 	cdb->opcode = READ_CAPACITY;
391 	if (reladr)
392 		cdb->byte2 = SRC_RELADR;
393 	if (pmi)
394 		cdb->pmi = SRC_PMI;
395 	scsi_ulto4b(addr, cdb->addr);
396 	cdb->control = control;
397 	io->io_hdr.io_type = CTL_IO_SCSI;
398 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
399 	io->scsiio.tag_type = tag_type;
400 	io->scsiio.ext_data_ptr = data_ptr;
401 	io->scsiio.ext_data_len = data_len;
402 	io->scsiio.ext_sg_entries = 0;
403 	io->scsiio.ext_data_filled = 0;
404 	io->scsiio.sense_len = SSD_FULL_SIZE;
405 }
406 
407 void
408 ctl_scsi_read_capacity_16(union ctl_io *io, uint8_t *data_ptr,
409 			  uint32_t data_len, uint64_t addr, int reladr,
410 			  int pmi, ctl_tag_type tag_type, uint8_t control)
411 {
412 	struct scsi_read_capacity_16 *cdb;
413 
414 	ctl_scsi_zero_io(io);
415 
416 	io->io_hdr.io_type = CTL_IO_SCSI;
417 	cdb = (struct scsi_read_capacity_16 *)io->scsiio.cdb;
418 
419 	cdb->opcode = SERVICE_ACTION_IN;
420 	cdb->service_action = SRC16_SERVICE_ACTION;
421 	if (reladr)
422 		cdb->reladr |= SRC16_RELADR;
423 	if (pmi)
424 		cdb->reladr |= SRC16_PMI;
425 	scsi_u64to8b(addr, cdb->addr);
426 	scsi_ulto4b(data_len, cdb->alloc_len);
427 	cdb->control = control;
428 
429 	io->io_hdr.io_type = CTL_IO_SCSI;
430 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
431 	io->scsiio.tag_type = tag_type;
432 	io->scsiio.ext_data_ptr = data_ptr;
433 	io->scsiio.ext_data_len = data_len;
434 	io->scsiio.ext_sg_entries = 0;
435 	io->scsiio.ext_data_filled = 0;
436 	io->scsiio.sense_len = SSD_FULL_SIZE;
437 }
438 
439 void
440 ctl_scsi_mode_sense(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
441 		    int dbd, int llbaa, uint8_t page_code, uint8_t pc,
442 		    uint8_t subpage, int minimum_cdb_size,
443 		    ctl_tag_type tag_type, uint8_t control)
444 {
445 	ctl_scsi_zero_io(io);
446 
447 	if ((minimum_cdb_size < 10)
448 	 && (llbaa == 0)
449 	 && (data_len < 256)) {
450 		struct scsi_mode_sense_6 *cdb;
451 
452 		cdb = (struct scsi_mode_sense_6 *)io->scsiio.cdb;
453 
454 		cdb->opcode = MODE_SENSE_6;
455 		if (dbd)
456 			cdb->byte2 |= SMS_DBD;
457 		cdb->page = page_code | pc;
458 		cdb->subpage = subpage;
459 		cdb->length = data_len;
460 		cdb->control = control;
461 	} else {
462 		struct scsi_mode_sense_10 *cdb;
463 
464 		cdb = (struct scsi_mode_sense_10 *)io->scsiio.cdb;
465 
466 		cdb->opcode = MODE_SENSE_10;
467 		if (dbd)
468 			cdb->byte2 |= SMS_DBD;
469 		if (llbaa)
470 			cdb->byte2 |= SMS10_LLBAA;
471 		cdb->page = page_code | pc;
472 		cdb->subpage = subpage;
473 		scsi_ulto2b(data_len, cdb->length);
474 		cdb->control = control;
475 	}
476 
477 	io->io_hdr.io_type = CTL_IO_SCSI;
478 	io->io_hdr.flags = CTL_FLAG_DATA_IN;
479 	io->scsiio.tag_type = tag_type;
480 	io->scsiio.ext_data_ptr = data_ptr;
481 	io->scsiio.ext_data_len = data_len;
482 	io->scsiio.ext_sg_entries = 0;
483 	io->scsiio.ext_data_filled = 0;
484 	io->scsiio.sense_len = SSD_FULL_SIZE;
485 }
486 
487 void
488 ctl_scsi_start_stop(union ctl_io *io, int start, int load_eject, int immediate,
489 		    int power_conditions, int onoffline __unused,
490 		    ctl_tag_type tag_type, uint8_t control)
491 {
492 	struct scsi_start_stop_unit *cdb;
493 
494 	cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
495 
496 	ctl_scsi_zero_io(io);
497 
498 	cdb->opcode = START_STOP_UNIT;
499 	if (immediate)
500 		cdb->byte2 |= SSS_IMMED;
501 #ifdef NEEDTOPORT
502 	if (onoffline)
503 		cdb->byte2 |= SSS_ONOFFLINE;
504 #endif
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(struct ctl_id 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 #endif /* !_KERNEL */
703 void
704 ctl_scsi_zero_io(union ctl_io *io)
705 {
706 	void *pool_ref;
707 
708 	if (io == NULL)
709 		return;
710 
711 	pool_ref = io->io_hdr.pool;
712 
713 	memset(io, 0, sizeof(*io));
714 
715 	io->io_hdr.pool = pool_ref;
716 }
717 
718 const char *
719 ctl_scsi_task_string(struct ctl_taskio *taskio)
720 {
721 	unsigned int i;
722 
723 	for (i = 0; i < (sizeof(ctl_task_table)/sizeof(ctl_task_table[0]));
724 	     i++) {
725 		if (taskio->task_action == ctl_task_table[i].task_action) {
726 			return (ctl_task_table[i].description);
727 		}
728 	}
729 
730 	return (NULL);
731 }
732 
733 void
734 ctl_io_sbuf(union ctl_io *io, struct sbuf *sb)
735 {
736 	const char *task_desc;
737 	char path_str[64];
738 
739 	ctl_scsi_path_string(io, path_str, sizeof(path_str));
740 
741 	switch (io->io_hdr.io_type) {
742 	case CTL_IO_SCSI:
743 		sbuf_cat(sb, path_str);
744 		ctl_scsi_command_string(&io->scsiio, NULL, sb);
745 		sbuf_printf(sb, " Tag: %#x/%d\n",
746 			    io->scsiio.tag_num, io->scsiio.tag_type);
747 		break;
748 	case CTL_IO_TASK:
749 		sbuf_cat(sb, path_str);
750 		task_desc = ctl_scsi_task_string(&io->taskio);
751 		if (task_desc == NULL)
752 			sbuf_printf(sb, "Unknown Task Action %d (%#x)",
753 			    io->taskio.task_action, io->taskio.task_action);
754 		else
755 			sbuf_printf(sb, "Task Action: %s", task_desc);
756 		switch (io->taskio.task_action) {
757 		case CTL_TASK_ABORT_TASK:
758 			sbuf_printf(sb, " Tag: %#x/%d\n",
759 			    io->taskio.tag_num, io->taskio.tag_type);
760 			break;
761 		default:
762 			sbuf_printf(sb, "\n");
763 			break;
764 		}
765 		break;
766 	default:
767 		break;
768 	}
769 }
770 
771 void
772 ctl_io_error_sbuf(union ctl_io *io, struct scsi_inquiry_data *inq_data,
773 		  struct sbuf *sb)
774 {
775 	struct ctl_status_desc *status_desc;
776 	char path_str[64];
777 	unsigned int i;
778 
779 	ctl_io_sbuf(io, sb);
780 
781 	status_desc = NULL;
782 	for (i = 0; i < (sizeof(ctl_status_table)/sizeof(ctl_status_table[0]));
783 	     i++) {
784 		if ((io->io_hdr.status & CTL_STATUS_MASK) ==
785 		     ctl_status_table[i].status) {
786 			status_desc = &ctl_status_table[i];
787 			break;
788 		}
789 	}
790 
791 	ctl_scsi_path_string(io, path_str, sizeof(path_str));
792 
793 	sbuf_cat(sb, path_str);
794 	if (status_desc == NULL)
795 		sbuf_printf(sb, "CTL Status: Unknown status %#x\n",
796 			    io->io_hdr.status);
797 	else
798 		sbuf_printf(sb, "CTL Status: %s\n", status_desc->description);
799 
800 	if ((io->io_hdr.io_type == CTL_IO_SCSI)
801 	 && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR)) {
802 		sbuf_cat(sb, path_str);
803 		sbuf_printf(sb, "SCSI Status: %s\n",
804 			    ctl_scsi_status_string(&io->scsiio));
805 
806 		if (io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND)
807 			ctl_scsi_sense_sbuf(&io->scsiio, inq_data,
808 					    sb, SSS_FLAG_NONE);
809 	}
810 }
811 
812 char *
813 ctl_io_string(union ctl_io *io, char *str, int str_len)
814 {
815 	struct sbuf sb;
816 
817 	sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
818 	ctl_io_sbuf(io, &sb);
819 	sbuf_finish(&sb);
820 	return (sbuf_data(&sb));
821 }
822 
823 char *
824 ctl_io_error_string(union ctl_io *io, struct scsi_inquiry_data *inq_data,
825 		    char *str, int str_len)
826 {
827 	struct sbuf sb;
828 
829 	sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
830 	ctl_io_error_sbuf(io, inq_data, &sb);
831 	sbuf_finish(&sb);
832 	return (sbuf_data(&sb));
833 }
834 
835 #ifdef _KERNEL
836 
837 void
838 ctl_io_print(union ctl_io *io)
839 {
840 	char str[512];
841 
842 	printf("%s", ctl_io_string(io, str, sizeof(str)));
843 }
844 
845 void
846 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data)
847 {
848 	char str[512];
849 #ifdef NEEDTOPORT
850 	char *message;
851 	char *line;
852 
853 	message = io_error_string(io, inq_data, str, sizeof(str));
854 
855 	for (line = strsep(&message, "\n"); line != NULL;
856 	     line = strsep(&message, "\n")) {
857 		csevent_log(CSC_CTL | CSC_SHELF_SW | CTL_ERROR_REPORT,
858                             csevent_LogType_Trace,
859                             csevent_Severity_Information,
860                             csevent_AlertLevel_Green,
861                             csevent_FRU_Firmware,
862                             csevent_FRU_Unknown, "%s", line);
863 	}
864 #else
865 	printf("%s", ctl_io_error_string(io, inq_data, str, sizeof(str)));
866 #endif
867 
868 }
869 
870 void
871 ctl_data_print(union ctl_io *io)
872 {
873 	char str[128];
874 	char path_str[64];
875 	struct sbuf sb;
876 	int i, j, len;
877 
878 	if (io->io_hdr.io_type != CTL_IO_SCSI)
879 		return;
880 	if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
881 		return;
882 	if (io->io_hdr.flags & CTL_FLAG_EDPTR_SGLIST)	/* XXX: Implement */
883 		return;
884 	ctl_scsi_path_string(io, path_str, sizeof(path_str));
885 	len = min(io->scsiio.kern_data_len, 4096);
886 	for (i = 0; i < len; ) {
887 		sbuf_new(&sb, str, sizeof(str), SBUF_FIXEDLEN);
888 		sbuf_cat(&sb, path_str);
889 		sbuf_printf(&sb, " %#6x:%04x:", io->scsiio.tag_num, i);
890 		for (j = 0; j < 16 && i < len; i++, j++) {
891 			if (j == 8)
892 				sbuf_cat(&sb, " ");
893 			sbuf_printf(&sb, " %02x", io->scsiio.kern_data_ptr[i]);
894 		}
895 		sbuf_cat(&sb, "\n");
896 		sbuf_finish(&sb);
897 		printf("%s", sbuf_data(&sb));
898 	}
899 }
900 
901 #else /* _KERNEL */
902 
903 void
904 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data,
905 		   FILE *ofile)
906 {
907 	char str[512];
908 
909 	fprintf(ofile, "%s", ctl_io_error_string(io, inq_data, str,
910 		sizeof(str)));
911 }
912 
913 #endif /* _KERNEL */
914 
915 /*
916  * vim: ts=8
917  */
918