iPXE
iobuf.h
Go to the documentation of this file.
00001 #ifndef _IPXE_IOBUF_H
00002 #define _IPXE_IOBUF_H
00003 
00004 /** @file
00005  *
00006  * I/O buffers
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <stdint.h>
00013 #include <assert.h>
00014 #include <ipxe/list.h>
00015 
00016 /**
00017  * Minimum I/O buffer length
00018  *
00019  * alloc_iob() will round up the allocated length to this size if
00020  * necessary.  This is used on behalf of hardware that is not capable
00021  * of auto-padding.
00022  */
00023 #define IOB_ZLEN 128
00024 
00025 /**
00026  * A persistent I/O buffer
00027  *
00028  * This data structure encapsulates a long-lived I/O buffer.  The
00029  * buffer may be passed between multiple owners, queued for possible
00030  * retransmission, etc.
00031  */
00032 struct io_buffer {
00033         /** List of which this buffer is a member
00034          *
00035          * The list must belong to the current owner of the buffer.
00036          * Different owners may maintain different lists (e.g. a
00037          * retransmission list for TCP).
00038          */
00039         struct list_head list;
00040 
00041         /** Start of the buffer */
00042         void *head;
00043         /** Start of data */
00044         void *data;
00045         /** End of data */
00046         void *tail;
00047         /** End of the buffer */
00048         void *end;
00049 };
00050 
00051 /**
00052  * Reserve space at start of I/O buffer
00053  *
00054  * @v iobuf     I/O buffer
00055  * @v len       Length to reserve
00056  * @ret data    Pointer to new start of buffer
00057  */
00058 static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
00059         iobuf->data += len;
00060         iobuf->tail += len;
00061         return iobuf->data;
00062 }
00063 #define iob_reserve( iobuf, len ) ( {                   \
00064         void *__result;                                 \
00065         __result = iob_reserve ( (iobuf), (len) );      \
00066         assert ( (iobuf)->tail <= (iobuf)->end );       \
00067         __result; } )
00068 
00069 /**
00070  * Add data to start of I/O buffer
00071  *
00072  * @v iobuf     I/O buffer
00073  * @v len       Length to add
00074  * @ret data    Pointer to new start of buffer
00075  */
00076 static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
00077         iobuf->data -= len;
00078         return iobuf->data;
00079 }
00080 #define iob_push( iobuf, len ) ( {                      \
00081         void *__result;                                 \
00082         __result = iob_push ( (iobuf), (len) );         \
00083         assert ( (iobuf)->data >= (iobuf)->head );      \
00084         __result; } )
00085 
00086 /**
00087  * Remove data from start of I/O buffer
00088  *
00089  * @v iobuf     I/O buffer
00090  * @v len       Length to remove
00091  * @ret data    Pointer to new start of buffer
00092  */
00093 static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
00094         iobuf->data += len;
00095         assert ( iobuf->data <= iobuf->tail );
00096         return iobuf->data;
00097 }
00098 #define iob_pull( iobuf, len ) ( {                      \
00099         void *__result;                                 \
00100         __result = iob_pull ( (iobuf), (len) );         \
00101         assert ( (iobuf)->data <= (iobuf)->tail );      \
00102         __result; } )
00103 
00104 /**
00105  * Add data to end of I/O buffer
00106  *
00107  * @v iobuf     I/O buffer
00108  * @v len       Length to add
00109  * @ret data    Pointer to newly added space
00110  */
00111 static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
00112         void *old_tail = iobuf->tail;
00113         iobuf->tail += len;
00114         return old_tail;
00115 }
00116 #define iob_put( iobuf, len ) ( {                       \
00117         void *__result;                                 \
00118         __result = iob_put ( (iobuf), (len) );          \
00119         assert ( (iobuf)->tail <= (iobuf)->end );       \
00120         __result; } )
00121 
00122 /**
00123  * Remove data from end of I/O buffer
00124  *
00125  * @v iobuf     I/O buffer
00126  * @v len       Length to remove
00127  */
00128 static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
00129         iobuf->tail -= len;
00130 }
00131 #define iob_unput( iobuf, len ) do {                    \
00132         iob_unput ( (iobuf), (len) );                   \
00133         assert ( (iobuf)->tail >= (iobuf)->data );      \
00134         } while ( 0 )
00135 
00136 /**
00137  * Empty an I/O buffer
00138  *
00139  * @v iobuf     I/O buffer
00140  */
00141 static inline void iob_empty ( struct io_buffer *iobuf ) {
00142         iobuf->tail = iobuf->data;
00143 }
00144 
00145 /**
00146  * Calculate length of data in an I/O buffer
00147  *
00148  * @v iobuf     I/O buffer
00149  * @ret len     Length of data in buffer
00150  */
00151 static inline size_t iob_len ( struct io_buffer *iobuf ) {
00152         return ( iobuf->tail - iobuf->data );
00153 }
00154 
00155 /**
00156  * Calculate available space at start of an I/O buffer
00157  *
00158  * @v iobuf     I/O buffer
00159  * @ret len     Length of data available at start of buffer
00160  */
00161 static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
00162         return ( iobuf->data - iobuf->head );
00163 }
00164 
00165 /**
00166  * Calculate available space at end of an I/O buffer
00167  *
00168  * @v iobuf     I/O buffer
00169  * @ret len     Length of data available at end of buffer
00170  */
00171 static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
00172         return ( iobuf->end - iobuf->tail );
00173 }
00174 
00175 /**
00176  * Create a temporary I/O buffer
00177  *
00178  * @v iobuf     I/O buffer
00179  * @v data      Data buffer
00180  * @v len       Length of data
00181  * @v max_len   Length of buffer
00182  *
00183  * It is sometimes useful to use the iob_xxx() methods on temporary
00184  * data buffers.
00185  */
00186 static inline void iob_populate ( struct io_buffer *iobuf,
00187                                   void *data, size_t len, size_t max_len ) {
00188         iobuf->head = iobuf->data = data;
00189         iobuf->tail = ( data + len );
00190         iobuf->end = ( data + max_len );
00191 }
00192 
00193 /**
00194  * Disown an I/O buffer
00195  *
00196  * @v iobuf     I/O buffer
00197  *
00198  * There are many functions that take ownership of the I/O buffer they
00199  * are passed as a parameter.  The caller should not retain a pointer
00200  * to the I/O buffer.  Use iob_disown() to automatically nullify the
00201  * caller's pointer, e.g.:
00202  *
00203  *     xfer_deliver_iob ( xfer, iob_disown ( iobuf ) );
00204  *
00205  * This will ensure that iobuf is set to NULL for any code after the
00206  * call to xfer_deliver_iob().
00207  */
00208 #define iob_disown( iobuf ) ( {                         \
00209         struct io_buffer *__iobuf = (iobuf);            \
00210         (iobuf) = NULL;                                 \
00211         __iobuf; } )
00212 
00213 extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align,
00214                                                    size_t offset );
00215 extern struct io_buffer * __malloc alloc_iob ( size_t len );
00216 extern void free_iob ( struct io_buffer *iobuf );
00217 extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
00218 extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
00219 extern struct io_buffer * iob_concatenate ( struct list_head *list );
00220 extern struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len );
00221 
00222 #endif /* _IPXE_IOBUF_H */