summaryrefslogtreecommitdiffstats
path: root/src/drivers/block/scsi.c
diff options
context:
space:
mode:
authorMichael Brown2006-12-12 19:18:54 +0100
committerMichael Brown2006-12-12 19:18:54 +0100
commit3bd7e479a2fc8c56259643d88d9c58e8032376cc (patch)
tree42cd04bce9e0d7fa38dfbc05ca5650f31b5e4111 /src/drivers/block/scsi.c
parentTypo (diff)
downloadipxe-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.c33
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;