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