summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-07-08 00:01:28 +0200
committerMichael Brown2009-07-18 00:01:20 +0200
commit54ec3673cc319a5646c21a87bbf41198b1f462b5 (patch)
tree1f9082322c78bc0b6110784198782126dd0394ee
parent[scsi] Improve SCSI debugging (diff)
downloadipxe-54ec3673cc319a5646c21a87bbf41198b1f462b5.tar.gz
ipxe-54ec3673cc319a5646c21a87bbf41198b1f462b5.tar.xz
ipxe-54ec3673cc319a5646c21a87bbf41198b1f462b5.zip
[ata] Make ATA command issuing partially asynchronous
Move the icky call to step() from aoe.c to ata.c; this takes it at least one step further away from where it really doesn't belong. Unfortunately, AoE has the ugly aoe_discover() mechanism which means that we still have a step() loop in aoe.c for now; this needs to be replaced at some future point.
-rw-r--r--src/drivers/block/ata.c25
-rw-r--r--src/include/gpxe/ata.h2
-rw-r--r--src/include/gpxe/errfile.h1
-rw-r--r--src/net/aoe.c10
4 files changed, 29 insertions, 9 deletions
diff --git a/src/drivers/block/ata.c b/src/drivers/block/ata.c
index fd636458..dc851d72 100644
--- a/src/drivers/block/ata.c
+++ b/src/drivers/block/ata.c
@@ -21,8 +21,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stddef.h>
#include <string.h>
#include <assert.h>
+#include <errno.h>
#include <byteswap.h>
#include <gpxe/blockdev.h>
+#include <gpxe/process.h>
#include <gpxe/ata.h>
/** @file
@@ -45,13 +47,34 @@ block_to_ata ( struct block_device *blockdev ) {
*/
static inline __attribute__ (( always_inline )) int
ata_command ( struct ata_device *ata, struct ata_command *command ) {
+ int rc;
+
DBG ( "ATA cmd %02x dev %02x LBA%s %llx count %04x\n",
command->cb.cmd_stat, command->cb.device,
( command->cb.lba48 ? "48" : "" ),
( unsigned long long ) command->cb.lba.native,
command->cb.count.native );
- return ata->command ( ata, command );
+ /* Flag command as in-progress */
+ command->rc = -EINPROGRESS;
+
+ /* Issue ATA command */
+ if ( ( rc = ata->command ( ata, command ) ) != 0 ) {
+ /* Something went wrong with the issuing mechanism */
+ DBG ( "ATA could not issue command: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Wait for command to complete */
+ while ( command->rc == -EINPROGRESS )
+ step();
+ if ( ( rc = command->rc ) != 0 ) {
+ /* Something went wrong with the command execution */
+ DBG ( "ATA command failed: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
}
/**
diff --git a/src/include/gpxe/ata.h b/src/include/gpxe/ata.h
index 643b7cd9..3c565844 100644
--- a/src/include/gpxe/ata.h
+++ b/src/include/gpxe/ata.h
@@ -154,6 +154,8 @@ struct ata_command {
* sectors in size.
*/
userptr_t data_in;
+ /** Command status code */
+ int rc;
};
/**
diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h
index 7ca9c998..1312cbc9 100644
--- a/src/include/gpxe/errfile.h
+++ b/src/include/gpxe/errfile.h
@@ -115,6 +115,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
#define ERRFILE_hermon ( ERRFILE_DRIVER | 0x00720000 )
#define ERRFILE_linda ( ERRFILE_DRIVER | 0x00730000 )
+#define ERRFILE_ata ( ERRFILE_DRIVER | 0x00740000 )
#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 )
#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )
diff --git a/src/net/aoe.c b/src/net/aoe.c
index 9e6a99e2..f274ddf5 100644
--- a/src/net/aoe.c
+++ b/src/net/aoe.c
@@ -68,6 +68,7 @@ static void aoe_done ( struct aoe_session *aoe, int rc ) {
/* Record overall command status */
if ( aoe->command ) {
aoe->command->cb.cmd_stat = aoe->status;
+ aoe->command->rc = rc;
aoe->command = NULL;
}
@@ -356,7 +357,6 @@ static int aoe_command ( struct ata_device *ata,
struct ata_command *command ) {
struct aoe_session *aoe =
container_of ( ata->backend, struct aoe_session, refcnt );
- int rc;
aoe->command = command;
aoe->status = 0;
@@ -365,15 +365,9 @@ static int aoe_command ( struct ata_device *ata,
aoe_send_command ( aoe );
- aoe->rc = -EINPROGRESS;
- while ( aoe->rc == -EINPROGRESS )
- step();
- rc = aoe->rc;
-
- return rc;
+ return 0;
}
-
/**
* Issue AoE config query for AoE target discovery
*