diff options
Diffstat (limited to 'drivers/scsi/constants.c')
-rw-r--r-- | drivers/scsi/constants.c | 599 |
1 files changed, 244 insertions, 355 deletions
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index d35a5d6c8d7c..e2068a2621c4 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -21,15 +21,21 @@ /* Commands with service actions that change the command name */ -#define SERVICE_ACTION_IN_12 0xab -#define SERVICE_ACTION_OUT_12 0xa9 -#define SERVICE_ACTION_BIDIRECTIONAL 0x9d -#define SERVICE_ACTION_IN_16 0x9e -#define SERVICE_ACTION_OUT_16 0x9f #define THIRD_PARTY_COPY_OUT 0x83 #define THIRD_PARTY_COPY_IN 0x84 +#define VENDOR_SPECIFIC_CDB 0xc0 +struct sa_name_list { + int opcode; + const struct value_name_pair *arr; + int arr_sz; +}; + +struct value_name_pair { + int value; + const char * name; +}; #ifdef CONFIG_SCSI_CONSTANTS static const char * cdb_byte0_names[] = { @@ -102,11 +108,6 @@ static const char * cdb_byte0_names[] = { "Volume set (out), Send DVD structure", }; -struct value_name_pair { - int value; - const char * name; -}; - static const struct value_name_pair maint_in_arr[] = { {0x5, "Report identifying information"}, {0xa, "Report target port groups"}, @@ -244,170 +245,119 @@ static const struct value_name_pair variable_length_arr[] = { }; #define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr) -static const char * get_sa_name(const struct value_name_pair * arr, - int arr_sz, int service_action) -{ - int k; +static struct sa_name_list sa_names_arr[] = { + {VARIABLE_LENGTH_CMD, variable_length_arr, VARIABLE_LENGTH_SZ}, + {MAINTENANCE_IN, maint_in_arr, MAINT_IN_SZ}, + {MAINTENANCE_OUT, maint_out_arr, MAINT_OUT_SZ}, + {PERSISTENT_RESERVE_IN, pr_in_arr, PR_IN_SZ}, + {PERSISTENT_RESERVE_OUT, pr_out_arr, PR_OUT_SZ}, + {SERVICE_ACTION_IN_12, serv_in12_arr, SERV_IN12_SZ}, + {SERVICE_ACTION_OUT_12, serv_out12_arr, SERV_OUT12_SZ}, + {SERVICE_ACTION_BIDIRECTIONAL, serv_bidi_arr, SERV_BIDI_SZ}, + {SERVICE_ACTION_IN_16, serv_in16_arr, SERV_IN16_SZ}, + {SERVICE_ACTION_OUT_16, serv_out16_arr, SERV_OUT16_SZ}, + {THIRD_PARTY_COPY_IN, tpc_in_arr, TPC_IN_SZ}, + {THIRD_PARTY_COPY_OUT, tpc_out_arr, TPC_OUT_SZ}, + {0, NULL, 0}, +}; - for (k = 0; k < arr_sz; ++k, ++arr) { - if (service_action == arr->value) - break; - } - return (k < arr_sz) ? arr->name : NULL; -} +#else /* ifndef CONFIG_SCSI_CONSTANTS */ +static const char *cdb_byte0_names[0]; + +static struct sa_name_list sa_names_arr[] = { + {VARIABLE_LENGTH_CMD, NULL, 0}, + {MAINTENANCE_IN, NULL, 0}, + {MAINTENANCE_OUT, NULL, 0}, + {PERSISTENT_RESERVE_IN, NULL, 0}, + {PERSISTENT_RESERVE_OUT, NULL, 0}, + {SERVICE_ACTION_IN_12, NULL, 0}, + {SERVICE_ACTION_OUT_12, NULL, 0}, + {SERVICE_ACTION_BIDIRECTIONAL, NULL, 0}, + {SERVICE_ACTION_IN_16, NULL, 0}, + {SERVICE_ACTION_OUT_16, NULL, 0}, + {THIRD_PARTY_COPY_IN, NULL, 0}, + {THIRD_PARTY_COPY_OUT, NULL, 0}, + {0, NULL, 0}, +}; +#endif /* CONFIG_SCSI_CONSTANTS */ -/* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */ -static void print_opcode_name(unsigned char * cdbp, int cdb_len) +static bool scsi_opcode_sa_name(int opcode, int service_action, + const char **cdb_name, const char **sa_name) { - int sa, len, cdb0; - int fin_name = 0; - const char * name; + struct sa_name_list *sa_name_ptr; + const struct value_name_pair *arr = NULL; + int arr_sz, k; - cdb0 = cdbp[0]; - switch(cdb0) { - case VARIABLE_LENGTH_CMD: - len = scsi_varlen_cdb_length(cdbp); - if (len < 10) { - printk("short variable length command, " - "len=%d ext_len=%d", len, cdb_len); - break; - } - sa = (cdbp[8] << 8) + cdbp[9]; - name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ, - sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + *cdb_name = NULL; + if (opcode >= VENDOR_SPECIFIC_CDB) + return false; - if ((cdb_len > 0) && (len != cdb_len)) - printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len); + if (opcode < ARRAY_SIZE(cdb_byte0_names)) + *cdb_name = cdb_byte0_names[opcode]; - break; - case MAINTENANCE_IN: - sa = cdbp[1] & 0x1f; - name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa); - fin_name = 1; - break; - case MAINTENANCE_OUT: - sa = cdbp[1] & 0x1f; - name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa); - fin_name = 1; - break; - case PERSISTENT_RESERVE_IN: - sa = cdbp[1] & 0x1f; - name = get_sa_name(pr_in_arr, PR_IN_SZ, sa); - fin_name = 1; - break; - case PERSISTENT_RESERVE_OUT: - sa = cdbp[1] & 0x1f; - name = get_sa_name(pr_out_arr, PR_OUT_SZ, sa); - fin_name = 1; - break; - case SERVICE_ACTION_IN_12: - sa = cdbp[1] & 0x1f; - name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa); - fin_name = 1; - break; - case SERVICE_ACTION_OUT_12: - sa = cdbp[1] & 0x1f; - name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa); - fin_name = 1; - break; - case SERVICE_ACTION_BIDIRECTIONAL: - sa = cdbp[1] & 0x1f; - name = get_sa_name(serv_bidi_arr, SERV_BIDI_SZ, sa); - fin_name = 1; - break; - case SERVICE_ACTION_IN_16: - sa = cdbp[1] & 0x1f; - name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa); - fin_name = 1; - break; - case SERVICE_ACTION_OUT_16: - sa = cdbp[1] & 0x1f; - name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa); - fin_name = 1; - break; - case THIRD_PARTY_COPY_IN: - sa = cdbp[1] & 0x1f; - name = get_sa_name(tpc_in_arr, TPC_IN_SZ, sa); - fin_name = 1; - break; - case THIRD_PARTY_COPY_OUT: - sa = cdbp[1] & 0x1f; - name = get_sa_name(tpc_out_arr, TPC_OUT_SZ, sa); - fin_name = 1; - break; - default: - if (cdb0 < 0xc0) { - name = cdb_byte0_names[cdb0]; - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x (reserved)", cdb0); - } else - printk("cdb[0]=0x%x (vendor)", cdb0); - break; + for (sa_name_ptr = sa_names_arr; sa_name_ptr->arr; ++sa_name_ptr) { + if (sa_name_ptr->opcode == opcode) { + arr = sa_name_ptr->arr; + arr_sz = sa_name_ptr->arr_sz; + break; + } } - if (fin_name) { - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + if (!arr) + return false; + + for (k = 0; k < arr_sz; ++k, ++arr) { + if (service_action == arr->value) + break; } -} + if (k < arr_sz) + *sa_name = arr->name; -#else /* ifndef CONFIG_SCSI_CONSTANTS */ + return true; +} -static void print_opcode_name(unsigned char * cdbp, int cdb_len) +static void print_opcode_name(const unsigned char *cdbp, size_t cdb_len) { - int sa, len, cdb0; + int sa, cdb0; + const char *cdb_name = NULL, *sa_name = NULL; cdb0 = cdbp[0]; - switch(cdb0) { - case VARIABLE_LENGTH_CMD: - len = scsi_varlen_cdb_length(cdbp); - if (len < 10) { - printk("short opcode=0x%x command, len=%d " - "ext_len=%d", cdb0, len, cdb_len); - break; + if (cdb0 == VARIABLE_LENGTH_CMD) { + if (cdb_len < 10) { + printk("short variable length command, len=%zu", + cdb_len); + return; } sa = (cdbp[8] << 8) + cdbp[9]; - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); - if (len != cdb_len) - printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len); - break; - case MAINTENANCE_IN: - case MAINTENANCE_OUT: - case PERSISTENT_RESERVE_IN: - case PERSISTENT_RESERVE_OUT: - case SERVICE_ACTION_IN_12: - case SERVICE_ACTION_OUT_12: - case SERVICE_ACTION_BIDIRECTIONAL: - case SERVICE_ACTION_IN_16: - case SERVICE_ACTION_OUT_16: - case THIRD_PARTY_COPY_IN: - case THIRD_PARTY_COPY_OUT: + } else sa = cdbp[1] & 0x1f; - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); - break; - default: - if (cdb0 < 0xc0) + + if (!scsi_opcode_sa_name(cdb0, sa, &cdb_name, &sa_name)) { + if (cdb_name) + printk("%s", cdb_name); + else if (cdb0 >= VENDOR_SPECIFIC_CDB) + printk("cdb[0]=0x%x (vendor)", cdb0); + else if (cdb0 >= 0x60 && cdb0 < 0x7e) + printk("cdb[0]=0x%x (reserved)", cdb0); + else printk("cdb[0]=0x%x", cdb0); + } else { + if (sa_name) + printk("%s", sa_name); + else if (cdb_name) + printk("%s, sa=0x%x", cdb_name, sa); else - printk("cdb[0]=0x%x (vendor)", cdb0); - break; + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); } } -#endif -void __scsi_print_command(unsigned char *cdb) +void __scsi_print_command(const unsigned char *cdb, size_t cdb_len) { int k, len; - print_opcode_name(cdb, 0); + print_opcode_name(cdb, cdb_len); len = scsi_command_size(cdb); + if (cdb_len < len) + len = cdb_len; /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); @@ -433,41 +383,6 @@ void scsi_print_command(struct scsi_cmnd *cmd) } EXPORT_SYMBOL(scsi_print_command); -/** - * scsi_print_status - print scsi status description - * @scsi_status: scsi status value - * - * If the status is recognized, the description is printed. - * Otherwise "Unknown status" is output. No trailing space. - * If CONFIG_SCSI_CONSTANTS is not set, then print status in hex - * (e.g. "0x2" for Check Condition). - **/ -void -scsi_print_status(unsigned char scsi_status) { -#ifdef CONFIG_SCSI_CONSTANTS - const char * ccp; - - switch (scsi_status) { - case 0: ccp = "Good"; break; - case 0x2: ccp = "Check Condition"; break; - case 0x4: ccp = "Condition Met"; break; - case 0x8: ccp = "Busy"; break; - case 0x10: ccp = "Intermediate"; break; - case 0x14: ccp = "Intermediate-Condition Met"; break; - case 0x18: ccp = "Reservation Conflict"; break; - case 0x22: ccp = "Command Terminated"; break; /* obsolete */ - case 0x28: ccp = "Task set Full"; break; /* was: Queue Full */ - case 0x30: ccp = "ACA Active"; break; - case 0x40: ccp = "Task Aborted"; break; - default: ccp = "Unknown status"; - } - printk(KERN_INFO "%s", ccp); -#else - printk(KERN_INFO "0x%0x", scsi_status); -#endif -} -EXPORT_SYMBOL(scsi_print_status); - #ifdef CONFIG_SCSI_CONSTANTS struct error_info { @@ -1292,18 +1207,19 @@ static const struct error_info additional[] = struct error_info2 { unsigned char code1, code2_min, code2_max; + const char * str; const char * fmt; }; static const struct error_info2 additional2[] = { - {0x40, 0x00, 0x7f, "Ram failure (%x)"}, - {0x40, 0x80, 0xff, "Diagnostic failure on component (%x)"}, - {0x41, 0x00, 0xff, "Data path failure (%x)"}, - {0x42, 0x00, 0xff, "Power-on or self-test failure (%x)"}, - {0x4D, 0x00, 0xff, "Tagged overlapped commands (task tag %x)"}, - {0x70, 0x00, 0xff, "Decompression exception short algorithm id of %x"}, - {0, 0, 0, NULL} + {0x40, 0x00, 0x7f, "Ram failure", ""}, + {0x40, 0x80, 0xff, "Diagnostic failure on component", ""}, + {0x41, 0x00, 0xff, "Data path failure", ""}, + {0x42, 0x00, 0xff, "Power-on or self-test failure", ""}, + {0x4D, 0x00, 0xff, "Tagged overlapped commands", "task tag "}, + {0x70, 0x00, 0xff, "Decompression exception", "short algorithm id of "}, + {0, 0, 0, NULL, NULL} }; /* description of the sense key values */ @@ -1349,69 +1265,79 @@ EXPORT_SYMBOL(scsi_sense_key_string); * This string may contain a "%x" and should be printed with ascq as arg. */ const char * -scsi_extd_sense_format(unsigned char asc, unsigned char ascq) { +scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt) +{ #ifdef CONFIG_SCSI_CONSTANTS int i; unsigned short code = ((asc << 8) | ascq); + *fmt = NULL; for (i = 0; additional[i].text; i++) if (additional[i].code12 == code) return additional[i].text; for (i = 0; additional2[i].fmt; i++) { if (additional2[i].code1 == asc && ascq >= additional2[i].code2_min && - ascq <= additional2[i].code2_max) - return additional2[i].fmt; + ascq <= additional2[i].code2_max) { + *fmt = additional2[i].fmt; + return additional2[i].str; + } } +#else + *fmt = NULL; #endif return NULL; } EXPORT_SYMBOL(scsi_extd_sense_format); void -scsi_show_extd_sense(unsigned char asc, unsigned char ascq) +scsi_show_extd_sense(const struct scsi_device *sdev, const char *name, + unsigned char asc, unsigned char ascq) { - const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq); - - if (extd_sense_fmt) { - if (strstr(extd_sense_fmt, "%x")) { - printk("Add. Sense: "); - printk(extd_sense_fmt, ascq); - } else - printk("Add. Sense: %s", extd_sense_fmt); - } else { - if (asc >= 0x80) - printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc, - ascq); - if (ascq >= 0x80) - printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc, - ascq); + const char *extd_sense_fmt = NULL; + const char *extd_sense_str = scsi_extd_sense_format(asc, ascq, + &extd_sense_fmt); + + if (extd_sense_str) { + if (extd_sense_fmt) + sdev_prefix_printk(KERN_INFO, sdev, name, + "Add. Sense: %s (%s%x)", + extd_sense_str, extd_sense_fmt, + ascq); else - printk("ASC=0x%x ASCQ=0x%x", asc, ascq); - } + sdev_prefix_printk(KERN_INFO, sdev, name, + "Add. Sense: %s", extd_sense_str); - printk("\n"); + } else { + sdev_prefix_printk(KERN_INFO, sdev, name, + "%sASC=0x%x %sASCQ=0x%x\n", + asc >= 0x80 ? "<<vendor>> " : "", asc, + ascq >= 0x80 ? "<<vendor>> " : "", ascq); + } } EXPORT_SYMBOL(scsi_show_extd_sense); void -scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr) +scsi_show_sense_hdr(const struct scsi_device *sdev, const char *name, + const struct scsi_sense_hdr *sshdr) { const char *sense_txt; sense_txt = scsi_sense_key_string(sshdr->sense_key); if (sense_txt) - printk("Sense Key : %s ", sense_txt); + sdev_prefix_printk(KERN_INFO, sdev, name, + "Sense Key : %s [%s]%s\n", sense_txt, + scsi_sense_is_deferred(sshdr) ? + "deferred" : "current", + sshdr->response_code >= 0x72 ? + " [descriptor]" : ""); else - printk("Sense Key : 0x%x ", sshdr->sense_key); - - printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " : - "[current] "); - - if (sshdr->response_code >= 0x72) - printk("[descriptor]"); - - printk("\n"); + sdev_prefix_printk(KERN_INFO, sdev, name, + "Sense Key : 0x%x [%s]%s", sshdr->sense_key, + scsi_sense_is_deferred(sshdr) ? + "deferred" : "current", + sshdr->response_code >= 0x72 ? + " [descriptor]" : ""); } EXPORT_SYMBOL(scsi_show_sense_hdr); @@ -1419,141 +1345,55 @@ EXPORT_SYMBOL(scsi_show_sense_hdr); * Print normalized SCSI sense header with a prefix. */ void -scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) +scsi_print_sense_hdr(const struct scsi_device *sdev, const char *name, + const struct scsi_sense_hdr *sshdr) { - printk(KERN_INFO "%s: ", name); - scsi_show_sense_hdr(sshdr); - printk(KERN_INFO "%s: ", name); - scsi_show_extd_sense(sshdr->asc, sshdr->ascq); + scsi_show_sense_hdr(sdev, name, sshdr); + scsi_show_extd_sense(sdev, name, sshdr->asc, sshdr->ascq); } EXPORT_SYMBOL(scsi_print_sense_hdr); -/* - * Print normalized SCSI sense header with device information and a prefix. - */ -void -scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc, - struct scsi_sense_hdr *sshdr) -{ - scmd_printk(KERN_INFO, scmd, "%s: ", desc); - scsi_show_sense_hdr(sshdr); - scmd_printk(KERN_INFO, scmd, "%s: ", desc); - scsi_show_extd_sense(sshdr->asc, sshdr->ascq); -} -EXPORT_SYMBOL(scsi_cmd_print_sense_hdr); - static void -scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, - struct scsi_sense_hdr *sshdr) +scsi_dump_sense_buffer(const unsigned char *sense_buffer, int sense_len) { - int k, num, res; - - res = scsi_normalize_sense(sense_buffer, sense_len, sshdr); - if (0 == res) { - /* this may be SCSI-1 sense data */ - num = (sense_len < 32) ? sense_len : 32; - printk("Unrecognized sense data (in hex):"); - for (k = 0; k < num; ++k) { - if (0 == (k % 16)) { - printk("\n"); - printk(KERN_INFO " "); - } - printk("%02x ", sense_buffer[k]); + int k, num; + + num = (sense_len < 32) ? sense_len : 32; + printk("Unrecognized sense data (in hex):"); + for (k = 0; k < num; ++k) { + if (0 == (k % 16)) { + printk("\n"); + printk(KERN_INFO " "); } - printk("\n"); - return; + printk("%02x ", sense_buffer[k]); } -} - -static void -scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, - struct scsi_sense_hdr *sshdr) -{ - int k, num, res; - - if (sshdr->response_code < 0x72) - { - /* only decode extras for "fixed" format now */ - char buff[80]; - int blen, fixed_valid; - unsigned int info; - - fixed_valid = sense_buffer[0] & 0x80; - info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) | - (sense_buffer[5] << 8) | sense_buffer[6]); - res = 0; - memset(buff, 0, sizeof(buff)); - blen = sizeof(buff) - 1; - if (fixed_valid) - res += snprintf(buff + res, blen - res, - "Info fld=0x%x", info); - if (sense_buffer[2] & 0x80) { - /* current command has read a filemark */ - if (res > 0) - res += snprintf(buff + res, blen - res, ", "); - res += snprintf(buff + res, blen - res, "FMK"); - } - if (sense_buffer[2] & 0x40) { - /* end-of-medium condition exists */ - if (res > 0) - res += snprintf(buff + res, blen - res, ", "); - res += snprintf(buff + res, blen - res, "EOM"); - } - if (sense_buffer[2] & 0x20) { - /* incorrect block length requested */ - if (res > 0) - res += snprintf(buff + res, blen - res, ", "); - res += snprintf(buff + res, blen - res, "ILI"); - } - if (res > 0) - printk("%s\n", buff); - } else if (sshdr->additional_length > 0) { - /* descriptor format with sense descriptors */ - num = 8 + sshdr->additional_length; - num = (sense_len < num) ? sense_len : num; - printk("Descriptor sense data with sense descriptors " - "(in hex):"); - for (k = 0; k < num; ++k) { - if (0 == (k % 16)) { - printk("\n"); - printk(KERN_INFO " "); - } - printk("%02x ", sense_buffer[k]); - } - - printk("\n"); - } - + printk("\n"); + return; } /* Normalize and print sense buffer with name prefix */ -void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, - int sense_len) +void __scsi_print_sense(const struct scsi_device *sdev, const char *name, + const unsigned char *sense_buffer, int sense_len) { struct scsi_sense_hdr sshdr; - printk(KERN_INFO "%s: ", name); - scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr); - scsi_show_sense_hdr(&sshdr); - scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr); - printk(KERN_INFO "%s: ", name); - scsi_show_extd_sense(sshdr.asc, sshdr.ascq); + if (!scsi_normalize_sense(sense_buffer, sense_len, &sshdr)) { + scsi_dump_sense_buffer(sense_buffer, sense_len); + return; + } + scsi_show_sense_hdr(sdev, name, &sshdr); + scsi_show_extd_sense(sdev, name, sshdr.asc, sshdr.ascq); } EXPORT_SYMBOL(__scsi_print_sense); /* Normalize and print sense buffer in SCSI command */ -void scsi_print_sense(char *name, struct scsi_cmnd *cmd) +void scsi_print_sense(const struct scsi_cmnd *cmd) { - struct scsi_sense_hdr sshdr; + struct gendisk *disk = cmd->request->rq_disk; + const char *disk_name = disk ? disk->disk_name : NULL; - scmd_printk(KERN_INFO, cmd, " "); - scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, - &sshdr); - scsi_show_sense_hdr(&sshdr); - scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, - &sshdr); - scmd_printk(KERN_INFO, cmd, " "); - scsi_show_extd_sense(sshdr.asc, sshdr.ascq); + __scsi_print_sense(cmd->device, disk_name, cmd->sense_buffer, + SCSI_SENSE_BUFFERSIZE); } EXPORT_SYMBOL(scsi_print_sense); @@ -1565,38 +1405,87 @@ static const char * const hostbyte_table[]={ "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE", "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE", "DID_NEXUS_FAILURE" }; -#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table) static const char * const driverbyte_table[]={ "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; -#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) -void scsi_show_result(int result) +#endif + +const char *scsi_hostbyte_string(int result) { + const char *hb_string = NULL; +#ifdef CONFIG_SCSI_CONSTANTS int hb = host_byte(result); - int db = driver_byte(result); - printk("Result: hostbyte=%s driverbyte=%s\n", - (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), - (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid")); + if (hb < ARRAY_SIZE(hostbyte_table)) + hb_string = hostbyte_table[hb]; +#endif + return hb_string; } +EXPORT_SYMBOL(scsi_hostbyte_string); -#else - -void scsi_show_result(int result) +const char *scsi_driverbyte_string(int result) { - printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n", - host_byte(result), driver_byte(result)); + const char *db_string = NULL; +#ifdef CONFIG_SCSI_CONSTANTS + int db = driver_byte(result); + + if (db < ARRAY_SIZE(driverbyte_table)) + db_string = driverbyte_table[db]; +#endif + return db_string; } +EXPORT_SYMBOL(scsi_driverbyte_string); +#ifdef CONFIG_SCSI_CONSTANTS +#define scsi_mlreturn_name(result) { result, #result } +static const struct value_name_pair scsi_mlreturn_arr[] = { + scsi_mlreturn_name(NEEDS_RETRY), + scsi_mlreturn_name(SUCCESS), + scsi_mlreturn_name(FAILED), + scsi_mlreturn_name(QUEUED), + scsi_mlreturn_name(SOFT_ERROR), + scsi_mlreturn_name(ADD_TO_MLQUEUE), + scsi_mlreturn_name(TIMEOUT_ERROR), + scsi_mlreturn_name(SCSI_RETURN_NOT_HANDLED), + scsi_mlreturn_name(FAST_IO_FAIL) +}; #endif -EXPORT_SYMBOL(scsi_show_result); +const char *scsi_mlreturn_string(int result) +{ +#ifdef CONFIG_SCSI_CONSTANTS + const struct value_name_pair *arr = scsi_mlreturn_arr; + int k; -void scsi_print_result(struct scsi_cmnd *cmd) + for (k = 0; k < ARRAY_SIZE(scsi_mlreturn_arr); ++k, ++arr) { + if (result == arr->value) + return arr->name; + } +#endif + return NULL; +} +EXPORT_SYMBOL(scsi_mlreturn_string); + +void scsi_print_result(struct scsi_cmnd *cmd, const char *msg, int disposition) { - scmd_printk(KERN_INFO, cmd, " "); - scsi_show_result(cmd->result); + const char *mlret_string = scsi_mlreturn_string(disposition); + const char *hb_string = scsi_hostbyte_string(cmd->result); + const char *db_string = scsi_driverbyte_string(cmd->result); + + if (hb_string || db_string) + scmd_printk(KERN_INFO, cmd, + "%s%s Result: hostbyte=%s driverbyte=%s", + msg ? msg : "", + mlret_string ? mlret_string : "UNKNOWN", + hb_string ? hb_string : "invalid", + db_string ? db_string : "invalid"); + else + scmd_printk(KERN_INFO, cmd, + "%s%s Result: hostbyte=0x%02x driverbyte=0x%02x", + msg ? msg : "", + mlret_string ? mlret_string : "UNKNOWN", + host_byte(cmd->result), driver_byte(cmd->result)); } EXPORT_SYMBOL(scsi_print_result); |