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