mirror of
https://github.com/ipxe/ipxe
synced 2025-12-19 19:49:45 +03:00
Added generic asynchronous operations code.
Removed data_in_len and data_out_len from ata_command structure; the lengths are implied by the sector count and the presence of the data_in or data_out pointers. Changed AoE code to use subcommands by default, and made aoe_issue() nonblocking (with completion via async_wait()).
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include <stdint.h>
|
||||
#include <gpxe/list.h>
|
||||
#include <gpxe/if_ether.h>
|
||||
#include <gpxe/retry.h>
|
||||
#include <gpxe/async.h>
|
||||
#include <gpxe/ata.h>
|
||||
|
||||
/** An AoE ATA command */
|
||||
@@ -89,29 +91,31 @@ struct aoe_session {
|
||||
/** Target MAC address */
|
||||
uint8_t target[ETH_ALEN];
|
||||
|
||||
/** Tag for current command */
|
||||
/** Tag for current AoE command */
|
||||
uint32_t tag;
|
||||
|
||||
/** Current ATA command */
|
||||
struct ata_command *command;
|
||||
/** Status of the command */
|
||||
int status;
|
||||
/** Overall status of current ATA command */
|
||||
unsigned int status;
|
||||
/** Byte offset within command's data buffer */
|
||||
unsigned int command_offset;
|
||||
/** Asynchronous operation for this command */
|
||||
struct async_operation aop;
|
||||
|
||||
/** Retransmission timer */
|
||||
struct retry_timer timer;
|
||||
};
|
||||
|
||||
#define AOE_STATUS_ERR_MASK 0x0f /**< Error portion of status code */
|
||||
#define AOE_STATUS_PENDING 0x80 /**< Command pending */
|
||||
#define AOE_STATUS_UNDERRUN 0x40 /**< Buffer overrun */
|
||||
#define AOE_STATUS_OVERRUN 0x20 /**< Buffer underrun */
|
||||
|
||||
/** Maximum number of sectors per packet */
|
||||
#define AOE_MAX_COUNT 2
|
||||
|
||||
extern void aoe_open ( struct aoe_session *aoe );
|
||||
extern void aoe_close ( struct aoe_session *aoe );
|
||||
extern int aoe_issue ( struct aoe_session *aoe, struct ata_command *command );
|
||||
extern int aoe_issue_split ( struct aoe_session *aoe,
|
||||
struct ata_command *command );
|
||||
extern void aoe_issue ( struct aoe_session *aoe, struct ata_command *command );
|
||||
|
||||
/** An AoE device */
|
||||
struct aoe_device {
|
||||
|
||||
62
src/include/gpxe/async.h
Normal file
62
src/include/gpxe/async.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef _GPXE_ASYNC_H
|
||||
#define _GPXE_ASYNC_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Asynchronous operations
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
/** An asynchronous operation */
|
||||
struct async_operation {
|
||||
/** Operation status
|
||||
*
|
||||
* This is an error code as defined in errno.h, plus an offset
|
||||
* of EINPROGRESS. This means that a status value of 0
|
||||
* corresponds to a return status code of -EINPROGRESS,
|
||||
* i.e. that the default state of an asynchronous operation is
|
||||
* "not yet completed".
|
||||
*/
|
||||
int status;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set asynchronous operation status
|
||||
*
|
||||
* @v aop Asynchronous operation
|
||||
* @v rc Return status code
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
async_set_status ( struct async_operation *aop, int rc ) {
|
||||
aop->status = ( rc + EINPROGRESS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get asynchronous operation status
|
||||
*
|
||||
* @v aop Asynchronous operation
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
async_status ( struct async_operation *aop ) {
|
||||
return ( aop->status - EINPROGRESS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag asynchronous operation as complete
|
||||
*
|
||||
* @v aop Asynchronous operation
|
||||
* @v rc Return status code
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
async_done ( struct async_operation *aop, int rc ) {
|
||||
assert ( rc != -EINPROGRESS );
|
||||
async_set_status ( aop, rc );
|
||||
}
|
||||
|
||||
extern int async_wait ( struct async_operation *aop );
|
||||
|
||||
#endif /* _GPXE_ASYNC_H */
|
||||
@@ -139,20 +139,18 @@ struct ata_cb {
|
||||
struct ata_command {
|
||||
/** ATA command block */
|
||||
struct ata_cb cb;
|
||||
/** Data-out buffer (may be NULL) */
|
||||
/** Data-out buffer (may be NULL)
|
||||
*
|
||||
* If non-NULL, this buffer must be ata_command::cb::count
|
||||
* sectors in size.
|
||||
*/
|
||||
userptr_t data_out;
|
||||
/** Data-out buffer length
|
||||
/** Data-in buffer (may be NULL)
|
||||
*
|
||||
* Must be zero if @c data_out is NULL
|
||||
* If non-NULL, this buffer must be ata_command::cb::count
|
||||
* sectors in size.
|
||||
*/
|
||||
size_t data_out_len;
|
||||
/** Data-in buffer (may be NULL) */
|
||||
userptr_t data_in;
|
||||
/** Data-in buffer length
|
||||
*
|
||||
* Must be zero if @c data_in is NULL
|
||||
*/
|
||||
size_t data_in_len;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user