fifo8.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Generic FIFO component, implemented as a circular buffer.
  3. *
  4. * Copyright (c) 2012 Peter A. G. Crosthwaite
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. *
  11. * You should have received a copy of the GNU General Public License along
  12. * with this program; if not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #include "qemu/osdep.h"
  15. #include "migration/vmstate.h"
  16. #include "qemu/fifo8.h"
  17. void fifo8_create(Fifo8 *fifo, uint32_t capacity)
  18. {
  19. fifo->data = g_new(uint8_t, capacity);
  20. fifo->capacity = capacity;
  21. fifo->head = 0;
  22. fifo->num = 0;
  23. }
  24. void fifo8_destroy(Fifo8 *fifo)
  25. {
  26. g_free(fifo->data);
  27. }
  28. void fifo8_push(Fifo8 *fifo, uint8_t data)
  29. {
  30. if (fifo->num == fifo->capacity) {
  31. abort();
  32. }
  33. fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
  34. fifo->num++;
  35. }
  36. void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num)
  37. {
  38. uint32_t start, avail;
  39. if (fifo->num + num > fifo->capacity) {
  40. abort();
  41. }
  42. start = (fifo->head + fifo->num) % fifo->capacity;
  43. if (start + num <= fifo->capacity) {
  44. memcpy(&fifo->data[start], data, num);
  45. } else {
  46. avail = fifo->capacity - start;
  47. memcpy(&fifo->data[start], data, avail);
  48. memcpy(&fifo->data[0], &data[avail], num - avail);
  49. }
  50. fifo->num += num;
  51. }
  52. uint8_t fifo8_pop(Fifo8 *fifo)
  53. {
  54. uint8_t ret;
  55. if (fifo->num == 0) {
  56. abort();
  57. }
  58. ret = fifo->data[fifo->head++];
  59. fifo->head %= fifo->capacity;
  60. fifo->num--;
  61. return ret;
  62. }
  63. const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num)
  64. {
  65. uint8_t *ret;
  66. if (max == 0 || max > fifo->num) {
  67. abort();
  68. }
  69. *num = MIN(fifo->capacity - fifo->head, max);
  70. ret = &fifo->data[fifo->head];
  71. fifo->head += *num;
  72. fifo->head %= fifo->capacity;
  73. fifo->num -= *num;
  74. return ret;
  75. }
  76. void fifo8_reset(Fifo8 *fifo)
  77. {
  78. fifo->num = 0;
  79. fifo->head = 0;
  80. }
  81. bool fifo8_is_empty(Fifo8 *fifo)
  82. {
  83. return (fifo->num == 0);
  84. }
  85. bool fifo8_is_full(Fifo8 *fifo)
  86. {
  87. return (fifo->num == fifo->capacity);
  88. }
  89. uint32_t fifo8_num_free(Fifo8 *fifo)
  90. {
  91. return fifo->capacity - fifo->num;
  92. }
  93. uint32_t fifo8_num_used(Fifo8 *fifo)
  94. {
  95. return fifo->num;
  96. }
  97. const VMStateDescription vmstate_fifo8 = {
  98. .name = "Fifo8",
  99. .version_id = 1,
  100. .minimum_version_id = 1,
  101. .fields = (VMStateField[]) {
  102. VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, capacity),
  103. VMSTATE_UINT32(head, Fifo8),
  104. VMSTATE_UINT32(num, Fifo8),
  105. VMSTATE_END_OF_LIST()
  106. }
  107. };