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
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_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
94void
95ctl_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
118void
119ctl_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
148void
149ctl_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
177void
178ctl_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
206void
207ctl_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
245void
246ctl_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
346void
347ctl_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
375void
376ctl_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
407void
408ctl_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
455void
456ctl_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
489void
490ctl_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
540void
541ctl_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
566void
567ctl_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
624void
625ctl_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
649union ctl_io *
650ctl_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
660bailout:
661	return (io);
662}
663
664void
665ctl_scsi_free_io(union ctl_io *io)
666{
667	free(io);
668}
669
670#endif /* !_KERNEL */
671void
672ctl_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
686const char *
687ctl_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
701void
702ctl_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
785char *
786ctl_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
802void
803ctl_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
829void
830ctl_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