#ifndef common_ipmbox_queue_h #define common_ipmbox_queue_h /* Cesar project {{{ * * Copyright (C) 2011 Spidcom * * <<>> * * }}} */ /** * \file common/ipmbox/queue.h * \brief IPMbox queue management * * This file contains interfaces used to access the different queues for * IPMbox. */ #include "common/universe.h" /** * Shared queue management pointers. * They must follow each others in memory. A structure is used to prevent too * much indirections when accessing those pointers. * Order of pointers is important and must not be changed (otherwise * everything will fail). * Only contains physical address. */ typedef struct ipmbox_queue_ptr_t { unsigned long tail; unsigned long head; } ipmbox_queue_ptr_t; /** * A queue (implemented as a circular ring). */ typedef struct ipmbox_queue_t { /** Base address of start of the queue. */ u32 *base_ptr; /** End of the queue (past the queue). */ u32 *end_ptr; #if !CESAR /** Virtual to physical address offset. */ u32 virt_to_phys_offset; #endif /** Pointers of queue. */ volatile ipmbox_queue_ptr_t *ptr; /** Queue size in words. */ unsigned int size; } ipmbox_queue_t; /** * List of queues in the IPMBox. */ typedef enum ipmbox_queue_type_t { /** All other types of messages (MME, RPC, debug types). */ IPMBOX_QUEUE_MBX = 0, /** Empty buffer to free or for storing message (empty buf only). */ IPMBOX_QUEUE_EMPTY_BUF, /** Data (PLC frame) queue (type data only). */ IPMBOX_QUEUE_DATA, IPMBOX_QUEUE_TYPE_NB } ipmbox_queue_type_t; /** * IPMbox direction. */ typedef enum ipmbox_queue_direction_t { /** ARM to Leon. */ IPMBOX_A2L = 0, /** Leon to ARM. */ IPMBOX_L2A, IPMBOX_QUEUE_DIRECTION_NB } ipmbox_queue_direction_t; /** * Convert virtual address to physical address for a pointer into a queue. * \param queue queue context * \param virt virtual address * \return physical address */ extern inline u32 ipmbox_queue_virt_to_phys (ipmbox_queue_t *queue, void *virt) { #if CESAR return (u32) virt; #else return (u32) virt + queue->virt_to_phys_offset; #endif } /** * Convert physical address to virtual address for a pointer into a queue. * \param queue queue context * \param phys physical address * \return virtual address */ extern inline void * ipmbox_queue_phys_to_virt (ipmbox_queue_t *queue, u32 phys) { #if CESAR return (void *) phys; #else return (void *) (phys - queue->virt_to_phys_offset); #endif } /** * Get free space in a queue. * \param queue queue to check * \return free size in words */ extern inline unsigned int ipmbox_queue_get_free_space (ipmbox_queue_t *queue) { u32 *tail, *head; /* Check parameter. */ dbg_claim (queue); tail = (u32 *) queue->ptr->tail; head = (u32 *) queue->ptr->head; if (tail >= head) return queue->size - (tail - head) - 1; else return head - tail - 1; } /** * Get used space in a queue. * \param queue queue to check * \return used size in words */ extern inline unsigned int ipmbox_queue_get_used_space (ipmbox_queue_t *queue) { u32 *tail, *head; /* Check parameter. */ dbg_claim (queue); tail = (u32 *) queue->ptr->tail; head = (u32 *) queue->ptr->head; if (tail >= head) return tail - head; else return queue->size + tail - head; } /** * Copy data to a queue. * \param queue queue in which to add data * \param data pointer to the data * \param size data size in words * * \warning callee is responsible to check there is enough space in queue * to copy data. */ void ipmbox_queue_copy_to (ipmbox_queue_t *queue, u32 *data, unsigned int size); /** * Copy data from a queue. * \param queue queue in which to get data from * \param data pointer to the data where to store them * \param size data size in words (space available in data buffer) * * \warning Callee is responsible to check that size is in sync with current * queue size: size must be inferior or equal to used space in queue (never * over queue size - 1). */ void ipmbox_queue_copy_from (ipmbox_queue_t *queue, u32 *data, unsigned int size); #endif /* common_ipmbox_queue_h */