util/fifo8: implement push/pop of multiple bytes
The patch adds functions fifo8_push_all() and fifo8_pop_buf() which can be used respectively to push the content of a memory buffer to the fifo and to pop multiple bytes obtaining a pointer to the fifo backing buffer. In addition, it implements fifo8_num_free() and fifo8_num_used() which allow to check if a multi-byte operation can be performed. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									999b53ec87
								
							
						
					
					
						commit
						c4e57af852
					
				| @ -43,6 +43,19 @@ void fifo8_destroy(Fifo8 *fifo); | ||||
| 
 | ||||
| void fifo8_push(Fifo8 *fifo, uint8_t data); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_push_all: | ||||
|  * @fifo: FIFO to push to | ||||
|  * @data: data to push | ||||
|  * @size: number of bytes to push | ||||
|  * | ||||
|  * Push a byte array to the FIFO. Behaviour is undefined if the FIFO is full. | ||||
|  * Clients are responsible for checking the space left in the FIFO using | ||||
|  * fifo8_num_free(). | ||||
|  */ | ||||
| 
 | ||||
| void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_pop: | ||||
|  * @fifo: fifo to pop from | ||||
| @ -55,6 +68,32 @@ void fifo8_push(Fifo8 *fifo, uint8_t data); | ||||
| 
 | ||||
| uint8_t fifo8_pop(Fifo8 *fifo); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_pop_buf: | ||||
|  * @fifo: FIFO to pop from | ||||
|  * @max: maximum number of bytes to pop | ||||
|  * @num: actual number of returned bytes | ||||
|  * | ||||
|  * Pop a number of elements from the FIFO up to a maximum of max. The buffer | ||||
|  * containing the popped data is returned. This buffer points directly into | ||||
|  * the FIFO backing store and data is invalidated once any of the fifo8_* APIs | ||||
|  * are called on the FIFO. | ||||
|  * | ||||
|  * The function may return fewer bytes than requested when the data wraps | ||||
|  * around in the ring buffer; in this case only a contiguous part of the data | ||||
|  * is returned. | ||||
|  * | ||||
|  * The number of valid bytes returned is populated in *num; will always return | ||||
|  * at least 1 byte. max must not be 0 or greater than the number of bytes in | ||||
|  * the FIFO. | ||||
|  * | ||||
|  * Clients are responsible for checking the availability of requested data | ||||
|  * using fifo8_num_used(). | ||||
|  * | ||||
|  * Returns: A pointer to popped data. | ||||
|  */ | ||||
| const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_reset: | ||||
|  * @fifo: FIFO to reset | ||||
| @ -86,6 +125,28 @@ bool fifo8_is_empty(Fifo8 *fifo); | ||||
| 
 | ||||
| bool fifo8_is_full(Fifo8 *fifo); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_num_free: | ||||
|  * @fifo: FIFO to check | ||||
|  * | ||||
|  * Return the number of free bytes in the FIFO. | ||||
|  * | ||||
|  * Returns: Number of free bytes. | ||||
|  */ | ||||
| 
 | ||||
| uint32_t fifo8_num_free(Fifo8 *fifo); | ||||
| 
 | ||||
| /**
 | ||||
|  * fifo8_num_used: | ||||
|  * @fifo: FIFO to check | ||||
|  * | ||||
|  * Return the number of used bytes in the FIFO. | ||||
|  * | ||||
|  * Returns: Number of used bytes. | ||||
|  */ | ||||
| 
 | ||||
| uint32_t fifo8_num_used(Fifo8 *fifo); | ||||
| 
 | ||||
| extern const VMStateDescription vmstate_fifo8; | ||||
| 
 | ||||
| #define VMSTATE_FIFO8(_field, _state) {                              \ | ||||
|  | ||||
							
								
								
									
										46
									
								
								util/fifo8.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								util/fifo8.c
									
									
									
									
									
								
							| @ -37,6 +37,27 @@ void fifo8_push(Fifo8 *fifo, uint8_t data) | ||||
|     fifo->num++; | ||||
| } | ||||
| 
 | ||||
| void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) | ||||
| { | ||||
|     uint32_t start, avail; | ||||
| 
 | ||||
|     if (fifo->num + num > fifo->capacity) { | ||||
|         abort(); | ||||
|     } | ||||
| 
 | ||||
|     start = (fifo->head + fifo->num) % fifo->capacity; | ||||
| 
 | ||||
|     if (start + num <= fifo->capacity) { | ||||
|         memcpy(&fifo->data[start], data, num); | ||||
|     } else { | ||||
|         avail = fifo->capacity - start; | ||||
|         memcpy(&fifo->data[start], data, avail); | ||||
|         memcpy(&fifo->data[0], &data[avail], num - avail); | ||||
|     } | ||||
| 
 | ||||
|     fifo->num += num; | ||||
| } | ||||
| 
 | ||||
| uint8_t fifo8_pop(Fifo8 *fifo) | ||||
| { | ||||
|     uint8_t ret; | ||||
| @ -50,6 +71,21 @@ uint8_t fifo8_pop(Fifo8 *fifo) | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num) | ||||
| { | ||||
|     uint8_t *ret; | ||||
| 
 | ||||
|     if (max == 0 || max > fifo->num) { | ||||
|         abort(); | ||||
|     } | ||||
|     *num = MIN(fifo->capacity - fifo->head, max); | ||||
|     ret = &fifo->data[fifo->head]; | ||||
|     fifo->head += *num; | ||||
|     fifo->head %= fifo->capacity; | ||||
|     fifo->num -= *num; | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void fifo8_reset(Fifo8 *fifo) | ||||
| { | ||||
|     fifo->num = 0; | ||||
| @ -65,6 +101,16 @@ bool fifo8_is_full(Fifo8 *fifo) | ||||
|     return (fifo->num == fifo->capacity); | ||||
| } | ||||
| 
 | ||||
| uint32_t fifo8_num_free(Fifo8 *fifo) | ||||
| { | ||||
|     return fifo->capacity - fifo->num; | ||||
| } | ||||
| 
 | ||||
| uint32_t fifo8_num_used(Fifo8 *fifo) | ||||
| { | ||||
|     return fifo->num; | ||||
| } | ||||
| 
 | ||||
| const VMStateDescription vmstate_fifo8 = { | ||||
|     .name = "Fifo8", | ||||
|     .version_id = 1, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Beniamino Galvani
						Beniamino Galvani