iobuf.h

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

Generated on Tue Apr 6 20:01:08 2010 for gPXE by  doxygen 1.5.7.1