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