Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * ASCII values for a number of symbolic constants, printing functions,
0004  * etc.
0005  * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422)
0006  * Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
0007  *   by D. Gilbert and aeb (20020609)
0008  * Updated to SPC-4 T10/1713-D Rev 36g, D. Gilbert 20130701
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 /* Commands with service actions that change the command name */
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 /* 00-03 */ "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
0039 /* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL,
0040         "Reassign Blocks",
0041 /* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
0042 /* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
0043 /* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
0044         "Reserve(6)",
0045 /* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)",
0046 /* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
0047 /* 1e-1f */ "Prevent/Allow Medium Removal", NULL,
0048 /* 20-22 */  NULL, NULL, NULL,
0049 /* 23-28 */ "Read Format Capacities", "Set Window",
0050         "Read Capacity(10)", NULL, NULL, "Read(10)",
0051 /* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
0052             "Read updated block",
0053 /* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
0054 /* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
0055 /* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
0056         "Read Defect Data(10)",
0057 /* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
0058         "Read Buffer",
0059 /* 3d-3f */ "Update Block", "Read Long(10)",  "Write Long(10)",
0060 /* 40-41 */ "Change Definition", "Write Same(10)",
0061 /* 42-48 */ "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 /* 49-4f */ "Play track relative(10)", "Get event status notification",
0065             "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
0066             NULL,
0067 /* 50-55 */ "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
0068             "Reserve track", "Send OPC info", "Mode Select(10)",
0069 /* 56-5b */ "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
0070             "Mode Sense(10)", "Close track/session",
0071 /* 5c-5f */ "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
0072             "Persistent reserve out",
0073 /* 60-67 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0074 /* 68-6f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0075 /* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0076 /* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB",
0077         "Variable length",
0078 /* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)",
0079         "Third party copy out", "Third party copy in",
0080 /* 85-89 */ "ATA command pass through(16)", "Access control in",
0081         "Access control out", "Read(16)", "Compare and Write",
0082 /* 8a-8f */ "Write(16)", "ORWrite", "Read attributes", "Write attributes",
0083             "Write and verify(16)", "Verify(16)",
0084 /* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
0085             "Lock/unlock cache(16)", "Write same(16)", NULL,
0086 /* 95-99 */ NULL, NULL, NULL, NULL, NULL,
0087 /* 9a-9f */ NULL, NULL, NULL, "Service action bidirectional",
0088         "Service action in(16)", "Service action out(16)",
0089 /* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank",
0090             "Security protocol in", "Maintenance in", "Maintenance out",
0091         "Move medium/play audio(12)",
0092 /* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
0093             "Play track relative(12)",
0094 /* aa-ae */ "Write(12)", NULL, "Erase(12), Get Performance",
0095             "Read DVD structure", "Write and verify(12)",
0096 /* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
0097 /* b2-b4 */ "Search data low(12)", "Set limits(12)",
0098             "Read element status attached",
0099 /* b5-b6 */ "Security protocol out", "Send volume tag, set streaming",
0100 /* b7-b9 */ "Read defect data(12)", "Read element status", "Read CD msf",
0101 /* ba-bc */ "Redundancy group (in), Scan",
0102             "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
0103 /* bd-bf */ "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 /* SPC-4 rev 34 renamed the Extended Copy opcode to Third Party Copy Out.
0180    LID1 (List Identifier length: 1 byte) is the Extended Copy found in SPC-2
0181    and SPC-3 */
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;  /* 0x0302 looks better than 0x03,0x02 */
0296     unsigned short size;
0297 };
0298 
0299 /*
0300  * There are 700+ entries in this table. To save space, we don't store
0301  * (code, pointer) pairs, which would make sizeof(struct
0302  * error_info)==16 on 64 bits. Rather, the second element just stores
0303  * the size (including \0) of the corresponding string, and we use the
0304  * sum of these to get the appropriate offset into additional_text
0305  * defined below. This approach saves 12 bytes per entry.
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 /* description of the sense key values */
0338 static const char * const snstext[] = {
0339     "No Sense",     /* 0: There is no sense information */
0340     "Recovered Error",  /* 1: The last command completed successfully
0341                   but used error correction */
0342     "Not Ready",        /* 2: The addressed target is not ready */
0343     "Medium Error",     /* 3: Data error detected on the medium */
0344     "Hardware Error",   /* 4: Controller or device failure */
0345     "Illegal Request",  /* 5: Error in request */
0346     "Unit Attention",   /* 6: Removable medium was changed, or
0347                   the target has been reset, or ... */
0348     "Data Protect",     /* 7: Access to the data is blocked */
0349     "Blank Check",      /* 8: Reached unexpected written or unwritten
0350                   region of the medium */
0351     "Vendor Specific(9)",
0352     "Copy Aborted",     /* A: COPY or COMPARE was aborted */
0353     "Aborted Command",  /* B: The target aborted the command */
0354     "Equal",        /* C: A SEARCH DATA command found data equal,
0355                   reserved in SPC-4 rev 36 */
0356     "Volume Overflow",  /* D: Medium full with still data to be written */
0357     "Miscompare",       /* E: Source data and data on the medium
0358                   do not agree */
0359     "Completed",        /* F: command completed sense data reported,
0360                   may occur for successful command */
0361 };
0362 
0363 /* Get sense key string or NULL if not available */
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  * Get additional sense code string or NULL if not available.
0375  * This string may contain a "%x" and should be printed with ascq as arg.
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);