1229997Sken/*-
2229997Sken * Implementation of Utility functions for all SCSI device types.
3229997Sken *
4229997Sken * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
5229997Sken * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry.
6229997Sken * All rights reserved.
7229997Sken *
8229997Sken * Redistribution and use in source and binary forms, with or without
9229997Sken * modification, are permitted provided that the following conditions
10229997Sken * are met:
11229997Sken * 1. Redistributions of source code must retain the above copyright
12229997Sken *    notice, this list of conditions, and the following disclaimer,
13229997Sken *    without modification, immediately at the beginning of the file.
14229997Sken * 2. The name of the author may not be used to endorse or promote products
15229997Sken *    derived from this software without specific prior written permission.
16229997Sken *
17229997Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18229997Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19229997Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20229997Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21229997Sken * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25229997Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26229997Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27229997Sken * SUCH DAMAGE.
28229997Sken *
29229997Sken * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_scsi_all.c#2 $
30229997Sken */
31229997Sken
32229997Sken#include <sys/param.h>
33229997Sken
34229997Sken__FBSDID("$FreeBSD$");
35229997Sken
36229997Sken#include <sys/types.h>
37229997Sken#ifdef _KERNEL
38229997Sken#include <sys/systm.h>
39229997Sken#include <sys/libkern.h>
40229997Sken#include <sys/kernel.h>
41229997Sken#include <sys/sysctl.h>
42229997Sken#else
43229997Sken#include <errno.h>
44229997Sken#include <stdio.h>
45229997Sken#include <stdlib.h>
46229997Sken#include <string.h>
47229997Sken#include <inttypes.h>
48229997Sken#endif
49229997Sken
50229997Sken#include <cam/cam.h>
51229997Sken#include <cam/cam_ccb.h>
52229997Sken#include <cam/cam_queue.h>
53229997Sken#include <cam/cam_xpt.h>
54229997Sken#include <cam/scsi/scsi_all.h>
55229997Sken
56229997Sken#include <cam/ctl/ctl_io.h>
57229997Sken#include <cam/ctl/ctl_scsi_all.h>
58229997Sken#include <sys/sbuf.h>
59229997Sken#ifndef _KERNEL
60229997Sken#include <camlib.h>
61229997Sken#endif
62229997Sken
63229997Skenconst char *
64229997Skenctl_scsi_status_string(struct ctl_scsiio *ctsio)
65229997Sken{
66229997Sken	switch(ctsio->scsi_status) {
67229997Sken	case SCSI_STATUS_OK:
68229997Sken		return("OK");
69229997Sken	case SCSI_STATUS_CHECK_COND:
70229997Sken		return("Check Condition");
71229997Sken	case SCSI_STATUS_BUSY:
72229997Sken		return("Busy");
73229997Sken	case SCSI_STATUS_INTERMED:
74229997Sken		return("Intermediate");
75229997Sken	case SCSI_STATUS_INTERMED_COND_MET:
76229997Sken		return("Intermediate-Condition Met");
77229997Sken	case SCSI_STATUS_RESERV_CONFLICT:
78229997Sken		return("Reservation Conflict");
79229997Sken	case SCSI_STATUS_CMD_TERMINATED:
80229997Sken		return("Command Terminated");
81229997Sken	case SCSI_STATUS_QUEUE_FULL:
82229997Sken		return("Queue Full");
83229997Sken	case SCSI_STATUS_ACA_ACTIVE:
84229997Sken		return("ACA Active");
85229997Sken	case SCSI_STATUS_TASK_ABORTED:
86229997Sken		return("Task Aborted");
87229997Sken	default: {
88229997Sken		static char unkstr[64];
89229997Sken		snprintf(unkstr, sizeof(unkstr), "Unknown %#x",
90229997Sken			 ctsio->scsi_status);
91229997Sken		return(unkstr);
92229997Sken	}
93229997Sken	}
94229997Sken}
95229997Sken
96229997Sken/*
97229997Sken * scsi_command_string() returns 0 for success and -1 for failure.
98229997Sken */
99229997Skenint
100229997Skenctl_scsi_command_string(struct ctl_scsiio *ctsio,
101229997Sken			struct scsi_inquiry_data *inq_data, struct sbuf *sb)
102229997Sken{
103229997Sken	char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
104229997Sken
105229997Sken	sbuf_printf(sb, "%s. CDB: %s",
106229997Sken		    scsi_op_desc(ctsio->cdb[0], inq_data),
107229997Sken		    scsi_cdb_string(ctsio->cdb, cdb_str, sizeof(cdb_str)));
108229997Sken
109229997Sken	return(0);
110229997Sken}
111229997Sken
112229997Skenvoid
113229997Skenctl_scsi_path_string(union ctl_io *io, char *path_str, int len)
114229997Sken{
115229997Sken	if (io->io_hdr.nexus.targ_target.wwid[0] == 0) {
116229997Sken		snprintf(path_str, len, "(%ju:%d:%ju:%d): ",
117229997Sken			 (uintmax_t)io->io_hdr.nexus.initid.id,
118229997Sken			 io->io_hdr.nexus.targ_port,
119229997Sken			 (uintmax_t)io->io_hdr.nexus.targ_target.id,
120229997Sken			 io->io_hdr.nexus.targ_lun);
121229997Sken	} else {
122229997Sken		/*
123229997Sken		 * XXX KDM find a better way to display FC WWIDs.
124229997Sken		 */
125229997Sken#ifdef _KERNEL
126229997Sken		snprintf(path_str, len, "(%ju:%d:%#jx,%#jx:%d): ",
127229997Sken			 (uintmax_t)io->io_hdr.nexus.initid.id,
128229997Sken			 io->io_hdr.nexus.targ_port,
129229997Sken			 (intmax_t)io->io_hdr.nexus.targ_target.wwid[0],
130229997Sken			 (intmax_t)io->io_hdr.nexus.targ_target.wwid[1],
131229997Sken			 io->io_hdr.nexus.targ_lun);
132229997Sken#else /* _KERNEL */
133229997Sken		snprintf(path_str, len, "(%ju:%d:%#jx,%#jx:%d): ",
134229997Sken			 (uintmax_t)io->io_hdr.nexus.initid.id,
135229997Sken			 io->io_hdr.nexus.targ_port,
136229997Sken			 (intmax_t)io->io_hdr.nexus.targ_target.wwid[0],
137229997Sken			 (intmax_t)io->io_hdr.nexus.targ_target.wwid[1],
138229997Sken			 io->io_hdr.nexus.targ_lun);
139229997Sken#endif /* _KERNEL */
140229997Sken	}
141229997Sken}
142229997Sken
143229997Sken/*
144229997Sken * ctl_scsi_sense_sbuf() returns 0 for success and -1 for failure.
145229997Sken */
146229997Skenint
147229997Skenctl_scsi_sense_sbuf(struct ctl_scsiio *ctsio,
148229997Sken		    struct scsi_inquiry_data *inq_data, struct sbuf *sb,
149229997Sken		    scsi_sense_string_flags flags)
150229997Sken{
151229997Sken	char	  path_str[64];
152229997Sken
153229997Sken	if ((ctsio == NULL) || (sb == NULL))
154229997Sken		return(-1);
155229997Sken
156229997Sken	ctl_scsi_path_string((union ctl_io *)ctsio, path_str, sizeof(path_str));
157229997Sken
158229997Sken	if (flags & SSS_FLAG_PRINT_COMMAND) {
159229997Sken
160229997Sken		sbuf_cat(sb, path_str);
161229997Sken
162229997Sken		ctl_scsi_command_string(ctsio, inq_data, sb);
163229997Sken
164229997Sken		sbuf_printf(sb, "\n");
165229997Sken	}
166229997Sken
167229997Sken	scsi_sense_only_sbuf(&ctsio->sense_data, ctsio->sense_len, sb,
168229997Sken			     path_str, inq_data, ctsio->cdb, ctsio->cdb_len);
169229997Sken
170229997Sken	return(0);
171229997Sken}
172229997Sken
173229997Skenchar *
174229997Skenctl_scsi_sense_string(struct ctl_scsiio *ctsio,
175229997Sken		      struct scsi_inquiry_data *inq_data, char *str,
176229997Sken		      int str_len)
177229997Sken{
178229997Sken	struct sbuf sb;
179229997Sken
180229997Sken	sbuf_new(&sb, str, str_len, 0);
181229997Sken
182229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
183229997Sken
184229997Sken	sbuf_finish(&sb);
185229997Sken
186229997Sken	return(sbuf_data(&sb));
187229997Sken}
188229997Sken
189229997Sken#ifdef _KERNEL
190229997Skenvoid
191229997Skenctl_scsi_sense_print(struct ctl_scsiio *ctsio,
192229997Sken		     struct scsi_inquiry_data *inq_data)
193229997Sken{
194229997Sken	struct sbuf sb;
195229997Sken	char str[512];
196229997Sken
197229997Sken	sbuf_new(&sb, str, sizeof(str), 0);
198229997Sken
199229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
200229997Sken
201229997Sken	sbuf_finish(&sb);
202229997Sken
203229997Sken	printf("%s", sbuf_data(&sb));
204229997Sken}
205229997Sken
206229997Sken#else /* _KERNEL */
207229997Skenvoid
208229997Skenctl_scsi_sense_print(struct ctl_scsiio *ctsio,
209229997Sken		     struct scsi_inquiry_data *inq_data, FILE *ofile)
210229997Sken{
211229997Sken	struct sbuf sb;
212229997Sken	char str[512];
213229997Sken
214229997Sken	if ((ctsio == NULL) || (ofile == NULL))
215229997Sken		return;
216229997Sken
217229997Sken	sbuf_new(&sb, str, sizeof(str), 0);
218229997Sken
219229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
220229997Sken
221229997Sken	sbuf_finish(&sb);
222229997Sken
223229997Sken	fprintf(ofile, "%s", sbuf_data(&sb));
224229997Sken}
225229997Sken
226229997Sken#endif /* _KERNEL */
227229997Sken
228