summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi/scsi_all.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/scsi/scsi_all.c')
-rw-r--r--sys/cam/scsi/scsi_all.c1834
1 files changed, 835 insertions, 999 deletions
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index cd74165..cb0f9d6 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -1,7 +1,7 @@
/*
* Implementation of Utility functions for all SCSI device types.
*
- * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
* Copyright (c) 1997, 1998 Kenneth D. Merry.
* All rights reserved.
*
@@ -35,9 +35,11 @@
#include <opt_scsi.h>
#include <sys/systm.h>
+#include <sys/libkern.h>
#else
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#endif
@@ -45,6 +47,7 @@
#include <cam/cam_ccb.h>
#include <cam/cam_xpt.h>
#include <cam/scsi/scsi_all.h>
+#include <sys/sbuf.h>
#ifndef _KERNEL
#include <camlib.h>
@@ -58,25 +61,12 @@
#define EJUSTRETURN -2 /* don't modify regs, just return */
#endif /* !_KERNEL */
-const char *scsi_sense_key_text[] =
-{
- "NO SENSE",
- "RECOVERED ERROR",
- "NOT READY",
- "MEDIUM ERROR",
- "HARDWARE FAILURE",
- "ILLEGAL REQUEST",
- "UNIT ATTENTION",
- "DATA PROTECT",
- "BLANK CHECK",
- "Vendor Specific",
- "COPY ABORTED",
- "ABORTED COMMAND",
- "EQUAL",
- "VOLUME OVERFLOW",
- "MISCOMPARE",
- "RESERVED"
-};
+static int ascentrycomp(const void *key, const void *member);
+static int senseentrycomp(const void *key, const void *member);
+static void fetchtableentries(int sense_key, int asc, int ascq,
+ struct scsi_inquiry_data *,
+ const struct sense_key_table_entry **,
+ const struct asc_table_entry **);
#if !defined(SCSI_NO_OP_STRINGS)
@@ -95,10 +85,6 @@ const char *scsi_sense_key_text[] =
#define ALL 0xFFF
-/*
- * WARNING: You must update the num_ops field below for this quirk table
- * entry if you add more entries.
- */
static struct op_table_entry plextor_cd_ops[] = {
{0xD8, R, "CD-DA READ"}
};
@@ -115,7 +101,7 @@ static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
* feel free to change this quirk entry.
*/
{T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
- 1, /* number of vendor-specific opcodes for this entry */
+ sizeof(plextor_cd_ops)/sizeof(struct op_table_entry),
plextor_cd_ops
}
};
@@ -701,27 +687,48 @@ scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
#include <sys/param.h>
-
#if !defined(SCSI_NO_SENSE_STRINGS)
#define SST(asc, ascq, action, desc) \
asc, ascq, action, desc
#else
+const char empty_string[] = "";
+
#define SST(asc, ascq, action, desc) \
- asc, ascq, action
+ asc, ascq, action, empty_string
#endif
static const char quantum[] = "QUANTUM";
-/*
- * WARNING: You must update the num_ascs field below for this quirk table
- * entry if you add more entries.
- */
+const struct sense_key_table_entry sense_key_table[] =
+{
+ { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
+ { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
+ {
+ SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
+ "NOT READY"
+ },
+ { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
+ { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
+ { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
+ { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
+ { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
+ { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
+ { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
+ { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
+ { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
+ { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
+ { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
+};
+
+const int sense_key_table_size =
+ sizeof(sense_key_table)/sizeof(sense_key_table[0]);
+
static struct asc_table_entry quantum_fireball_entries[] = {
{SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
"Logical unit not ready, initializing cmd. required")}
};
-static struct scsi_sense_quirk_entry asc_quirk_table[] = {
+static struct scsi_sense_quirk_entry sense_quirk_table[] = {
{
/*
* The Quantum Fireball ST and SE like to return 0x04 0x0b when
@@ -730,12 +737,17 @@ static struct scsi_sense_quirk_entry asc_quirk_table[] = {
* hardware manual for these drives.
*/
{T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
- 1, /* number of vendor-specific sense codes for this entry */
+ /*num_sense_keys*/0,
+ sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
+ /*sense key entries*/NULL,
quantum_fireball_entries
}
};
-static struct asc_table_entry asc_text[] = {
+const int sense_quirk_table_size =
+ sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
+
+static struct asc_table_entry asc_table[] = {
/*
* From File: ASC-NUM.TXT
* SCSI ASC/ASCQ Assignments
@@ -756,43 +768,43 @@ static struct asc_table_entry asc_text[] = {
* . . . . E - ENCLOSURE SERVICES DEVICE (SES)
* DTLPWRSOMCAE ASC ASCQ Action Description
* ------------ ---- ---- ------ -----------------------------------*/
-/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NEPDEF,
+/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
"No additional sense information") },
-/* T S */{SST(0x00, 0x01, SS_DEF,
+/* T S */{SST(0x00, 0x01, SS_RDEF,
"Filemark detected") },
-/* T S */{SST(0x00, 0x02, SS_DEF,
+/* T S */{SST(0x00, 0x02, SS_RDEF,
"End-of-partition/medium detected") },
-/* T */{SST(0x00, 0x03, SS_DEF,
+/* T */{SST(0x00, 0x03, SS_RDEF,
"Setmark detected") },
-/* T S */{SST(0x00, 0x04, SS_DEF,
+/* T S */{SST(0x00, 0x04, SS_RDEF,
"Beginning-of-partition/medium detected") },
-/* T S */{SST(0x00, 0x05, SS_DEF,
+/* T S */{SST(0x00, 0x05, SS_RDEF,
"End-of-data detected") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
"I/O process terminated") },
-/* R */{SST(0x00, 0x11, SS_NEDEF|EBUSY,
+/* R */{SST(0x00, 0x11, SS_FATAL|EBUSY,
"Audio play operation in progress") },
-/* R */{SST(0x00, 0x12, SS_NEDEF,
+/* R */{SST(0x00, 0x12, SS_NOP,
"Audio play operation paused") },
-/* R */{SST(0x00, 0x13, SS_NEDEF,
+/* R */{SST(0x00, 0x13, SS_NOP,
"Audio play operation successfully completed") },
-/* R */{SST(0x00, 0x14, SS_DEF,
+/* R */{SST(0x00, 0x14, SS_RDEF,
"Audio play operation stopped due to error") },
-/* R */{SST(0x00, 0x15, SS_DEF,
+/* R */{SST(0x00, 0x15, SS_NOP,
"No current audio status to return") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_NEDEF|EBUSY,
+/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
"Operation in progress") },
-/* DTL WRSOM AE */{SST(0x00, 0x17, SS_DEF,
+/* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
"Cleaning requested") },
-/* D W O */{SST(0x01, 0x00, SS_DEF,
+/* D W O */{SST(0x01, 0x00, SS_RDEF,
"No index/sector signal") },
-/* D WR OM */{SST(0x02, 0x00, SS_DEF,
+/* D WR OM */{SST(0x02, 0x00, SS_RDEF,
"No seek complete") },
-/* DTL W SO */{SST(0x03, 0x00, SS_DEF,
+/* DTL W SO */{SST(0x03, 0x00, SS_RDEF,
"Peripheral device write fault") },
-/* T */{SST(0x03, 0x01, SS_DEF,
+/* T */{SST(0x03, 0x01, SS_RDEF,
"No write current") },
-/* T */{SST(0x03, 0x02, SS_DEF,
+/* T */{SST(0x03, 0x02, SS_RDEF,
"Excessive write errors") },
/* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
"Logical unit not ready, cause not reportable") },
@@ -800,754 +812,864 @@ static struct asc_table_entry asc_text[] = {
"Logical unit is in process of becoming ready") },
/* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
"Logical unit not ready, initializing cmd. required") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_NEDEF|ENXIO,
+/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
"Logical unit not ready, manual intervention required")},
-/* DTL O */{SST(0x04, 0x04, SS_NEDEF|EBUSY,
+/* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY,
"Logical unit not ready, format in progress") },
-/* DT W OMCA */{SST(0x04, 0x05, SS_NEDEF|EBUSY,
+/* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY,
"Logical unit not ready, rebuild in progress") },
-/* DT W OMCA */{SST(0x04, 0x06, SS_NEDEF|EBUSY,
+/* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY,
"Logical unit not ready, recalculation in progress") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_NEDEF|EBUSY,
+/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
"Logical unit not ready, operation in progress") },
-/* R */{SST(0x04, 0x08, SS_NEDEF|EBUSY,
+/* R */{SST(0x04, 0x08, SS_FATAL|EBUSY,
"Logical unit not ready, long write in progress") },
-/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
"Logical unit does not respond to selection") },
-/* D WR OM */{SST(0x06, 0x00, SS_DEF,
+/* D WR OM */{SST(0x06, 0x00, SS_RDEF,
"No reference position found") },
-/* DTL WRSOM */{SST(0x07, 0x00, SS_DEF,
+/* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF,
"Multiple peripheral devices selected") },
-/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
"Logical unit communication failure") },
-/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
"Logical unit communication time-out") },
-/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
"Logical unit communication parity error") },
-/* DT R OM */{SST(0x08, 0x03, SS_DEF,
+/* DT R OM */{SST(0x08, 0x03, SS_RDEF,
"Logical unit communication crc error (ultra-dma/32)")},
-/* DT WR O */{SST(0x09, 0x00, SS_DEF,
+/* DT WR O */{SST(0x09, 0x00, SS_RDEF,
"Track following error") },
-/* WR O */{SST(0x09, 0x01, SS_DEF,
+/* WR O */{SST(0x09, 0x01, SS_RDEF,
"Tracking servo failure") },
-/* WR O */{SST(0x09, 0x02, SS_DEF,
+/* WR O */{SST(0x09, 0x02, SS_RDEF,
"Focus servo failure") },
-/* WR O */{SST(0x09, 0x03, SS_DEF,
+/* WR O */{SST(0x09, 0x03, SS_RDEF,
"Spindle servo failure") },
-/* DT WR O */{SST(0x09, 0x04, SS_DEF,
+/* DT WR O */{SST(0x09, 0x04, SS_RDEF,
"Head select fault") },
-/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_NEDEF|ENOSPC,
+/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
"Error log overflow") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
"Warning") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
"Specified temperature exceeded") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
"Enclosure degraded") },
-/* T RS */{SST(0x0C, 0x00, SS_DEF,
+/* T RS */{SST(0x0C, 0x00, SS_RDEF,
"Write error") },
-/* D W O */{SST(0x0C, 0x01, SS_NEDEF,
+/* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
"Write error - recovered with auto reallocation") },
-/* D W O */{SST(0x0C, 0x02, SS_DEF,
+/* D W O */{SST(0x0C, 0x02, SS_RDEF,
"Write error - auto reallocation failed") },
-/* D W O */{SST(0x0C, 0x03, SS_DEF,
+/* D W O */{SST(0x0C, 0x03, SS_RDEF,
"Write error - recommend reassignment") },
-/* DT W O */{SST(0x0C, 0x04, SS_NEPDEF,
+/* DT W O */{SST(0x0C, 0x04, SS_RDEF,
"Compression check miscompare error") },
-/* DT W O */{SST(0x0C, 0x05, SS_DEF,
+/* DT W O */{SST(0x0C, 0x05, SS_RDEF,
"Data expansion occurred during compression") },
-/* DT W O */{SST(0x0C, 0x06, SS_DEF,
+/* DT W O */{SST(0x0C, 0x06, SS_RDEF,
"Block not compressible") },
-/* R */{SST(0x0C, 0x07, SS_DEF,
+/* R */{SST(0x0C, 0x07, SS_RDEF,
"Write error - recovery needed") },
-/* R */{SST(0x0C, 0x08, SS_DEF,
+/* R */{SST(0x0C, 0x08, SS_RDEF,
"Write error - recovery failed") },
-/* R */{SST(0x0C, 0x09, SS_DEF,
+/* R */{SST(0x0C, 0x09, SS_RDEF,
"Write error - loss of streaming") },
-/* R */{SST(0x0C, 0x0A, SS_DEF,
+/* R */{SST(0x0C, 0x0A, SS_RDEF,
"Write error - padding blocks added") },
-/* D W O */{SST(0x10, 0x00, SS_DEF,
+/* D W O */{SST(0x10, 0x00, SS_RDEF,
"ID CRC or ECC error") },
-/* DT WRSO */{SST(0x11, 0x00, SS_DEF,
+/* DT WRSO */{SST(0x11, 0x00, SS_RDEF,
"Unrecovered read error") },
-/* DT W SO */{SST(0x11, 0x01, SS_DEF,
+/* DT W SO */{SST(0x11, 0x01, SS_RDEF,
"Read retries exhausted") },
-/* DT W SO */{SST(0x11, 0x02, SS_DEF,
+/* DT W SO */{SST(0x11, 0x02, SS_RDEF,
"Error too long to correct") },
-/* DT W SO */{SST(0x11, 0x03, SS_DEF,
+/* DT W SO */{SST(0x11, 0x03, SS_RDEF,
"Multiple read errors") },
-/* D W O */{SST(0x11, 0x04, SS_DEF,
+/* D W O */{SST(0x11, 0x04, SS_RDEF,
"Unrecovered read error - auto reallocate failed") },
-/* WR O */{SST(0x11, 0x05, SS_DEF,
+/* WR O */{SST(0x11, 0x05, SS_RDEF,
"L-EC uncorrectable error") },
-/* WR O */{SST(0x11, 0x06, SS_DEF,
+/* WR O */{SST(0x11, 0x06, SS_RDEF,
"CIRC unrecovered error") },
-/* W O */{SST(0x11, 0x07, SS_DEF,
+/* W O */{SST(0x11, 0x07, SS_RDEF,
"Data re-synchronization error") },
-/* T */{SST(0x11, 0x08, SS_DEF,
+/* T */{SST(0x11, 0x08, SS_RDEF,
"Incomplete block read") },
-/* T */{SST(0x11, 0x09, SS_DEF,
+/* T */{SST(0x11, 0x09, SS_RDEF,
"No gap found") },
-/* DT O */{SST(0x11, 0x0A, SS_DEF,
+/* DT O */{SST(0x11, 0x0A, SS_RDEF,
"Miscorrected error") },
-/* D W O */{SST(0x11, 0x0B, SS_DEF,
+/* D W O */{SST(0x11, 0x0B, SS_RDEF,
"Unrecovered read error - recommend reassignment") },
-/* D W O */{SST(0x11, 0x0C, SS_DEF,
+/* D W O */{SST(0x11, 0x0C, SS_RDEF,
"Unrecovered read error - recommend rewrite the data")},
-/* DT WR O */{SST(0x11, 0x0D, SS_DEF,
+/* DT WR O */{SST(0x11, 0x0D, SS_RDEF,
"De-compression CRC error") },
-/* DT WR O */{SST(0x11, 0x0E, SS_DEF,
+/* DT WR O */{SST(0x11, 0x0E, SS_RDEF,
"Cannot decompress using declared algorithm") },
-/* R */{SST(0x11, 0x0F, SS_DEF,
+/* R */{SST(0x11, 0x0F, SS_RDEF,
"Error reading UPC/EAN number") },
-/* R */{SST(0x11, 0x10, SS_DEF,
+/* R */{SST(0x11, 0x10, SS_RDEF,
"Error reading ISRC number") },
-/* R */{SST(0x11, 0x11, SS_DEF,
+/* R */{SST(0x11, 0x11, SS_RDEF,
"Read error - loss of streaming") },
-/* D W O */{SST(0x12, 0x00, SS_DEF,
+/* D W O */{SST(0x12, 0x00, SS_RDEF,
"Address mark not found for id field") },
-/* D W O */{SST(0x13, 0x00, SS_DEF,
+/* D W O */{SST(0x13, 0x00, SS_RDEF,
"Address mark not found for data field") },
-/* DTL WRSO */{SST(0x14, 0x00, SS_DEF,
+/* DTL WRSO */{SST(0x14, 0x00, SS_RDEF,
"Recorded entity not found") },
-/* DT WR O */{SST(0x14, 0x01, SS_DEF,
+/* DT WR O */{SST(0x14, 0x01, SS_RDEF,
"Record not found") },
-/* T */{SST(0x14, 0x02, SS_DEF,
+/* T */{SST(0x14, 0x02, SS_RDEF,
"Filemark or setmark not found") },
-/* T */{SST(0x14, 0x03, SS_DEF,
+/* T */{SST(0x14, 0x03, SS_RDEF,
"End-of-data not found") },
-/* T */{SST(0x14, 0x04, SS_DEF,
+/* T */{SST(0x14, 0x04, SS_RDEF,
"Block sequence error") },
-/* DT W O */{SST(0x14, 0x05, SS_DEF,
+/* DT W O */{SST(0x14, 0x05, SS_RDEF,
"Record not found - recommend reassignment") },
-/* DT W O */{SST(0x14, 0x06, SS_DEF,
+/* DT W O */{SST(0x14, 0x06, SS_RDEF,
"Record not found - data auto-reallocated") },
-/* DTL WRSOM */{SST(0x15, 0x00, SS_DEF,
+/* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF,
"Random positioning error") },
-/* DTL WRSOM */{SST(0x15, 0x01, SS_DEF,
+/* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF,
"Mechanical positioning error") },
-/* DT WR O */{SST(0x15, 0x02, SS_DEF,
+/* DT WR O */{SST(0x15, 0x02, SS_RDEF,
"Positioning error detected by read of medium") },
-/* D W O */{SST(0x16, 0x00, SS_DEF,
+/* D W O */{SST(0x16, 0x00, SS_RDEF,
"Data synchronization mark error") },
-/* D W O */{SST(0x16, 0x01, SS_DEF,
+/* D W O */{SST(0x16, 0x01, SS_RDEF,
"Data sync error - data rewritten") },
-/* D W O */{SST(0x16, 0x02, SS_DEF,
+/* D W O */{SST(0x16, 0x02, SS_RDEF,
"Data sync error - recommend rewrite") },
-/* D W O */{SST(0x16, 0x03, SS_NEDEF,
+/* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
"Data sync error - data auto-reallocated") },
-/* D W O */{SST(0x16, 0x04, SS_DEF,
+/* D W O */{SST(0x16, 0x04, SS_RDEF,
"Data sync error - recommend reassignment") },
-/* DT WRSO */{SST(0x17, 0x00, SS_NEDEF,
+/* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with no error correction applied") },
-/* DT WRSO */{SST(0x17, 0x01, SS_NEDEF,
+/* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with retries") },
-/* DT WR O */{SST(0x17, 0x02, SS_NEDEF,
+/* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with positive head offset") },
-/* DT WR O */{SST(0x17, 0x03, SS_NEDEF,
+/* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with negative head offset") },
-/* WR O */{SST(0x17, 0x04, SS_NEDEF,
+/* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with retries and/or CIRC applied") },
-/* D WR O */{SST(0x17, 0x05, SS_NEDEF,
+/* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data using previous sector id") },
-/* D W O */{SST(0x17, 0x06, SS_NEDEF,
+/* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data without ECC - data auto-reallocated") },
-/* D W O */{SST(0x17, 0x07, SS_NEDEF,
+/* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data without ECC - recommend reassignment")},
-/* D W O */{SST(0x17, 0x08, SS_NEDEF,
+/* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data without ECC - recommend rewrite") },
-/* D W O */{SST(0x17, 0x09, SS_NEDEF,
+/* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data without ECC - data rewritten") },
-/* D W O */{SST(0x18, 0x00, SS_NEDEF,
+/* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with error correction applied") },
-/* D WR O */{SST(0x18, 0x01, SS_NEDEF,
+/* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with error corr. & retries applied") },
-/* D WR O */{SST(0x18, 0x02, SS_NEDEF,
+/* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data - data auto-reallocated") },
-/* R */{SST(0x18, 0x03, SS_NEDEF,
+/* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with CIRC") },
-/* R */{SST(0x18, 0x04, SS_NEDEF,
+/* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with L-EC") },
-/* D WR O */{SST(0x18, 0x05, SS_NEDEF,
+/* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data - recommend reassignment") },
-/* D WR O */{SST(0x18, 0x06, SS_NEDEF,
+/* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data - recommend rewrite") },
-/* D W O */{SST(0x18, 0x07, SS_NEDEF,
+/* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
"Recovered data with ECC - data rewritten") },
-/* D O */{SST(0x19, 0x00, SS_DEF,
+/* D O */{SST(0x19, 0x00, SS_RDEF,
"Defect list error") },
-/* D O */{SST(0x19, 0x01, SS_DEF,
+/* D O */{SST(0x19, 0x01, SS_RDEF,
"Defect list not available") },
-/* D O */{SST(0x19, 0x02, SS_DEF,
+/* D O */{SST(0x19, 0x02, SS_RDEF,
"Defect list error in primary list") },
-/* D O */{SST(0x19, 0x03, SS_DEF,
+/* D O */{SST(0x19, 0x03, SS_RDEF,
"Defect list error in grown list") },
-/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
"Parameter list length error") },
-/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
"Synchronous data transfer error") },
-/* D O */{SST(0x1C, 0x00, SS_DEF,
+/* D O */{SST(0x1C, 0x00, SS_RDEF,
"Defect list not found") },
-/* D O */{SST(0x1C, 0x01, SS_DEF,
+/* D O */{SST(0x1C, 0x01, SS_RDEF,
"Primary defect list not found") },
-/* D O */{SST(0x1C, 0x02, SS_DEF,
+/* D O */{SST(0x1C, 0x02, SS_RDEF,
"Grown defect list not found") },
-/* D W O */{SST(0x1D, 0x00, SS_NEPDEF,
+/* D W O */{SST(0x1D, 0x00, SS_FATAL,
"Miscompare during verify operation" )},
-/* D W O */{SST(0x1E, 0x00, SS_NEDEF,
+/* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
"Recovered id with ecc correction") },
-/* D O */{SST(0x1F, 0x00, SS_DEF,
+/* D O */{SST(0x1F, 0x00, SS_RDEF,
"Partial defect list transfer") },
-/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
"Invalid command operation code") },
-/* DT WR OM */{SST(0x21, 0x00, SS_DEF,
+/* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL,
"Logical block address out of range" )},
-/* DT WR OM */{SST(0x21, 0x01, SS_DEF,
+/* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL,
"Invalid element address") },
-/* D */{SST(0x22, 0x00, SS_DEF,
+/* D */{SST(0x22, 0x00, SS_FATAL|EINVAL,
"Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
-/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_NEDEF|EINVAL,
+/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
"Invalid field in CDB") },
-/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_NEDEF|ENXIO,
+/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
"Logical unit not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_NEDEF|EINVAL,
+/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
"Invalid field in parameter list") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_NEDEF|EINVAL,
+/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
"Parameter not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_NEDEF|EINVAL,
+/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
"Parameter value invalid") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
"Threshold parameters not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
"Invalid release of active persistent reservation") },
-/* DT W O */{SST(0x27, 0x00, SS_NEDEF|EACCES,
+/* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES,
"Write protected") },
-/* DT W O */{SST(0x27, 0x01, SS_NEDEF|EACCES,
+/* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES,
"Hardware write protected") },
-/* DT W O */{SST(0x27, 0x02, SS_NEDEF|EACCES,
+/* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES,
"Logical unit software write protected") },
-/* T */{SST(0x27, 0x03, SS_NEDEF|EACCES,
+/* T */{SST(0x27, 0x03, SS_FATAL|EACCES,
"Associated write protect") },
-/* T */{SST(0x27, 0x04, SS_NEDEF|EACCES,
+/* T */{SST(0x27, 0x04, SS_FATAL|EACCES,
"Persistent write protect") },
-/* T */{SST(0x27, 0x05, SS_NEDEF|EACCES,
+/* T */{SST(0x27, 0x05, SS_FATAL|EACCES,
"Permanent write protect") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_NEDEF|ENXIO,
+/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_FATAL|ENXIO,
"Not ready to ready change, medium may have changed") },
-/* DT WR OM */{SST(0x28, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
"Import or export element accessed") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_NEDEF|ENXIO,
+/*
+ * XXX JGibbs - All of these should use the same errno, but I don't think
+ * ENXIO is the correct choice. Should we borrow from the networking
+ * errnos? ECONNRESET anyone?
+ */
+/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_FATAL|ENXIO,
"Power on, reset, or bus device reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
"Power on occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
"Scsi bus reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
"Bus device reset function occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
"Device internal reset") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
"Transceiver mode changed to single-ended") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
"Transceiver mode changed to LVD") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
"Parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
"Mode parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
"Log parameters changed") },
-/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
"Reservations preempted") },
-/* DTLPWRSO C */{SST(0x2B, 0x00, SS_DEF,
+/* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF,
"Copy cannot execute since host cannot disconnect") },
-/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
"Command sequence error") },
-/* S */{SST(0x2C, 0x01, SS_DEF,
+/* S */{SST(0x2C, 0x01, SS_RDEF,
"Too many windows specified") },
-/* S */{SST(0x2C, 0x02, SS_DEF,
+/* S */{SST(0x2C, 0x02, SS_RDEF,
"Invalid combination of windows specified") },
-/* R */{SST(0x2C, 0x03, SS_DEF,
+/* R */{SST(0x2C, 0x03, SS_RDEF,
"Current program area is not empty") },
-/* R */{SST(0x2C, 0x04, SS_DEF,
+/* R */{SST(0x2C, 0x04, SS_RDEF,
"Current program area is empty") },
-/* T */{SST(0x2D, 0x00, SS_DEF,
+/* T */{SST(0x2D, 0x00, SS_RDEF,
"Overwrite error on update in place") },
-/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
"Commands cleared by another initiator") },
-/* DT WR OM */{SST(0x30, 0x00, SS_DEF,
+/* DT WR OM */{SST(0x30, 0x00, SS_RDEF,
"Incompatible medium installed") },
-/* DT WR O */{SST(0x30, 0x01, SS_DEF,
+/* DT WR O */{SST(0x30, 0x01, SS_RDEF,
"Cannot read medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x02, SS_DEF,
+/* DT WR O */{SST(0x30, 0x02, SS_RDEF,
"Cannot read medium - incompatible format") },
-/* DT */{SST(0x30, 0x03, SS_DEF,
+/* DT */{SST(0x30, 0x03, SS_RDEF,
"Cleaning cartridge installed") },
-/* DT WR O */{SST(0x30, 0x04, SS_DEF,
+/* DT WR O */{SST(0x30, 0x04, SS_RDEF,
"Cannot write medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x05, SS_DEF,
+/* DT WR O */{SST(0x30, 0x05, SS_RDEF,
"Cannot write medium - incompatible format") },
-/* DT W O */{SST(0x30, 0x06, SS_DEF,
+/* DT W O */{SST(0x30, 0x06, SS_RDEF,
"Cannot format medium - incompatible medium") },
-/* DTL WRSOM AE */{SST(0x30, 0x07, SS_DEF,
+/* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
"Cleaning failure") },
-/* R */{SST(0x30, 0x08, SS_DEF,
+/* R */{SST(0x30, 0x08, SS_RDEF,
"Cannot write - application code mismatch") },
-/* R */{SST(0x30, 0x09, SS_DEF,
+/* R */{SST(0x30, 0x09, SS_RDEF,
"Current session not fixated for append") },
-/* DT WR O */{SST(0x31, 0x00, SS_DEF,
+/* DT WR O */{SST(0x31, 0x00, SS_RDEF,
"Medium format corrupted") },
-/* D L R O */{SST(0x31, 0x01, SS_DEF,
+/* D L R O */{SST(0x31, 0x01, SS_RDEF,
"Format command failed") },
-/* D W O */{SST(0x32, 0x00, SS_DEF,
+/* D W O */{SST(0x32, 0x00, SS_RDEF,
"No defect spare location available") },
-/* D W O */{SST(0x32, 0x01, SS_DEF,
+/* D W O */{SST(0x32, 0x01, SS_RDEF,
"Defect list update failure") },
-/* T */{SST(0x33, 0x00, SS_DEF,
+/* T */{SST(0x33, 0x00, SS_RDEF,
"Tape length error") },
-/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
"Enclosure failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
"Enclosure services failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
"Unsupported enclosure function") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
"Enclosure services unavailable") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
"Enclosure services transfer failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
"Enclosure services transfer refused") },
-/* L */{SST(0x36, 0x00, SS_DEF,
+/* L */{SST(0x36, 0x00, SS_RDEF,
"Ribbon, ink, or toner failure") },
-/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
"Rounded parameter") },
-/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_DEF,
+/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
"Saving parameters not supported") },
-/* DTL WRSOM */{SST(0x3A, 0x00, SS_NEDEF|ENXIO,
+/* DTL WRSOM */{SST(0x3A, 0x00, SS_FATAL|ENXIO,
"Medium not present") },
-/* DT WR OM */{SST(0x3A, 0x01, SS_NEDEF|ENXIO,
+/* DT WR OM */{SST(0x3A, 0x01, SS_FATAL|ENXIO,
"Medium not present - tray closed") },
-/* DT WR OM */{SST(0x3A, 0x02, SS_NEDEF|ENXIO,
+/* DT WR OM */{SST(0x3A, 0x02, SS_FATAL|ENXIO,
"Medium not present - tray open") },
-/* TL */{SST(0x3B, 0x00, SS_DEF,
+/* TL */{SST(0x3B, 0x00, SS_RDEF,
"Sequential positioning error") },
-/* T */{SST(0x3B, 0x01, SS_DEF,
+/* T */{SST(0x3B, 0x01, SS_RDEF,
"Tape position error at beginning-of-medium") },
-/* T */{SST(0x3B, 0x02, SS_DEF,
+/* T */{SST(0x3B, 0x02, SS_RDEF,
"Tape position error at end-of-medium") },
-/* L */{SST(0x3B, 0x03, SS_DEF,
+/* L */{SST(0x3B, 0x03, SS_RDEF,
"Tape or electronic vertical forms unit not ready") },
-/* L */{SST(0x3B, 0x04, SS_DEF,
+/* L */{SST(0x3B, 0x04, SS_RDEF,
"Slew failure") },
-/* L */{SST(0x3B, 0x05, SS_DEF,
+/* L */{SST(0x3B, 0x05, SS_RDEF,
"Paper jam") },
-/* L */{SST(0x3B, 0x06, SS_DEF,
+/* L */{SST(0x3B, 0x06, SS_RDEF,
"Failed to sense top-of-form") },
-/* L */{SST(0x3B, 0x07, SS_DEF,
+/* L */{SST(0x3B, 0x07, SS_RDEF,
"Failed to sense bottom-of-form") },
-/* T */{SST(0x3B, 0x08, SS_DEF,
+/* T */{SST(0x3B, 0x08, SS_RDEF,
"Reposition error") },
-/* S */{SST(0x3B, 0x09, SS_DEF,
+/* S */{SST(0x3B, 0x09, SS_RDEF,
"Read past end of medium") },
-/* S */{SST(0x3B, 0x0A, SS_DEF,
+/* S */{SST(0x3B, 0x0A, SS_RDEF,
"Read past beginning of medium") },
-/* S */{SST(0x3B, 0x0B, SS_DEF,
+/* S */{SST(0x3B, 0x0B, SS_RDEF,
"Position past end of medium") },
-/* T S */{SST(0x3B, 0x0C, SS_DEF,
+/* T S */{SST(0x3B, 0x0C, SS_RDEF,
"Position past beginning of medium") },
-/* DT WR OM */{SST(0x3B, 0x0D, SS_NEDEF|ENOSPC,
+/* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
"Medium destination element full") },
-/* DT WR OM */{SST(0x3B, 0x0E, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF,
"Medium source element empty") },
-/* R */{SST(0x3B, 0x0F, SS_DEF,
+/* R */{SST(0x3B, 0x0F, SS_RDEF,
"End of medium reached") },
-/* DT WR OM */{SST(0x3B, 0x11, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x11, SS_RDEF,
"Medium magazine not accessible") },
-/* DT WR OM */{SST(0x3B, 0x12, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x12, SS_RDEF,
"Medium magazine removed") },
-/* DT WR OM */{SST(0x3B, 0x13, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x13, SS_RDEF,
"Medium magazine inserted") },
-/* DT WR OM */{SST(0x3B, 0x14, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x14, SS_RDEF,
"Medium magazine locked") },
-/* DT WR OM */{SST(0x3B, 0x15, SS_DEF,
+/* DT WR OM */{SST(0x3B, 0x15, SS_RDEF,
"Medium magazine unlocked") },
-/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
"Invalid bits in identify message") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
"Logical unit has not self-configured yet") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
"Logical unit failure") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
"Timeout on logical unit") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
"Target operating conditions have changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
"Microcode has been changed") },
-/* DTLPWRSOMC */{SST(0x3F, 0x02, SS_DEF,
+/* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF,
"Changed operating definition") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_RDEF,
"Inquiry data has changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x04, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
"Component device attached") },
-/* DT WR OMCAE */{SST(0x3F, 0x05, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
"Device identifier changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x06, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
"Redundancy group created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x07, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
"Redundancy group deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x08, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
"Spare created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x09, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
"Spare deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0A, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
"Volume set created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x0B, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
"Volume set deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0C, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
"Volume set deassigned") },
-/* DT WR OMCAE */{SST(0x3F, 0x0D, SS_DEF,
+/* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
"Volume set reassigned") },
-/* D */{SST(0x40, 0x00, SS_DEF,
+/* D */{SST(0x40, 0x00, SS_RDEF,
"Ram failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
"Diagnostic failure: ASCQ = Component ID") },
-/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_DEF|SSQ_RANGE,
+/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
NULL) },/* Range 0x80->0xFF */
-/* D */{SST(0x41, 0x00, SS_DEF,
+/* D */{SST(0x41, 0x00, SS_RDEF,
"Data path failure") }, /* deprecated - use 40 NN instead */
-/* D */{SST(0x42, 0x00, SS_DEF,
+/* D */{SST(0x42, 0x00, SS_RDEF,
"Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
"Message error") },
-/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
"Internal target failure") },
-/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
"Select or reselect failure") },
-/* DTLPWRSOMC */{SST(0x46, 0x00, SS_DEF,
+/* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF,
"Unsuccessful soft reset") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF,
"SCSI parity error") },
-/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF,
"Initiator detected error message received") },
-/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
"Invalid message error") },
-/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
"Command phase error") },
-/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
"Data phase error") },
-/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
"Logical unit failed self-configuration") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
"Tagged overlapped commands: ASCQ = Queue tag ID") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_DEF|SSQ_RANGE,
+/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
NULL)}, /* Range 0x00->0xFF */
-/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
"Overlapped commands attempted") },
-/* T */{SST(0x50, 0x00, SS_DEF,
+/* T */{SST(0x50, 0x00, SS_RDEF,
"Write append error") },
-/* T */{SST(0x50, 0x01, SS_DEF,
+/* T */{SST(0x50, 0x01, SS_RDEF,
"Write append position error") },
-/* T */{SST(0x50, 0x02, SS_DEF,
+/* T */{SST(0x50, 0x02, SS_RDEF,
"Position error related to timing") },
-/* T O */{SST(0x51, 0x00, SS_DEF,
+/* T O */{SST(0x51, 0x00, SS_RDEF,
"Erase failure") },
-/* T */{SST(0x52, 0x00, SS_DEF,
+/* T */{SST(0x52, 0x00, SS_RDEF,
"Cartridge fault") },
-/* DTL WRSOM */{SST(0x53, 0x00, SS_DEF,
+/* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF,
"Media load or eject failed") },
-/* T */{SST(0x53, 0x01, SS_DEF,
+/* T */{SST(0x53, 0x01, SS_RDEF,
"Unload tape failure") },
-/* DT WR OM */{SST(0x53, 0x02, SS_DEF,
+/* DT WR OM */{SST(0x53, 0x02, SS_RDEF,
"Medium removal prevented") },
-/* P */{SST(0x54, 0x00, SS_DEF,
+/* P */{SST(0x54, 0x00, SS_RDEF,
"Scsi to host system interface failure") },
-/* P */{SST(0x55, 0x00, SS_DEF,
+/* P */{SST(0x55, 0x00, SS_RDEF,
"System resource failure") },
-/* D O */{SST(0x55, 0x01, SS_NEDEF|ENOSPC,
+/* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
"System buffer full") },
-/* R */{SST(0x57, 0x00, SS_DEF,
+/* R */{SST(0x57, 0x00, SS_RDEF,
"Unable to recover table-of-contents") },
-/* O */{SST(0x58, 0x00, SS_DEF,
+/* O */{SST(0x58, 0x00, SS_RDEF,
"Generation does not exist") },
-/* O */{SST(0x59, 0x00, SS_DEF,
+/* O */{SST(0x59, 0x00, SS_RDEF,
"Updated block read") },
-/* DTLPWRSOM */{SST(0x5A, 0x00, SS_DEF,
+/* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF,
"Operator request or state change input") },
-/* DT WR OM */{SST(0x5A, 0x01, SS_DEF,
+/* DT WR OM */{SST(0x5A, 0x01, SS_RDEF,
"Operator medium removal request") },
-/* DT W O */{SST(0x5A, 0x02, SS_DEF,
+/* DT W O */{SST(0x5A, 0x02, SS_RDEF,
"Operator selected write protect") },
-/* DT W O */{SST(0x5A, 0x03, SS_DEF,
+/* DT W O */{SST(0x5A, 0x03, SS_RDEF,
"Operator selected write permit") },
-/* DTLPWRSOM */{SST(0x5B, 0x00, SS_DEF,
+/* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF,
"Log exception") },
-/* DTLPWRSOM */{SST(0x5B, 0x01, SS_DEF,
+/* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF,
"Threshold condition met") },
-/* DTLPWRSOM */{SST(0x5B, 0x02, SS_DEF,
+/* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF,
"Log counter at maximum") },
-/* DTLPWRSOM */{SST(0x5B, 0x03, SS_DEF,
+/* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF,
"Log list codes exhausted") },
-/* D O */{SST(0x5C, 0x00, SS_DEF,
+/* D O */{SST(0x5C, 0x00, SS_RDEF,
"RPL status change") },
-/* D O */{SST(0x5C, 0x01, SS_NEDEF,
+/* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
"Spindles synchronized") },
-/* D O */{SST(0x5C, 0x02, SS_DEF,
+/* D O */{SST(0x5C, 0x02, SS_RDEF,
"Spindles not synchronized") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
"Failure prediction threshold exceeded") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
"Failure prediction threshold exceeded (false)") },
-/* DTLPWRSO CA */{SST(0x5E, 0x00, SS_DEF,
+/* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF,
"Low power condition on") },
-/* DTLPWRSO CA */{SST(0x5E, 0x01, SS_DEF,
+/* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF,
"Idle condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x02, SS_DEF,
+/* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF,
"Standby condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x03, SS_DEF,
+/* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF,
"Idle condition activated by command") },
-/* DTLPWRSO CA */{SST(0x5E, 0x04, SS_DEF,
+/* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF,
"Standby condition activated by command") },
-/* S */{SST(0x60, 0x00, SS_DEF,
+/* S */{SST(0x60, 0x00, SS_RDEF,
"Lamp failure") },
-/* S */{SST(0x61, 0x00, SS_DEF,
+/* S */{SST(0x61, 0x00, SS_RDEF,
"Video acquisition error") },
-/* S */{SST(0x61, 0x01, SS_DEF,
+/* S */{SST(0x61, 0x01, SS_RDEF,
"Unable to acquire video") },
-/* S */{SST(0x61, 0x02, SS_DEF,
+/* S */{SST(0x61, 0x02, SS_RDEF,
"Out of focus") },
-/* S */{SST(0x62, 0x00, SS_DEF,
+/* S */{SST(0x62, 0x00, SS_RDEF,
"Scan head positioning error") },
-/* R */{SST(0x63, 0x00, SS_DEF,
+/* R */{SST(0x63, 0x00, SS_RDEF,
"End of user area encountered on this track") },
-/* R */{SST(0x63, 0x01, SS_NEDEF|ENOSPC,
+/* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
"Packet does not fit in available space") },
-/* R */{SST(0x64, 0x00, SS_DEF,
+/* R */{SST(0x64, 0x00, SS_RDEF,
"Illegal mode for this track") },
-/* R */{SST(0x64, 0x01, SS_DEF,
+/* R */{SST(0x64, 0x01, SS_RDEF,
"Invalid packet size") },
-/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_DEF,
+/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
"Voltage fault") },
-/* S */{SST(0x66, 0x00, SS_DEF,
+/* S */{SST(0x66, 0x00, SS_RDEF,
"Automatic document feeder cover up") },
-/* S */{SST(0x66, 0x01, SS_DEF,
+/* S */{SST(0x66, 0x01, SS_RDEF,
"Automatic document feeder lift up") },
-/* S */{SST(0x66, 0x02, SS_DEF,
+/* S */{SST(0x66, 0x02, SS_RDEF,
"Document jam in automatic document feeder") },
-/* S */{SST(0x66, 0x03, SS_DEF,
+/* S */{SST(0x66, 0x03, SS_RDEF,
"Document miss feed automatic in document feeder") },
-/* A */{SST(0x67, 0x00, SS_DEF,
+/* A */{SST(0x67, 0x00, SS_RDEF,
"Configuration failure") },
-/* A */{SST(0x67, 0x01, SS_DEF,
+/* A */{SST(0x67, 0x01, SS_RDEF,
"Configuration of incapable logical units failed") },
-/* A */{SST(0x67, 0x02, SS_DEF,
+/* A */{SST(0x67, 0x02, SS_RDEF,
"Add logical unit failed") },
-/* A */{SST(0x67, 0x03, SS_DEF,
+/* A */{SST(0x67, 0x03, SS_RDEF,
"Modification of logical unit failed") },
-/* A */{SST(0x67, 0x04, SS_DEF,
+/* A */{SST(0x67, 0x04, SS_RDEF,
"Exchange of logical unit failed") },
-/* A */{SST(0x67, 0x05, SS_DEF,
+/* A */{SST(0x67, 0x05, SS_RDEF,
"Remove of logical unit failed") },
-/* A */{SST(0x67, 0x06, SS_DEF,
+/* A */{SST(0x67, 0x06, SS_RDEF,
"Attachment of logical unit failed") },
-/* A */{SST(0x67, 0x07, SS_DEF,
+/* A */{SST(0x67, 0x07, SS_RDEF,
"Creation of logical unit failed") },
-/* A */{SST(0x68, 0x00, SS_DEF,
+/* A */{SST(0x68, 0x00, SS_RDEF,
"Logical unit not configured") },
-/* A */{SST(0x69, 0x00, SS_DEF,
+/* A */{SST(0x69, 0x00, SS_RDEF,
"Data loss on logical unit") },
-/* A */{SST(0x69, 0x01, SS_DEF,
+/* A */{SST(0x69, 0x01, SS_RDEF,
"Multiple logical unit failures") },
-/* A */{SST(0x69, 0x02, SS_DEF,
+/* A */{SST(0x69, 0x02, SS_RDEF,
"Parity/data mismatch") },
-/* A */{SST(0x6A, 0x00, SS_DEF,
+/* A */{SST(0x6A, 0x00, SS_RDEF,
"Informational, refer to log") },
-/* A */{SST(0x6B, 0x00, SS_DEF,
+/* A */{SST(0x6B, 0x00, SS_RDEF,
"State change has occurred") },
-/* A */{SST(0x6B, 0x01, SS_DEF,
+/* A */{SST(0x6B, 0x01, SS_RDEF,
"Redundancy level got better") },
-/* A */{SST(0x6B, 0x02, SS_DEF,
+/* A */{SST(0x6B, 0x02, SS_RDEF,
"Redundancy level got worse") },
-/* A */{SST(0x6C, 0x00, SS_DEF,
+/* A */{SST(0x6C, 0x00, SS_RDEF,
"Rebuild failure occurred") },
-/* A */{SST(0x6D, 0x00, SS_DEF,
+/* A */{SST(0x6D, 0x00, SS_RDEF,
"Recalculate failure occurred") },
-/* A */{SST(0x6E, 0x00, SS_DEF,
+/* A */{SST(0x6E, 0x00, SS_RDEF,
"Command to logical unit failed") },
-/* T */{SST(0x70, 0x00, SS_DEF,
+/* T */{SST(0x70, 0x00, SS_RDEF,
"Decompression exception short: ASCQ = Algorithm ID") },
-/* T */{SST(0x70, 0xFF, SS_DEF|SSQ_RANGE,
+/* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
NULL) }, /* Range 0x00 -> 0xFF */
-/* T */{SST(0x71, 0x00, SS_DEF,
+/* T */{SST(0x71, 0x00, SS_RDEF,
"Decompression exception long: ASCQ = Algorithm ID") },
-/* T */{SST(0x71, 0xFF, SS_DEF|SSQ_RANGE,
+/* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
NULL) }, /* Range 0x00 -> 0xFF */
-/* R */{SST(0x72, 0x00, SS_DEF,
+/* R */{SST(0x72, 0x00, SS_RDEF,
"Session fixation error") },
-/* R */{SST(0x72, 0x01, SS_DEF,
+/* R */{SST(0x72, 0x01, SS_RDEF,
"Session fixation error writing lead-in") },
-/* R */{SST(0x72, 0x02, SS_DEF,
+/* R */{SST(0x72, 0x02, SS_RDEF,
"Session fixation error writing lead-out") },
-/* R */{SST(0x72, 0x03, SS_DEF,
+/* R */{SST(0x72, 0x03, SS_RDEF,
"Session fixation error - incomplete track in session") },
-/* R */{SST(0x72, 0x04, SS_DEF,
+/* R */{SST(0x72, 0x04, SS_RDEF,
"Empty or partially written reserved track") },
-/* R */{SST(0x73, 0x00, SS_DEF,
+/* R */{SST(0x73, 0x00, SS_RDEF,
"CD control error") },
-/* R */{SST(0x73, 0x01, SS_DEF,
+/* R */{SST(0x73, 0x01, SS_RDEF,
"Power calibration area almost full") },
-/* R */{SST(0x73, 0x02, SS_NEDEF|ENOSPC,
+/* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
"Power calibration area is full") },
-/* R */{SST(0x73, 0x03, SS_DEF,
+/* R */{SST(0x73, 0x03, SS_RDEF,
"Power calibration area error") },
-/* R */{SST(0x73, 0x04, SS_DEF,
+/* R */{SST(0x73, 0x04, SS_RDEF,
"Program memory area update failure") },
-/* R */{SST(0x73, 0x05, SS_DEF,
+/* R */{SST(0x73, 0x05, SS_RDEF,
"program memory area is full") }
};
-#if !defined(SCSI_NO_SENSE_STRINGS)
-const char *
-scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
+const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
+
+struct asc_key
{
- int i, j;
- caddr_t match;
- struct asc_table_entry *table[2];
- int table_size[2];
- int num_tables;
+ int asc;
+ int ascq;
+};
+
+static int
+ascentrycomp(const void *key, const void *member)
+{
+ int asc;
+ int ascq;
+ const struct asc_table_entry *table_entry;
+
+ asc = ((const struct asc_key *)key)->asc;
+ ascq = ((const struct asc_key *)key)->ascq;
+ table_entry = (const struct asc_table_entry *)member;
+
+ if (asc >= table_entry->asc) {
+
+ if (asc > table_entry->asc)
+ return (1);
+
+ if (ascq <= table_entry->ascq) {
+ /* Check for ranges */
+ if (ascq == table_entry->ascq
+ || ((table_entry->action & SSQ_RANGE) != 0
+ && ascq >= (table_entry - 1)->ascq))
+ return (0);
+ return (-1);
+ }
+ return (1);
+ }
+ return (-1);
+}
- if (inq_data == NULL)
- return(NULL);
+static int
+senseentrycomp(const void *key, const void *member)
+{
+ int sense_key;
+ const struct sense_key_table_entry *table_entry;
- match = cam_quirkmatch((caddr_t)inq_data,
- (caddr_t)asc_quirk_table,
- sizeof(asc_quirk_table)/sizeof(*asc_quirk_table),
- sizeof(*asc_quirk_table), scsi_inquiry_match);
+ sense_key = *((const int *)key);
+ table_entry = (const struct sense_key_table_entry *)member;
+
+ if (sense_key >= table_entry->sense_key) {
+ if (sense_key == table_entry->sense_key)
+ return (0);
+ return (1);
+ }
+ return (-1);
+}
+
+static void
+fetchtableentries(int sense_key, int asc, int ascq,
+ struct scsi_inquiry_data *inq_data,
+ const struct sense_key_table_entry **sense_entry,
+ const struct asc_table_entry **asc_entry)
+{
+ caddr_t match;
+ const struct asc_table_entry *asc_tables[2];
+ const struct sense_key_table_entry *sense_tables[2];
+ struct asc_key asc_ascq;
+ size_t asc_tables_size[2];
+ size_t sense_tables_size[2];
+ int num_asc_tables;
+ int num_sense_tables;
+ int i;
+
+ /* Default to failure */
+ *sense_entry = NULL;
+ *asc_entry = NULL;
+ match = NULL;
+ if (inq_data != NULL)
+ match = cam_quirkmatch((caddr_t)inq_data,
+ (caddr_t)sense_quirk_table,
+ sense_quirk_table_size,
+ sizeof(*sense_quirk_table),
+ scsi_inquiry_match);
if (match != NULL) {
- table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
- table_size[0] =
- ((struct scsi_sense_quirk_entry *)match)->num_ascs;
- table[1] = asc_text;
- table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
- num_tables = 2;
+ struct scsi_sense_quirk_entry *quirk;
+
+ quirk = (struct scsi_sense_quirk_entry *)match;
+ asc_tables[0] = quirk->asc_info;
+ asc_tables_size[0] = quirk->num_ascs;
+ asc_tables[1] = asc_table;
+ asc_tables_size[1] = asc_table_size;
+ num_asc_tables = 2;
+ sense_tables[0] = quirk->sense_key_info;
+ sense_tables_size[0] = quirk->num_sense_keys;
+ sense_tables[1] = sense_key_table;
+ sense_tables_size[1] = sense_key_table_size;
+ num_sense_tables = 2;
} else {
- table[0] = asc_text;
- table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
- num_tables = 1;
+ asc_tables[0] = asc_table;
+ asc_tables_size[0] = asc_table_size;
+ num_asc_tables = 1;
+ sense_tables[0] = sense_key_table;
+ sense_tables_size[0] = sense_key_table_size;
+ num_sense_tables = 1;
}
- for (j = 0; j < num_tables; j++) {
- for (i = 0; i < table_size[j]; i++) {
- if (table[j][i].asc == asc) {
+ asc_ascq.asc = asc;
+ asc_ascq.ascq = ascq;
+ for (i = 0; i < num_asc_tables; i++) {
+ void *found_entry;
- /* Check for ranges */
- if ((table[j][i].action & SSQ_RANGE) != 0) {
-
- if (table[j][i].ascq >= ascq
- && table[j][i-1].ascq <= ascq)
- return table[j][i-1].desc;
+ found_entry = bsearch(&asc_ascq, asc_tables[i],
+ asc_tables_size[i],
+ sizeof(**asc_tables),
+ ascentrycomp);
- continue;
- }
-
- if (table[j][i].ascq == ascq)
- return table[j][i].desc;
- }
+ if (found_entry) {
+ *asc_entry = (struct asc_table_entry *)found_entry;
+ break;
}
}
- if (asc >= 0x80 && asc <= 0xff)
- return "Vendor Specific ASC";
+ for (i = 0; i < num_sense_tables; i++) {
+ void *found_entry;
- if (ascq >= 0x80 && ascq <= 0xff)
- return "Vendor Specific ASCQ";
+ found_entry = bsearch(&sense_key, sense_tables[i],
+ sense_tables_size[i],
+ sizeof(**sense_tables),
+ senseentrycomp);
- return "Reserved ASC/ASCQ pair";
+ if (found_entry) {
+ *sense_entry =
+ (struct sense_key_table_entry *)found_entry;
+ break;
+ }
+ }
}
-#else /* SCSI_NO_SENSE_STRINGS */
-const char *
-scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
+void
+scsi_sense_desc(int sense_key, int asc, int ascq,
+ struct scsi_inquiry_data *inq_data,
+ const char **sense_key_desc, const char **asc_desc)
{
- return ("");
+ const struct asc_table_entry *asc_entry;
+ const struct sense_key_table_entry *sense_entry;
+
+ fetchtableentries(sense_key, asc, ascq,
+ inq_data,
+ &sense_entry,
+ &asc_entry);
+
+ *sense_key_desc = sense_entry->desc;
+
+ if (asc_entry != NULL)
+ *asc_desc = asc_entry->desc;
+ else if (asc >= 0x80 && asc <= 0xff)
+ *asc_desc = "Vendor Specific ASC";
+ else if (ascq >= 0x80 && ascq <= 0xff)
+ *asc_desc = "Vendor Specific ASCQ";
+ else
+ *asc_desc = "Reserved ASC/ASCQ pair";
}
-#endif
/*
- * Given a particular failed CCB and its device type information, return
- * the appropriate action from either the sense code quirk table or the
- * sense code table.
+ * Given sense and device type information, return the appropriate action.
+ * If we do not understand the specific error as identified by the ASC/ASCQ
+ * pair, fall back on the more generic actions derived from the sense key.
*/
scsi_sense_action
-scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data)
+scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
+ u_int32_t sense_flags)
{
- caddr_t match;
- struct asc_table_entry *table[2];
- int table_size[2];
- int num_tables;
- int i, j;
+ const struct asc_table_entry *asc_entry;
+ const struct sense_key_table_entry *sense_entry;
+ int error_code, sense_key, asc, ascq;
+ scsi_sense_action action;
- /*
- * If we don't have inquiry data, we can't match against any quirk
- * entries.
- */
- if (inq_data != NULL) {
- match = cam_quirkmatch((caddr_t)inq_data,
- (caddr_t)asc_quirk_table,
- sizeof(asc_quirk_table) /
- sizeof(*asc_quirk_table),
- sizeof(*asc_quirk_table),
- scsi_inquiry_match);
- } else
- match = NULL;
+ scsi_extract_sense(&csio->sense_data, &error_code,
+ &sense_key, &asc, &ascq);
- if (match != NULL) {
- table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
- table_size[0] =
- ((struct scsi_sense_quirk_entry *)match)->num_ascs;
- table[1] = asc_text;
- table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
- num_tables = 2;
+ if (error_code == SSD_DEFERRED_ERROR) {
+ /*
+ * XXX dufault@FreeBSD.org
+ * This error doesn't relate to the command associated
+ * with this request sense. A deferred error is an error
+ * for a command that has already returned GOOD status
+ * (see SCSI2 8.2.14.2).
+ *
+ * By my reading of that section, it looks like the current
+ * command has been cancelled, we should now clean things up
+ * (hopefully recovering any lost data) and then retry the
+ * current command. There are two easy choices, both wrong:
+ *
+ * 1. Drop through (like we had been doing), thus treating
+ * this as if the error were for the current command and
+ * return and stop the current command.
+ *
+ * 2. Issue a retry (like I made it do) thus hopefully
+ * recovering the current transfer, and ignoring the
+ * fact that we've dropped a command.
+ *
+ * These should probably be handled in a device specific
+ * sense handler or punted back up to a user mode daemon
+ */
+ action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
} else {
- table[0] = asc_text;
- table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
- num_tables = 1;
- }
-
- for (j = 0; j < num_tables; j++) {
- for (i = 0; i < table_size[j]; i++) {
- if (table[j][i].asc == asc) {
-
- /* Check for ranges */
- if ((table[j][i].action & SSQ_RANGE) != 0){
-
- if (table[j][i].ascq >= ascq
- && table[j][i-1].ascq <= ascq)
- return table[j][i].action;
+ fetchtableentries(sense_key, asc, ascq,
+ inq_data,
+ &sense_entry,
+ &asc_entry);
- continue;
- }
+ /*
+ * Override the 'No additional Sense' entry (0,0)
+ * with the error action of the sense key.
+ */
+ if (asc_entry != NULL
+ && (asc != 0 || ascq != 0))
+ action = asc_entry->action;
+ else
+ action = sense_entry->action;
- /*
- * Check to see if we have a match. If the
- * current ascq in the table is greater
- * than our ascq, and there aren't any more
- * tables to search, just return the
- * default action.
- */
- if (table[j][i].ascq == ascq)
- return(table[j][i].action);
- else if ((j == (num_tables - 1)) &&
- (table[j][i].ascq > ascq))
- return(SS_DEF);
+ if (sense_key == SSD_KEY_RECOVERED_ERROR) {
+ /*
+ * The action succeeded but the device wants
+ * the user to know that some recovery action
+ * was required.
+ */
+ action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
+ action |= SS_NOP|SSQ_PRINT_SENSE;
+ } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
+ if ((sense_flags & SF_QUIET_IR) != 0)
+ action &= ~SSQ_PRINT_SENSE;
+ } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
+ if ((sense_flags & SF_RETRY_UA) != 0
+ && (action & SS_MASK) == SS_FAIL) {
+ action &= ~(SS_MASK|SSQ_MASK);
+ action |= SS_RETRY|SSQ_DECREMENT_COUNT|
+ SSQ_PRINT_SENSE;
}
}
}
- /*
- * If we get to this point, it's most likely a vendor specific
- * ASC and we don't have a quirk entry for it. Oh well, we just
- * tell the error handling code to take the default action.
- */
- return(SS_DEF);
+#ifdef KERNEL
+ if (bootverbose)
+ sense_flags |= SF_PRINT_ALWAYS;
+#endif
+ if ((sense_flags & SF_PRINT_ALWAYS) != 0)
+ action |= SSQ_PRINT_SENSE;
+ else if ((sense_flags & SF_NO_PRINT) != 0)
+ action &= ~SSQ_PRINT_SENSE;
+
+ return (action);
}
char *
@@ -1600,42 +1722,63 @@ scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
*cdb_string = '\0';
for (i = 0; i < cdb_len; i++)
snprintf(cdb_string + strlen(cdb_string),
- len - strlen(cdb_string), "%x ", cdb_ptr[i]);
+ len - strlen(cdb_string), "%x ", cdb_ptr[i]);
return(cdb_string);
}
+
+const char *
+scsi_status_string(struct ccb_scsiio *csio)
+{
+ switch(csio->scsi_status) {
+ case SCSI_STATUS_OK:
+ return("OK");
+ case SCSI_STATUS_CHECK_COND:
+ return("Check Condition");
+ case SCSI_STATUS_BUSY:
+ return("Busy");
+ case SCSI_STATUS_INTERMED:
+ return("Intermediate");
+ case SCSI_STATUS_INTERMED_COND_MET:
+ return("Intermediate-Condition Met");
+ case SCSI_STATUS_RESERV_CONFLICT:
+ return("Reservation Conflict");
+ case SCSI_STATUS_CMD_TERMINATED:
+ return("Command Terminated");
+ case SCSI_STATUS_QUEUE_FULL:
+ return("Queue Full");
+ case SCSI_STATUS_ACA_ACTIVE:
+ return("ACA Active");
+ case SCSI_STATUS_TASK_ABORTED:
+ return("Task Aborted");
+ default: {
+ static char unkstr[64];
+ snprintf(unkstr, sizeof(unkstr), "Unknown %#x",
+ csio->scsi_status);
+ return(unkstr);
+ }
+ }
+}
+
/*
- * scsi_sense_print will decode the sense data into human
- * readable form. Sense handlers can use this to generate
- * a report.
- */
-/*
- * Because scsi_sense_print() utilizes transport layer functions, it will
- * only work in the kernel.
+ * scsi_command_string() returns 0 for success and -1 for failure.
*/
#ifdef _KERNEL
-
-void
-scsi_sense_print(struct ccb_scsiio *csio)
+int
+scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb)
+#else /* !_KERNEL */
+int
+scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
+ struct sbuf *sb)
+#endif /* _KERNEL/!_KERNEL */
{
- struct scsi_sense_data *sense;
- u_int32_t info;
- int error_code;
- int sense_key;
- int asc, ascq;
- struct ccb_getdev cgd;
- u_int8_t command_print;
-
- sense = &csio->sense_data;
-
- /*
- * If the CDB is a physical address, we can't deal with it..
- */
- if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
- command_print = 0;
- else
- command_print = 1;
+ struct scsi_inquiry_data *inq_data;
+ char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
+#ifdef _KERNEL
+ struct ccb_getdev cgd;
+#endif /* _KERNEL */
+#ifdef _KERNEL
/*
* Get the device information.
*/
@@ -1652,209 +1795,109 @@ scsi_sense_print(struct ccb_scsiio *csio)
if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
cgd.inq_data.device = T_DIRECT;
- if (command_print != 0) {
- char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
-
- xpt_print_path(csio->ccb_h.path);
-
- if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
- printf("%s. CDB: %s\n",
- scsi_op_desc(csio->cdb_io.cdb_ptr[0],
- &cgd.inq_data),
- scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
- sizeof(cdb_str)));
- } else {
- printf("%s. CDB: %s\n",
- scsi_op_desc(csio->cdb_io.cdb_bytes[0],
- &cgd.inq_data), scsi_cdb_string(
- csio->cdb_io.cdb_bytes, cdb_str,
- sizeof(cdb_str)));
- }
- }
-
- /*
- * If the sense data is a physical pointer, forget it.
- */
- if (csio->ccb_h.flags & CAM_SENSE_PTR) {
- if (csio->ccb_h.flags & CAM_SENSE_PHYS)
- return;
- else {
- /*
- * XXX KDM this is stupid, but casting the
- * structure doesn't work...
- */
- bcopy(&csio->sense_data, sense,
- sizeof(struct scsi_sense_data *));
- }
- } else {
- /*
- * If the physical sense flag is set, but the sense pointer
- * is not also set, we assume that the user is an idiot and
- * return. (Well, okay, it could be that somehow, the
- * entire csio is physical, but we would have probably core
- * dumped on one of the bogus pointer deferences above
- * already.)
- */
- if (csio->ccb_h.flags & CAM_SENSE_PHYS)
- return;
- else
- sense = &csio->sense_data;
- }
-
- xpt_print_path(csio->ccb_h.path);
- error_code = sense->error_code & SSD_ERRCODE;
- sense_key = sense->flags & SSD_KEY;
-
- switch (error_code) {
- case SSD_DEFERRED_ERROR:
- printf("Deferred Error: ");
- /* FALLTHROUGH */
- case SSD_CURRENT_ERROR:
-
- printf("%s", scsi_sense_key_text[sense_key]);
- info = scsi_4btoul(sense->info);
-
- if (sense->error_code & SSD_ERRCODE_VALID) {
-
- switch (sense_key) {
- case SSD_KEY_NOT_READY:
- case SSD_KEY_ILLEGAL_REQUEST:
- case SSD_KEY_UNIT_ATTENTION:
- case SSD_KEY_DATA_PROTECT:
- break;
- case SSD_KEY_BLANK_CHECK:
- printf(" req sz: %d (decimal)",
- info);
- break;
- default:
- if (info) {
- if (sense->flags & SSD_ILI) {
- printf(" ILI (length mismatch):"
- " %d", info);
- } else {
- printf(" info:%x", info);
- }
- }
- }
- } else if (info)
- printf(" info?:%x", info);
-
- if (sense->extra_len >= 4) {
- if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
- printf(" csi:%x,%x,%x,%x",
- sense->cmd_spec_info[0],
- sense->cmd_spec_info[1],
- sense->cmd_spec_info[2],
- sense->cmd_spec_info[3]);
- }
- }
-
- asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
- ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
-
- if (asc || ascq) {
- const char *desc = scsi_sense_desc(asc, ascq,
- &cgd.inq_data);
- printf(" asc:%x,%x\n", asc, ascq);
+ inq_data = &cgd.inq_data;
- xpt_print_path(csio->ccb_h.path);
- printf("%s", desc);
- }
+#else /* !_KERNEL */
- if (sense->extra_len >= 7 && sense->fru) {
- printf(" field replaceable unit: %x", sense->fru);
- }
+ inq_data = &device->inq_data;
- if ((sense->extra_len >= 10)
- && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
- printf(" sks:%x,%x", sense->sense_key_spec[0],
- scsi_2btoul(&sense->sense_key_spec[1]));
- }
- break;
+#endif /* _KERNEL/!_KERNEL */
- default:
- printf("error code %d",
- sense->error_code & SSD_ERRCODE);
- if (sense->error_code & SSD_ERRCODE_VALID) {
- printf(" at block no. %d (decimal)",
- info = scsi_4btoul(sense->info));
- }
+ if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
+ sbuf_printf(sb, "%s. CDB: %s",
+ scsi_op_desc(csio->cdb_io.cdb_ptr[0], inq_data),
+ scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
+ sizeof(cdb_str)));
+ } else {
+ sbuf_printf(sb, "%s. CDB: %s",
+ scsi_op_desc(csio->cdb_io.cdb_bytes[0], inq_data),
+ scsi_cdb_string(csio->cdb_io.cdb_bytes, cdb_str,
+ sizeof(cdb_str)));
}
- printf("\n");
+ return(0);
}
-#else /* !_KERNEL */
-
-char *
-scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
- char *str, int str_len)
+/*
+ * scsi_sense_sbuf() returns 0 for success and -1 for failure.
+ */
+#ifdef _KERNEL
+int
+scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
+ scsi_sense_string_flags flags)
+#else /* !_KERNEL */
+int
+scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
+ struct sbuf *sb, scsi_sense_string_flags flags)
+#endif /* _KERNEL/!_KERNEL */
{
struct scsi_sense_data *sense;
+ struct scsi_inquiry_data *inq_data;
+#ifdef _KERNEL
+ struct ccb_getdev cgd;
+#endif /* _KERNEL */
u_int32_t info;
int error_code;
int sense_key;
int asc, ascq;
- u_int8_t command_print;
char path_str[64];
- char tmpstr[2048];
- int tmpstrlen = 2048;
- int cur_len = 0, tmplen = 0, retlen;
- if ((device == NULL) || (csio == NULL) || (str == NULL))
- return(NULL);
-
- if (str_len <= 0)
- return(NULL);
+#ifndef _KERNEL
+ if (device == NULL)
+ return(-1);
+#endif /* !_KERNEL */
+ if ((csio == NULL) || (sb == NULL))
+ return(-1);
/*
* If the CDB is a physical address, we can't deal with it..
*/
if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
- command_print = 0;
- else
- command_print = 1;
+ flags &= ~SSS_FLAG_PRINT_COMMAND;
+
+#ifdef _KERNEL
+ xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str));
+#else /* !_KERNEL */
+ cam_path_string(device, path_str, sizeof(path_str));
+#endif /* _KERNEL/!_KERNEL */
+
+#ifdef _KERNEL
+ /*
+ * Get the device information.
+ */
+ xpt_setup_ccb(&cgd.ccb_h,
+ csio->ccb_h.path,
+ /*priority*/ 1);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+
+ /*
+ * If the device is unconfigured, just pretend that it is a hard
+ * drive. scsi_op_desc() needs this.
+ */
+ if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
+ cgd.inq_data.device = T_DIRECT;
+
+ inq_data = &cgd.inq_data;
+
+#else /* !_KERNEL */
- cam_path_string(device, path_str, 64);
+ inq_data = &device->inq_data;
- str[0] = '\0';
+#endif /* _KERNEL/!_KERNEL */
sense = NULL;
- if (command_print != 0) {
- char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
-
- retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
-
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
-
- if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
- retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
- scsi_op_desc(csio->cdb_io.cdb_ptr[0],
- &device->inq_data),
- scsi_cdb_string(csio->cdb_io.cdb_ptr,
- cdb_str,
- sizeof(cdb_str)));
- } else {
- retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
- scsi_op_desc(csio->cdb_io.cdb_bytes[0],
- &device->inq_data), scsi_cdb_string(
- csio->cdb_io.cdb_bytes, cdb_str,
- sizeof(cdb_str)));
- }
+ if (flags & SSS_FLAG_PRINT_COMMAND) {
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
+ sbuf_cat(sb, path_str);
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+#ifdef _KERNEL
+ scsi_command_string(csio, sb);
+#else /* !_KERNEL */
+ scsi_command_string(device, csio, sb);
+#endif /* _KERNEL/!_KERNEL */
}
/*
@@ -1862,11 +1905,12 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
*/
if (csio->ccb_h.flags & CAM_SENSE_PTR) {
if (csio->ccb_h.flags & CAM_SENSE_PHYS)
- return(NULL);
+ return(-1);
else {
/*
- * XXX KDM this is stupid, but casting the
- * structure doesn't work...
+ * bcopy the pointer to avoid unaligned access
+ * errors on finicky architectures. We don't
+ * ensure that the sense data is pointer aligned.
*/
bcopy(&csio->sense_data, sense,
sizeof(struct scsi_sense_data *));
@@ -1881,46 +1925,32 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
* already.)
*/
if (csio->ccb_h.flags & CAM_SENSE_PHYS)
- return(NULL);
+ return(-1);
else
sense = &csio->sense_data;
}
- retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
-
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_cat(sb, path_str);
error_code = sense->error_code & SSD_ERRCODE;
sense_key = sense->flags & SSD_KEY;
switch (error_code) {
case SSD_DEFERRED_ERROR:
- retlen = snprintf(tmpstr, tmpstrlen, "Deferred Error: ");
-
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
+ sbuf_printf(sb, "Deferred Error: ");
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
/* FALLTHROUGH */
case SSD_CURRENT_ERROR:
+ {
+ const char *sense_key_desc;
+ const char *asc_desc;
- retlen = snprintf(tmpstr, tmpstrlen, "%s",
- scsi_sense_key_text[sense_key]);
-
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
+ ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
+ scsi_sense_desc(sense_key, asc, ascq, inq_data,
+ &sense_key_desc, &asc_desc);
+ sbuf_cat(sb, sense_key_desc);
info = scsi_4btoul(sense->info);
@@ -1933,363 +1963,169 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
case SSD_KEY_DATA_PROTECT:
break;
case SSD_KEY_BLANK_CHECK:
- retlen = snprintf(tmpstr, tmpstrlen,
- " req sz: %d (decimal)",
- info);
-
- if ((tmplen = str_len - cur_len - 1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, " req sz: %d (decimal)", info);
break;
default:
if (info) {
if (sense->flags & SSD_ILI) {
- retlen = snprintf (tmpstr,
- tmpstrlen,
- " ILI (length "
+ sbuf_printf(sb, " ILI (length "
"mismatch): %d", info);
} else {
- retlen = snprintf(tmpstr,
- tmpstrlen,
- " info:%x",
- info);
+ sbuf_printf(sb, " info:%x",
+ info);
}
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
}
}
} else if (info) {
- retlen = snprintf(tmpstr, tmpstrlen," info?:%x", info);
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, " info?:%x", info);
}
if (sense->extra_len >= 4) {
if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
- retlen = snprintf(tmpstr, tmpstrlen,
- " csi:%x,%x,%x,%x",
- sense->cmd_spec_info[0],
- sense->cmd_spec_info[1],
- sense->cmd_spec_info[2],
- sense->cmd_spec_info[3]);
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, " csi:%x,%x,%x,%x",
+ sense->cmd_spec_info[0],
+ sense->cmd_spec_info[1],
+ sense->cmd_spec_info[2],
+ sense->cmd_spec_info[3]);
}
}
- asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
- ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
-
if (asc || ascq) {
- const char *desc = scsi_sense_desc(asc, ascq,
- &device->inq_data);
- retlen = snprintf(tmpstr, tmpstrlen,
- " asc:%x,%x\n%s%s", asc, ascq,
- path_str, desc);
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq,
+ path_str, asc_desc);
}
if (sense->extra_len >= 7 && sense->fru) {
- retlen = snprintf(tmpstr, tmpstrlen,
- " field replaceable unit: %x",
- sense->fru);
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- str[str_len - 1] = '\0';
- cur_len += retlen;
+ sbuf_printf(sb, " field replaceable unit: %x",
+ sense->fru);
}
if ((sense->extra_len >= 10)
&& (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
- retlen = snprintf(tmpstr, tmpstrlen, " sks:%x,%x",
- sense->sense_key_spec[0],
- scsi_2btoul(&sense->sense_key_spec[1]));
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- str[str_len - 1] = '\0';
- cur_len += retlen;
+ switch(sense_key) {
+ case SSD_KEY_ILLEGAL_REQUEST: {
+ int bad_command;
+ char tmpstr2[40];
+
+ if (sense->sense_key_spec[0] & 0x40)
+ bad_command = 1;
+ else
+ bad_command = 0;
+
+ tmpstr2[0] = '\0';
+
+ /* Bit pointer is valid */
+ if (sense->sense_key_spec[0] & 0x08)
+ snprintf(tmpstr2, sizeof(tmpstr2),
+ "bit %d",
+ sense->sense_key_spec[0] & 0x7);
+ sbuf_printf(sb,
+ ": %s byte %d %s is invalid",
+ bad_command ?
+ "Command" : "Data",
+ scsi_2btoul(
+ &sense->sense_key_spec[1]),
+ tmpstr2);
+ break;
+ }
+ case SSD_KEY_RECOVERED_ERROR:
+ case SSD_KEY_HARDWARE_ERROR:
+ case SSD_KEY_MEDIUM_ERROR:
+ sbuf_printf(sb, " actual retry count: %d",
+ scsi_2btoul(
+ &sense->sense_key_spec[1]));
+ break;
+ default:
+ sbuf_printf(sb, " sks:%#x,%#x",
+ sense->sense_key_spec[0],
+ scsi_2btoul(
+ &sense->sense_key_spec[1]));
+ break;
+ }
}
break;
+ }
default:
- retlen = snprintf(tmpstr, tmpstrlen, "error code %d",
- sense->error_code & SSD_ERRCODE);
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, "error code %d",
+ sense->error_code & SSD_ERRCODE);
if (sense->error_code & SSD_ERRCODE_VALID) {
- retlen = snprintf(tmpstr, tmpstrlen,
- " at block no. %d (decimal)",
- info = scsi_4btoul(sense->info));
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
-
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ sbuf_printf(sb, " at block no. %d (decimal)",
+ info = scsi_4btoul(sense->info));
}
}
- retlen = snprintf(tmpstr, tmpstrlen, "\n");
-
- if ((tmplen = str_len - cur_len -1) < 0)
- goto sst_bailout;
+ sbuf_printf(sb, "\n");
- strncat(str, tmpstr, tmplen);
- cur_len += retlen;
- str[str_len - 1] = '\0';
+ return(0);
+}
-sst_bailout:
- return(str);
-}
-void
-scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio,
- FILE *ofile)
+#ifdef _KERNEL
+char *
+scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len)
+#else /* !_KERNEL */
+char *
+scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
+ char *str, int str_len)
+#endif /* _KERNEL/!_KERNEL */
{
- char str[2048];
-
- if ((device == NULL) || (csio == NULL) || (ofile == NULL))
- return;
+ struct sbuf sb;
- fprintf(ofile, "%s", scsi_sense_string(device, csio, str, 2048));
-}
+ sbuf_new(&sb, str, str_len, 0);
+#ifdef _KERNEL
+ scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
+#else /* !_KERNEL */
+ scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
#endif /* _KERNEL/!_KERNEL */
+ sbuf_finish(&sb);
+
+ return(sbuf_data(&sb));
+}
+
#ifdef _KERNEL
-int
-scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags,
- u_int32_t *relsim_flags, u_int32_t *openings,
- u_int32_t *timeout, scsi_sense_action error_action)
-#else
-int
-scsi_interpret_sense(struct cam_device *device, union ccb *ccb,
- u_int32_t sense_flags, u_int32_t *relsim_flags,
- u_int32_t *openings, u_int32_t *timeout,
- scsi_sense_action error_action)
-#endif
+void
+scsi_sense_print(struct ccb_scsiio *csio)
{
- struct scsi_sense_data *sense;
- int error_code, sense_key, asc, ascq;
- int error;
- int print_sense;
- struct ccb_scsiio *csio;
- int retry;
+ struct sbuf sb;
+ char str[512];
- csio = &ccb->csio;
- sense = &csio->sense_data;
- scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
+ sbuf_new(&sb, str, sizeof(str), 0);
-#ifdef _KERNEL
- if (bootverbose) {
- sense_flags |= SF_PRINT_ALWAYS;
- print_sense = TRUE;
- } else if ((sense_flags & SF_NO_PRINT) == 0)
-#else
- if ((sense_flags & SF_NO_PRINT) == 0)
-#endif
- print_sense = TRUE;
- else
- print_sense = FALSE;
+ scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
- switch (error_code) {
- case SSD_DEFERRED_ERROR:
- {
- /*
- * XXX dufault@FreeBSD.org
- * This error doesn't relate to the command associated
- * with this request sense. A deferred error is an error
- * for a command that has already returned GOOD status
- * (see 8.2.14.2).
- *
- * By my reading of that section, it looks like the current
- * command has been cancelled, we should now clean things up
- * (hopefully recovering any lost data) and then retry the
- * current command. There are two easy choices, both wrong:
- *
- * 1. Drop through (like we had been doing), thus treating
- * this as if the error were for the current command and
- * return and stop the current command.
- *
- * 2. Issue a retry (like I made it do) thus hopefully
- * recovering the current transfer, and ignoring the
- * fact that we've dropped a command.
- *
- * These should probably be handled in a device specific
- * sense handler or punted back up to a user mode daemon
- */
+ sbuf_finish(&sb);
- /* decrement the number of retries */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry)
- ccb->ccb_h.retry_count--;
+ printf("%s", sbuf_data(&sb));
+}
- error = ERESTART;
- break;
- }
- case SSD_CURRENT_ERROR:
- {
-
- switch (sense_key) {
- case SSD_KEY_NO_SENSE:
- /* Why were we called then? Well don't bail now */
- /* FALLTHROUGH */
- case SSD_KEY_EQUAL:
- /* These should be filtered by the peripheral drivers */
- print_sense = FALSE;
- /* FALLTHROUGH */
- case SSD_KEY_MISCOMPARE:
- /* decrement the number of retries */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry) {
- error = ERESTART;
- ccb->ccb_h.retry_count--;
- } else {
- error = EIO;
- }
- case SSD_KEY_RECOVERED_ERROR:
- error = 0; /* not an error */
- break;
- case SSD_KEY_ILLEGAL_REQUEST:
- if (((sense_flags & SF_QUIET_IR) != 0)
- && ((sense_flags & SF_PRINT_ALWAYS) == 0))
- print_sense = FALSE;
- error = EINVAL;
- break;
- case SSD_KEY_NOT_READY:
- case SSD_KEY_DATA_PROTECT:
- case SSD_KEY_VOLUME_OVERFLOW:
- case SSD_KEY_BLANK_CHECK: /* should be filtered out by
- peripheral drivers */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry) {
- ccb->ccb_h.retry_count--;
- error = ERESTART;
- print_sense = FALSE;
- } else {
- if (((error_action & SSQ_PRINT_SENSE) == 0)
- && ((sense_flags & SF_PRINT_ALWAYS) == 0))
- print_sense = FALSE;
-
- error = error_action & SS_ERRMASK;
- }
+#else /* !_KERNEL */
+void
+scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio,
+ FILE *ofile)
+{
+ struct sbuf sb;
+ char str[512];
- break;
- case SSD_KEY_UNIT_ATTENTION:
- /*
- * This should also be filtered out by
- * peripheral drivers since each has a different
- * concept of what it means to invalidate the media.
- */
- if ((sense_flags & SF_RETRY_UA) != 0) {
- /* don't decrement retry count */
- error = ERESTART;
- print_sense = FALSE;
- } else {
- /* decrement the number of retries */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry) {
- ccb->ccb_h.retry_count--;
- error = ERESTART;
- print_sense = FALSE;
- } else {
- if (((error_action &
- SSQ_PRINT_SENSE) == 0)
- && ((sense_flags &
- SF_PRINT_ALWAYS) == 0))
- print_sense = FALSE;
-
- error = error_action & SS_ERRMASK;
- }
- }
- break;
- case SSD_KEY_ABORTED_COMMAND:
- default:
- /* decrement the number of retries */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry) {
- ccb->ccb_h.retry_count--;
- error = ERESTART;
- print_sense = FALSE;
- } else {
- if (((error_action & SSQ_PRINT_SENSE) == 0)
- && ((sense_flags & SF_PRINT_ALWAYS) == 0))
- print_sense = FALSE;
-
- error = error_action & SS_ERRMASK;
- }
- /*
- * Make sure ABORTED COMMAND errors get
- * printed as they're indicative of marginal
- * SCSI busses that people should address.
- */
- if (sense_key == SSD_KEY_ABORTED_COMMAND)
- print_sense = TRUE;
- }
- break;
- }
- default:
- /* decrement the number of retries */
- retry = ccb->ccb_h.retry_count > 0;
- if (retry) {
- ccb->ccb_h.retry_count--;
- error = ERESTART;
- print_sense = FALSE;
- } else
- error = EIO;
- break;
- }
+ if ((device == NULL) || (csio == NULL) || (ofile == NULL))
+ return;
- if (print_sense) {
-#ifdef _KERNEL
- scsi_sense_print(csio);
-#else
- scsi_sense_print(device, csio, stdout);
-#endif
- }
-
- return (error);
+ sbuf_new(&sb, str, sizeof(str), 0);
+
+ scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
+
+ sbuf_finish(&sb);
+
+ fprintf(ofile, "%s", sbuf_data(&sb));
}
+#endif /* _KERNEL/!_KERNEL */
+
/*
* This function currently requires at least 36 bytes, or
* SHORT_INQUIRY_LENGTH, worth of data to function properly. If this
@@ -2849,7 +2685,7 @@ scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
bzero(scsi_cmd, sizeof(*scsi_cmd));
scsi_cmd->opcode = START_STOP_UNIT;
if (start != 0) {
- scsi_cmd->how |= SSS_START;
+ scsi_cmd->how |= SS_START;
/* it takes a lot of power to start a drive */
extra_flags |= CAM_HIGH_POWER;
}
OpenPOWER on IntegriCloud