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