diff options
author | Michael Brown | 2014-06-02 03:17:28 +0200 |
---|---|---|
committer | Michael Brown | 2014-06-03 03:04:46 +0200 |
commit | e047811c859bd11777c9a01d7ca89ca948567199 (patch) | |
tree | c84557d88a049527dfc80631dcc3d9cb3bed2380 /src/drivers/block | |
parent | [ethernet] Provide eth_random_addr() to generate random Ethernet addresses (diff) | |
download | ipxe-e047811c859bd11777c9a01d7ca89ca948567199.tar.gz ipxe-e047811c859bd11777c9a01d7ca89ca948567199.tar.xz ipxe-e047811c859bd11777c9a01d7ca89ca948567199.zip |
[scsi] Improve sense code parsing
Parse the sense data to extract the reponse code, the sense key, the
additional sense code, and the additional sense code qualifier.
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/block')
-rw-r--r-- | src/drivers/block/scsi.c | 34 | ||||
-rw-r--r-- | src/drivers/block/srp.c | 11 |
2 files changed, 37 insertions, 8 deletions
diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index 4245f019..64d69298 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -132,6 +132,33 @@ int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) { return 0; } +/** + * Parse SCSI sense data + * + * @v data Raw sense data + * @v len Length of raw sense data + * @v sense Descriptor-format sense data to fill in + */ +void scsi_parse_sense ( const void *data, size_t len, + struct scsi_sns_descriptor *sense ) { + const union scsi_sns *sns = data; + + /* Avoid returning uninitialised data */ + memset ( sense, 0, sizeof ( *sense ) ); + + /* Copy, assuming descriptor-format data */ + if ( len < sizeof ( sns->desc ) ) + return; + memcpy ( sense, &sns->desc, sizeof ( *sense ) ); + + /* Convert fixed-format to descriptor-format, if applicable */ + if ( len < sizeof ( sns->fixed ) ) + return; + if ( ! SCSI_SENSE_FIXED ( sns->code ) ) + return; + sense->additional = sns->fixed.additional; +} + /****************************************************************************** * * Interface methods @@ -468,9 +495,10 @@ static void scsicmd_response ( struct scsi_command *scsicmd, underrun = -(response->overrun); DBGC ( scsidev, " underrun -%zd", underrun ); } - DBGC ( scsidev, " sense %02x:%02x:%08x\n", - response->sense.code, response->sense.key, - ntohl ( response->sense.info ) ); + DBGC ( scsidev, " sense %02x key %02x additional %04x\n", + ( response->sense.code & SCSI_SENSE_CODE_MASK ), + ( response->sense.key & SCSI_SENSE_KEY_MASK ), + ntohs ( response->sense.additional ) ); /* Construct error number from sense data */ rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK ); diff --git a/src/drivers/block/srp.c b/src/drivers/block/srp.c index 70a97b2f..7edf69ac 100644 --- a/src/drivers/block/srp.c +++ b/src/drivers/block/srp.c @@ -476,12 +476,14 @@ static int srp_rsp ( struct srp_device *srpdev, const struct srp_rsp *rsp = data; struct srp_command *srpcmd; struct scsi_rsp response; - const void *sense; ssize_t data_out_residual_count; ssize_t data_in_residual_count; /* Sanity check */ - if ( len < sizeof ( *rsp ) ) { + if ( ( len < sizeof ( *rsp ) ) || + ( len < ( sizeof ( *rsp ) + + srp_rsp_response_data_len ( rsp ) + + srp_rsp_sense_data_len ( rsp ) ) ) ) { DBGC ( srpdev, "SRP %p RSP too short (%zd bytes)\n", srpdev, len ); return -EINVAL; @@ -523,9 +525,8 @@ static int srp_rsp ( struct srp_device *srpdev, } else if ( rsp->valid & SRP_RSP_VALID_DIUNDER ) { response.overrun = -(data_in_residual_count); } - sense = srp_rsp_sense_data ( rsp ); - if ( sense ) - memcpy ( &response.sense, sense, sizeof ( response.sense ) ); + scsi_parse_sense ( srp_rsp_sense_data ( rsp ), + srp_rsp_sense_data_len ( rsp ), &response.sense ); /* Report SCSI response */ scsi_response ( &srpcmd->scsi, &response ); |