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