ctl_util.c revision 288731
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: stable/10/sys/cam/ctl/ctl_util.c 288731 2015-10-05 08:55:59Z mav $");
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
63struct ctl_status_desc {
64	ctl_io_status status;
65	const char *description;
66};
67
68struct ctl_task_desc {
69	ctl_task_type	task_action;
70	const char	*description;
71};
72static 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
82static 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
95void
96ctl_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
119void
120ctl_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
149void
150ctl_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
178void
179ctl_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
207void
208ctl_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
246void
247ctl_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
347void
348ctl_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
378void
379ctl_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
407void
408ctl_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
439void
440ctl_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
487void
488ctl_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
521void
522ctl_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
572void
573ctl_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
598void
599ctl_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
656void
657ctl_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
681union ctl_io *
682ctl_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
692bailout:
693	return (io);
694}
695
696void
697ctl_scsi_free_io(union ctl_io *io)
698{
699	free(io);
700}
701
702#endif /* !_KERNEL */
703void
704ctl_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
718const char *
719ctl_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
733void
734ctl_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
771void
772ctl_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
812char *
813ctl_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
823char *
824ctl_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
837void
838ctl_io_print(union ctl_io *io)
839{
840	char str[512];
841
842	printf("%s", ctl_io_string(io, str, sizeof(str)));
843}
844
845void
846ctl_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
870void
871ctl_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
903void
904ctl_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