diff options
author | Beniamino Galvani <b.galvani@gmail.com> | 2014-01-30 23:02:04 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-02-08 14:50:48 +0000 |
commit | c4e57af85272f98c28ccaaace040d2abb0ec85c4 (patch) | |
tree | 938aac8abdac098c0fe345eabae33c033894ceb2 /util | |
parent | 999b53ec8794f203964db3ecf939a3da5c4bc843 (diff) | |
download | hqemu-c4e57af85272f98c28ccaaace040d2abb0ec85c4.zip hqemu-c4e57af85272f98c28ccaaace040d2abb0ec85c4.tar.gz |
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>
Diffstat (limited to 'util')
-rw-r--r-- | util/fifo8.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/util/fifo8.c b/util/fifo8.c index 013e903..a7503c2 100644 --- a/util/fifo8.c +++ b/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, |