Merge branch 'bkl/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[safe/jmp/linux-2.6] / drivers / scsi / constants.c
index 61f6024..cd05e04 100644 (file)
@@ -4,8 +4,7 @@
  * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422)
  * Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
  *   by D. Gilbert and aeb (20020609)
- * Additions for SPC-3 T10/1416-D Rev 21 22 Sept 2004, D. Gilbert 20041025
- * Update to SPC-4 T10/1713-D Rev 5a, 14 June 2006, D. Gilbert 20060702
+ * Update to SPC-4 T10/1713-D Rev 20, 22 May 2009, D. Gilbert 20090624
  */
 
 #include <linux/blkdev.h>
@@ -28,7 +27,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -57,9 +55,9 @@ static const char * cdb_byte0_names[] = {
             "Read Buffer", 
 /* 3d-3f */ "Update Block", "Read Long(10)",  "Write Long(10)",
 /* 40-41 */ "Change Definition", "Write Same(10)",
-/* 42-48 */ "Read sub-channel", "Read TOC/PMA/ATIP", "Read density support",
-            "Play audio(10)", "Get configuration", "Play audio msf",
-            "Play audio track/index",
+/* 42-48 */ "Unmap/Read sub-channel", "Read TOC/PMA/ATIP",
+           "Read density support", "Play audio(10)", "Get configuration",
+           "Play audio msf", "Play audio track/index",
 /* 49-4f */ "Play track relative(10)", "Get event status notification",
             "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
             NULL,
@@ -72,12 +70,13 @@ static const char * cdb_byte0_names[] = {
 /* 60-67 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 /* 68-6f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 /* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Variable length",
+/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB",
+           "Variable length",
 /* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy",
             "Receive copy results",
 /* 85-89 */ "ATA command pass through(16)", "Access control in",
            "Access control out", "Read(16)", "Memory Export Out(16)",
-/* 8a-8f */ "Write(16)", NULL, "Read attributes", "Write attributes",
+/* 8a-8f */ "Write(16)", "ORWrite", "Read attributes", "Write attributes",
             "Write and verify(16)", "Verify(16)",
 /* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
             "Lock/unlock cache(16)", "Write same(16)", NULL,
@@ -108,22 +107,24 @@ struct value_name_pair {
 };
 
 static const struct value_name_pair maint_in_arr[] = {
-       {0x5, "Report device identifier"},
+       {0x5, "Report identifying information"},
        {0xa, "Report target port groups"},
        {0xb, "Report aliases"},
        {0xc, "Report supported operation codes"},
        {0xd, "Report supported task management functions"},
        {0xe, "Report priority"},
        {0xf, "Report timestamp"},
+       {0x10, "Management protocol in"},
 };
 #define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
 
 static const struct value_name_pair maint_out_arr[] = {
-       {0x6, "Set device identifier"},
+       {0x6, "Set identifying information"},
        {0xa, "Set target port groups"},
        {0xb, "Change aliases"},
        {0xe, "Set priority"},
-       {0xe, "Set timestamp"},
+       {0xf, "Set timestamp"},
+       {0x10, "Management protocol out"},
 };
 #define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
 
@@ -140,6 +141,7 @@ static const struct value_name_pair serv_out12_arr[] = {
 static const struct value_name_pair serv_in16_arr[] = {
        {0x10, "Read capacity(16)"},
        {0x11, "Read long(16)"},
+       {0x12, "Get LBA status"},
 };
 #define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
 
@@ -202,117 +204,109 @@ static const char * get_sa_name(const struct value_name_pair * arr,
 }
 
 /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-                             int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
        int sa, len, cdb0;
        const char * name;
-       const char * leadin = start_of_line ? KERN_INFO : "";
 
        cdb0 = cdbp[0];
        switch(cdb0) {
        case VARIABLE_LENGTH_CMD:
-               len = cdbp[7] + 8;
+               len = scsi_varlen_cdb_length(cdbp);
                if (len < 10) {
-                       printk("%sshort variable length command, "
-                              "len=%d ext_len=%d", leadin, len, cdb_len);
+                       printk("short variable length command, "
+                              "len=%d ext_len=%d", len, cdb_len);
                        break;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
-               name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
-               if (name) {
-                       printk("%s%s", leadin, name);
-                       if ((cdb_len > 0) && (len != cdb_len))
-                               printk(", in_cdb_len=%d, ext_len=%d",
-                                      len, cdb_len);
-               } else {
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
-                       if ((cdb_len > 0) && (len != cdb_len))
-                               printk(", in_cdb_len=%d, ext_len=%d",
-                                      len, cdb_len);
-               }
+               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);
+
+               if ((cdb_len > 0) && (len != cdb_len))
+                       printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
+
                break;
        case MAINTENANCE_IN:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case MAINTENANCE_OUT:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_IN_12:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_OUT_12:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_IN_16:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_OUT_16:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        default:
                if (cdb0 < 0xc0) {
                        name = cdb_byte0_names[cdb0];
                        if (name)
-                               printk("%s%s", leadin, name);
+                               printk("%s", name);
                        else
-                               printk("%scdb[0]=0x%x (reserved)",
-                                      leadin, cdb0);
+                               printk("cdb[0]=0x%x (reserved)", cdb0);
                } else
-                       printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+                       printk("cdb[0]=0x%x (vendor)", cdb0);
                break;
        }
 }
 
 #else /* ifndef CONFIG_SCSI_CONSTANTS */
 
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-                             int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
        int sa, len, cdb0;
-       const char * leadin = start_of_line ? KERN_INFO : "";
 
        cdb0 = cdbp[0];
        switch(cdb0) {
        case VARIABLE_LENGTH_CMD:
-               len = cdbp[7] + 8;
+               len = scsi_varlen_cdb_length(cdbp);
                if (len < 10) {
-                       printk("%sshort opcode=0x%x command, len=%d "
-                              "ext_len=%d", leadin, cdb0, len, cdb_len);
+                       printk("short opcode=0x%x command, len=%d "
+                              "ext_len=%d", cdb0, len, cdb_len);
                        break;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
-               printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+               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;
@@ -323,52 +317,50 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len,
        case SERVICE_ACTION_IN_16:
        case SERVICE_ACTION_OUT_16:
                sa = cdbp[1] & 0x1f;
-               printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        default:
                if (cdb0 < 0xc0)
-                       printk("%scdb[0]=0x%x", leadin, cdb0);
+                       printk("cdb[0]=0x%x", cdb0);
                else
-                       printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+                       printk("cdb[0]=0x%x (vendor)", cdb0);
                break;
        }
 }
 #endif  
 
-void __scsi_print_command(unsigned char *command)
+void __scsi_print_command(unsigned char *cdb)
 {
        int k, len;
 
-       print_opcode_name(command, 0, 1);
-       if (VARIABLE_LENGTH_CMD == command[0])
-               len = command[7] + 8;
-       else
-               len = COMMAND_SIZE(command[0]);
+       print_opcode_name(cdb, 0);
+       len = scsi_command_size(cdb);
        /* print out all bytes in cdb */
        for (k = 0; k < len; ++k) 
-               printk(" %02x", command[k]);
+               printk(" %02x", cdb[k]);
        printk("\n");
 }
 EXPORT_SYMBOL(__scsi_print_command);
 
-/* This function (perhaps with the addition of peripheral device type)
- * is more approriate than __scsi_print_command(). Perhaps that static
- * can be dropped later if it replaces the __scsi_print_command version.
- */
-static void scsi_print_cdb(unsigned char *cdb, int cdb_len, int start_of_line)
+void scsi_print_command(struct scsi_cmnd *cmd)
 {
        int k;
 
-       print_opcode_name(cdb, cdb_len, start_of_line);
+       if (cmd->cmnd == NULL)
+               return;
+
+       scmd_printk(KERN_INFO, cmd, "CDB: ");
+       print_opcode_name(cmd->cmnd, cmd->cmd_len);
+
        /* print out all bytes in cdb */
        printk(":");
-       for (k = 0; k < cdb_len; ++k) 
-               printk(" %02x", cdb[k]);
+       for (k = 0; k < cmd->cmd_len; ++k)
+               printk(" %02x", cmd->cmnd[k]);
        printk("\n");
 }
+EXPORT_SYMBOL(scsi_print_command);
 
 /**
- *
  *     scsi_print_status - print scsi status description
  *     @scsi_status: scsi status value
  *
@@ -410,7 +402,11 @@ struct error_info {
        const char * text;
 };
 
-static struct error_info additional[] =
+/*
+ * The canonical list of T10 Additional Sense Codes is available at:
+ * http://www.t10.org/lists/asc-num.txt
+ */
+static const struct error_info additional[] =
 {
        {0x0000, "No additional sense information"},
        {0x0001, "Filemark detected"},
@@ -419,6 +415,7 @@ static struct error_info additional[] =
        {0x0004, "Beginning-of-partition/medium detected"},
        {0x0005, "End-of-data detected"},
        {0x0006, "I/O process terminated"},
+       {0x0007, "Programmable early warning detected"},
        {0x0011, "Audio play operation in progress"},
        {0x0012, "Audio play operation paused"},
        {0x0013, "Audio play operation successfully completed"},
@@ -432,6 +429,7 @@ static struct error_info additional[] =
        {0x001B, "Set capacity operation in progress"},
        {0x001C, "Verify operation in progress"},
        {0x001D, "ATA pass through information available"},
+       {0x001E, "Conflicting SA creation request"},
 
        {0x0100, "No index/sector signal"},
 
@@ -456,9 +454,12 @@ static struct error_info additional[] =
        {0x040B, "Logical unit not accessible, target port in standby state"},
        {0x040C, "Logical unit not accessible, target port in unavailable "
         "state"},
+       {0x040D, "Logical unit not ready, structure check required"},
        {0x0410, "Logical unit not ready, auxiliary memory not accessible"},
        {0x0411, "Logical unit not ready, notify (enable spinup) required"},
        {0x0412, "Logical unit not ready, offline"},
+       {0x0413, "Logical unit not ready, SA creation in progress"},
+       {0x0414, "Logical unit not ready, space allocation in progress"},
 
        {0x0500, "Logical unit does not respond to selection"},
 
@@ -486,6 +487,9 @@ static struct error_info additional[] =
        {0x0B03, "Warning - background self-test failed"},
        {0x0B04, "Warning - background pre-scan detected medium error"},
        {0x0B05, "Warning - background medium scan detected medium error"},
+       {0x0B06, "Warning - non-volatile cache now volatile"},
+       {0x0B07, "Warning - degraded power to non-volatile cache"},
+       {0x0B08, "Warning - power loss expected"},
 
        {0x0C00, "Write error"},
        {0x0C01, "Write error - recovered with auto reallocation"},
@@ -600,6 +604,7 @@ static struct error_info additional[] =
        {0x1C02, "Grown defect list not found"},
 
        {0x1D00, "Miscompare during verify operation"},
+       {0x1D01, "Miscompare verify of unmapped LBA"},
 
        {0x1E00, "Recovered id with ECC correction"},
 
@@ -633,6 +638,7 @@ static struct error_info additional[] =
        {0x2405, "Security working key frozen"},
        {0x2406, "Nonce not unique"},
        {0x2407, "Nonce timestamp out of range"},
+       {0x2408, "Invalid XCDB"},
 
        {0x2500, "Logical unit not supported"},
 
@@ -663,10 +669,12 @@ static struct error_info additional[] =
        {0x2704, "Persistent write protect"},
        {0x2705, "Permanent write protect"},
        {0x2706, "Conditional write protect"},
+       {0x2707, "Space allocation failed write protect"},
 
        {0x2800, "Not ready to ready change, medium may have changed"},
        {0x2801, "Import or export element accessed"},
        {0x2802, "Format-layer may have changed"},
+       {0x2803, "Import/export element accessed, medium changed"},
 
        {0x2900, "Power on, reset, or bus device reset occurred"},
        {0x2901, "Power on occurred"},
@@ -687,11 +695,16 @@ static struct error_info additional[] =
        {0x2A07, "Implicit asymmetric access state transition failed"},
        {0x2A08, "Priority changed"},
        {0x2A09, "Capacity data has changed"},
+       {0x2A0A, "Error history I_T nexus cleared"},
+       {0x2A0B, "Error history snapshot released"},
+       {0x2A0C, "Error recovery attributes have changed"},
+       {0x2A0D, "Data encryption capabilities changed"},
        {0x2A10, "Timestamp changed"},
        {0x2A11, "Data encryption parameters changed by another i_t nexus"},
        {0x2A12, "Data encryption parameters changed by vendor specific "
                 "event"},
        {0x2A13, "Data encryption key instance counter has changed"},
+       {0x2A14, "SA creation capabilities data has changed"},
 
        {0x2B00, "Copy cannot execute since host cannot disconnect"},
 
@@ -714,6 +727,7 @@ static struct error_info additional[] =
 
        {0x2F00, "Commands cleared by another initiator"},
        {0x2F01, "Commands cleared by power loss notification"},
+       {0x2F02, "Commands cleared by device server"},
 
        {0x3000, "Incompatible medium installed"},
        {0x3001, "Cannot read medium - unknown format"},
@@ -729,6 +743,8 @@ static struct error_info additional[] =
        {0x300C, "WORM medium - overwrite attempted"},
        {0x300D, "WORM medium - integrity check"},
        {0x3010, "Medium not formatted"},
+       {0x3011, "Incompatible volume type"},
+       {0x3012, "Incompatible volume qualifier"},
 
        {0x3100, "Medium format corrupted"},
        {0x3101, "Format command failed"},
@@ -788,6 +804,10 @@ static struct error_info additional[] =
        {0x3B15, "Medium magazine unlocked"},
        {0x3B16, "Mechanical positioning or changer error"},
        {0x3B17, "Read past end of user object"},
+       {0x3B18, "Element disabled"},
+       {0x3B19, "Element enabled"},
+       {0x3B1A, "Data transfer device removed"},
+       {0x3B1B, "Data transfer device inserted"},
 
        {0x3D00, "Invalid bits in identify message"},
 
@@ -888,6 +908,8 @@ static struct error_info additional[] =
        {0x5506, "Auxiliary memory out of space"},
        {0x5507, "Quota error"},
        {0x5508, "Maximum number of supplemental decryption keys exceeded"},
+       {0x5509, "Medium auxiliary memory not accessible"},
+       {0x550A, "Data currently unavailable"},
 
        {0x5700, "Unable to recover table-of-contents"},
 
@@ -999,6 +1021,12 @@ static struct error_info additional[] =
        {0x5E02, "Standby condition activated by timer"},
        {0x5E03, "Idle condition activated by command"},
        {0x5E04, "Standby condition activated by command"},
+       {0x5E05, "Idle_b condition activated by timer"},
+       {0x5E06, "Idle_b condition activated by command"},
+       {0x5E07, "Idle_c condition activated by timer"},
+       {0x5E08, "Idle_c condition activated by command"},
+       {0x5E09, "Standby_y condition activated by timer"},
+       {0x5E0A, "Standby_y condition activated by command"},
        {0x5E41, "Power state change to active"},
        {0x5E42, "Power state change to idle"},
        {0x5E43, "Power state change to standby"},
@@ -1097,7 +1125,28 @@ static struct error_info additional[] =
        {0x7403, "Incorrect data encryption key"},
        {0x7404, "Cryptographic integrity validation failed"},
        {0x7405, "Error decrypting data"},
+       {0x7406, "Unknown signature verification key"},
+       {0x7407, "Encryption parameters not useable"},
+       {0x7408, "Digital signature validation failure"},
+       {0x7409, "Encryption mode mismatch on read"},
+       {0x740A, "Encrypted block not raw read enabled"},
+       {0x740B, "Incorrect Encryption parameters"},
+       {0x740C, "Unable to decrypt parameter list"},
+       {0x740D, "Encryption algorithm disabled"},
+       {0x7410, "SA creation parameter value invalid"},
+       {0x7411, "SA creation parameter value rejected"},
+       {0x7412, "Invalid SA usage"},
+       {0x7421, "Data Encryption configuration prevented"},
+       {0x7430, "SA creation parameter not supported"},
+       {0x7440, "Authentication failed"},
+       {0x7461, "External data encryption key manager access error"},
+       {0x7462, "External data encryption key manager error"},
+       {0x7463, "External data encryption key not found"},
+       {0x7464, "External data encryption request not authorized"},
+       {0x746E, "External data encryption control timeout"},
+       {0x746F, "External data encryption control error"},
        {0x7471, "Logical unit access not authorized"},
+       {0x7479, "Security conflict in translated device"},
 
        {0, NULL}
 };
@@ -1109,12 +1158,12 @@ struct error_info2 {
 
 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 (queue tag %x)"},
-       {0x70,0x00,0xff,"Decompression exception short algorithm id of %x"},
+       {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}
 };
 
@@ -1163,80 +1212,105 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq) {
        int i;
        unsigned short code = ((asc << 8) | ascq);
 
-       for (i=0; additional[i].text; i++)
+       for (i = 0; additional[i].text; i++)
                if (additional[i].code12 == code)
                        return additional[i].text;
-       for (i=0; additional2[i].fmt; i++)
+       for (i = 0; additional2[i].fmt; i++) {
                if (additional2[i].code1 == asc &&
-                   additional2[i].code2_min >= ascq &&
-                   additional2[i].code2_max <= ascq)
+                   ascq >= additional2[i].code2_min &&
+                   ascq <= additional2[i].code2_max)
                        return additional2[i].fmt;
+       }
 #endif
        return NULL;
 }
 EXPORT_SYMBOL(scsi_extd_sense_format);
 
-/* Print extended sense information; no leadin, no linefeed */
-static void
+void
 scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
 {
-       const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
+        const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
 
        if (extd_sense_fmt) {
                if (strstr(extd_sense_fmt, "%x")) {
-                       printk("Additional sense: ");
+                       printk("Add. Sense: ");
                        printk(extd_sense_fmt, ascq);
                } else
-                       printk("Additional sense: %s", extd_sense_fmt);
+                       printk("Add. Sense: %s", extd_sense_fmt);
        } else {
                if (asc >= 0x80)
-                       printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc, ascq);
+                       printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc,
+                              ascq);
                if (ascq >= 0x80)
-                       printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc, ascq);
+                       printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc,
+                              ascq);
                else
                        printk("ASC=0x%x ASCQ=0x%x", asc, ascq);
        }
+
+       printk("\n");
 }
+EXPORT_SYMBOL(scsi_show_extd_sense);
 
 void
-scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr)
 {
        const char *sense_txt;
-       /* An example of deferred is when an earlier write to disk cache
-        * succeeded, but now the disk discovers that it cannot write the
-        * data to the magnetic media.
-        */
-       const char *error = scsi_sense_is_deferred(sshdr) ? 
-               "<<DEFERRED>>" : "Current";
-       printk(KERN_INFO "%s: %s", name, error);
-       if (sshdr->response_code >= 0x72)
-               printk(" [descriptor]");
 
        sense_txt = scsi_sense_key_string(sshdr->sense_key);
        if (sense_txt)
-               printk(": sense key: %s\n", sense_txt);
+               printk("Sense Key : %s ", sense_txt);
        else
-               printk(": sense key=0x%x\n", sshdr->sense_key);
-       printk(KERN_INFO "    ");
-       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+               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");
 }
+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)
+{
+       printk(KERN_INFO "%s: ", name);
+       scsi_show_sense_hdr(sshdr);
+       printk(KERN_INFO "%s: ", name);
+       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
-/* Print sense information */
+/*
+ * Print normalized SCSI sense header with device information and a prefix.
+ */
 void
-__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
-                  int sense_len)
+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)
 {
        int k, num, res;
-       unsigned int info;
-       struct scsi_sense_hdr ssh;
     
-       res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
+       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(KERN_INFO "Unrecognized sense data (in hex):");
+               printk("Unrecognized sense data (in hex):");
                for (k = 0; k < num; ++k) {
                        if (0 == (k % 16)) {
                                printk("\n");
@@ -1247,11 +1321,20 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                printk("\n");
                return;
        }
-       scsi_print_sense_hdr(name, &ssh);
-       if (ssh.response_code < 0x72) {
+}
+
+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) |
@@ -1281,13 +1364,13 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                        res += snprintf(buff + res, blen - res, "ILI");
                }
                if (res > 0)
-                       printk(KERN_INFO "%s\n", buff);
-       } else if (ssh.additional_length > 0) {
+                       printk("%s\n", buff);
+       } else if (sshdr->additional_length > 0) {
                /* descriptor format with sense descriptors */
-               num = 8 + ssh.additional_length;
+               num = 8 + sshdr->additional_length;
                num = (sense_len < num) ? sense_len : num;
-               printk(KERN_INFO "Descriptor sense data with sense "
-                      "descriptors (in hex):");
+               printk("Descriptor sense data with sense descriptors "
+                      "(in hex):");
                for (k = 0; k < num; ++k) {
                        if (0 == (k % 16)) {
                                printk("\n");
@@ -1295,80 +1378,84 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                        }
                        printk("%02x ", sense_buffer[k]);
                }
+
                printk("\n");
        }
+
 }
-EXPORT_SYMBOL(__scsi_print_sense);
 
-void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer with name prefix */
+void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+                       int sense_len)
 {
-       const char *name = devclass;
-
-       if (cmd->request->rq_disk)
-               name = cmd->request->rq_disk->disk_name;
-       __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+       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);
 }
-EXPORT_SYMBOL(scsi_print_sense);
+EXPORT_SYMBOL(__scsi_print_sense);
 
-void scsi_print_command(struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer in SCSI command */
+void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
 {
-       /* Assume appended output (i.e. not at start of line) */
-       sdev_printk("", cmd->device, "\n");
-       printk(KERN_INFO "        command: ");
-       scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0);
+       struct scsi_sense_hdr sshdr;
+
+       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);
 }
-EXPORT_SYMBOL(scsi_print_command);
+EXPORT_SYMBOL(scsi_print_sense);
 
 #ifdef CONFIG_SCSI_CONSTANTS
 
 static const char * const hostbyte_table[]={
 "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
 "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
-"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
+"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
+"DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST" };
 #define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
 
-void scsi_print_hostbyte(int scsiresult)
-{
-       int hb = host_byte(scsiresult);
-
-       printk("Hostbyte=0x%02x", hb);
-       if (hb < NUM_HOSTBYTE_STRS)
-               printk("(%s) ", hostbyte_table[hb]);
-       else
-               printk("is invalid ");
-}
-#else
-void scsi_print_hostbyte(int scsiresult)
-{
-       printk("Hostbyte=0x%02x ", host_byte(scsiresult));
-}
-#endif
-
-#ifdef CONFIG_SCSI_CONSTANTS
-
 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)
 
-static const char * const driversuggest_table[]={"SUGGEST_OK",
-"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
-"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
-#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
-
-void scsi_print_driverbyte(int scsiresult)
+void scsi_show_result(int result)
 {
-       int dr = (driver_byte(scsiresult) & DRIVER_MASK);
-       int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4);
+       int hb = host_byte(result);
+       int db = driver_byte(result);
 
-       printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
-       printk("(%s,%s) ",
-              (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"),
-              (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid"));
+       printk("Result: hostbyte=%s driverbyte=%s\n",
+              (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb]     : "invalid"),
+              (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"));
 }
+
 #else
-void scsi_print_driverbyte(int scsiresult)
+
+void scsi_show_result(int result)
 {
-       printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
+       printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n",
+              host_byte(result), driver_byte(result));
 }
+
 #endif
+EXPORT_SYMBOL(scsi_show_result);
+
+
+void scsi_print_result(struct scsi_cmnd *cmd)
+{
+       scmd_printk(KERN_INFO, cmd, "");
+       scsi_show_result(cmd->result);
+}
+EXPORT_SYMBOL(scsi_print_result);
+
+