0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/blkdev.h>
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014
0015 #include <scsi/scsi.h>
0016 #include <scsi/scsi_cmnd.h>
0017 #include <scsi/scsi_device.h>
0018 #include <scsi/scsi_host.h>
0019 #include <scsi/scsi_eh.h>
0020 #include <scsi/scsi_dbg.h>
0021
0022
0023 #define THIRD_PARTY_COPY_OUT 0x83
0024 #define THIRD_PARTY_COPY_IN 0x84
0025
0026 struct sa_name_list {
0027 int opcode;
0028 const struct value_name_pair *arr;
0029 int arr_sz;
0030 };
0031
0032 struct value_name_pair {
0033 int value;
0034 const char * name;
0035 };
0036
0037 static const char * cdb_byte0_names[] = {
0038 "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
0039 "Format Unit/Medium", "Read Block Limits", NULL,
0040 "Reassign Blocks",
0041 "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
0042 NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
0043 "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
0044 "Reserve(6)",
0045 "Release(6)", "Copy", "Erase", "Mode Sense(6)",
0046 "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
0047 "Prevent/Allow Medium Removal", NULL,
0048 NULL, NULL, NULL,
0049 "Read Format Capacities", "Set Window",
0050 "Read Capacity(10)", NULL, NULL, "Read(10)",
0051 "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
0052 "Read updated block",
0053 "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
0054 "Search Low", "Set Limits", "Prefetch/Read Position",
0055 "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
0056 "Read Defect Data(10)",
0057 "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
0058 "Read Buffer",
0059 "Update Block", "Read Long(10)", "Write Long(10)",
0060 "Change Definition", "Write Same(10)",
0061 "Unmap/Read sub-channel", "Read TOC/PMA/ATIP",
0062 "Read density support", "Play audio(10)", "Get configuration",
0063 "Play audio msf", "Sanitize/Play audio track/index",
0064 "Play track relative(10)", "Get event status notification",
0065 "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
0066 NULL,
0067 "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
0068 "Reserve track", "Send OPC info", "Mode Select(10)",
0069 "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
0070 "Mode Sense(10)", "Close track/session",
0071 "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
0072 "Persistent reserve out",
0073 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0074 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0075 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0076 NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB",
0077 "Variable length",
0078 "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)",
0079 "Third party copy out", "Third party copy in",
0080 "ATA command pass through(16)", "Access control in",
0081 "Access control out", "Read(16)", "Compare and Write",
0082 "Write(16)", "ORWrite", "Read attributes", "Write attributes",
0083 "Write and verify(16)", "Verify(16)",
0084 "Pre-fetch(16)", "Synchronize cache(16)",
0085 "Lock/unlock cache(16)", "Write same(16)", NULL,
0086 NULL, NULL, NULL, NULL, NULL,
0087 NULL, NULL, NULL, "Service action bidirectional",
0088 "Service action in(16)", "Service action out(16)",
0089 "Report luns", "ATA command pass through(12)/Blank",
0090 "Security protocol in", "Maintenance in", "Maintenance out",
0091 "Move medium/play audio(12)",
0092 "Exchange medium", "Move medium attached", "Read(12)",
0093 "Play track relative(12)",
0094 "Write(12)", NULL, "Erase(12), Get Performance",
0095 "Read DVD structure", "Write and verify(12)",
0096 "Verify(12)", "Search data high(12)", "Search data equal(12)",
0097 "Search data low(12)", "Set limits(12)",
0098 "Read element status attached",
0099 "Security protocol out", "Send volume tag, set streaming",
0100 "Read defect data(12)", "Read element status", "Read CD msf",
0101 "Redundancy group (in), Scan",
0102 "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
0103 "Spare (out), Mechanism status", "Volume set (in), Read cd",
0104 "Volume set (out), Send DVD structure",
0105 };
0106
0107 static const struct value_name_pair maint_in_arr[] = {
0108 {0x5, "Report identifying information"},
0109 {0xa, "Report target port groups"},
0110 {0xb, "Report aliases"},
0111 {0xc, "Report supported operation codes"},
0112 {0xd, "Report supported task management functions"},
0113 {0xe, "Report priority"},
0114 {0xf, "Report timestamp"},
0115 {0x10, "Management protocol in"},
0116 };
0117 #define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
0118
0119 static const struct value_name_pair maint_out_arr[] = {
0120 {0x6, "Set identifying information"},
0121 {0xa, "Set target port groups"},
0122 {0xb, "Change aliases"},
0123 {0xc, "Remove I_T nexus"},
0124 {0xe, "Set priority"},
0125 {0xf, "Set timestamp"},
0126 {0x10, "Management protocol out"},
0127 };
0128 #define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
0129
0130 static const struct value_name_pair serv_in12_arr[] = {
0131 {0x1, "Read media serial number"},
0132 };
0133 #define SERV_IN12_SZ ARRAY_SIZE(serv_in12_arr)
0134
0135 static const struct value_name_pair serv_out12_arr[] = {
0136 {-1, "dummy entry"},
0137 };
0138 #define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr)
0139
0140 static const struct value_name_pair serv_bidi_arr[] = {
0141 {-1, "dummy entry"},
0142 };
0143 #define SERV_BIDI_SZ ARRAY_SIZE(serv_bidi_arr)
0144
0145 static const struct value_name_pair serv_in16_arr[] = {
0146 {0x10, "Read capacity(16)"},
0147 {0x11, "Read long(16)"},
0148 {0x12, "Get LBA status"},
0149 {0x13, "Report referrals"},
0150 };
0151 #define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
0152
0153 static const struct value_name_pair serv_out16_arr[] = {
0154 {0x11, "Write long(16)"},
0155 {0x1f, "Notify data transfer device(16)"},
0156 };
0157 #define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr)
0158
0159 static const struct value_name_pair pr_in_arr[] = {
0160 {0x0, "Persistent reserve in, read keys"},
0161 {0x1, "Persistent reserve in, read reservation"},
0162 {0x2, "Persistent reserve in, report capabilities"},
0163 {0x3, "Persistent reserve in, read full status"},
0164 };
0165 #define PR_IN_SZ ARRAY_SIZE(pr_in_arr)
0166
0167 static const struct value_name_pair pr_out_arr[] = {
0168 {0x0, "Persistent reserve out, register"},
0169 {0x1, "Persistent reserve out, reserve"},
0170 {0x2, "Persistent reserve out, release"},
0171 {0x3, "Persistent reserve out, clear"},
0172 {0x4, "Persistent reserve out, preempt"},
0173 {0x5, "Persistent reserve out, preempt and abort"},
0174 {0x6, "Persistent reserve out, register and ignore existing key"},
0175 {0x7, "Persistent reserve out, register and move"},
0176 };
0177 #define PR_OUT_SZ ARRAY_SIZE(pr_out_arr)
0178
0179
0180
0181
0182 static const struct value_name_pair tpc_out_arr[] = {
0183 {0x0, "Extended copy(LID1)"},
0184 {0x1, "Extended copy(LID4)"},
0185 {0x10, "Populate token"},
0186 {0x11, "Write using token"},
0187 {0x1c, "Copy operation abort"},
0188 };
0189 #define TPC_OUT_SZ ARRAY_SIZE(tpc_out_arr)
0190
0191 static const struct value_name_pair tpc_in_arr[] = {
0192 {0x0, "Receive copy status(LID1)"},
0193 {0x1, "Receive copy data(LID1)"},
0194 {0x3, "Receive copy operating parameters"},
0195 {0x4, "Receive copy failure details(LID1)"},
0196 {0x5, "Receive copy status(LID4)"},
0197 {0x6, "Receive copy data(LID4)"},
0198 {0x7, "Receive ROD token information"},
0199 {0x8, "Report all ROD tokens"},
0200 };
0201 #define TPC_IN_SZ ARRAY_SIZE(tpc_in_arr)
0202
0203
0204 static const struct value_name_pair variable_length_arr[] = {
0205 {0x1, "Rebuild(32)"},
0206 {0x2, "Regenerate(32)"},
0207 {0x3, "Xdread(32)"},
0208 {0x4, "Xdwrite(32)"},
0209 {0x5, "Xdwrite extended(32)"},
0210 {0x6, "Xpwrite(32)"},
0211 {0x7, "Xdwriteread(32)"},
0212 {0x8, "Xdwrite extended(64)"},
0213 {0x9, "Read(32)"},
0214 {0xa, "Verify(32)"},
0215 {0xb, "Write(32)"},
0216 {0xc, "Write an verify(32)"},
0217 {0xd, "Write same(32)"},
0218 {0x8801, "Format OSD"},
0219 {0x8802, "Create (osd)"},
0220 {0x8803, "List (osd)"},
0221 {0x8805, "Read (osd)"},
0222 {0x8806, "Write (osd)"},
0223 {0x8807, "Append (osd)"},
0224 {0x8808, "Flush (osd)"},
0225 {0x880a, "Remove (osd)"},
0226 {0x880b, "Create partition (osd)"},
0227 {0x880c, "Remove partition (osd)"},
0228 {0x880e, "Get attributes (osd)"},
0229 {0x880f, "Set attributes (osd)"},
0230 {0x8812, "Create and write (osd)"},
0231 {0x8815, "Create collection (osd)"},
0232 {0x8816, "Remove collection (osd)"},
0233 {0x8817, "List collection (osd)"},
0234 {0x8818, "Set key (osd)"},
0235 {0x8819, "Set master key (osd)"},
0236 {0x881a, "Flush collection (osd)"},
0237 {0x881b, "Flush partition (osd)"},
0238 {0x881c, "Flush OSD"},
0239 {0x8f7e, "Perform SCSI command (osd)"},
0240 {0x8f7f, "Perform task management function (osd)"},
0241 };
0242 #define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr)
0243
0244 static struct sa_name_list sa_names_arr[] = {
0245 {VARIABLE_LENGTH_CMD, variable_length_arr, VARIABLE_LENGTH_SZ},
0246 {MAINTENANCE_IN, maint_in_arr, MAINT_IN_SZ},
0247 {MAINTENANCE_OUT, maint_out_arr, MAINT_OUT_SZ},
0248 {PERSISTENT_RESERVE_IN, pr_in_arr, PR_IN_SZ},
0249 {PERSISTENT_RESERVE_OUT, pr_out_arr, PR_OUT_SZ},
0250 {SERVICE_ACTION_IN_12, serv_in12_arr, SERV_IN12_SZ},
0251 {SERVICE_ACTION_OUT_12, serv_out12_arr, SERV_OUT12_SZ},
0252 {SERVICE_ACTION_BIDIRECTIONAL, serv_bidi_arr, SERV_BIDI_SZ},
0253 {SERVICE_ACTION_IN_16, serv_in16_arr, SERV_IN16_SZ},
0254 {SERVICE_ACTION_OUT_16, serv_out16_arr, SERV_OUT16_SZ},
0255 {THIRD_PARTY_COPY_IN, tpc_in_arr, TPC_IN_SZ},
0256 {THIRD_PARTY_COPY_OUT, tpc_out_arr, TPC_OUT_SZ},
0257 {0, NULL, 0},
0258 };
0259
0260 bool scsi_opcode_sa_name(int opcode, int service_action,
0261 const char **cdb_name, const char **sa_name)
0262 {
0263 struct sa_name_list *sa_name_ptr;
0264 const struct value_name_pair *arr = NULL;
0265 int arr_sz, k;
0266
0267 *cdb_name = NULL;
0268 if (opcode >= VENDOR_SPECIFIC_CDB)
0269 return false;
0270
0271 if (opcode < ARRAY_SIZE(cdb_byte0_names))
0272 *cdb_name = cdb_byte0_names[opcode];
0273
0274 for (sa_name_ptr = sa_names_arr; sa_name_ptr->arr; ++sa_name_ptr) {
0275 if (sa_name_ptr->opcode == opcode) {
0276 arr = sa_name_ptr->arr;
0277 arr_sz = sa_name_ptr->arr_sz;
0278 break;
0279 }
0280 }
0281 if (!arr)
0282 return false;
0283
0284 for (k = 0; k < arr_sz; ++k, ++arr) {
0285 if (service_action == arr->value)
0286 break;
0287 }
0288 if (k < arr_sz)
0289 *sa_name = arr->name;
0290
0291 return true;
0292 }
0293
0294 struct error_info {
0295 unsigned short code12;
0296 unsigned short size;
0297 };
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 static const struct error_info additional[] =
0308 {
0309 #define SENSE_CODE(c, s) {c, sizeof(s)},
0310 #include "sense_codes.h"
0311 #undef SENSE_CODE
0312 };
0313
0314 static const char *additional_text =
0315 #define SENSE_CODE(c, s) s "\0"
0316 #include "sense_codes.h"
0317 #undef SENSE_CODE
0318 ;
0319
0320 struct error_info2 {
0321 unsigned char code1, code2_min, code2_max;
0322 const char * str;
0323 const char * fmt;
0324 };
0325
0326 static const struct error_info2 additional2[] =
0327 {
0328 {0x40, 0x00, 0x7f, "Ram failure", ""},
0329 {0x40, 0x80, 0xff, "Diagnostic failure on component", ""},
0330 {0x41, 0x00, 0xff, "Data path failure", ""},
0331 {0x42, 0x00, 0xff, "Power-on or self-test failure", ""},
0332 {0x4D, 0x00, 0xff, "Tagged overlapped commands", "task tag "},
0333 {0x70, 0x00, 0xff, "Decompression exception", "short algorithm id of "},
0334 {0, 0, 0, NULL, NULL}
0335 };
0336
0337
0338 static const char * const snstext[] = {
0339 "No Sense",
0340 "Recovered Error",
0341
0342 "Not Ready",
0343 "Medium Error",
0344 "Hardware Error",
0345 "Illegal Request",
0346 "Unit Attention",
0347
0348 "Data Protect",
0349 "Blank Check",
0350
0351 "Vendor Specific(9)",
0352 "Copy Aborted",
0353 "Aborted Command",
0354 "Equal",
0355
0356 "Volume Overflow",
0357 "Miscompare",
0358
0359 "Completed",
0360
0361 };
0362
0363
0364 const char *
0365 scsi_sense_key_string(unsigned char key)
0366 {
0367 if (key < ARRAY_SIZE(snstext))
0368 return snstext[key];
0369 return NULL;
0370 }
0371 EXPORT_SYMBOL(scsi_sense_key_string);
0372
0373
0374
0375
0376
0377 const char *
0378 scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt)
0379 {
0380 int i;
0381 unsigned short code = ((asc << 8) | ascq);
0382 unsigned offset = 0;
0383
0384 *fmt = NULL;
0385 for (i = 0; i < ARRAY_SIZE(additional); i++) {
0386 if (additional[i].code12 == code)
0387 return additional_text + offset;
0388 offset += additional[i].size;
0389 }
0390 for (i = 0; additional2[i].fmt; i++) {
0391 if (additional2[i].code1 == asc &&
0392 ascq >= additional2[i].code2_min &&
0393 ascq <= additional2[i].code2_max) {
0394 *fmt = additional2[i].fmt;
0395 return additional2[i].str;
0396 }
0397 }
0398 return NULL;
0399 }
0400 EXPORT_SYMBOL(scsi_extd_sense_format);
0401
0402 static const char * const hostbyte_table[]={
0403 "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
0404 "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
0405 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
0406 "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE",
0407 "DID_NEXUS_FAILURE", "DID_ALLOC_FAILURE", "DID_MEDIUM_ERROR" };
0408
0409 const char *scsi_hostbyte_string(int result)
0410 {
0411 enum scsi_host_status hb = host_byte(result);
0412 const char *hb_string = NULL;
0413
0414 if (hb < ARRAY_SIZE(hostbyte_table))
0415 hb_string = hostbyte_table[hb];
0416 return hb_string;
0417 }
0418 EXPORT_SYMBOL(scsi_hostbyte_string);
0419
0420 #define scsi_mlreturn_name(result) { result, #result }
0421 static const struct value_name_pair scsi_mlreturn_arr[] = {
0422 scsi_mlreturn_name(NEEDS_RETRY),
0423 scsi_mlreturn_name(SUCCESS),
0424 scsi_mlreturn_name(FAILED),
0425 scsi_mlreturn_name(QUEUED),
0426 scsi_mlreturn_name(SOFT_ERROR),
0427 scsi_mlreturn_name(ADD_TO_MLQUEUE),
0428 scsi_mlreturn_name(TIMEOUT_ERROR),
0429 scsi_mlreturn_name(SCSI_RETURN_NOT_HANDLED),
0430 scsi_mlreturn_name(FAST_IO_FAIL)
0431 };
0432
0433 const char *scsi_mlreturn_string(int result)
0434 {
0435 const struct value_name_pair *arr = scsi_mlreturn_arr;
0436 int k;
0437
0438 for (k = 0; k < ARRAY_SIZE(scsi_mlreturn_arr); ++k, ++arr) {
0439 if (result == arr->value)
0440 return arr->name;
0441 }
0442 return NULL;
0443 }
0444 EXPORT_SYMBOL(scsi_mlreturn_string);