| /****************************************************************************** |
| |
| Copyright (c) 2006-2015 Lantiq Deutschland GmbH |
| Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG |
| Copyright 2018, Intel Corporation. |
| |
| For licensing information, see the file 'LICENSE' in the root folder of |
| this software module. |
| |
| ******************************************************************************/ |
| |
| /** |
| \file dxs_fifo.c |
| Implementation of DxS fifo functions. |
| */ |
| |
| /* ========================================================================== */ |
| /* Includes */ |
| /* ========================================================================== */ |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <pthread.h> |
| |
| #include "dxs_config.h" |
| #include "dxs_fifo.h" |
| #include "dxs_error.h" |
| |
| /* ========================================================================== */ |
| /* Macro definitions */ |
| /* ========================================================================== */ |
| /* two fifos per device: |
| one for messages, one for command outbox data */ |
| #define FIFOS_PER_DEVICE 2 |
| |
| /* ========================================================================== */ |
| /* Type definitions */ |
| /* ========================================================================== */ |
| |
| /* ========================================================================== */ |
| /* Global variables */ |
| /* ========================================================================== */ |
| /** placeholder for the fifos */ |
| FIFO_t dxs_fifos[DXS_MAX_DEVICES * FIFOS_PER_DEVICE]; |
| |
| /* ========================================================================== */ |
| /* Function prototypes */ |
| /* ========================================================================== */ |
| |
| /* ========================================================================== */ |
| /* Function implementation */ |
| /* ========================================================================== */ |
| /** |
| Function fifo_init |
| |
| \param elements - elements |
| |
| \return |
| - FIFO_t |
| */ |
| FIFO_t* fifo_init (uint32_t elements) |
| { |
| FIFO_t *p; |
| int idx; |
| |
| for (idx=0; idx<(DXS_MAX_DEVICES * FIFOS_PER_DEVICE); idx++) |
| { |
| p = &dxs_fifos[idx]; |
| if (!p->in_use) |
| break; |
| } |
| if (idx == (DXS_MAX_DEVICES * FIFOS_PER_DEVICE)) |
| { |
| return NULL; |
| } |
| |
| p->magic = DXS_FIFO_MAGIC_CODE; |
| |
| if (elements > MAX_FIFO_SIZE) |
| elements = MAX_FIFO_SIZE; |
| |
| p->fifo_size = elements; |
| p->count = p->wr_idx = p->rd_idx = 0; |
| |
| pthread_mutex_init(&p->mtx, NULL); |
| |
| p->in_use = 1; |
| |
| return p; |
| } |
| |
| /** |
| Function fifo_destroy |
| |
| \param fifo - pointer to FIFO_t |
| |
| */ |
| void fifo_destroy (FIFO_t *fifo) |
| { |
| int err; |
| err = pthread_mutex_unlock(&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| err = pthread_mutex_destroy(&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| fifo->in_use = 0; |
| fifo->magic = 0; |
| } |
| |
| /** |
| Function fifo_flush |
| |
| \param fifo - pointer to FIFO_t |
| |
| */ |
| void fifo_flush (FIFO_t *fifo) |
| { |
| int err; |
| err = pthread_mutex_lock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| fifo->count = fifo->wr_idx = fifo->rd_idx = 0; |
| |
| err = pthread_mutex_unlock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| } |
| |
| /** |
| Function fifo_count |
| |
| \param fifo - pointer to FIFO_t |
| |
| \return |
| - uint32_t count |
| */ |
| uint32_t fifo_count (FIFO_t *fifo) |
| { |
| return fifo->count; |
| } |
| |
| /** |
| Function fifo_put |
| |
| \param fifo - pointer to FIFO_t |
| \param data - pointer to data |
| \param size - size |
| |
| \return |
| DXS_FIFO_INV |
| DXS_FIFO_FULL |
| DXS_FIFO_OK |
| */ |
| int32_t fifo_put (FIFO_t *fifo, void *data, uint32_t size) |
| { |
| FIFO_Elem_t *p; |
| int err; |
| |
| if (fifo->magic != DXS_FIFO_MAGIC_CODE) |
| return DXS_FIFO_INV; |
| |
| if (fifo->count == fifo->fifo_size) |
| return DXS_FIFO_FULL; |
| |
| err = pthread_mutex_lock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| p = &fifo->elem[fifo->wr_idx]; |
| |
| p->data = data; |
| p->size = size; |
| fifo->count++; |
| |
| if (++fifo->wr_idx == fifo->fifo_size) |
| fifo->wr_idx = 0; |
| |
| err = pthread_mutex_unlock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| return DXS_FIFO_OK; |
| } |
| |
| /** |
| Function fifo_get |
| |
| \param fifo - pointer to FIFO_t |
| \param data - pointer to data |
| \param size - pointer size |
| |
| \return |
| DXS_FIFO_INV |
| DXS_FIFO_EMPTY |
| DXS_FIFO_OK |
| */ |
| int32_t fifo_get (FIFO_t *fifo, void **data, uint32_t *size) |
| { |
| FIFO_Elem_t *p; |
| int err; |
| |
| if (fifo->magic != DXS_FIFO_MAGIC_CODE) |
| return DXS_FIFO_INV; |
| |
| if (fifo->count == 0) |
| return DXS_FIFO_EMPTY; |
| |
| err = pthread_mutex_lock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| p = &fifo->elem[fifo->rd_idx]; |
| |
| *data = p->data; |
| *size = p->size; |
| fifo->count--; |
| |
| if (++fifo->rd_idx == fifo->fifo_size) |
| fifo->rd_idx = 0; |
| |
| err = pthread_mutex_unlock (&fifo->mtx); |
| if (err != 0) |
| DXS_ERROR_PUSH(err); |
| |
| return DXS_FIFO_OK; |
| } |
| |