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…
	
		Reference in New Issue