diff options
author | Michael Brown <mcb30@etherboot.org> | 2007-05-15 15:23:09 +0000 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2007-05-15 15:23:09 +0000 |
commit | 5471bfbbbe9f49f7be7f2ca92b8c99a02c435458 (patch) | |
tree | b2dcb5f373672a767336ddba8d7e25fcc3f0c554 | |
parent | 817a446cc6e80e04388250624a335ac0083ea79a (diff) | |
download | ipxe-5471bfbbbe9f49f7be7f2ca92b8c99a02c435458.tar.gz |
Data-transfer interface should now be functionally complete.
-rw-r--r-- | src/core/downloader.c | 31 | ||||
-rw-r--r-- | src/core/hw.c | 68 | ||||
-rw-r--r-- | src/core/xfer.c | 124 | ||||
-rw-r--r-- | src/include/gpxe/xfer.h | 93 |
4 files changed, 243 insertions, 73 deletions
diff --git a/src/core/downloader.c b/src/core/downloader.c index f539bb687..2e466cbff 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -115,7 +115,7 @@ static void downloader_job_start ( struct job_interface *job ) { container_of ( job, struct downloader, job ); /* Start data transfer */ - xfer_start ( &downloader->xfer ); + xfer_request_all ( &downloader->xfer ); } /** @@ -152,17 +152,30 @@ static struct job_interface_operations downloader_job_operations = { * @v pos New position * @ret rc Return status code */ -static int downloader_xfer_seek ( struct xfer_interface *xfer, size_t pos ) { +static int downloader_xfer_seek ( struct xfer_interface *xfer, off_t offset, + int whence ) { struct downloader *downloader = container_of ( xfer, struct downloader, xfer ); + off_t new_pos; int rc; + /* Calculate new buffer position */ + switch ( whence ) { + case SEEK_SET: + new_pos = offset; + break; + case SEEK_CUR: + new_pos = ( downloader->pos + offset ); + break; + default: + assert ( 0 ); + return -EINVAL; + } + /* Ensure that we have enough buffer space for this buffer position */ - if ( ( rc = downloader_ensure_size ( downloader, pos ) ) != 0 ) + if ( ( rc = downloader_ensure_size ( downloader, new_pos ) ) != 0 ) return rc; - - /* Update current buffer position */ - downloader->pos = pos; + downloader->pos = new_pos; return 0; } @@ -216,11 +229,11 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) { /** Downloader data transfer interface operations */ static struct xfer_interface_operations downloader_xfer_operations = { - .start = ignore_xfer_start, .close = downloader_xfer_close, - .vredirect = default_xfer_vredirect, + .vredirect = vopen, + .request = ignore_xfer_request, .seek = downloader_xfer_seek, - .deliver = xfer_deliver_as_raw, + .deliver_iob = xfer_deliver_as_raw, .deliver_raw = downloader_xfer_deliver_raw, }; diff --git a/src/core/hw.c b/src/core/hw.c new file mode 100644 index 000000000..80cac99c8 --- /dev/null +++ b/src/core/hw.c @@ -0,0 +1,68 @@ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <gpxe/refcnt.h> +#include <gpxe/xfer.h> +#include <gpxe/open.h> + +/** @file + * + * "Hello World" data source + * + */ + +struct hw { + struct refcnt refcnt; + struct xfer_interface xfer; +}; + +static const char hw_msg[] = "Hello world!\n"; + +static void hw_finished ( struct hw *hw, int rc ) { + xfer_nullify ( &hw->xfer ); + xfer_close ( &hw->xfer, rc ); + ref_put ( &hw->refcnt ); +} + +static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) { + struct hw *hw = container_of ( xfer, struct hw, xfer ); + + hw_finished ( hw, rc ); +} + +static int hw_xfer_request ( struct xfer_interface *xfer, off_t start __unused, + int whence __unused, size_t len __unused ) { + struct hw *hw = container_of ( xfer, struct hw, xfer ); + + xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) ); + hw_finished ( hw, 0 ); + return 0; +} + +static struct xfer_interface_operations hw_xfer_operations = { + .close = hw_xfer_close, + .vredirect = ignore_xfer_vredirect, + .request = hw_xfer_request, + .seek = ignore_xfer_seek, + .deliver_iob = xfer_deliver_as_raw, + .deliver_raw = ignore_xfer_deliver_raw, +}; + +static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) { + struct hw *hw; + + hw = malloc ( sizeof ( *hw ) ); + if ( ! hw ) + return -ENOMEM; + memset ( hw, 0, sizeof ( *hw ) ); + xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt ); + + xfer_plug_plug ( &hw->xfer, xfer ); + return 0; +} + +struct uri_opener hw_uri_opener __uri_opener = { + .scheme = "hw", + .open = hw_open, +}; diff --git a/src/core/xfer.c b/src/core/xfer.c index 8a5d03d83..bfbf1ceda 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -40,19 +40,6 @@ void xfer_close ( struct xfer_interface *xfer, int rc ) { } /** - * Seek to position - * - * @v xfer Data transfer interface - * @v pos New position - * @ret rc Return status code - */ -int xfer_seek ( struct xfer_interface *xfer, size_t pos ) { - struct xfer_interface *dest = xfer_dest ( xfer ); - - return dest->op->seek ( dest, pos ); -} - -/** * Send redirection event * * @v xfer Data transfer interface @@ -85,16 +72,69 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) { } /** + * Request data + * + * @v xfer Data transfer interface + * @v offset Offset to new position + * @v whence Basis for new position + * @v len Length of requested data + * @ret rc Return status code + */ +int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence, + size_t len ) { + struct xfer_interface *dest = xfer_dest ( xfer ); + + return dest->op->request ( dest, offset, whence, len ); +} + +/** + * Request all data + * + * @v xfer Data transfer interface + * @ret rc Return status code + */ +int xfer_request_all ( struct xfer_interface *xfer ) { + return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) ); +} + +/** + * Seek to position + * + * @v xfer Data transfer interface + * @v offset Offset to new position + * @v whence Basis for new position + * @ret rc Return status code + */ +int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) { + struct xfer_interface *dest = xfer_dest ( xfer ); + + return dest->op->seek ( dest, offset, whence ); +} + +/** + * Allocate I/O buffer + * + * @v xfer Data transfer interface + * @v len I/O buffer payload length + * @ret iobuf I/O buffer + */ +struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) { + struct xfer_interface *dest = xfer_dest ( xfer ); + + return dest->op->alloc_iob ( dest, len ); +} + +/** * Deliver datagram * * @v xfer Data transfer interface * @v iobuf Datagram I/O buffer * @ret rc Return status code */ -int xfer_deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { +int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { struct xfer_interface *dest = xfer_dest ( xfer ); - return dest->op->deliver ( dest, iobuf ); + return dest->op->deliver_iob ( dest, iobuf ); } /** @@ -121,15 +161,6 @@ int xfer_deliver_raw ( struct xfer_interface *xfer, */ /** - * Ignore start() event - * - * @v xfer Data transfer interface - */ -void ignore_xfer_start ( struct xfer_interface *xfer __unused ) { - /* Nothing to do */ -} - -/** * Ignore close() event * * @v xfer Data transfer interface @@ -154,18 +185,46 @@ int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused, } /** + * Ignore request() event + * + * @v xfer Data transfer interface + * @v offset Offset to new position + * @v whence Basis for new position + * @v len Length of requested data + * @ret rc Return status code + */ +int ignore_xfer_request ( struct xfer_interface *xfer __unused, + off_t offset __unused, int whence __unused, + size_t len __unused ) { + return 0; +} + +/** * Ignore seek() event * * @v xfer Data transfer interface - * @v pos New position + * @v offset Offset to new position + * @v whence Basis for new position * @ret rc Return status code */ int ignore_xfer_seek ( struct xfer_interface *xfer __unused, - size_t pos __unused ) { + off_t offset __unused, int whence __unused ) { return 0; } /** + * Allocate I/O buffer + * + * @v xfer Data transfer interface + * @v len I/O buffer payload length + * @ret iobuf I/O buffer + */ +struct io_buffer * +default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) { + return alloc_iob ( len ); +} + +/** * Deliver datagram as raw data * * @v xfer Data transfer interface @@ -195,16 +254,16 @@ int xfer_deliver_as_raw ( struct xfer_interface *xfer, * This function is intended to be used as the deliver_raw() method * for data transfer interfaces that prefer to handle I/O buffers. */ -int xfer_deliver_as_iobuf ( struct xfer_interface *xfer, - const void *data, size_t len ) { +int xfer_deliver_as_iob ( struct xfer_interface *xfer, + const void *data, size_t len ) { struct io_buffer *iobuf; - iobuf = alloc_iob ( len ); + iobuf = xfer->op->alloc_iob ( xfer, len ); if ( ! iobuf ) return -ENOMEM; memcpy ( iob_put ( iobuf, len ), data, len ); - return xfer->op->deliver ( xfer, iobuf ); + return xfer->op->deliver_iob ( xfer, iobuf ); } /** @@ -225,11 +284,12 @@ int ignore_xfer_deliver_raw ( struct xfer_interface *xfer, /** Null data transfer interface operations */ struct xfer_interface_operations null_xfer_ops = { - .start = ignore_xfer_start, .close = ignore_xfer_close, .vredirect = ignore_xfer_vredirect, + .request = ignore_xfer_request, .seek = ignore_xfer_seek, - .deliver = xfer_deliver_as_raw, + .alloc_iob = default_xfer_alloc_iob, + .deliver_iob = xfer_deliver_as_raw, .deliver_raw = ignore_xfer_deliver_raw, }; diff --git a/src/include/gpxe/xfer.h b/src/include/gpxe/xfer.h index 61f5d86cf..4fb3a5196 100644 --- a/src/include/gpxe/xfer.h +++ b/src/include/gpxe/xfer.h @@ -16,22 +16,6 @@ struct xfer_interface; /** Data transfer interface operations */ struct xfer_interface_operations { - - /* Missing features: - * - * notification of non-close status - e.g. connected/opened, ... - * - * prompt for data delivery - * - * I/O buffer preparation - * - */ - - /** Start data transfer - * - * @v xfer Data transfer interface - */ - void ( * start ) ( struct xfer_interface *xfer ); /** Close interface * * @v xfer Data transfer interface @@ -47,14 +31,39 @@ struct xfer_interface_operations { */ int ( * vredirect ) ( struct xfer_interface *xfer, int type, va_list args ); + /** Request data + * + * @v xfer Data transfer interface + * @v offset Offset to new position + * @v whence Basis for new position + * @v len Length of requested data + * @ret rc Return status code + */ + int ( * request ) ( struct xfer_interface *xfer, off_t offset, + int whence, size_t len ); /** Seek to position * * @v xfer Data transfer interface - * @v pos New position + * @v offset Offset to new position + * @v whence Basis for new position * @ret rc Return status code + * + * @c whence must be one of @c SEEK_SET or @c SEEK_CUR. A + * successful return indicates that the interface is ready to + * immediately accept datagrams; return -EAGAIN if this is not + * the case. */ - int ( * seek ) ( struct xfer_interface *xfer, size_t pos ); - /** Deliver datagram + int ( * seek ) ( struct xfer_interface *xfer, off_t offset, + int whence ); + /** Allocate I/O buffer + * + * @v xfer Data transfer interface + * @v len I/O buffer payload length + * @ret iobuf I/O buffer + */ + struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer, + size_t len ); + /** Deliver datagram as I/O buffer * * @v xfer Data transfer interface * @v iobuf Datagram I/O buffer @@ -63,9 +72,13 @@ struct xfer_interface_operations { * A data transfer interface that wishes to support only raw * data delivery should set this method to * xfer_deliver_as_raw(). + * + * Interfaces may not temporarily refuse to accept data by + * returning -EAGAIN; such a response may be treated as a + * fatal error. */ - int ( * deliver ) ( struct xfer_interface *xfer, - struct io_buffer *iobuf ); + int ( * deliver_iob ) ( struct xfer_interface *xfer, + struct io_buffer *iobuf ); /** Deliver datagram as raw data * * @v xfer Data transfer interface @@ -75,7 +88,11 @@ struct xfer_interface_operations { * * A data transfer interface that wishes to support only I/O * buffer delivery should set this method to - * xfer_deliver_as_iobuf(). + * xfer_deliver_as_iob(). + * + * Interfaces may not temporarily refuse to accept data by + * returning -EAGAIN; such a response may be treated as a + * fatal error. */ int ( * deliver_raw ) ( struct xfer_interface *xfer, const void *data, size_t len ); @@ -89,31 +106,43 @@ struct xfer_interface { struct xfer_interface_operations *op; }; +/** Basis positions for seek() events */ +enum seek_whence { + SEEK_SET = 0, + SEEK_CUR, +}; + extern struct xfer_interface null_xfer; extern struct xfer_interface_operations null_xfer_ops; -extern void xfer_start ( struct xfer_interface *xfer ); extern void xfer_close ( struct xfer_interface *xfer, int rc ); -extern int xfer_seek ( struct xfer_interface *xfer, size_t pos ); extern int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ); extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... ); -extern int xfer_deliver ( struct xfer_interface *xfer, - struct io_buffer *iobuf ); +extern int xfer_request ( struct xfer_interface *xfer, off_t offset, + int whence, size_t len ); +extern int xfer_request_all ( struct xfer_interface *xfer ); +extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ); +extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, + size_t len ); +extern int xfer_deliver_iob ( struct xfer_interface *xfer, + struct io_buffer *iobuf ); extern int xfer_deliver_raw ( struct xfer_interface *xfer, const void *data, size_t len ); -extern void ignore_xfer_start ( struct xfer_interface *xfer ); extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc ); extern int ignore_xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ); -extern int default_xfer_vredirect ( struct xfer_interface *xfer, - int type, va_list args ); -extern int ignore_xfer_seek ( struct xfer_interface *xfer, size_t pos ); +extern int ignore_xfer_request ( struct xfer_interface *xfer, off_t offset, + int whence, size_t len ); +extern int ignore_xfer_seek ( struct xfer_interface *xfer, off_t offset, + int whence ); +extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer, + size_t len ); extern int xfer_deliver_as_raw ( struct xfer_interface *xfer, struct io_buffer *iobuf ); -extern int xfer_deliver_as_iobuf ( struct xfer_interface *xfer, - const void *data, size_t len ); +extern int xfer_deliver_as_iob ( struct xfer_interface *xfer, + const void *data, size_t len ); extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer, const void *data __unused, size_t len ); |