• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1999-2018 Douglas Gilbert.
3  * All rights reserved.
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the BSD_LICENSE file.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <stdbool.h>
12 #include <string.h>
13 #include <ctype.h>
14 
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #ifdef SG_LIB_LINUX
20 
21 #include "sg_io_linux.h"
22 
23 
24 /* Version 1.07 20160405 */
25 
26 #if defined(__GNUC__) || defined(__clang__)
27 static int pr2ws(const char * fmt, ...)
28         __attribute__ ((format (printf, 1, 2)));
29 #else
30 static int pr2ws(const char * fmt, ...);
31 #endif
32 
33 
34 static int
pr2ws(const char * fmt,...)35 pr2ws(const char * fmt, ...)
36 {
37     va_list args;
38     int n;
39 
40     va_start(args, fmt);
41     n = vfprintf(sg_warnings_strm ? sg_warnings_strm : stderr, fmt, args);
42     va_end(args);
43     return n;
44 }
45 
46 
47 void
sg_print_masked_status(int masked_status)48 sg_print_masked_status(int masked_status)
49 {
50     int scsi_status = (masked_status << 1) & 0x7e;
51 
52     sg_print_scsi_status(scsi_status);
53 }
54 
55 static const char * linux_host_bytes[] = {
56     "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
57     "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR",
58     "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR",
59     "DID_IMM_RETRY", "DID_REQUEUE", "DID_TRANSPORT_DISRUPTED",
60     "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE", "DID_NEXUS_FAILURE",
61     "DID_ALLOC_FAILURE", "DID_MEDIUM_ERROR",
62 };
63 
64 #define LINUX_HOST_BYTES_SZ \
65         (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0]))
66 
67 void
sg_print_host_status(int host_status)68 sg_print_host_status(int host_status)
69 {
70     pr2ws("Host_status=0x%02x ", host_status);
71     if ((host_status < 0) || (host_status >= LINUX_HOST_BYTES_SZ))
72         pr2ws("is invalid ");
73     else
74         pr2ws("[%s] ", linux_host_bytes[host_status]);
75 }
76 
77 static const char * linux_driver_bytes[] = {
78     "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA",
79     "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",
80     "DRIVER_SENSE"
81 };
82 
83 #define LINUX_DRIVER_BYTES_SZ \
84     (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0]))
85 
86 #if 0
87 static const char * linux_driver_suggests[] = {
88     "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP",
89     "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN",
90     "SUGGEST_SENSE"
91 };
92 
93 #define LINUX_DRIVER_SUGGESTS_SZ \
94     (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0]))
95 #endif
96 
97 
98 void
sg_print_driver_status(int driver_status)99 sg_print_driver_status(int driver_status)
100 {
101     int driv;
102     const char * driv_cp = "invalid";
103 
104     driv = driver_status & SG_LIB_DRIVER_MASK;
105     if (driv < LINUX_DRIVER_BYTES_SZ)
106         driv_cp = linux_driver_bytes[driv];
107 #if 0
108     sugg = (driver_status & SG_LIB_SUGGEST_MASK) >> 4;
109     if (sugg < LINUX_DRIVER_SUGGESTS_SZ)
110         sugg_cp = linux_driver_suggests[sugg];
111 #endif
112     pr2ws("Driver_status=0x%02x", driver_status);
113     pr2ws(" [%s] ", driv_cp);
114 }
115 
116 /* Returns 1 if no errors found and thus nothing printed; otherwise
117    prints error/warning (prefix by 'leadin') and returns 0. */
118 static int
sg_linux_sense_print(const char * leadin,int scsi_status,int host_status,int driver_status,const unsigned char * sense_buffer,int sb_len,bool raw_sinfo)119 sg_linux_sense_print(const char * leadin, int scsi_status, int host_status,
120                      int driver_status, const unsigned char * sense_buffer,
121                      int sb_len, bool raw_sinfo)
122 {
123     bool done_leadin = false;
124     bool done_sense = false;
125 
126     scsi_status &= 0x7e; /*sanity */
127     if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
128         return 1;       /* No problems */
129     if (0 != scsi_status) {
130         if (leadin)
131             pr2ws("%s: ", leadin);
132         done_leadin = true;
133         pr2ws("SCSI status: ");
134         sg_print_scsi_status(scsi_status);
135         pr2ws("\n");
136         if (sense_buffer && ((scsi_status == SAM_STAT_CHECK_CONDITION) ||
137                              (scsi_status == SAM_STAT_COMMAND_TERMINATED))) {
138             /* SAM_STAT_COMMAND_TERMINATED is obsolete */
139             sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
140             done_sense = true;
141         }
142     }
143     if (0 != host_status) {
144         if (leadin && (! done_leadin))
145             pr2ws("%s: ", leadin);
146         if (done_leadin)
147             pr2ws("plus...: ");
148         else
149             done_leadin = true;
150         sg_print_host_status(host_status);
151         pr2ws("\n");
152     }
153     if (0 != driver_status) {
154         if (done_sense &&
155             (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status)))
156             return 0;
157         if (leadin && (! done_leadin))
158             pr2ws("%s: ", leadin);
159         if (done_leadin)
160             pr2ws("plus...: ");
161         sg_print_driver_status(driver_status);
162         pr2ws("\n");
163         if (sense_buffer && (! done_sense) &&
164             (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status)))
165             sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
166     }
167     return 0;
168 }
169 
170 #ifdef SG_IO
171 
172 bool
sg_normalize_sense(const struct sg_io_hdr * hp,struct sg_scsi_sense_hdr * sshp)173 sg_normalize_sense(const struct sg_io_hdr * hp,
174                    struct sg_scsi_sense_hdr * sshp)
175 {
176     if ((NULL == hp) || (0 == hp->sb_len_wr)) {
177         if (sshp)
178             memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
179         return 0;
180     }
181     return sg_scsi_normalize_sense(hp->sbp, hp->sb_len_wr, sshp);
182 }
183 
184 /* Returns 1 if no errors found and thus nothing printed; otherwise
185    returns 0. */
186 int
sg_chk_n_print3(const char * leadin,struct sg_io_hdr * hp,bool raw_sinfo)187 sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp,
188                 bool raw_sinfo)
189 {
190     return sg_linux_sense_print(leadin, hp->status, hp->host_status,
191                                 hp->driver_status, hp->sbp, hp->sb_len_wr,
192                                 raw_sinfo);
193 }
194 #endif
195 
196 /* Returns 1 if no errors found and thus nothing printed; otherwise
197    returns 0. */
198 int
sg_chk_n_print(const char * leadin,int masked_status,int host_status,int driver_status,const unsigned char * sense_buffer,int sb_len,bool raw_sinfo)199 sg_chk_n_print(const char * leadin, int masked_status, int host_status,
200                int driver_status, const unsigned char * sense_buffer,
201                int sb_len, bool raw_sinfo)
202 {
203     int scsi_status = (masked_status << 1) & 0x7e;
204 
205     return sg_linux_sense_print(leadin, scsi_status, host_status,
206                                 driver_status, sense_buffer, sb_len,
207                                 raw_sinfo);
208 }
209 
210 #ifdef SG_IO
211 int
sg_err_category3(struct sg_io_hdr * hp)212 sg_err_category3(struct sg_io_hdr * hp)
213 {
214     return sg_err_category_new(hp->status, hp->host_status,
215                                hp->driver_status, hp->sbp, hp->sb_len_wr);
216 }
217 #endif
218 
219 int
sg_err_category(int masked_status,int host_status,int driver_status,const unsigned char * sense_buffer,int sb_len)220 sg_err_category(int masked_status, int host_status, int driver_status,
221                 const unsigned char * sense_buffer, int sb_len)
222 {
223     int scsi_status = (masked_status << 1) & 0x7e;
224 
225     return sg_err_category_new(scsi_status, host_status, driver_status,
226                                sense_buffer, sb_len);
227 }
228 
229 int
sg_err_category_new(int scsi_status,int host_status,int driver_status,const unsigned char * sense_buffer,int sb_len)230 sg_err_category_new(int scsi_status, int host_status, int driver_status,
231                     const unsigned char * sense_buffer, int sb_len)
232 {
233     int masked_driver_status = (SG_LIB_DRIVER_MASK & driver_status);
234 
235     scsi_status &= 0x7e;
236     if ((0 == scsi_status) && (0 == host_status) &&
237         (0 == masked_driver_status))
238         return SG_LIB_CAT_CLEAN;
239     if ((SAM_STAT_CHECK_CONDITION == scsi_status) ||
240         (SAM_STAT_COMMAND_TERMINATED == scsi_status) ||
241         (SG_LIB_DRIVER_SENSE == masked_driver_status))
242         return sg_err_category_sense(sense_buffer, sb_len);
243     if (0 != host_status) {
244         if ((SG_LIB_DID_NO_CONNECT == host_status) ||
245             (SG_LIB_DID_BUS_BUSY == host_status) ||
246             (SG_LIB_DID_TIME_OUT == host_status))
247             return SG_LIB_CAT_TIMEOUT;
248         if (SG_LIB_DID_NEXUS_FAILURE == host_status)
249             return SG_LIB_CAT_RES_CONFLICT;
250     }
251     if (SG_LIB_DRIVER_TIMEOUT == masked_driver_status)
252         return SG_LIB_CAT_TIMEOUT;
253     return SG_LIB_CAT_OTHER;
254 }
255 
256 #endif  /* if SG_LIB_LINUX defined */
257