xref: /openbmc/qemu/util/fifo8.c (revision 0ed93f4c)
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  
15  #include "qemu/osdep.h"
16  #include "migration/vmstate.h"
17  #include "qemu/fifo8.h"
18  
19  void fifo8_create(Fifo8 *fifo, uint32_t capacity)
20  {
21      fifo->data = g_new(uint8_t, capacity);
22      fifo->capacity = capacity;
23      fifo->head = 0;
24      fifo->num = 0;
25  }
26  
27  void fifo8_destroy(Fifo8 *fifo)
28  {
29      g_free(fifo->data);
30  }
31  
32  void fifo8_push(Fifo8 *fifo, uint8_t data)
33  {
34      if (fifo->num == fifo->capacity) {
35          abort();
36      }
37      fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
38      fifo->num++;
39  }
40  
41  void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num)
42  {
43      uint32_t start, avail;
44  
45      if (fifo->num + num > fifo->capacity) {
46          abort();
47      }
48  
49      start = (fifo->head + fifo->num) % fifo->capacity;
50  
51      if (start + num <= fifo->capacity) {
52          memcpy(&fifo->data[start], data, num);
53      } else {
54          avail = fifo->capacity - start;
55          memcpy(&fifo->data[start], data, avail);
56          memcpy(&fifo->data[0], &data[avail], num - avail);
57      }
58  
59      fifo->num += num;
60  }
61  
62  uint8_t fifo8_pop(Fifo8 *fifo)
63  {
64      uint8_t ret;
65  
66      if (fifo->num == 0) {
67          abort();
68      }
69      ret = fifo->data[fifo->head++];
70      fifo->head %= fifo->capacity;
71      fifo->num--;
72      return ret;
73  }
74  
75  const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num)
76  {
77      uint8_t *ret;
78  
79      if (max == 0 || max > fifo->num) {
80          abort();
81      }
82      *num = MIN(fifo->capacity - fifo->head, max);
83      ret = &fifo->data[fifo->head];
84      fifo->head += *num;
85      fifo->head %= fifo->capacity;
86      fifo->num -= *num;
87      return ret;
88  }
89  
90  void fifo8_reset(Fifo8 *fifo)
91  {
92      fifo->num = 0;
93      fifo->head = 0;
94  }
95  
96  bool fifo8_is_empty(Fifo8 *fifo)
97  {
98      return (fifo->num == 0);
99  }
100  
101  bool fifo8_is_full(Fifo8 *fifo)
102  {
103      return (fifo->num == fifo->capacity);
104  }
105  
106  uint32_t fifo8_num_free(Fifo8 *fifo)
107  {
108      return fifo->capacity - fifo->num;
109  }
110  
111  uint32_t fifo8_num_used(Fifo8 *fifo)
112  {
113      return fifo->num;
114  }
115  
116  const VMStateDescription vmstate_fifo8 = {
117      .name = "Fifo8",
118      .version_id = 1,
119      .minimum_version_id = 1,
120      .fields = (VMStateField[]) {
121          VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, capacity),
122          VMSTATE_UINT32(head, Fifo8),
123          VMSTATE_UINT32(num, Fifo8),
124          VMSTATE_END_OF_LIST()
125      }
126  };
127