diff options
Diffstat (limited to 'freebsd/sys/cam/scsi/scsi_all.c')
-rw-r--r-- | freebsd/sys/cam/scsi/scsi_all.c | 832 |
1 files changed, 431 insertions, 401 deletions
diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c index 9e8924c5..6ebf9eec 100644 --- a/freebsd/sys/cam/scsi/scsi_all.c +++ b/freebsd/sys/cam/scsi/scsi_all.c @@ -1240,58 +1240,58 @@ static struct asc_table_entry asc_table[] = { { SST(0x0A, 0x00, SS_FATAL | ENOSPC, "Error log overflow") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x00, SS_RDEF, + { SST(0x0B, 0x00, SS_NOP | SSQ_PRINT_SENSE, "Warning") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x01, SS_RDEF, + { SST(0x0B, 0x01, SS_NOP | SSQ_PRINT_SENSE, "Warning - specified temperature exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x02, SS_RDEF, + { SST(0x0B, 0x02, SS_NOP | SSQ_PRINT_SENSE, "Warning - enclosure degraded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x03, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x03, SS_NOP | SSQ_PRINT_SENSE, "Warning - background self-test failed") }, /* DTLPWRO AEBKVF */ - { SST(0x0B, 0x04, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x04, SS_NOP | SSQ_PRINT_SENSE, "Warning - background pre-scan detected medium error") }, /* DTLPWRO AEBKVF */ - { SST(0x0B, 0x05, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x05, SS_NOP | SSQ_PRINT_SENSE, "Warning - background medium scan detected medium error") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x06, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x06, SS_NOP | SSQ_PRINT_SENSE, "Warning - non-volatile cache now volatile") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x07, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x07, SS_NOP | SSQ_PRINT_SENSE, "Warning - degraded power to non-volatile cache") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x08, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x08, SS_NOP | SSQ_PRINT_SENSE, "Warning - power loss expected") }, /* D */ - { SST(0x0B, 0x09, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x09, SS_NOP | SSQ_PRINT_SENSE, "Warning - device statistics notification available") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0A, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0A, SS_NOP | SSQ_PRINT_SENSE, "Warning - High critical temperature limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0B, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0B, SS_NOP | SSQ_PRINT_SENSE, "Warning - Low critical temperature limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0C, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0C, SS_NOP | SSQ_PRINT_SENSE, "Warning - High operating temperature limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0D, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0D, SS_NOP | SSQ_PRINT_SENSE, "Warning - Low operating temperature limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0E, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0E, SS_NOP | SSQ_PRINT_SENSE, "Warning - High citical humidity limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x0F, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x0F, SS_NOP | SSQ_PRINT_SENSE, "Warning - Low citical humidity limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x10, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x10, SS_NOP | SSQ_PRINT_SENSE, "Warning - High operating humidity limit exceeded") }, /* DTLPWROMAEBKVF */ - { SST(0x0B, 0x11, SS_RDEF, /* XXX TBD */ + { SST(0x0B, 0x11, SS_NOP | SSQ_PRINT_SENSE, "Warning - Low operating humidity limit exceeded") }, /* T R */ { SST(0x0C, 0x00, SS_RDEF, @@ -2620,253 +2620,259 @@ static struct asc_table_entry asc_table[] = { { SST(0x5C, 0x02, SS_RDEF, "Spindles not synchronized") }, /* DTLPWROMAEBKVF */ - { SST(0x5D, 0x00, SS_RDEF, + { SST(0x5D, 0x00, SS_NOP | SSQ_PRINT_SENSE, "Failure prediction threshold exceeded") }, /* R B */ - { SST(0x5D, 0x01, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x01, SS_NOP | SSQ_PRINT_SENSE, "Media failure prediction threshold exceeded") }, /* R */ - { SST(0x5D, 0x02, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x02, SS_NOP | SSQ_PRINT_SENSE, "Logical unit failure prediction threshold exceeded") }, /* R */ - { SST(0x5D, 0x03, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x03, SS_NOP | SSQ_PRINT_SENSE, "Spare area exhaustion prediction threshold exceeded") }, /* D B */ - { SST(0x5D, 0x10, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x10, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x11, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x11, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x12, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x12, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x13, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x13, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x14, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x14, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x15, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x15, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x16, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x16, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x17, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x17, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x18, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x18, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x19, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x19, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x1A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x1A, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x1B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x1B, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x1C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x1C, SS_NOP | SSQ_PRINT_SENSE, "Hardware impending failure drive calibration retry count") }, /* D B */ - { SST(0x5D, 0x20, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x1D, SS_NOP | SSQ_PRINT_SENSE, + "Hardware impending failure power loss protection circuit") }, + /* D B */ + { SST(0x5D, 0x20, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x21, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x21, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x22, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x22, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x23, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x23, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x24, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x24, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x25, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x25, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x26, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x26, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x27, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x27, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x28, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x28, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x29, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x29, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x2A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x2A, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x2B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x2B, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x2C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x2C, SS_NOP | SSQ_PRINT_SENSE, "Controller impending failure drive calibration retry count") }, /* D B */ - { SST(0x5D, 0x30, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x30, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x31, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x31, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x32, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x32, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x33, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x33, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x34, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x34, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x35, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x35, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x36, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x36, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x37, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x37, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x38, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x38, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x39, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x39, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x3A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x3A, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x3B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x3B, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x3C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x3C, SS_NOP | SSQ_PRINT_SENSE, "Data channel impending failure drive calibration retry count") }, /* D B */ - { SST(0x5D, 0x40, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x40, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x41, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x41, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x42, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x42, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x43, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x43, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x44, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x44, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x45, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x45, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x46, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x46, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x47, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x47, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x48, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x48, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x49, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x49, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x4A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x4A, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x4B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x4B, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x4C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x4C, SS_NOP | SSQ_PRINT_SENSE, "Servo impending failure drive calibration retry count") }, /* D B */ - { SST(0x5D, 0x50, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x50, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x51, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x51, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x52, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x52, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x53, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x53, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x54, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x54, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x55, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x55, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x56, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x56, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x57, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x57, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x58, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x58, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x59, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x59, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x5A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x5A, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x5B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x5B, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x5C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x5C, SS_NOP | SSQ_PRINT_SENSE, "Spindle impending failure drive calibration retry count") }, /* D B */ - { SST(0x5D, 0x60, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x60, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure general hard drive failure") }, /* D B */ - { SST(0x5D, 0x61, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x61, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure drive error rate too high") }, /* D B */ - { SST(0x5D, 0x62, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x62, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure data error rate too high") }, /* D B */ - { SST(0x5D, 0x63, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x63, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure seek error rate too high") }, /* D B */ - { SST(0x5D, 0x64, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x64, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure too many block reassigns") }, /* D B */ - { SST(0x5D, 0x65, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x65, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure access times too high") }, /* D B */ - { SST(0x5D, 0x66, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x66, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure start unit times too high") }, /* D B */ - { SST(0x5D, 0x67, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x67, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure channel parametrics") }, /* D B */ - { SST(0x5D, 0x68, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x68, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure controller detected") }, /* D B */ - { SST(0x5D, 0x69, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x69, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure throughput performance") }, /* D B */ - { SST(0x5D, 0x6A, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x6A, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure seek time performance") }, /* D B */ - { SST(0x5D, 0x6B, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x6B, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure spin-up retry count") }, /* D B */ - { SST(0x5D, 0x6C, SS_RDEF, /* XXX TBD */ + { SST(0x5D, 0x6C, SS_NOP | SSQ_PRINT_SENSE, "Firmware impending failure drive calibration retry count") }, + /* D B */ + { SST(0x5D, 0x73, SS_NOP | SSQ_PRINT_SENSE, + "Media impending failure endurance limit met") }, /* DTLPWROMAEBKVF */ - { SST(0x5D, 0xFF, SS_RDEF, + { SST(0x5D, 0xFF, SS_NOP | SSQ_PRINT_SENSE, "Failure prediction threshold exceeded (false)") }, /* DTLPWRO A K */ { SST(0x5E, 0x00, SS_RDEF, @@ -3744,335 +3750,300 @@ scsi_find_desc(struct scsi_sense_data_desc *sense, u_int sense_len, #endif /* __rtems__ */ /* - * Fill in SCSI sense data with the specified parameters. This routine can - * fill in either fixed or descriptor type sense data. + * Fill in SCSI descriptor sense data with the specified parameters. */ -void -scsi_set_sense_data_va(struct scsi_sense_data *sense_data, - scsi_sense_data_type sense_format, int current_error, - int sense_key, int asc, int ascq, va_list ap) +static void +scsi_set_sense_data_desc_va(struct scsi_sense_data *sense_data, + u_int *sense_len, scsi_sense_data_type sense_format, int current_error, + int sense_key, int asc, int ascq, va_list ap) { - int descriptor_sense; + struct scsi_sense_data_desc *sense; scsi_sense_elem_type elem_type; + int space, len; + uint8_t *desc, *data; - /* - * Determine whether to return fixed or descriptor format sense - * data. If the user specifies SSD_TYPE_NONE for some reason, - * they'll just get fixed sense data. - */ - if (sense_format == SSD_TYPE_DESC) - descriptor_sense = 1; - else - descriptor_sense = 0; - - /* - * Zero the sense data, so that we don't pass back any garbage data - * to the user. - */ memset(sense_data, 0, sizeof(*sense_data)); + sense = (struct scsi_sense_data_desc *)sense_data; + if (current_error != 0) + sense->error_code = SSD_DESC_CURRENT_ERROR; + else + sense->error_code = SSD_DESC_DEFERRED_ERROR; + sense->sense_key = sense_key; + sense->add_sense_code = asc; + sense->add_sense_code_qual = ascq; + sense->flags = 0; + + desc = &sense->sense_desc[0]; + space = *sense_len - offsetof(struct scsi_sense_data_desc, sense_desc); + while ((elem_type = va_arg(ap, scsi_sense_elem_type)) != + SSD_ELEM_NONE) { + if (elem_type >= SSD_ELEM_MAX) { + printf("%s: invalid sense type %d\n", __func__, + elem_type); + break; + } + len = va_arg(ap, int); + data = va_arg(ap, uint8_t *); - if (descriptor_sense != 0) { - struct scsi_sense_data_desc *sense; - - sense = (struct scsi_sense_data_desc *)sense_data; - /* - * The descriptor sense format eliminates the use of the - * valid bit. - */ - if (current_error != 0) - sense->error_code = SSD_DESC_CURRENT_ERROR; - else - sense->error_code = SSD_DESC_DEFERRED_ERROR; - sense->sense_key = sense_key; - sense->add_sense_code = asc; - sense->add_sense_code_qual = ascq; - /* - * Start off with no extra length, since the above data - * fits in the standard descriptor sense information. - */ - sense->extra_len = 0; - while ((elem_type = (scsi_sense_elem_type)va_arg(ap, - scsi_sense_elem_type)) != SSD_ELEM_NONE) { - int sense_len, len_to_copy; - uint8_t *data; - - if (elem_type >= SSD_ELEM_MAX) { - printf("%s: invalid sense type %d\n", __func__, - elem_type); + switch (elem_type) { + case SSD_ELEM_SKIP: + break; + case SSD_ELEM_DESC: + if (space < len) { + sense->flags |= SSDD_SDAT_OVFL; break; } + bcopy(data, desc, len); + desc += len; + space -= len; + break; + case SSD_ELEM_SKS: { + struct scsi_sense_sks *sks = (void *)desc; - sense_len = (int)va_arg(ap, int); - len_to_copy = MIN(sense_len, SSD_EXTRA_MAX - - sense->extra_len); - data = (uint8_t *)va_arg(ap, uint8_t *); - - /* - * We've already consumed the arguments for this one. - */ - if (elem_type == SSD_ELEM_SKIP) - continue; - - switch (elem_type) { - case SSD_ELEM_DESC: { - - /* - * This is a straight descriptor. All we - * need to do is copy the data in. - */ - bcopy(data, &sense->sense_desc[ - sense->extra_len], len_to_copy); - sense->extra_len += len_to_copy; + if (len > sizeof(sks->sense_key_spec)) + break; + if (space < sizeof(*sks)) { + sense->flags |= SSDD_SDAT_OVFL; break; } - case SSD_ELEM_SKS: { - struct scsi_sense_sks sks; - - bzero(&sks, sizeof(sks)); + sks->desc_type = SSD_DESC_SKS; + sks->length = sizeof(*sks) - + (offsetof(struct scsi_sense_sks, length) + 1); + bcopy(data, &sks->sense_key_spec, len); + desc += sizeof(*sks); + space -= sizeof(*sks); + break; + } + case SSD_ELEM_COMMAND: { + struct scsi_sense_command *cmd = (void *)desc; - /* - * This is already-formatted sense key - * specific data. We just need to fill out - * the header and copy everything in. - */ - bcopy(data, &sks.sense_key_spec, - MIN(len_to_copy, - sizeof(sks.sense_key_spec))); - - sks.desc_type = SSD_DESC_SKS; - sks.length = sizeof(sks) - - offsetof(struct scsi_sense_sks, reserved1); - bcopy(&sks,&sense->sense_desc[sense->extra_len], - sizeof(sks)); - sense->extra_len += sizeof(sks); + if (len > sizeof(cmd->command_info)) + break; + if (space < sizeof(*cmd)) { + sense->flags |= SSDD_SDAT_OVFL; break; } - case SSD_ELEM_INFO: - case SSD_ELEM_COMMAND: { - struct scsi_sense_command cmd; - struct scsi_sense_info info; - uint8_t *data_dest; - uint8_t *descriptor; - int descriptor_size, i, copy_len; - - bzero(&cmd, sizeof(cmd)); - bzero(&info, sizeof(info)); - - /* - * Command or information data. The - * operate in pretty much the same way. - */ - if (elem_type == SSD_ELEM_COMMAND) { - len_to_copy = MIN(len_to_copy, - sizeof(cmd.command_info)); - descriptor = (uint8_t *)&cmd; - descriptor_size = sizeof(cmd); - data_dest =(uint8_t *)&cmd.command_info; - cmd.desc_type = SSD_DESC_COMMAND; - cmd.length = sizeof(cmd) - - offsetof(struct scsi_sense_command, - reserved); - } else { - len_to_copy = MIN(len_to_copy, - sizeof(info.info)); - descriptor = (uint8_t *)&info; - descriptor_size = sizeof(cmd); - data_dest = (uint8_t *)&info.info; - info.desc_type = SSD_DESC_INFO; - info.byte2 = SSD_INFO_VALID; - info.length = sizeof(info) - - offsetof(struct scsi_sense_info, - byte2); - } - - /* - * Copy this in reverse because the spec - * (SPC-4) says that when 4 byte quantities - * are stored in this 8 byte field, the - * first four bytes shall be 0. - * - * So we fill the bytes in from the end, and - * if we have less than 8 bytes to copy, - * the initial, most significant bytes will - * be 0. - */ - for (i = sense_len - 1; i >= 0 && - len_to_copy > 0; i--, len_to_copy--) - data_dest[len_to_copy - 1] = data[i]; + cmd->desc_type = SSD_DESC_COMMAND; + cmd->length = sizeof(*cmd) - + (offsetof(struct scsi_sense_command, length) + 1); + bcopy(data, &cmd->command_info[ + sizeof(cmd->command_info) - len], len); + desc += sizeof(*cmd); + space -= sizeof(*cmd); + break; + } + case SSD_ELEM_INFO: { + struct scsi_sense_info *info = (void *)desc; - /* - * This calculation looks much like the - * initial len_to_copy calculation, but - * we have to do it again here, because - * we're looking at a larger amount that - * may or may not fit. It's not only the - * data the user passed in, but also the - * rest of the descriptor. - */ - copy_len = MIN(descriptor_size, - SSD_EXTRA_MAX - sense->extra_len); - bcopy(descriptor, &sense->sense_desc[ - sense->extra_len], copy_len); - sense->extra_len += copy_len; + if (len > sizeof(info->info)) break; - } - case SSD_ELEM_FRU: { - struct scsi_sense_fru fru; - int copy_len; - - bzero(&fru, sizeof(fru)); - - fru.desc_type = SSD_DESC_FRU; - fru.length = sizeof(fru) - - offsetof(struct scsi_sense_fru, reserved); - fru.fru = *data; - - copy_len = MIN(sizeof(fru), SSD_EXTRA_MAX - - sense->extra_len); - bcopy(&fru, &sense->sense_desc[ - sense->extra_len], copy_len); - sense->extra_len += copy_len; + if (space < sizeof(*info)) { + sense->flags |= SSDD_SDAT_OVFL; break; } - case SSD_ELEM_STREAM: { - struct scsi_sense_stream stream_sense; - int copy_len; - - bzero(&stream_sense, sizeof(stream_sense)); - stream_sense.desc_type = SSD_DESC_STREAM; - stream_sense.length = sizeof(stream_sense) - - offsetof(struct scsi_sense_stream, reserved); - stream_sense.byte3 = *data; - - copy_len = MIN(sizeof(stream_sense), - SSD_EXTRA_MAX - sense->extra_len); - bcopy(&stream_sense, &sense->sense_desc[ - sense->extra_len], copy_len); - sense->extra_len += copy_len; + info->desc_type = SSD_DESC_INFO; + info->length = sizeof(*info) - + (offsetof(struct scsi_sense_info, length) + 1); + info->byte2 = SSD_INFO_VALID; + bcopy(data, &info->info[sizeof(info->info) - len], len); + desc += sizeof(*info); + space -= sizeof(*info); + break; + } + case SSD_ELEM_FRU: { + struct scsi_sense_fru *fru = (void *)desc; + + if (len > sizeof(fru->fru)) break; - } - default: - /* - * We shouldn't get here, but if we do, do - * nothing. We've already consumed the - * arguments above. - */ + if (space < sizeof(*fru)) { + sense->flags |= SSDD_SDAT_OVFL; break; } + fru->desc_type = SSD_DESC_FRU; + fru->length = sizeof(*fru) - + (offsetof(struct scsi_sense_fru, length) + 1); + fru->fru = *data; + desc += sizeof(*fru); + space -= sizeof(*fru); + break; } - } else { - struct scsi_sense_data_fixed *sense; - - sense = (struct scsi_sense_data_fixed *)sense_data; - - if (current_error != 0) - sense->error_code = SSD_CURRENT_ERROR; - else - sense->error_code = SSD_DEFERRED_ERROR; + case SSD_ELEM_STREAM: { + struct scsi_sense_stream *stream = (void *)desc; - sense->flags = sense_key; - sense->add_sense_code = asc; - sense->add_sense_code_qual = ascq; - /* - * We've set the ASC and ASCQ, so we have 6 more bytes of - * valid data. If we wind up setting any of the other - * fields, we'll bump this to 10 extra bytes. - */ - sense->extra_len = 6; - - while ((elem_type = (scsi_sense_elem_type)va_arg(ap, - scsi_sense_elem_type)) != SSD_ELEM_NONE) { - int sense_len, len_to_copy; - uint8_t *data; - - if (elem_type >= SSD_ELEM_MAX) { - printf("%s: invalid sense type %d\n", __func__, - elem_type); + if (len > sizeof(stream->byte3)) + break; + if (space < sizeof(*stream)) { + sense->flags |= SSDD_SDAT_OVFL; break; } + stream->desc_type = SSD_DESC_STREAM; + stream->length = sizeof(*stream) - + (offsetof(struct scsi_sense_stream, length) + 1); + stream->byte3 = *data; + desc += sizeof(*stream); + space -= sizeof(*stream); + break; + } + default: /* - * If we get in here, just bump the extra length to - * 10 bytes. That will encompass anything we're - * going to set here. + * We shouldn't get here, but if we do, do nothing. + * We've already consumed the arguments above. */ - sense->extra_len = 10; - sense_len = (int)va_arg(ap, int); - data = (uint8_t *)va_arg(ap, uint8_t *); + break; + } + } + sense->extra_len = desc - &sense->sense_desc[0]; + *sense_len = offsetof(struct scsi_sense_data_desc, extra_len) + 1 + + sense->extra_len; +} - switch (elem_type) { - case SSD_ELEM_SKS: - /* - * The user passed in pre-formatted sense - * key specific data. - */ - bcopy(data, &sense->sense_key_spec[0], - MIN(sizeof(sense->sense_key_spec), - sense_len)); - break; - case SSD_ELEM_INFO: - case SSD_ELEM_COMMAND: { - uint8_t *data_dest; - int i; - - if (elem_type == SSD_ELEM_COMMAND) { - data_dest = &sense->cmd_spec_info[0]; - len_to_copy = MIN(sense_len, - sizeof(sense->cmd_spec_info)); - } else { - data_dest = &sense->info[0]; - len_to_copy = MIN(sense_len, - sizeof(sense->info)); - /* - * We're setting the info field, so - * set the valid bit. - */ - sense->error_code |= SSD_ERRCODE_VALID; - } +/* + * Fill in SCSI fixed sense data with the specified parameters. + */ +static void +scsi_set_sense_data_fixed_va(struct scsi_sense_data *sense_data, + u_int *sense_len, scsi_sense_data_type sense_format, int current_error, + int sense_key, int asc, int ascq, va_list ap) +{ + struct scsi_sense_data_fixed *sense; + scsi_sense_elem_type elem_type; + uint8_t *data; + int len; - /* - * Copy this in reverse so that if we have - * less than 4 bytes to fill, the least - * significant bytes will be at the end. - * If we have more than 4 bytes, only the - * least significant bytes will be included. - */ - for (i = sense_len - 1; i >= 0 && - len_to_copy > 0; i--, len_to_copy--) - data_dest[len_to_copy - 1] = data[i]; + memset(sense_data, 0, sizeof(*sense_data)); + sense = (struct scsi_sense_data_fixed *)sense_data; + if (current_error != 0) + sense->error_code = SSD_CURRENT_ERROR; + else + sense->error_code = SSD_DEFERRED_ERROR; + sense->flags = sense_key & SSD_KEY; + sense->extra_len = 0; + if (*sense_len >= 13) { + sense->add_sense_code = asc; + sense->extra_len = MAX(sense->extra_len, 5); + } else + sense->flags |= SSD_SDAT_OVFL; + if (*sense_len >= 14) { + sense->add_sense_code_qual = ascq; + sense->extra_len = MAX(sense->extra_len, 6); + } else + sense->flags |= SSD_SDAT_OVFL; + + while ((elem_type = va_arg(ap, scsi_sense_elem_type)) != + SSD_ELEM_NONE) { + if (elem_type >= SSD_ELEM_MAX) { + printf("%s: invalid sense type %d\n", __func__, + elem_type); + break; + } + len = va_arg(ap, int); + data = va_arg(ap, uint8_t *); + switch (elem_type) { + case SSD_ELEM_SKIP: + break; + case SSD_ELEM_SKS: + if (len > sizeof(sense->sense_key_spec)) break; - } - case SSD_ELEM_FRU: - sense->fru = *data; + if (*sense_len < 18) { + sense->flags |= SSD_SDAT_OVFL; break; - case SSD_ELEM_STREAM: - sense->flags |= *data; + } + bcopy(data, &sense->sense_key_spec[0], len); + sense->extra_len = MAX(sense->extra_len, 10); + break; + case SSD_ELEM_COMMAND: + if (*sense_len < 12) { + sense->flags |= SSD_SDAT_OVFL; break; - case SSD_ELEM_DESC: - default: - - /* - * If the user passes in descriptor sense, - * we can't handle that in fixed format. - * So just skip it, and any unknown argument - * types. - */ + } + if (len > sizeof(sense->cmd_spec_info)) { + data += len - sizeof(sense->cmd_spec_info); + len -= len - sizeof(sense->cmd_spec_info); + } + bcopy(data, &sense->cmd_spec_info[ + sizeof(sense->cmd_spec_info) - len], len); + sense->extra_len = MAX(sense->extra_len, 4); + break; + case SSD_ELEM_INFO: + /* Set VALID bit only if no overflow. */ + sense->error_code |= SSD_ERRCODE_VALID; + while (len > sizeof(sense->info)) { + if (data[0] != 0) + sense->error_code &= ~SSD_ERRCODE_VALID; + data ++; + len --; + } + bcopy(data, &sense->info[sizeof(sense->info) - len], len); + break; + case SSD_ELEM_FRU: + if (*sense_len < 15) { + sense->flags |= SSD_SDAT_OVFL; break; } + sense->fru = *data; + sense->extra_len = MAX(sense->extra_len, 7); + break; + case SSD_ELEM_STREAM: + sense->flags |= *data & + (SSD_ILI | SSD_EOM | SSD_FILEMARK); + break; + default: + + /* + * We can't handle that in fixed format. Skip it. + */ + break; } } + *sense_len = offsetof(struct scsi_sense_data_fixed, extra_len) + 1 + + sense->extra_len; +} + +/* + * Fill in SCSI sense data with the specified parameters. This routine can + * fill in either fixed or descriptor type sense data. + */ +void +scsi_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len, + scsi_sense_data_type sense_format, int current_error, + int sense_key, int asc, int ascq, va_list ap) +{ + + if (*sense_len > SSD_FULL_SIZE) + *sense_len = SSD_FULL_SIZE; + if (sense_format == SSD_TYPE_DESC) + scsi_set_sense_data_desc_va(sense_data, sense_len, + sense_format, current_error, sense_key, asc, ascq, ap); + else + scsi_set_sense_data_fixed_va(sense_data, sense_len, + sense_format, current_error, sense_key, asc, ascq, ap); +} + +void +scsi_set_sense_data(struct scsi_sense_data *sense_data, + scsi_sense_data_type sense_format, int current_error, + int sense_key, int asc, int ascq, ...) +{ + va_list ap; + u_int sense_len = SSD_FULL_SIZE; + + va_start(ap, ascq); + scsi_set_sense_data_va(sense_data, &sense_len, sense_format, + current_error, sense_key, asc, ascq, ap); + va_end(ap); } void -scsi_set_sense_data(struct scsi_sense_data *sense_data, +scsi_set_sense_data_len(struct scsi_sense_data *sense_data, u_int *sense_len, scsi_sense_data_type sense_format, int current_error, - int sense_key, int asc, int ascq, ...) + int sense_key, int asc, int ascq, ...) { va_list ap; va_start(ap, ascq); - scsi_set_sense_data_va(sense_data, sense_format, current_error, - sense_key, asc, ascq, ap); + scsi_set_sense_data_va(sense_data, sense_len, sense_format, + current_error, sense_key, asc, ascq, ap); va_end(ap); } @@ -4708,6 +4679,26 @@ scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, sbuf_printf(sb, "device: %02x, ", res->device); } +void +scsi_sense_forwarded_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, + u_int sense_len, uint8_t *cdb, int cdb_len, + struct scsi_inquiry_data *inq_data, + struct scsi_sense_desc_header *header) +{ + struct scsi_sense_forwarded *forwarded; + const char *sense_key_desc; + const char *asc_desc; + int error_code, sense_key, asc, ascq; + + forwarded = (struct scsi_sense_forwarded *)header; + scsi_extract_sense_len((struct scsi_sense_data *)forwarded->sense_data, + forwarded->length - 2, &error_code, &sense_key, &asc, &ascq, 1); + scsi_sense_desc(sense_key, asc, ascq, NULL, &sense_key_desc, &asc_desc); + + sbuf_printf(sb, "Forwarded sense: %s asc:%x,%x (%s): ", + sense_key_desc, asc, ascq, asc_desc); +} + /* * Generic sense descriptor printing routine. This is used when we have * not yet implemented a specific printing routine for this descriptor. @@ -4755,7 +4746,8 @@ struct scsi_sense_desc_printer { {SSD_DESC_STREAM, scsi_sense_stream_sbuf}, {SSD_DESC_BLOCK, scsi_sense_block_sbuf}, {SSD_DESC_ATA, scsi_sense_ata_sbuf}, - {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf} + {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf}, + {SSD_DESC_FORWARDED, scsi_sense_forwarded_sbuf} }; void @@ -5693,6 +5685,32 @@ scsi_devid_is_lun_name(uint8_t *bufp) } int +scsi_devid_is_lun_md5(uint8_t *bufp) +{ + struct scsi_vpd_id_descriptor *descr; + + descr = (struct scsi_vpd_id_descriptor *)bufp; + if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) + return 0; + if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_MD5_LUN_ID) + return 0; + return 1; +} + +int +scsi_devid_is_lun_uuid(uint8_t *bufp) +{ + struct scsi_vpd_id_descriptor *descr; + + descr = (struct scsi_vpd_id_descriptor *)bufp; + if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) + return 0; + if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_UUID) + return 0; + return 1; +} + +int scsi_devid_is_port_naa(uint8_t *bufp) { struct scsi_vpd_id_descriptor *descr; @@ -7618,24 +7636,34 @@ scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries, } void -scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries, - void (*cbfcnp)(struct cam_periph *, union ccb *), - u_int8_t tag_action, int dbd, u_int8_t page_code, - u_int8_t page, u_int8_t *param_buf, u_int32_t param_len, - u_int8_t sense_len, u_int32_t timeout) +scsi_mode_sense(struct ccb_scsiio *csio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, + int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, + uint8_t sense_len, uint32_t timeout) { - scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd, - page_code, page, param_buf, param_len, 0, - sense_len, timeout); + scsi_mode_sense_subpage(csio, retries, cbfcnp, tag_action, dbd, + pc, page, 0, param_buf, param_len, 0, sense_len, timeout); } void -scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries, - void (*cbfcnp)(struct cam_periph *, union ccb *), - u_int8_t tag_action, int dbd, u_int8_t page_code, - u_int8_t page, u_int8_t *param_buf, u_int32_t param_len, - int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout) +scsi_mode_sense_len(struct ccb_scsiio *csio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, + int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, + int minimum_cmd_size, uint8_t sense_len, uint32_t timeout) +{ + + scsi_mode_sense_subpage(csio, retries, cbfcnp, tag_action, dbd, + pc, page, 0, param_buf, param_len, minimum_cmd_size, + sense_len, timeout); +} + +void +scsi_mode_sense_subpage(struct ccb_scsiio *csio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, + int dbd, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t *param_buf, + uint32_t param_len, int minimum_cmd_size, uint8_t sense_len, + uint32_t timeout) { u_int8_t cdb_len; @@ -7654,7 +7682,8 @@ scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries, scsi_cmd->opcode = MODE_SENSE_6; if (dbd != 0) scsi_cmd->byte2 |= SMS_DBD; - scsi_cmd->page = page_code | page; + scsi_cmd->page = pc | page; + scsi_cmd->subpage = subpage; scsi_cmd->length = param_len; cdb_len = sizeof(*scsi_cmd); } else { @@ -7668,7 +7697,8 @@ scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries, scsi_cmd->opcode = MODE_SENSE_10; if (dbd != 0) scsi_cmd->byte2 |= SMS_DBD; - scsi_cmd->page = page_code | page; + scsi_cmd->page = pc | page; + scsi_cmd->subpage = subpage; scsi_ulto2b(param_len, scsi_cmd->length); cdb_len = sizeof(*scsi_cmd); } |