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{
115273163Smav
116273163Smav	snprintf(path_str, len, "(%u:%u:%u/%u): ",
117287620Smav	    io->io_hdr.nexus.initid, io->io_hdr.nexus.targ_port,
118273163Smav	    io->io_hdr.nexus.targ_lun, io->io_hdr.nexus.targ_mapped_lun);
119229997Sken}
120229997Sken
121229997Sken/*
122229997Sken * ctl_scsi_sense_sbuf() returns 0 for success and -1 for failure.
123229997Sken */
124229997Skenint
125229997Skenctl_scsi_sense_sbuf(struct ctl_scsiio *ctsio,
126229997Sken		    struct scsi_inquiry_data *inq_data, struct sbuf *sb,
127229997Sken		    scsi_sense_string_flags flags)
128229997Sken{
129229997Sken	char	  path_str[64];
130229997Sken
131229997Sken	if ((ctsio == NULL) || (sb == NULL))
132229997Sken		return(-1);
133229997Sken
134229997Sken	ctl_scsi_path_string((union ctl_io *)ctsio, path_str, sizeof(path_str));
135229997Sken
136229997Sken	if (flags & SSS_FLAG_PRINT_COMMAND) {
137229997Sken
138229997Sken		sbuf_cat(sb, path_str);
139229997Sken
140229997Sken		ctl_scsi_command_string(ctsio, inq_data, sb);
141229997Sken
142229997Sken		sbuf_printf(sb, "\n");
143229997Sken	}
144229997Sken
145229997Sken	scsi_sense_only_sbuf(&ctsio->sense_data, ctsio->sense_len, sb,
146229997Sken			     path_str, inq_data, ctsio->cdb, ctsio->cdb_len);
147229997Sken
148229997Sken	return(0);
149229997Sken}
150229997Sken
151229997Skenchar *
152229997Skenctl_scsi_sense_string(struct ctl_scsiio *ctsio,
153229997Sken		      struct scsi_inquiry_data *inq_data, char *str,
154229997Sken		      int str_len)
155229997Sken{
156229997Sken	struct sbuf sb;
157229997Sken
158229997Sken	sbuf_new(&sb, str, str_len, 0);
159229997Sken
160229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
161229997Sken
162229997Sken	sbuf_finish(&sb);
163229997Sken
164229997Sken	return(sbuf_data(&sb));
165229997Sken}
166229997Sken
167229997Sken#ifdef _KERNEL
168229997Skenvoid
169229997Skenctl_scsi_sense_print(struct ctl_scsiio *ctsio,
170229997Sken		     struct scsi_inquiry_data *inq_data)
171229997Sken{
172229997Sken	struct sbuf sb;
173229997Sken	char str[512];
174229997Sken
175229997Sken	sbuf_new(&sb, str, sizeof(str), 0);
176229997Sken
177229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
178229997Sken
179229997Sken	sbuf_finish(&sb);
180229997Sken
181229997Sken	printf("%s", sbuf_data(&sb));
182229997Sken}
183229997Sken
184229997Sken#else /* _KERNEL */
185229997Skenvoid
186229997Skenctl_scsi_sense_print(struct ctl_scsiio *ctsio,
187229997Sken		     struct scsi_inquiry_data *inq_data, FILE *ofile)
188229997Sken{
189229997Sken	struct sbuf sb;
190229997Sken	char str[512];
191229997Sken
192229997Sken	if ((ctsio == NULL) || (ofile == NULL))
193229997Sken		return;
194229997Sken
195229997Sken	sbuf_new(&sb, str, sizeof(str), 0);
196229997Sken
197229997Sken	ctl_scsi_sense_sbuf(ctsio, inq_data, &sb, SSS_FLAG_PRINT_COMMAND);
198229997Sken
199229997Sken	sbuf_finish(&sb);
200229997Sken
201229997Sken	fprintf(ofile, "%s", sbuf_data(&sb));
202229997Sken}
203229997Sken
204229997Sken#endif /* _KERNEL */
205229997Sken
206