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