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" };
408
409static const char * const driverbyte_table[]={
410"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
411"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
412
413const char *scsi_hostbyte_string(int result)
414{
415 const char *hb_string = NULL;
416 int hb = host_byte(result);
417
418 if (hb < ARRAY_SIZE(hostbyte_table))
419 hb_string = hostbyte_table[hb];
420 return hb_string;
421}
422EXPORT_SYMBOL(scsi_hostbyte_string);
423
424const char *scsi_driverbyte_string(int result)
425{
426 const char *db_string = NULL;
427 int db = driver_byte(result);
428
429 if (db < ARRAY_SIZE(driverbyte_table))
430 db_string = driverbyte_table[db];
431 return db_string;
432}
433EXPORT_SYMBOL(scsi_driverbyte_string);
434
435#define scsi_mlreturn_name(result) { result, #result }
436static const struct value_name_pair scsi_mlreturn_arr[] = {
437 scsi_mlreturn_name(NEEDS_RETRY),
438 scsi_mlreturn_name(SUCCESS),
439 scsi_mlreturn_name(FAILED),
440 scsi_mlreturn_name(QUEUED),
441 scsi_mlreturn_name(SOFT_ERROR),
442 scsi_mlreturn_name(ADD_TO_MLQUEUE),
443 scsi_mlreturn_name(TIMEOUT_ERROR),
444 scsi_mlreturn_name(SCSI_RETURN_NOT_HANDLED),
445 scsi_mlreturn_name(FAST_IO_FAIL)
446};
447
448const char *scsi_mlreturn_string(int result)
449{
450 const struct value_name_pair *arr = scsi_mlreturn_arr;
451 int k;
452
453 for (k = 0; k < ARRAY_SIZE(scsi_mlreturn_arr); ++k, ++arr) {
454 if (result == arr->value)
455 return arr->name;
456 }
457 return NULL;
458}
459EXPORT_SYMBOL(scsi_mlreturn_string);
460