diff options
author | Michael Brown | 2006-12-12 19:18:54 +0100 |
---|---|---|
committer | Michael Brown | 2006-12-12 19:18:54 +0100 |
commit | 3bd7e479a2fc8c56259643d88d9c58e8032376cc (patch) | |
tree | 42cd04bce9e0d7fa38dfbc05ca5650f31b5e4111 /src/drivers/block/scsi.c | |
parent | Typo (diff) | |
download | ipxe-3bd7e479a2fc8c56259643d88d9c58e8032376cc.tar.gz ipxe-3bd7e479a2fc8c56259643d88d9c58e8032376cc.tar.xz ipxe-3bd7e479a2fc8c56259643d88d9c58e8032376cc.zip |
Catch SCSI errors, and work around the start-of-day CHECK CONDITION
that some targets send.
Diffstat (limited to 'src/drivers/block/scsi.c')
-rw-r--r-- | src/drivers/block/scsi.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index 1e906e13..0578403a 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -19,6 +19,7 @@ #include <stddef.h> #include <string.h> #include <byteswap.h> +#include <errno.h> #include <gpxe/blockdev.h> #include <gpxe/scsi.h> @@ -42,7 +43,30 @@ block_to_scsi ( struct block_device *blockdev ) { */ static int scsi_command ( struct scsi_device *scsi, struct scsi_command *command ) { - return scsi->command ( scsi, command ); + int rc; + + /* Clear sense response code before issuing command */ + command->sense_response = 0; + + /* Issue SCSI command */ + if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) { + /* Something went wrong with the issuing mechanism, + * (rather than with the command itself) + */ + DBG ( "SCSI %p " SCSI_CDB_FORMAT " err %d\n", + scsi, SCSI_CDB_DATA ( command->cdb ), rc ); + return rc; + } + + /* Check for SCSI errors */ + if ( command->status != 0 ) { + DBG ( "SCSI %p " SCSI_CDB_FORMAT " status %02x sense %02x\n", + scsi, SCSI_CDB_DATA ( command->cdb ), + command->status, command->sense_response ); + return -EIO; + } + + return 0; } /** @@ -163,6 +187,13 @@ static int scsi_read_capacity_16 ( struct block_device *blockdev ) { static int scsi_read_capacity ( struct block_device *blockdev ) { int rc; + /* Issue a theoretically extraneous READ CAPACITY (10) + * command, solely in order to draw out the "CHECK CONDITION + * (power-on occurred)" that some dumb targets insist on + * sending as an error at start of day. + */ + scsi_read_capacity_10 ( blockdev ); + /* Try READ CAPACITY (10), which is a mandatory command, first. */ if ( ( rc = scsi_read_capacity_10 ( blockdev ) ) != 0 ) return rc; |