iPXE
iobuf.h
Go to the documentation of this file.
1#ifndef _IPXE_IOBUF_H
2#define _IPXE_IOBUF_H
3
4/** @file
5 *
6 * I/O buffers
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11FILE_SECBOOT ( PERMITTED );
12
13#include <stdint.h>
14#include <assert.h>
15#include <ipxe/list.h>
16#include <ipxe/dma.h>
17
18/**
19 * Minimum I/O buffer length and alignment
20 *
21 * alloc_iob() will round up the allocated length to this size if
22 * necessary. This is used on behalf of hardware that is not capable
23 * of auto-padding.
24 *
25 * This length must be at least as large as the largest cacheline size
26 * that we expect to encounter, to allow for platforms where DMA
27 * devices are not in the same coherency domain as the CPU cache.
28 */
29#define IOB_ZLEN 128
30
31/**
32 * A persistent I/O buffer
33 *
34 * This data structure encapsulates a long-lived I/O buffer. The
35 * buffer may be passed between multiple owners, queued for possible
36 * retransmission, etc.
37 */
38struct io_buffer {
39 /** List of which this buffer is a member
40 *
41 * The list must belong to the current owner of the buffer.
42 * Different owners may maintain different lists (e.g. a
43 * retransmission list for TCP).
44 */
46
47 /** DMA mapping */
49
50 /** Start of the buffer */
51 void *head;
52 /** Start of data */
53 void *data;
54 /** End of data */
55 void *tail;
56 /** End of the buffer */
57 void *end;
58};
59
60/**
61 * Reserve space at start of I/O buffer
62 *
63 * @v iobuf I/O buffer
64 * @v len Length to reserve
65 * @ret data Pointer to new start of buffer
66 */
67static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
68 iobuf->data += len;
69 iobuf->tail += len;
70 return iobuf->data;
71}
72#define iob_reserve( iobuf, len ) ( { \
73 void *__result; \
74 __result = iob_reserve ( (iobuf), (len) ); \
75 assert ( (iobuf)->tail <= (iobuf)->end ); \
76 __result; } )
77
78/**
79 * Add data to start of I/O buffer
80 *
81 * @v iobuf I/O buffer
82 * @v len Length to add
83 * @ret data Pointer to new start of buffer
84 */
85static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
86 iobuf->data -= len;
87 return iobuf->data;
88}
89#define iob_push( iobuf, len ) ( { \
90 void *__result; \
91 __result = iob_push ( (iobuf), (len) ); \
92 assert ( (iobuf)->data >= (iobuf)->head ); \
93 __result; } )
94
95/**
96 * Remove data from start of I/O buffer
97 *
98 * @v iobuf I/O buffer
99 * @v len Length to remove
100 * @ret data Pointer to new start of buffer
101 */
102static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
103 iobuf->data += len;
104 assert ( iobuf->data <= iobuf->tail );
105 return iobuf->data;
106}
107#define iob_pull( iobuf, len ) ( { \
108 void *__result; \
109 __result = iob_pull ( (iobuf), (len) ); \
110 assert ( (iobuf)->data <= (iobuf)->tail ); \
111 __result; } )
112
113/**
114 * Add data to end of I/O buffer
115 *
116 * @v iobuf I/O buffer
117 * @v len Length to add
118 * @ret data Pointer to newly added space
119 */
120static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
121 void *old_tail = iobuf->tail;
122 iobuf->tail += len;
123 return old_tail;
124}
125#define iob_put( iobuf, len ) ( { \
126 void *__result; \
127 __result = iob_put ( (iobuf), (len) ); \
128 assert ( (iobuf)->tail <= (iobuf)->end ); \
129 __result; } )
130
131/**
132 * Remove data from end of I/O buffer
133 *
134 * @v iobuf I/O buffer
135 * @v len Length to remove
136 */
137static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
138 iobuf->tail -= len;
139}
140#define iob_unput( iobuf, len ) do { \
141 iob_unput ( (iobuf), (len) ); \
142 assert ( (iobuf)->tail >= (iobuf)->data ); \
143 } while ( 0 )
144
145/**
146 * Empty an I/O buffer
147 *
148 * @v iobuf I/O buffer
149 */
150static inline void iob_empty ( struct io_buffer *iobuf ) {
151 iobuf->tail = iobuf->data;
152}
153
154/**
155 * Calculate length of data in an I/O buffer
156 *
157 * @v iobuf I/O buffer
158 * @ret len Length of data in buffer
159 */
160static inline size_t iob_len ( struct io_buffer *iobuf ) {
161 return ( iobuf->tail - iobuf->data );
162}
163
164/**
165 * Calculate available space at start of an I/O buffer
166 *
167 * @v iobuf I/O buffer
168 * @ret len Length of data available at start of buffer
169 */
170static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
171 return ( iobuf->data - iobuf->head );
172}
173
174/**
175 * Calculate available space at end of an I/O buffer
176 *
177 * @v iobuf I/O buffer
178 * @ret len Length of data available at end of buffer
179 */
180static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
181 return ( iobuf->end - iobuf->tail );
182}
183
184/**
185 * Create a temporary I/O buffer
186 *
187 * @v iobuf I/O buffer
188 * @v data Data buffer
189 * @v len Length of data
190 * @v max_len Length of buffer
191 *
192 * It is sometimes useful to use the iob_xxx() methods on temporary
193 * data buffers.
194 */
195static inline void iob_populate ( struct io_buffer *iobuf,
196 void *data, size_t len, size_t max_len ) {
197 iobuf->head = iobuf->data = data;
198 iobuf->tail = ( data + len );
199 iobuf->end = ( data + max_len );
200}
201
202/**
203 * Disown an I/O buffer
204 *
205 * @v iobuf I/O buffer
206 *
207 * There are many functions that take ownership of the I/O buffer they
208 * are passed as a parameter. The caller should not retain a pointer
209 * to the I/O buffer. Use iob_disown() to automatically nullify the
210 * caller's pointer, e.g.:
211 *
212 * xfer_deliver_iob ( xfer, iob_disown ( iobuf ) );
213 *
214 * This will ensure that iobuf is set to NULL for any code after the
215 * call to xfer_deliver_iob().
216 */
217#define iob_disown( iobuf ) ( { \
218 struct io_buffer *__iobuf = (iobuf); \
219 (iobuf) = NULL; \
220 __iobuf; } )
221
222/**
223 * Map I/O buffer for DMA
224 *
225 * @v iobuf I/O buffer
226 * @v dma DMA device
227 * @v len Length to map
228 * @v flags Mapping flags
229 * @ret rc Return status code
230 */
231static inline __always_inline int iob_map ( struct io_buffer *iobuf,
232 struct dma_device *dma,
233 size_t len, int flags ) {
234 return dma_map ( dma, &iobuf->map, iobuf->data, len, flags );
235}
236
237/**
238 * Map I/O buffer for transmit DMA
239 *
240 * @v iobuf I/O buffer
241 * @v dma DMA device
242 * @ret rc Return status code
243 */
244static inline __always_inline int iob_map_tx ( struct io_buffer *iobuf,
245 struct dma_device *dma ) {
246 return iob_map ( iobuf, dma, iob_len ( iobuf ), DMA_TX );
247}
248
249/**
250 * Map empty I/O buffer for receive DMA
251 *
252 * @v iobuf I/O buffer
253 * @v dma DMA device
254 * @ret rc Return status code
255 */
256static inline __always_inline int iob_map_rx ( struct io_buffer *iobuf,
257 struct dma_device *dma ) {
258 assert ( iob_len ( iobuf ) == 0 );
259 return iob_map ( iobuf, dma, iob_tailroom ( iobuf ), DMA_RX );
260}
261
262/**
263 * Get I/O buffer DMA address
264 *
265 * @v iobuf I/O buffer
266 * @ret addr DMA address
267 */
268static inline __always_inline physaddr_t iob_dma ( struct io_buffer *iobuf ) {
269 return dma ( &iobuf->map, iobuf->data );
270}
271
272/**
273 * Unmap I/O buffer for DMA
274 *
275 * @v iobuf I/O buffer
276 * @v dma DMA device
277 * @ret rc Return status code
278 */
279static inline __always_inline void iob_unmap ( struct io_buffer *iobuf ) {
280 dma_unmap ( &iobuf->map, iob_len ( iobuf ) );
281}
282
283extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align,
284 size_t offset );
285extern struct io_buffer * __malloc alloc_iob ( size_t len );
286extern void free_iob ( struct io_buffer *iobuf );
287extern struct io_buffer * __malloc alloc_rx_iob ( size_t len,
288 struct dma_device *dma );
289extern void free_rx_iob ( struct io_buffer *iobuf );
290extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
291extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
292extern struct io_buffer * iob_concatenate ( struct list_head *list );
293extern struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len );
294
295#endif /* _IPXE_IOBUF_H */
unsigned long physaddr_t
Definition stdint.h:20
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t flags
Flags.
Definition ena.h:7
#define __malloc
Declare a pointer returned by a function as a unique memory address as returned by malloc-type functi...
Definition compiler.h:598
#define __always_inline
Declare a function to be always inline.
Definition compiler.h:611
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
static size_t iob_headroom(struct io_buffer *iobuf)
Calculate available space at start of an I/O buffer.
Definition iobuf.h:170
static void iob_empty(struct io_buffer *iobuf)
Empty an I/O buffer.
Definition iobuf.h:150
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:89
static void iob_populate(struct io_buffer *iobuf, void *data, size_t len, size_t max_len)
Create a temporary I/O buffer.
Definition iobuf.h:195
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition iobuf.c:235
static __always_inline void iob_unmap(struct io_buffer *iobuf)
Unmap I/O buffer for DMA.
Definition iobuf.h:279
#define iob_put(iobuf, len)
Definition iobuf.h:125
static __always_inline int iob_map_rx(struct io_buffer *iobuf, struct dma_device *dma)
Map empty I/O buffer for receive DMA.
Definition iobuf.h:256
struct io_buffer *__malloc alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
static __always_inline int iob_map_tx(struct io_buffer *iobuf, struct dma_device *dma)
Map I/O buffer for transmit DMA.
Definition iobuf.h:244
struct io_buffer *__malloc alloc_iob_raw(size_t len, size_t align, size_t offset)
Allocate I/O buffer with specified alignment and offset.
Definition iobuf.c:49
static __always_inline physaddr_t iob_dma(struct io_buffer *iobuf)
Get I/O buffer DMA address.
Definition iobuf.h:268
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition iobpad.c:50
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
void free_rx_iob(struct io_buffer *iobuf)
Unmap and free I/O buffer for receive DMA.
Definition iobuf.c:215
#define iob_pull(iobuf, len)
Definition iobuf.h:107
struct io_buffer *__malloc alloc_rx_iob(size_t len, struct dma_device *dma)
Allocate and map I/O buffer for receive DMA.
Definition iobuf.c:188
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition iobuf.c:250
#define iob_unput(iobuf, len)
Definition iobuf.h:140
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition iobuf.h:180
struct io_buffer * iob_split(struct io_buffer *iobuf, size_t len)
Split I/O buffer.
Definition iobuf.c:298
static __always_inline int iob_map(struct io_buffer *iobuf, struct dma_device *dma, size_t len, int flags)
Map I/O buffer for DMA.
Definition iobuf.h:231
DMA mappings.
#define DMA_TX
Device will read data from host memory.
Definition dma.h:135
#define DMA_RX
Device will write data to host memory.
Definition dma.h:138
void dma_unmap(struct dma_mapping *map, size_t len)
Unmap buffer.
physaddr_t dma(struct dma_mapping *map, void *addr)
Get DMA address from virtual address.
Linked lists.
A DMA-capable device.
Definition dma.h:48
A DMA mapping.
Definition dma.h:33
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
void * tail
End of data.
Definition iobuf.h:55
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
void * end
End of the buffer.
Definition iobuf.h:57
void * head
Start of the buffer.
Definition iobuf.h:51
struct dma_mapping map
DMA mapping.
Definition iobuf.h:48
A doubly-linked list entry (or list head)
Definition list.h:19