191 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Generic FIFO32 component, based on FIFO8.
 | |
|  *
 | |
|  * Copyright (c) 2016 Jean-Christophe Dubois
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version
 | |
|  * 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License along
 | |
|  * with this program; if not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| #ifndef FIFO32_H
 | |
| #define FIFO32_H
 | |
| 
 | |
| #include "qemu/fifo8.h"
 | |
| 
 | |
| typedef struct {
 | |
|     Fifo8 fifo;
 | |
| } Fifo32;
 | |
| 
 | |
| /**
 | |
|  * fifo32_create:
 | |
|  * @fifo: struct Fifo32 to initialise with new FIFO
 | |
|  * @capacity: capacity of the newly created FIFO expressed in 32 bit words
 | |
|  *
 | |
|  * Create a FIFO of the specified size. Clients should call fifo32_destroy()
 | |
|  * when finished using the fifo. The FIFO is initially empty.
 | |
|  */
 | |
| 
 | |
| static inline void fifo32_create(Fifo32 *fifo, uint32_t capacity)
 | |
| {
 | |
|     fifo8_create(&fifo->fifo, capacity * sizeof(uint32_t));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_destroy:
 | |
|  * @fifo: FIFO to cleanup
 | |
|  *
 | |
|  * Cleanup a FIFO created with fifo32_create(). Frees memory created for FIFO
 | |
|  * storage. The FIFO is no longer usable after this has been called.
 | |
|  */
 | |
| 
 | |
| static inline void fifo32_destroy(Fifo32 *fifo)
 | |
| {
 | |
|     fifo8_destroy(&fifo->fifo);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_num_free:
 | |
|  * @fifo: FIFO to check
 | |
|  *
 | |
|  * Return the number of free uint32_t slots in the FIFO.
 | |
|  *
 | |
|  * Returns: Number of free 32 bit words.
 | |
|  */
 | |
| 
 | |
| static inline uint32_t fifo32_num_free(Fifo32 *fifo)
 | |
| {
 | |
|     return DIV_ROUND_UP(fifo8_num_free(&fifo->fifo), sizeof(uint32_t));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_num_used:
 | |
|  * @fifo: FIFO to check
 | |
|  *
 | |
|  * Return the number of used uint32_t slots in the FIFO.
 | |
|  *
 | |
|  * Returns: Number of used 32 bit words.
 | |
|  */
 | |
| 
 | |
| static inline uint32_t fifo32_num_used(Fifo32 *fifo)
 | |
| {
 | |
|     return DIV_ROUND_UP(fifo8_num_used(&fifo->fifo), sizeof(uint32_t));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_push:
 | |
|  * @fifo: FIFO to push to
 | |
|  * @data: 32 bits data word to push
 | |
|  *
 | |
|  * Push a 32 bits data word to the FIFO. Behaviour is undefined if the FIFO
 | |
|  * is full. Clients are responsible for checking for fullness using
 | |
|  * fifo32_is_full().
 | |
|  */
 | |
| 
 | |
| static inline void fifo32_push(Fifo32 *fifo, uint32_t data)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < sizeof(data); i++) {
 | |
|         fifo8_push(&fifo->fifo, data & 0xff);
 | |
|         data >>= 8;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_push_all:
 | |
|  * @fifo: FIFO to push to
 | |
|  * @data: data to push
 | |
|  * @size: number of 32 bit words to push
 | |
|  *
 | |
|  * Push a 32 bit word array to the FIFO. Behaviour is undefined if the FIFO
 | |
|  * is full. Clients are responsible for checking the space left in the FIFO
 | |
|  * using fifo32_num_free().
 | |
|  */
 | |
| 
 | |
| static inline void fifo32_push_all(Fifo32 *fifo, const uint32_t *data,
 | |
|                                    uint32_t num)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < num; i++) {
 | |
|         fifo32_push(fifo, data[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_pop:
 | |
|  * @fifo: fifo to pop from
 | |
|  *
 | |
|  * Pop a 32 bits data word from the FIFO. Behaviour is undefined if the FIFO
 | |
|  * is empty. Clients are responsible for checking for emptiness using
 | |
|  * fifo32_is_empty().
 | |
|  *
 | |
|  * Returns: The popped 32 bits data word.
 | |
|  */
 | |
| 
 | |
| static inline uint32_t fifo32_pop(Fifo32 *fifo)
 | |
| {
 | |
|     uint32_t ret = 0;
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < sizeof(uint32_t); i++) {
 | |
|         ret |= (fifo8_pop(&fifo->fifo) << (i * 8));
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * There is no fifo32_pop_buf() because the data is not stored in the buffer
 | |
|  * as a set of native-order words.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * fifo32_reset:
 | |
|  * @fifo: FIFO to reset
 | |
|  *
 | |
|  * Reset a FIFO. All data is discarded and the FIFO is emptied.
 | |
|  */
 | |
| 
 | |
| static inline void fifo32_reset(Fifo32 *fifo)
 | |
| {
 | |
|     fifo8_reset(&fifo->fifo);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_is_empty:
 | |
|  * @fifo: FIFO to check
 | |
|  *
 | |
|  * Check if a FIFO is empty.
 | |
|  *
 | |
|  * Returns: True if the fifo is empty, false otherwise.
 | |
|  */
 | |
| 
 | |
| static inline bool fifo32_is_empty(Fifo32 *fifo)
 | |
| {
 | |
|     return fifo8_is_empty(&fifo->fifo);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * fifo32_is_full:
 | |
|  * @fifo: FIFO to check
 | |
|  *
 | |
|  * Check if a FIFO is full.
 | |
|  *
 | |
|  * Returns: True if the fifo is full, false otherwise.
 | |
|  */
 | |
| 
 | |
| static inline bool fifo32_is_full(Fifo32 *fifo)
 | |
| {
 | |
|     return fifo8_num_free(&fifo->fifo) < sizeof(uint32_t);
 | |
| }
 | |
| 
 | |
| #define VMSTATE_FIFO32(_field, _state) VMSTATE_FIFO8(_field.fifo, _state)
 | |
| 
 | |
| #endif /* FIFO32_H */
 |