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 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 FILE_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  */
38 struct 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  */
45  struct list_head list;
46 
47  /** DMA mapping */
48  struct dma_mapping map;
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  */
67 static 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  */
85 static 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  */
102 static 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  */
120 static 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  */
137 static 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  */
150 static 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  */
160 static 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  */
170 static 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  */
180 static 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  */
195 static 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  */
231 static 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  */
244 static 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  */
256 static 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  */
268 static 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  */
279 static inline __always_inline void iob_unmap ( struct io_buffer *iobuf ) {
280  dma_unmap ( &iobuf->map, iob_len ( iobuf ) );
281 }
282 
283 extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align,
284  size_t offset );
285 extern struct io_buffer * __malloc alloc_iob ( size_t len );
286 extern void free_iob ( struct io_buffer *iobuf );
287 extern struct io_buffer * __malloc alloc_rx_iob ( size_t len,
288  struct dma_device *dma );
289 extern void free_rx_iob ( struct io_buffer *iobuf );
290 extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
291 extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
292 extern struct io_buffer * iob_concatenate ( struct list_head *list );
293 extern struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len );
294 
295 #endif /* _IPXE_IOBUF_H */
#define iob_pull(iobuf, len)
Definition: iobuf.h:107
#define DMA_TX
Device will read data from host memory.
Definition: dma.h:135
#define iob_put(iobuf, len)
Definition: iobuf.h:125
FILE_SECBOOT(PERMITTED)
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
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 dma_mapping map
DMA mapping.
Definition: iobuf.h:48
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition: iobuf.c:250
#define iob_push(iobuf, len)
Definition: iobuf.h:89
void dma_unmap(struct dma_mapping *map, size_t len)
Unmap buffer.
#define DMA_RX
Device will write data to host memory.
Definition: dma.h:138
DMA mappings.
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
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
A doubly-linked list entry (or list head)
Definition: list.h:19
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
void free_rx_iob(struct io_buffer *iobuf)
Unmap and free I/O buffer for receive DMA.
Definition: iobuf.c:215
void * tail
End of data.
Definition: iobuf.h:55
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static __always_inline void iob_unmap(struct io_buffer *iobuf)
Unmap I/O buffer for DMA.
Definition: iobuf.h:279
ring len
Length.
Definition: dwmac.h:231
static __always_inline physaddr_t iob_dma(struct io_buffer *iobuf)
Get I/O buffer DMA address.
Definition: iobuf.h:268
static void iob_empty(struct io_buffer *iobuf)
Empty an I/O buffer.
Definition: iobuf.h:150
struct io_buffer *__malloc alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:131
Linked lists.
#define iob_unput(iobuf, len)
Definition: iobuf.h:140
uint8_t flags
Flags.
Definition: ena.h:18
struct io_buffer * iob_split(struct io_buffer *iobuf, size_t len)
Split I/O buffer.
Definition: iobuf.c:298
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:180
void * end
End of the buffer.
Definition: iobuf.h:57
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
unsigned long physaddr_t
Definition: stdint.h:20
#define iob_reserve(iobuf, len)
Definition: iobuf.h:72
static size_t iob_headroom(struct io_buffer *iobuf)
Calculate available space at start of an I/O buffer.
Definition: iobuf.h:170
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:45
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
#define __malloc
Declare a pointer returned by a function as a unique memory address as returned by malloc-type functi...
Definition: compiler.h:598
void * head
Start of the buffer.
Definition: iobuf.h:51
void * data
Start of data.
Definition: iobuf.h:53
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
A DMA mapping.
Definition: dma.h:33
physaddr_t dma(struct dma_mapping *map, void *addr)
Get DMA address from virtual address.
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition: iobuf.c:235
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition: iobpad.c:50
A DMA-capable device.
Definition: dma.h:48
A persistent I/O buffer.
Definition: iobuf.h:38