1
2
3
4
5
6
7
8
9
10
11#include <linux/blkdev.h>
12#include <linux/module.h>
13#include <linux/kernel.h>
14
15#include <scsi/scsi.h>
16#include <scsi/scsi_cmnd.h>
17#include <scsi/scsi_device.h>
18#include <scsi/scsi_host.h>
19#include <scsi/scsi_eh.h>
20#include <scsi/scsi_dbg.h>
21
22
23#define THIRD_PARTY_COPY_OUT 0x83
24#define THIRD_PARTY_COPY_IN 0x84
25
26struct sa_name_list {
27 int opcode;
28 const struct value_name_pair *arr;
29 int arr_sz;
30};
31
32struct value_name_pair {
33 int value;
34 const char * name;
35};
36
37static const char * cdb_byte0_names[] = {
38 "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
39 "Format Unit/Medium", "Read Block Limits", NULL,
40 "Reassign Blocks",
41 "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
42 NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
43 "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
44 "Reserve(6)",
45 "Release(6)", "Copy", "Erase", "Mode Sense(6)",
46 "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
47 "Prevent/Allow Medium Removal", NULL,
48 NULL, NULL, NULL,
49 "Read Format Capacities", "Set Window",
50 "Read Capacity(10)", NULL, NULL, "Read(10)",
51 "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
52 "Read updated block",
53 "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
54 "Search Low", "Set Limits", "Prefetch/Read Position",
55 "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
56 "Read Defect Data(10)",
57 "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
58 "Read Buffer",
59 "Update Block", "Read Long(10)", "Write Long(10)",
60 "Change Definition", "Write Same(10)",
61 "Unmap/Read sub-channel", "Read TOC/PMA/ATIP",
62 "Read density support", "Play audio(10)", "Get configuration",
63 "Play audio msf", "Sanitize/Play audio track/index",
64 "Play track relative(10)", "Get event status notification",
65 "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
66 NULL,
67 "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
68 "Reserve track", "Send OPC info", "Mode Select(10)",
69 "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
70 "Mode Sense(10)", "Close track/session",
71 "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
72 "Persistent reserve out",
73 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
74 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
75 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
76 NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB",
77 "Variable length",
78 "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)",
79 "Third party copy out", "Third party copy in",
80 "ATA command pass through(16)", "Access control in",
81 "Access control out", "Read(16)", "Compare and Write",
82 "Write(16)", "ORWrite", "Read attributes", "Write attributes",
83 "Write and verify(16)", "Verify(16)",
84 "Pre-fetch(16)", "Synchronize cache(16)",
85 "Lock/unlock cache(16)", "Write same(16)", NULL,
86 NULL, NULL, NULL, NULL, NULL,
87 NULL, NULL, NULL, "Service action bidirectional",
88 "Service action in(16)", "Service action out(16)",
89 "Report luns", "ATA command pass through(12)/Blank",
90 "Security protocol in", "Maintenance in", "Maintenance out",
91 "Move medium/play audio(12)",
92 "Exchange medium", "Move medium attached", "Read(12)",
93 "Play track relative(12)",
94 "Write(12)", NULL, "Erase(12), Get Performance",
95 "Read DVD structure", "Write and verify(12)",
96 "Verify(12)", "Search data high(12)", "Search data equal(12)",
97 "Search data low(12)", "Set limits(12)",
98 "Read element status attached",
99 "Security protocol out", "Send volume tag, set streaming",
100 "Read defect data(12)", "Read element status", "Read CD msf",
101 "Redundancy group (in), Scan",
102 "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
103 "Spare (out), Mechanism status", "Volume set (in), Read cd",
104 "Volume set (out), Send DVD structure",
105};
106
107static const struct value_name_pair maint_in_arr[] = {
108 {0x5, "Report identifying information"},
109 {0xa, "Report target port groups"},
110 {0xb, "Report aliases"},
111 {0xc, "Report supported operation codes"},
112 {0xd, "Report supported task management functions"},
113 {0xe, "Report priority"},
114 {0xf, "Report timestamp"},
115 {0x10, "Management protocol in"},
116};
117#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
118
119static const struct value_name_pair maint_out_arr[] = {
120 {0x6, "Set identifying information"},
121 {0xa, "Set target port groups"},
122 {0xb, "Change aliases"},
123 {0xc, "Remove I_T nexus"},
124 {0xe, "Set priority"},
125 {0xf, "Set timestamp"},
126 {0x10, "Management protocol out"},
127};
128#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
129
130static const struct value_name_pair serv_in12_arr[] = {
131 {0x1, "Read media serial number"},
132};
133#define SERV_IN12_SZ ARRAY_SIZE(serv_in12_arr)
134
135static const struct value_name_pair serv_out12_arr[] = {
136 {-1, "dummy entry"},
137};
138#define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr)
139
140static const struct value_name_pair serv_bidi_arr[] = {
141 {-1, "dummy entry"},
142};
143#define SERV_BIDI_SZ ARRAY_SIZE(serv_bidi_arr)
144
145static const struct value_name_pair serv_in16_arr[] = {
146 {0x10, "Read capacity(16)"},
147 {0x11, "Read long(16)"},
148 {0x12, "Get LBA status"},
149 {0x13, "Report referrals"},
150};
151#define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
152
153static const struct value_name_pair serv_out16_arr[] = {
154 {0x11, "Write long(16)"},
155 {0x1f, "Notify data transfer device(16)"},
156};
157#define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr)
158
159static const struct value_name_pair pr_in_arr[] = {
160 {0x0, "Persistent reserve in, read keys"},
161 {0x1, "Persistent reserve in, read reservation"},
162 {0x2, "Persistent reserve in, report capabilities"},
163 {0x3, "Persistent reserve in, read full status"},
164};
165#define PR_IN_SZ ARRAY_SIZE(pr_in_arr)
166
167static const struct value_name_pair pr_out_arr[] = {
168 {0x0, "Persistent reserve out, register"},
169 {0x1, "Persistent reserve out, reserve"},
170 {0x2, "Persistent reserve out, release"},
171 {0x3, "Persistent reserve out, clear"},
172 {0x4, "Persistent reserve out, preempt"},
173 {0x5, "Persistent reserve out, preempt and abort"},
174 {0x6, "Persistent reserve out, register and ignore existing key"},
175 {0x7, "Persistent reserve out, register and move"},
176};
177#define PR_OUT_SZ ARRAY_SIZE(pr_out_arr)
178
179
180
181
182static const struct value_name_pair tpc_out_arr[] = {
183 {0x0, "Extended copy(LID1)"},
184 {0x1, "Extended copy(LID4)"},
185 {0x10, "Populate token"},
186 {0x11, "Write using token"},
187 {0x1c, "Copy operation abort"},
188};
189#define TPC_OUT_SZ ARRAY_SIZE(tpc_out_arr)
190
191static const struct value_name_pair tpc_in_arr[] = {
192 {0x0, "Receive copy status(LID1)"},
193 {0x1, "Receive copy data(LID1)"},
194 {0x3, "Receive copy operating parameters"},
195 {0x4, "Receive copy failure details(LID1)"},
196 {0x5, "Receive copy status(LID4)"},
197 {0x6, "Receive copy data(LID4)"},
198 {0x7, "Receive ROD token information"},
199 {0x8, "Report all ROD tokens"},
200};
201#define TPC_IN_SZ ARRAY_SIZE(tpc_in_arr)
202
203
204static const struct value_name_pair variable_length_arr[] = {
205 {0x1, "Rebuild(32)"},
206 {0x2, "Regenerate(32)"},
207 {0x3, "Xdread(32)"},
208 {0x4, "Xdwrite(32)"},
209 {0x5, "Xdwrite extended(32)"},
210 {0x6, "Xpwrite(32)"},
211 {0x7, "Xdwriteread(32)"},
212 {0x8, "Xdwrite extended(64)"},
213 {0x9, "Read(32)"},
214 {0xa, "Verify(32)"},
215 {0xb, "Write(32)"},
216 {0xc, "Write an verify(32)"},
217 {0xd, "Write same(32)"},
218 {0x8801, "Format OSD"},
219 {0x8802, "Create (osd)"},
220 {0x8803, "List (osd)"},
221 {0x8805, "Read (osd)"},
222 {0x8806, "Write (osd)"},
223 {0x8807, "Append (osd)"},
224 {0x8808, "Flush (osd)"},
225 {0x880a, "Remove (osd)"},
226 {0x880b, "Create partition (osd)"},
227 {0x880c, "Remove partition (osd)"},
228 {0x880e, "Get attributes (osd)"},
229 {0x880f, "Set attributes (osd)"},
230 {0x8812, "Create and write (osd)"},
231 {0x8815, "Create collection (osd)"},
232 {0x8816, "Remove collection (osd)"},
233 {0x8817, "List collection (osd)"},
234 {0x8818, "Set key (osd)"},
235 {0x8819, "Set master key (osd)"},
236 {0x881a, "Flush collection (osd)"},
237 {0x881b, "Flush partition (osd)"},
238 {0x881c, "Flush OSD"},
239 {0x8f7e, "Perform SCSI command (osd)"},
240 {0x8f7f, "Perform task management function (osd)"},
241};
242#define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr)
243
244static struct sa_name_list sa_names_arr[] = {
245 {VARIABLE_LENGTH_CMD, variable_length_arr, VARIABLE_LENGTH_SZ},
246 {MAINTENANCE_IN, maint_in_arr, MAINT_IN_SZ},
247 {MAINTENANCE_OUT, maint_out_arr, MAINT_OUT_SZ},
248 {PERSISTENT_RESERVE_IN, pr_in_arr, PR_IN_SZ},
249 {PERSISTENT_RESERVE_OUT, pr_out_arr, PR_OUT_SZ},
250 {SERVICE_ACTION_IN_12, serv_in12_arr, SERV_IN12_SZ},
251 {SERVICE_ACTION_OUT_12, serv_out12_arr, SERV_OUT12_SZ},
252 {SERVICE_ACTION_BIDIRECTIONAL, serv_bidi_arr, SERV_BIDI_SZ},
253 {SERVICE_ACTION_IN_16, serv_in16_arr, SERV_IN16_SZ},
254 {SERVICE_ACTION_OUT_16, serv_out16_arr, SERV_OUT16_SZ},
255 {THIRD_PARTY_COPY_IN, tpc_in_arr, TPC_IN_SZ},
256 {THIRD_PARTY_COPY_OUT, tpc_out_arr, TPC_OUT_SZ},
257 {0, NULL, 0},
258};
259
260bool scsi_opcode_sa_name(int opcode, int service_action,
261 const char **cdb_name, const char **sa_name)
262{
263 struct sa_name_list *sa_name_ptr;
264 const struct value_name_pair *arr = NULL;
265 int arr_sz, k;
266
267 *cdb_name = NULL;
268 if (opcode >= VENDOR_SPECIFIC_CDB)
269 return false;
270
271 if (opcode < ARRAY_SIZE(cdb_byte0_names))
272 *cdb_name = cdb_byte0_names[opcode];
273
274 for (sa_name_ptr = sa_names_arr; sa_name_ptr->arr; ++sa_name_ptr) {
275 if (sa_name_ptr->opcode == opcode) {
276 arr = sa_name_ptr->arr;
277 arr_sz = sa_name_ptr->arr_sz;
278 break;
279 }
280 }
281 if (!arr)
282 return false;
283
284 for (k = 0; k < arr_sz; ++k, ++arr) {
285 if (service_action == arr->value)
286 break;
287 }
288 if (k < arr_sz)
289 *sa_name = arr->name;
290
291 return true;
292}
293
294struct error_info {
295 unsigned short code12;
296 unsigned short size;
297};
298
299
300
301
302
303
304
305
306
307static const struct error_info additional[] =
308{
309#define SENSE_CODE(c, s) {c, sizeof(s)},
310#include "sense_codes.h"
311#undef SENSE_CODE
312};
313
314static const char *additional_text =
315#define SENSE_CODE(c, s) s "\0"
316#include "sense_codes.h"
317#undef SENSE_CODE
318 ;
319
320struct error_info2 {
321 unsigned char code1, code2_min, code2_max;
322 const char * str;
323 const char * fmt;
324};
325
326static const struct error_info2 additional2[] =
327{
328 {0x40, 0x00, 0x7f, "Ram failure", ""},
329 {0x40, 0x80, 0xff, "Diagnostic failure on component", ""},
330 {0x41, 0x00, 0xff, "Data path failure", ""},
331 {0x42, 0x00, 0xff, "Power-on or self-test failure", ""},
332 {0x4D, 0x00, 0xff, "Tagged overlapped commands", "task tag "},
333 {0x70, 0x00, 0xff, "Decompression exception", "short algorithm id of "},
334 {0, 0, 0, NULL, NULL}
335};
336
337
338static const char * const snstext[] = {
339 "No Sense",
340 "Recovered Error",
341
342 "Not Ready",
343 "Medium Error",
344 "Hardware Error",
345 "Illegal Request",
346 "Unit Attention",
347
348 "Data Protect",
349 "Blank Check",
350
351 "Vendor Specific(9)",
352 "Copy Aborted",
353 "Aborted Command",
354 "Equal",
355
356 "Volume Overflow",
357 "Miscompare",
358
359 "Completed",
360
361};
362
363
364const char *
365scsi_sense_key_string(unsigned char key)
366{
367 if (key < ARRAY_SIZE(snstext))
368 return snstext[key];
369 return NULL;
370}
371EXPORT_SYMBOL(scsi_sense_key_string);
372
373
374
375
376
377const char *
378scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt)
379{
380 int i;
381 unsigned short code = ((asc << 8) | ascq);
382 unsigned offset = 0;
383
384 *fmt = NULL;
385 for (i = 0; i < ARRAY_SIZE(additional); i++) {
386 if (additional[i].code12 == code)
387 return additional_text + offset;
388 offset += additional[i].size;
389 }
390 for (i = 0; additional2[i].fmt; i++) {
391 if (additional2[i].code1 == asc &&
392 ascq >= additional2[i].code2_min &&
393 ascq <= additional2[i].code2_max) {
394 *fmt = additional2[i].fmt;
395 return additional2[i].str;
396 }
397 }
398 return NULL;
399}
400EXPORT_SYMBOL(scsi_extd_sense_format);
401
402static const char * const hostbyte_table[]={
403"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
404"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
405"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
406"DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE",
407"DID_NEXUS_FAILURE", "DID_ALLOC_FAILURE", "DID_MEDIUM_ERROR" };
408
409const char *scsi_hostbyte_string(int result)
410{
411 enum scsi_host_status hb = host_byte(result);
412 const char *hb_string = NULL;
413
414 if (hb < ARRAY_SIZE(hostbyte_table))
415 hb_string = hostbyte_table[hb];
416 return hb_string;
417}
418EXPORT_SYMBOL(scsi_hostbyte_string);
419
420#define scsi_mlreturn_name(result) { result, #result }
421static const struct value_name_pair scsi_mlreturn_arr[] = {
422 scsi_mlreturn_name(NEEDS_RETRY),
423 scsi_mlreturn_name(SUCCESS),
424 scsi_mlreturn_name(FAILED),
425 scsi_mlreturn_name(QUEUED),
426 scsi_mlreturn_name(SOFT_ERROR),
427 scsi_mlreturn_name(ADD_TO_MLQUEUE),
428 scsi_mlreturn_name(TIMEOUT_ERROR),
429 scsi_mlreturn_name(SCSI_RETURN_NOT_HANDLED),
430 scsi_mlreturn_name(FAST_IO_FAIL)
431};
432
433const char *scsi_mlreturn_string(int result)
434{
435 const struct value_name_pair *arr = scsi_mlreturn_arr;
436 int k;
437
438 for (k = 0; k < ARRAY_SIZE(scsi_mlreturn_arr); ++k, ++arr) {
439 if (result == arr->value)
440 return arr->name;
441 }
442 return NULL;
443}
444EXPORT_SYMBOL(scsi_mlreturn_string);
445