| /* |
| <:copyright-BRCM:2016:DUAL/GPL:standard |
| |
| Broadcom Proprietary and Confidential.(c) 2016 Broadcom |
| All Rights Reserved |
| |
| Unless you and Broadcom execute a separate written software license |
| agreement governing use of this software, this software is licensed |
| to you under the terms of the GNU General Public License version 2 |
| (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, |
| with the following added to such license: |
| |
| As a special exception, the copyright holders of this software give |
| you permission to link this software with independent modules, and |
| to copy and distribute the resulting executable under terms of your |
| choice, provided that you also meet, for each linked independent |
| module, the terms and conditions of the license of that module. |
| An independent module is a module which is not derived from this |
| software. The special exception does not apply to any modifications |
| of the software. |
| |
| Not withstanding the above, under no circumstances may you combine |
| this software in any way with any other Broadcom software provided |
| under a license other than the GPL, without Broadcom's express prior |
| written consent. |
| |
| :> |
| */ |
| |
| #ifndef BCMOS_COMMON_H_ |
| #define BCMOS_COMMON_H_ |
| |
| #ifndef BCMOS_SYSTEM_H_ |
| #error Please do not include bcmos_common.h directly. Include bcmos_system.h |
| #endif |
| |
| #include "bcmos_errno.h" |
| #include "bcmos_types.h" |
| #include "bcmos_queue.h" |
| #include "bcmos_tree.h" |
| /* Get constants, such as task, module, event id lists */ |
| #include "bcmos_platform.h" |
| #include "bcmos_pack.h" |
| #include "bcmos_sysif.h" |
| |
| #define MAX_TASK_NAME_SIZE 64 |
| #define MAX_MODULE_NAME_SIZE 64 |
| #define MAX_MSG_QUEUE_NAME_SIZE 64 |
| #define MAX_TIMER_NAME_SIZE 64 |
| #define MAX_POOL_NAME_SIZE 64 |
| #define MAX_EVENT_NAME_SIZE 64 |
| #define MAX_MUTEX_NAME_SIZE 64 |
| #define BCMOS_MSG_POOL_DEFAULT_SIZE 512 |
| |
| /* Define bcmos_bool - the boolean type for bcmos - based on C99 standard boolean type */ |
| #ifndef BCMOS_BOOLEAN |
| typedef _Bool bcmos_bool; |
| #define BCMOS_FALSE 0 |
| #define BCMOS_TRUE 1 |
| #endif |
| |
| #define BCM_SIZEOFARRAY(arr) (sizeof(arr)/sizeof(*arr)) |
| #define BCM_SIZEOFFIELD(s, f) (sizeof(((s*)NULL)->f)) |
| #define BCM_MEMZERO_STRUCT(ptr) memset(ptr, 0, sizeof(*(ptr))) |
| #define BCM_MEMCPY_ARRAY(dst, src) memcpy(dst, src, sizeof(dst)) |
| #define TAB " " |
| #define TAB2 TAB TAB |
| #define TAB3 TAB2 TAB |
| #define TAB4 TAB2 TAB2 |
| |
| #define CHIP_REVISION_A0 0xA0 |
| #define CHIP_REVISION_B0 0xB0 |
| |
| #ifdef SIMULATION_BUILD |
| #define GET_CHIP_REVISION CHIP_REVISION_A0 |
| #else |
| extern uint32_t chip_revision; |
| #define GET_CHIP_REVISION (chip_revision != 0 ? chip_revision : (chip_revision = get_chip_revision())) |
| #endif |
| |
| typedef void (*f_bcmolt_sw_error_handler)(uint8_t pon_id, const char *file_name, uint32_t line_number); |
| |
| /* Similar to BUG_ON(), with the following features: |
| * 1. The condition is checked against BCM_ERR_OK. |
| * 2. In case on an error, the macro returns from the calling function with the error code. */ |
| #define BUG_ON_ERR_RET(f) \ |
| do \ |
| { \ |
| bcmos_errno _err; \ |
| _err = f; \ |
| BUG_ON(_err != BCM_ERR_OK); \ |
| return _err; \ |
| } \ |
| while (0) |
| |
| /** \addtogroup system_init |
| * @{ |
| */ |
| |
| /** Initialize system library |
| * Must be called before any other system function |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_init(void); |
| |
| /** Cleanup system library |
| */ |
| void bcmos_exit(void); |
| |
| /** @} system_init */ |
| |
| /** \addtogroup system_mem |
| * @{ |
| */ |
| |
| #ifndef BCMOS_MALLOC_FREE_INLINE |
| |
| /** \defgroup system_heap Default Heap |
| * @{ |
| */ |
| |
| /** Allocate memory from the main heap |
| * \param[in] size |
| * \returns memory block pointer or NULL |
| */ |
| void *bcmos_alloc(uint32_t size); |
| |
| /** Release memory to the main pool |
| * \param[in] ptr |
| */ |
| void bcmos_free(void *ptr); |
| |
| /** @} system_heap */ |
| |
| #endif /* #ifndef BCMOS_MALLOC_FREE_INLINE */ |
| |
| /** \defgroup blk_pool Block Memory Pool |
| * \ingroup system_mem |
| * @{ |
| */ |
| |
| /** Block memory pool parameters */ |
| typedef struct |
| { |
| const char *name; /**< Pool name */ |
| uint32_t blk_size; /**< Memory block size > 0 */ |
| uint32_t num_blks; /**< Number of blocks in the pool. If not set - it is derived from pool_size */ |
| void *start; /**< Start address. Can be NULL */ |
| uint32_t pool_size; /**< Total pool size in bytes. Only 1 of pool_size, num_blks must be set */ |
| uint32_t flags; /**< TBD flags */ |
| #define BCMOS_BLK_POOL_FLAG_MSG_POOL 0x80000000 /* Used by message pool */ |
| } bcmos_blk_pool_parm; |
| |
| /** Block memory pool statistics */ |
| typedef struct bcmos_blk_pool_stat |
| { |
| uint32_t allocated; /**< Number of blocks allocated */ |
| uint32_t released; /**< Number of blocks released */ |
| uint32_t free; /**< Number of free blocks in the pool */ |
| uint32_t alloc_failed; /**< Number of allocation failures */ |
| } bcmos_blk_pool_stat; |
| |
| /** Block memory pool info */ |
| typedef struct bcmos_blk_pool_info |
| { |
| bcmos_blk_pool_parm parm; /**< Pool parameters */ |
| bcmos_blk_pool_stat stat; /**< Pool statistics */ |
| } bcmos_blk_pool_info; |
| |
| /** Block memory pool control block */ |
| typedef struct bcmos_blk_pool bcmos_blk_pool; |
| |
| /** Create block memory pool |
| * \param[in,out] pool pool control block |
| * \param[in] parm pool parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_blk_pool_create(bcmos_blk_pool *pool, const bcmos_blk_pool_parm *parm); |
| |
| /** Destroy block memory pool |
| * \param[in] pool pool handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_blk_pool_destroy(bcmos_blk_pool *pool); |
| |
| /** Allocate block from block memory pool |
| * |
| * This allocates a single unit (unit_size bytes) |
| * \param[in] pool Pool handle |
| * \return memory block pointer or NULL. |
| * It is guaranteed that the returned pointer is aligned to pointer size |
| */ |
| void *bcmos_blk_pool_alloc(bcmos_blk_pool *pool); |
| |
| /** Allocate block from block memory pool and zero the block |
| * |
| * This allocates a single unit (unit_size bytes) |
| * \param[in] pool Pool handle |
| * \return memory block pointer or NULL. |
| * It is guaranteed that the returned pointer is aligned to pointer size |
| */ |
| void *bcmos_blk_pool_calloc(bcmos_blk_pool *pool); |
| |
| /** Release memory allocated using bcmos_blk_pool_alloc() |
| * |
| * \param[in] ptr pointer |
| */ |
| void bcmos_blk_pool_free(void *ptr); |
| |
| /** Release all blocks in memory pool. Block content is not affected |
| * This function is useful when application wants to pre-initialize |
| * some portion of each memory block at init time |
| * |
| * \param[in] pool Pool handle |
| */ |
| void bcmos_blk_pool_reset(bcmos_blk_pool *pool); |
| |
| /** Get pool info |
| * |
| * The pool must be created using bcmos_blk_pool_create() |
| * \param[in] pool Block memory pool handle |
| * \param[out] info Block memory pool info |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_blk_pool_query(const bcmos_blk_pool *pool, bcmos_blk_pool_info *info); |
| |
| /** Block pool iterator |
| * \param[in] prev Previous block pool. *prev==NULL - get first |
| * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE |
| */ |
| bcmos_errno bcmos_blk_pool_get_next(const bcmos_blk_pool **prev); |
| |
| /** @} blk_pool */ |
| |
| /** \defgroup byte_pool Byte Memory Pool |
| * \ingroup system_mem |
| * @{ |
| */ |
| |
| /** Byte memory pool parameters */ |
| typedef struct |
| { |
| const char *name; /**< Pool name */ |
| uint32_t size; /**< Pool size (bytes) */ |
| void *start; /**< Start address. Can be NULL */ |
| } bcmos_byte_pool_parm; |
| |
| /** Byte memory pool control block */ |
| typedef struct bcmos_byte_pool bcmos_byte_pool; |
| |
| /** Create byte memory pool |
| * \param[in,out] pool pool control block |
| * \param[in] parm pool parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm); |
| |
| /** Destroy byte memory pool |
| * \param[in] pool pool handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool); |
| |
| #ifndef BCMOS_BYTE_POOL_ALLOC_FREE_INLINE |
| /** Allocate memory from byte memory pool |
| * |
| * This function can only be used with byte memory pools created |
| * with unit_size==1 |
| * \param[in] pool Pool handle |
| * \param[in] size Block size (bytes) |
| * \return memory block pointer or NULL |
| */ |
| void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size); |
| |
| /** Release memory allocated using bcmos_pool_byte_alloc() |
| * |
| * \param[in] ptr pointer |
| */ |
| void bcmos_byte_pool_free(void *ptr); |
| |
| #endif /* BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */ |
| |
| /** @} byte_pool */ |
| |
| /** @} system_mem */ |
| |
| /** \addtogroup system_task |
| * @{ |
| */ |
| #ifndef BCMOS_WAIT_FOREVER |
| #define BCMOS_WAIT_FOREVER 0xFFFFFFFF /**< Wait timeout. Wait forever */ |
| #endif |
| #ifndef BCMOS_NO_WAIT |
| #define BCMOS_NO_WAIT 0 /**< Wait timeout. Don't wait */ |
| #endif |
| #define BCMOS_MICROSECONDS_IN_SECONDS (1000000) |
| |
| /** Task priority */ |
| typedef enum |
| { |
| BCMOS_TASK_PRIORITY_0, /**< Priority 0 - highest */ |
| BCMOS_TASK_PRIORITY_1, /**< Priority 1 */ |
| BCMOS_TASK_PRIORITY_2, /**< Priority 2 */ |
| BCMOS_TASK_PRIORITY_3, /**< Priority 3 */ |
| BCMOS_TASK_PRIORITY_4, /**< Priority 4 */ |
| BCMOS_TASK_PRIORITY_5, /**< Priority 5 */ |
| BCMOS_TASK_PRIORITY_6, /**< Priority 6 */ |
| BCMOS_TASK_PRIORITY_7, /**< Priority 7 */ |
| BCMOS_TASK_PRIORITY_8, /**< Priority 8 */ |
| BCMOS_TASK_PRIORITY_9, /**< Priority 9 */ |
| BCMOS_TASK_PRIORITY_10,/**< Priority 10 */ |
| BCMOS_TASK_PRIORITY_11,/**< Priority 11 */ |
| BCMOS_TASK_PRIORITY_12,/**< Priority 12 */ |
| BCMOS_TASK_PRIORITY_13,/**< Priority 13 */ |
| BCMOS_TASK_PRIORITY_14,/**< Priority 14 */ |
| BCMOS_TASK_PRIORITY_15,/**< Priority 15 */ |
| BCMOS_TASK_PRIORITY_16,/**< Priority 16 */ |
| BCMOS_TASK_PRIORITY_17,/**< Priority 17 */ |
| BCMOS_TASK_PRIORITY_18,/**< Priority 18 */ |
| BCMOS_TASK_PRIORITY_19,/**< Priority 19 */ |
| BCMOS_TASK_PRIORITY_20,/**< Priority 20 */ |
| BCMOS_TASK_PRIORITY_21,/**< Priority 21 */ |
| BCMOS_TASK_PRIORITY_22,/**< Priority 22 */ |
| BCMOS_TASK_PRIORITY_23,/**< Priority 23 */ |
| BCMOS_TASK_PRIORITY_24,/**< Priority 24 */ |
| BCMOS_TASK_PRIORITY_25,/**< Priority 25 */ |
| BCMOS_TASK_PRIORITY_26,/**< Priority 26 */ |
| BCMOS_TASK_PRIORITY_27,/**< Priority 27 */ |
| BCMOS_TASK_PRIORITY_28,/**< Priority 28 */ |
| BCMOS_TASK_PRIORITY_29,/**< Priority 29 */ |
| BCMOS_TASK_PRIORITY_30,/**< Priority 30 */ |
| BCMOS_TASK_PRIORITY_31,/**< Priority 31 - lowest */ |
| } bcmos_task_priority; |
| |
| /** Task handler */ |
| typedef int (*F_bcmos_task_handler)(long data); |
| |
| /* Default task handler */ |
| extern int bcmos_dft_task_handler(long data); |
| |
| /* This flags determines whether a task is to be suspended upon OOPS condition. */ |
| #define BCMOS_TASK_FLAG_NO_SUSPEND_ON_OOPS (1 << 0) |
| |
| /** Task parameters */ |
| typedef struct |
| { |
| const char *name; /**< Task name */ |
| bcmos_task_priority priority; /**< Task priority */ |
| bcmos_core core; /**< CPU core the task is locked to */ |
| uint32_t stack_size; /**< Task stack size */ |
| void *stack; /**< Stack location. NULL=allocate automatically */ |
| F_bcmos_task_handler init_handler; /**< Optional "init" handler. Called once in the task context when it is created. |
| This callback is only supported in integration mode (handler==NULL). |
| init_handler returns bcmos_errno. If it returns value other than BCM_ERR_OK, |
| the task is destroyed */ |
| F_bcmos_task_handler handler; /**< Task handler. NULL=default (integration mode) */ |
| F_bcmos_task_handler timeout_handler;/**< This function is used only in integration mode (handler==NULL) if |
| msg_wait_timeout is > 0. It is called if there were no messages for the task |
| for longer than msg_wait_timeout us. |
| If timeout handler returns value other than BCM_ERR_OK, task terminates. |
| */ |
| uint32_t msg_wait_timeout; /**< This parameter is used only in integration mode (handler==NULL) together with |
| timeout_handler. If > 0 and there were no messages for longer than |
| msg_wait_timeout us, timeout_handler is called. |
| */ |
| long data; /**< Data passed to the task handler */ |
| uint32_t flags; /**< flags */ |
| } bcmos_task_parm; |
| |
| /** Task control block */ |
| typedef struct bcmos_task bcmos_task; |
| |
| /** Create a new task |
| * |
| * \param[in,out] task Task control block |
| * \param[in] parm Task parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm); |
| |
| /** Set task timeout |
| * |
| * This function is only used in integration mode (handler==NULL). |
| * It sets max time the default task handler waits for message directed to one of the |
| * task's modules. |
| * |
| * \param[in,out] task Task control block |
| * \param[in] timeout Max time (us) to wait for messages. 0=FOREVER |
| * Changing timeout from infinite to finite only takes effect |
| * after message is received by any task module. |
| * \param[in] timeout_handler Handler to be called upon timeout. Must be != NULL if timeout > 0. |
| * If the handler returns error (!= BCM_ERR_OK), task terminates. |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_task_timeout_set(bcmos_task *task, uint32_t timeout, F_bcmos_task_handler timeout_handler); |
| |
| /** Destroy task |
| * |
| * \param[in] task Task handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_task_destroy(bcmos_task *task); |
| |
| /** Get current task |
| * \returns task handle or NULL if not in task context |
| */ |
| bcmos_task *bcmos_task_current(void); |
| |
| /** Query task info |
| * \param[in] task Task control block |
| * \param[out] parm Task parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_task_query(const bcmos_task *task, bcmos_task_parm *parm); |
| |
| /** Task iterator |
| * \param[in] prev Previous task. *prev==NULL - get first |
| * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE |
| */ |
| bcmos_errno bcmos_task_get_next(bcmos_task **prev); |
| |
| |
| /** @} system_task */ |
| |
| /** \addtogroup system_msg |
| * @{ |
| */ |
| |
| /** Message header */ |
| typedef struct bcmos_msg bcmos_msg; |
| |
| /** Message queue control block */ |
| typedef struct bcmos_msg_queue bcmos_msg_queue; |
| |
| /** Message queue group control block */ |
| typedef struct bcmos_msg_qgroup bcmos_msg_qgroup; |
| |
| #if defined(BCMOS_MSG_QUEUE_DOMAIN_SOCKET) || defined(BCMOS_MSG_QUEUE_UDP_SOCKET) || defined(BCMOS_MSG_QUEUE_USER_DEFINED) |
| #define BCMOS_MSG_QUEUE_REMOTE_SUPPORT |
| #endif |
| |
| /** Message queue endpoint type */ |
| typedef enum |
| { |
| BCMOS_MSG_QUEUE_EP_LOCAL, /**< Local endpoint (inter-thread communication) */ |
| #ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET |
| BCMOS_MSG_QUEUE_EP_DOMAIN_SOCKET, /**< Domain-socket based endpoint */ |
| #endif |
| #ifdef BCMOS_MSG_QUEUE_UDP_SOCKET |
| BCMOS_MSG_QUEUE_EP_UDP_SOCKET, /**< UDP socket-based endpoint */ |
| #endif |
| #ifdef BCMOS_MSG_QUEUE_USER_DEFINED |
| BCMOS_MSG_QUEUE_EP_USER_DEFINED /**< User-defined endpoint */ |
| #endif |
| } bcmos_msg_queue_ep_type; |
| |
| |
| /** Message queue parameters */ |
| typedef struct |
| { |
| const char *name; /**< Queue name (for logging and debugging) */ |
| uint32_t size; /**< Max queue size. 0=unlimited */ |
| uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */ |
| uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */ |
| uint32_t flags; /**< TBD flags. For example, single-core, m-core */ |
| void (*notify)(bcmos_msg_queue *q, const char *txt); /***< Called when queue congestion state changes */ |
| bcmos_msg_queue_ep_type ep_type; /**< Queue endpoint type */ |
| |
| #ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT |
| /* Remote message queue support allows queue endpoints to be located in |
| * different processes or even processors. |
| */ |
| const char *local_ep_address; /**< Queue local endpoint address */ |
| const char *remote_ep_address; /**< Queue local endpoint address */ |
| |
| uint32_t max_mtu; /**< Max MTU size */ |
| #define BCMOS_MSG_QUEUE_DEFAULT_MAX_MTU (64*1024) |
| |
| /** Optional "pack" callback. Not needed if 2 processes are on the same core. */ |
| bcmos_errno (*pack)(bcmos_msg_queue *queue, bcmos_msg *msg, uint8_t **buf, uint32_t *buf_length); |
| |
| /** Optional "unpack" callback. Not needed if 2 processes are on the same core. */ |
| bcmos_errno (*unpack)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length, bcmos_msg **msg); |
| |
| /** Optional callback that releases packed buffer */ |
| void (*free_packed)(bcmos_msg_queue *queue, uint8_t *buf); |
| |
| /** Optional "open" callback. Must be set for user-defined queue, NULL otherwise */ |
| bcmos_errno (*open)(bcmos_msg_queue *queue); |
| |
| /** Optional "close" callback. Must be set for user-defined queue, NULL otherwise */ |
| bcmos_errno (*close)(bcmos_msg_queue *queue); |
| |
| /** Optional "send" callback. Must be set for user-defined queue, NULL otherwise */ |
| bcmos_errno (*send)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length); |
| |
| /** Optional "recv" callback. Must be set for user-defined queue, NULL otherwise */ |
| bcmos_errno (*recv)(bcmos_msg_queue *queue, uint32_t timeout, uint8_t **buf, uint32_t *buf_length); |
| #endif |
| |
| } bcmos_msg_queue_parm; |
| |
| /** Message queue statistics */ |
| typedef struct |
| { |
| uint32_t msg_in; /**< Number of messages currently in the queue */ |
| uint32_t msg_sent; /**< Number of messages successfully submitted into the queue */ |
| uint32_t msg_received; /**< Number of messages received from the queue */ |
| uint32_t msg_discarded; /**< Number of messages discarded because of queue overflow */ |
| uint32_t msg_almost_full; /**< Number of messages submitted to queue when it was above high water mark */ |
| bcmos_bool is_congested; /**< True=the queue is currently congested */ |
| } bcmos_msg_queue_stat; |
| |
| /** Message queue info */ |
| typedef struct |
| { |
| bcmos_msg_queue_parm parm; /**< Queue parameters */ |
| bcmos_msg_queue_stat stat; /**< Queue statistics */ |
| } bcmos_msg_queue_info; |
| |
| /** Message priority in queue group */ |
| typedef uint32_t bcmos_qgroup_prty; |
| |
| /** Message queue group parameters */ |
| typedef struct |
| { |
| const char *name; /**< Queue group name (for logging and debugging) */ |
| bcmos_qgroup_prty nqueues; /**< Number of queues in the group */ |
| uint32_t size; /**< Total number of messages that can be stored in queue group. 0=unlimited */ |
| uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */ |
| uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */ |
| uint32_t flags; /**< TBD flags. For example, single-core, m-core */ |
| void (*notify)(bcmos_msg_qgroup *qgrp, const char *txt); /***< Called when queue group congestion state changes */ |
| } bcmos_msg_qgroup_parm; |
| |
| /** Message queue group info */ |
| typedef struct |
| { |
| bcmos_msg_qgroup_parm parm; /**< Queue group parameters */ |
| bcmos_msg_queue_stat stat; /**< Queue group statistics */ |
| } bcmos_msg_qgroup_info; |
| |
| /** Message recipient instance (e.g., optical link id) */ |
| typedef uint16_t bcmos_msg_instance; |
| |
| /** Message send flags */ |
| typedef enum |
| { |
| BCMOS_MSG_SEND_AUTO_FREE = 0x00000000, /**< Automatically release message in case of error. This is the default behaviour */ |
| BCMOS_MSG_SEND_NO_FREE_ON_ERROR =0x00000001,/**< Do NOT free message in case of transmit error */ |
| BCMOS_MSG_SEND_URGENT = 0x00000002, /**< Urgent message */ |
| BCMOS_MSG_SEND_NOLIMIT = 0x00000004, /**< Ignore destination queue size limit */ |
| } bcmos_msg_send_flags; |
| |
| /** Registered message handler */ |
| typedef void (*F_bcmos_msg_handler)(bcmos_module_id module_id, bcmos_msg *msg); |
| typedef bcmos_errno (*F_bcmos_module_init)(long data); |
| typedef void (*F_bcmos_module_exit)(long data); |
| |
| /** Message header */ |
| struct bcmos_msg |
| { |
| bcmos_msg_id type; /**< Message type */ |
| bcmos_msg_instance instance;/**< Message recipient instance (e.g., optical link id) */ |
| F_bcmos_msg_handler handler;/**< Message handler. Can be set by the sender or message dispatcher */ |
| bcmos_module_id sender; /**< Sender module */ |
| STAILQ_ENTRY(bcmos_msg) next; /**< Next message pointer */ |
| void *data; /**< Message data pointer */ |
| void *start; /**< Message data block start (for release) */ |
| uint32_t size; /**< Message data size */ |
| bcmos_msg_send_flags send_flags; /**< Flags the message was sent with */ |
| #define BCMOS_MSG_QUEUE_SIZE_UNLIMITED 0xFFFFFFFF /**< Unlimited queue */ |
| void (*release)(bcmos_msg *); /**< Release callback */ |
| void (*data_release)(bcmos_msg *); /**< Data release callback. Used when message is released to message pool */ |
| }; |
| |
| /* Helper functions that pack / unpack message header for IPC */ |
| #ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT |
| |
| /** Size of message header on the line for IPC */ |
| #define BCMOS_MSG_HDR_SIZE 8 |
| |
| void bcmos_msg_hdr_pack(const bcmos_msg *msg, uint8_t *buf, uint32_t data_size); |
| void bcmos_msg_hdr_unpack(const uint8_t *buf, bcmos_msg *msg); |
| |
| #endif |
| |
| /** Create message queue. |
| * |
| * This function can be called explicitly in "traditional" mode |
| * or implicitly by bcmos_module_create(). |
| * \param[in,out] queue Queue control block |
| * \param[in] parm Queue parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_queue_create(bcmos_msg_queue *queue, const bcmos_msg_queue_parm *parm); |
| |
| /** Destroy queue |
| * |
| * \param[in] queue Queue handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_queue_destroy(bcmos_msg_queue *queue); |
| |
| /** Get queue info |
| * |
| * \param[in] queue Queue handle |
| * \param[out] info Queue information |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_queue_query(const bcmos_msg_queue *queue, bcmos_msg_queue_info *info); |
| |
| /** Message queue iterator |
| * \param[in] prev Previous queue. *prev==NULL - get first |
| * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE |
| */ |
| bcmos_errno bcmos_msg_queue_get_next(const bcmos_msg_queue **prev); |
| |
| /** Create message queue group. |
| * |
| * Queue group contains configurable number of queues. The queues are drained |
| * in strict priority. Priority 0 is the highest. |
| * |
| * \param[in,out] qgroup Queue group control block |
| * \param[in] parm Queue group parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_qgroup_create(bcmos_msg_qgroup *qgroup, const bcmos_msg_qgroup_parm *parm); |
| |
| /** Destroy queue group |
| * |
| * \param[in] qgroup Queue group handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_qgroup_destroy(bcmos_msg_qgroup *qgroup); |
| |
| /** Get queue group info |
| * |
| * \param[in] qgroup Queue group handle |
| * \param[out] info Queue group information |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_qgroup_query(const bcmos_msg_qgroup *qgroup, bcmos_msg_qgroup_info *info); |
| |
| /** Message queue group iterator |
| * \param[in] prev Previous queue group. *prev==NULL - get first |
| * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE |
| */ |
| bcmos_errno bcmos_msg_qgroup_get_next(const bcmos_msg_qgroup **prev); |
| |
| /** Send message to queue |
| * |
| * \param[in] queue Queue handle |
| * \param[in] msg Message |
| * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits |
| * |
| * msg is released automatically regardless of bcmos_msg_send() outcome, unless |
| * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set. |
| * |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_send(bcmos_msg_queue *queue, bcmos_msg *msg, bcmos_msg_send_flags flags); |
| |
| /** Send message to module |
| * |
| * For module to be able to receive the message, it must be registered |
| * using bcmos_msg_register() |
| * |
| * \param[in] module_id Module id |
| * \param[in] msg Message. msg->handler must be set |
| * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits |
| * |
| * msg is released automatically regardless of bcmos_msg_send_to_module() outcome, unless |
| * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set. |
| * |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_send_to_module(bcmos_module_id module_id, bcmos_msg *msg, bcmos_msg_send_flags flags); |
| |
| /** Send message to queue group |
| * |
| * \param[in] qgroup Queue group handle |
| * \param[in] msg Message |
| * \param[in] prty Message priority in range 0-nqueues_in_group-1. |
| * 0 priority is the highest. If MAX number of messages are already queues |
| * in the queue group, sending message can leave to discard of the head message |
| * queued at lower priority |
| * \param[in] flags BCMOS_MSG_SEND_AUTO_FREE or BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag |
| * |
| * |
| * msg is released automatically regardless of bcmos_msg_send_to_qgroup() outcome, unless |
| * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set. |
| * |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_send_to_qgroup(bcmos_msg_qgroup *qgroup, bcmos_msg *msg, bcmos_qgroup_prty prty, |
| bcmos_msg_send_flags flags); |
| |
| /** Get message from the head of message queue |
| * |
| * The function can lead to the calling task being suspended for a period |
| * of time or indefinitely, until message is submitted to the queue.\n |
| * The function is only used in "traditional tasks" (see \ref system_model). |
| * |
| * \param[in] queue Queue handle |
| * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER |
| * \param[out] msg Message handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, bcmos_msg **msg); |
| |
| /** Get highest priority message from queue group |
| * |
| * The function can lead to the calling task being suspended for a period |
| * of time or indefinitely, until message is submitted to the queue group.\n |
| * The function is only used in "traditional tasks" (see \ref system_model). |
| * |
| * \param[in] qgroup Queue group handle |
| * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER |
| * \param[out] msg Message handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_recv_from_qgroup(bcmos_msg_qgroup *qgroup, uint32_t timeout, bcmos_msg **msg); |
| |
| /** Dispatch message. Send to module that registered for it. |
| * |
| * The message must be registered using bcmos_msg_register() |
| * |
| * This function should be used if the message sender doesn't know the target module and/or |
| * message handling callback. |
| * |
| * \param[in] msg Message handle |
| * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits |
| * |
| * msg is released automatically regardless of bcmos_msg_dispatch() outcome, unless |
| * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set. |
| * |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_dispatch(bcmos_msg *msg, bcmos_msg_send_flags flags); |
| |
| /** Register message for "push-mode" delivery. |
| * |
| * When registered message is sent to the target module and |
| * the module's task wakes up, message handler is called in the module's context. |
| * |
| * \param[in] msg_type Message type |
| * \param[in] instance Message type instance |
| * \param[in] module_id Target module id |
| * \param[in] handler Message handler |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_register(bcmos_msg_id msg_type, bcmos_msg_instance instance, |
| bcmos_module_id module_id, F_bcmos_msg_handler handler); |
| |
| /** Un-register message registered by bcmos_msg_register() |
| * |
| * \param[in] msg_type Message type |
| * \param[in] instance Message type instance |
| * \param[in] module_id Target module id |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_unregister(bcmos_msg_id msg_type, bcmos_msg_instance instance, |
| bcmos_module_id module_id); |
| |
| /** Put the OS message infrastructure in "shutdown mode". |
| * |
| * When in shutdown mode, bcmos_msg_dispatch() will return BCM_ERR_OK instead of BCM_ERR_NOENT when a handler is not |
| * found for the message. Additionally, bcmos_msg_dispatch() becomes safe to call concurrently with |
| * bcmos_msg_unregister() (this is not true in normal operation). |
| * |
| * \param[in] shutdown_mode Whether or not to enable shutdown mode |
| */ |
| void bcmos_msg_shutdown_mode_set(bcmos_bool shutdown_mode); |
| |
| /** Gets whether or not the OS message infrastructure is currently in "shutdown mode". |
| * \returns BCMOS_TRUE if we are in shutdown mode, BCMOS_FALSE otherwise |
| */ |
| bcmos_bool bcmos_msg_shutdown_mode_get(void); |
| |
| /** Helper type for storing message types alongside their handlers. */ |
| typedef struct |
| { |
| bcmos_msg_id msg_type; |
| F_bcmos_msg_handler handler; |
| } bcmos_msg_id2handler; |
| |
| /** Message pool */ |
| typedef struct bcmos_msg_pool bcmos_msg_pool; |
| |
| /** Message pool parameters */ |
| typedef struct bcmos_msg_pool_parm |
| { |
| const char *name; /**< Pool name */ |
| uint32_t size; /**< Number of messages in the pool */ |
| uint32_t data_size; /**< Message data size */ |
| uint32_t flags; /**< TBD flags */ |
| void (*data_release)(bcmos_msg *msg); /**< Optional data release callback. Called when message is released to the pool */ |
| } bcmos_msg_pool_parm; |
| |
| /** Message pool statistics */ |
| typedef bcmos_blk_pool_stat bcmos_msg_pool_stat; |
| |
| /** Message pool info */ |
| typedef struct bcmos_msg_pool_info |
| { |
| bcmos_msg_pool_parm parm; /**< Pool parameters */ |
| bcmos_msg_pool_stat stat; /**< Pool statistics */ |
| } bcmos_msg_pool_info; |
| |
| /** Create message pool |
| * |
| * Create pool containing pre-allocated messages with specified data size |
| * \param[in] pool Message pool handle |
| * \param[in] parm Message pool parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_pool_create(bcmos_msg_pool *pool, const bcmos_msg_pool_parm *parm); |
| |
| /** Destroy message pool |
| * |
| * All messages must be released to the pool before it can be destroyed. |
| * |
| * \param[in] pool Message pool handle |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_pool_destroy(bcmos_msg_pool *pool); |
| |
| /** Allocate message from pool |
| * |
| * The pool must be created using bcmos_pool_create() |
| * \param[in] pool Message pool handle |
| * \returns msg pointer or NULL if the pool is empty. |
| * "data" and "release" fields in the returned message are pre-set |
| * Once no longer needed, the message must be released using bcmos_msg_free() |
| */ |
| bcmos_msg *bcmos_msg_pool_alloc(bcmos_msg_pool *pool); |
| |
| /** Allocate message from pool and clear data |
| * |
| * The pool must be created using bcmos_pool_create() |
| * \param[in] pool Message pool handle |
| * \returns msg pointer or NULL if the pool is empty. |
| * "data" and "release" fields in the returned message are pre-set |
| * Once no longer needed, the message must be released using bcmos_msg_free() |
| */ |
| static inline bcmos_msg *bcmos_msg_pool_calloc(bcmos_msg_pool *pool) |
| { |
| bcmos_msg *msg = bcmos_msg_pool_alloc(pool); |
| if (msg) |
| { |
| memset(msg->data, 0, msg->size); |
| } |
| return msg; |
| } |
| |
| /** Get pool info |
| * |
| * The pool must be created using bcmos_pool_create() |
| * \param[in] pool Message pool handle |
| * \param[out] info Message pool info |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_msg_pool_query(const bcmos_msg_pool *pool, bcmos_msg_pool_info *info); |
| |
| /** Message pool iterator |
| * \param[in] prev Previous message pool. *prev==NULL - get first |
| * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE |
| */ |
| bcmos_errno bcmos_msg_pool_get_next(const bcmos_msg_pool **prev); |
| |
| /** @} system_msg */ |
| |
| /** \addtogroup system_module |
| * @{ |
| */ |
| |
| /** Max number of modules per task. Must be <= 32 */ |
| #define BCMOS_MAX_MODULES_PER_TASK 8 |
| |
| /** Module parameters */ |
| typedef struct |
| { |
| bcmos_msg_queue_parm qparm; /**< Message queue paramaters */ |
| F_bcmos_module_init init; /**< Init callback */ |
| F_bcmos_module_exit exit; /**< Exit callback */ |
| long data; /**< Module context initial value. Also passed to init and exit callbacks */ |
| } bcmos_module_parm; |
| |
| /** Module control block */ |
| typedef struct bcmos_module bcmos_module; |
| |
| /** Register module |
| * |
| * \param[in] module_id Module id |
| * \param[in] task Owner task ID |
| * \param[in] parm Module parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_module_create(bcmos_module_id module_id, bcmos_task *task, bcmos_module_parm *parm); |
| |
| /** Un-register module |
| * |
| * \param[in] module_id Module id |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_module_destroy(bcmos_module_id module_id); |
| |
| /** Get current module id in the current task |
| * |
| * \returns module_id |
| */ |
| bcmos_module_id bcmos_module_current(void); |
| |
| /** Get module context |
| * |
| * Module context is initialized as module_parm.data and can be modified using |
| * bcmos_module_context_set() |
| * |
| * \param[in] module_id Module_id |
| * \returns context pointer set by bcmos_module_context_set() or |
| * |
| * NULL if module_id is invalid or context is not set. |
| */ |
| void *bcmos_module_context(bcmos_module_id module_id); |
| |
| /** Set module context |
| * |
| * Context is an arbitrary structure used to store module-specific data. |
| * Usually this function is called from module init() callback |
| * |
| * \param[in] module_id Module_id |
| * \param[in] context Module context pointer |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_module_context_set(bcmos_module_id module_id, void *context); |
| |
| /* module control blocks */ |
| extern bcmos_module *bcmos_modules[BCMOS_MODULE_ID__NUM_OF]; |
| |
| static inline bcmos_module *_bcmos_module_get(bcmos_module_id module_id) |
| { |
| bcmos_module *module = bcmos_modules[module_id]; |
| if ((unsigned)module_id >= BCMOS_MODULE_ID__NUM_OF) |
| return NULL; |
| return module; |
| } |
| |
| /** Query module |
| * |
| * \param[in] module_id Module_id |
| * \param[out] task Task that owns the module |
| * \param[out] info Module queue info |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_module_query(bcmos_module_id module_id, const bcmos_task **task, bcmos_msg_queue_info *info); |
| |
| /** @} system_module */ |
| |
| /** \addtogroup system_event |
| * @{ |
| */ |
| |
| /** Registered event handler */ |
| typedef void (*F_bcmos_event_handler)(bcmos_event_id event_id, uint32_t active_bits); |
| |
| /** Event parameters */ |
| typedef struct |
| { |
| const char *name; /**< Event set name */ |
| bcmos_module_id module_id; /**< Module id. The module must be registered */ |
| uint32_t mask; /**< Event bits module is interested in */ |
| F_bcmos_event_handler handler; /**< Event handler. Called in module's context */ |
| uint32_t flags; /**< TBD flags. E.g., inter-core */ |
| } bcmos_event_parm; |
| |
| /** Event control block */ |
| typedef struct bcmos_event bcmos_event; |
| |
| /** Create event set |
| * |
| * \param[in] event_id Event set id |
| * \param[in] parm Event parameters. Used in "integration" mode. NULL in "traditional" mode |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_event_create(bcmos_event_id event_id, bcmos_event_parm *parm); |
| |
| /** Destroy event set created by bcmos_event_create() |
| * |
| * \param[in] event_id Event set id |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_event_destroy(bcmos_event_id event_id); |
| |
| /** Raise event |
| * |
| * Raised event is delivered to module(s) that registered for it |
| * using bcmos_event_register() or to the task waiting for event |
| * using bcmos_event_recv() |
| * |
| * \param[in] event_id Event set id |
| * \param[in] active_bits Active bit mask |
| * \returns 0=OK or error code <0. Can only fail if event is not registered |
| */ |
| bcmos_errno bcmos_event_raise(bcmos_event_id event_id, uint32_t active_bits); |
| |
| /** Wait for event |
| * |
| * This function is used in "traditional" mode.\n |
| * The caller can block for a time or indefinitely |
| * |
| * \param[in] event_id Event set id |
| * \param[in] mask Interesting bits. The functions returns when |
| * - timeout expires |
| * - event with (active_bits & mask) != 0 is raised |
| * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER |
| * \param[out] active_bits active bits in the event set. valid only if the function returns 0 |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_event_recv(bcmos_event_id event_id, uint32_t mask, |
| uint32_t timeout, uint32_t *active_bits); |
| |
| /* Event set array */ |
| extern bcmos_event *bcmos_events[BCMOS_EVENT_ID__NUM_OF]; |
| |
| /* Get event givern the event id */ |
| static inline bcmos_event *_bcmos_event_get(bcmos_event_id event_id) |
| { |
| bcmos_event *ev = bcmos_events[event_id]; |
| if ((unsigned)event_id >= BCMOS_EVENT_ID__NUM_OF) |
| return NULL; |
| return ev; |
| } |
| |
| /** @} system_event */ |
| |
| /** \addtogroup system_timer |
| * @{ |
| */ |
| |
| /** Max timer duration (us) */ |
| #define BCMOS_MAX_TIMER_DURATION 0x80000000 |
| |
| /** Timer control block */ |
| typedef struct bcmos_timer bcmos_timer; |
| |
| /** Timer handler completion code */ |
| typedef enum |
| { |
| BCMOS_TIMER_OK, /**< Restart timer if periodic or keep stopped if not */ |
| BCMOS_TIMER_STOP /**< Do not restart periodic timer */ |
| } bcmos_timer_rc; |
| |
| /** Timer handler |
| * \param[in] timer Expired timer handle |
| * \param[in] data User data supplied at timer creation time |
| * \returns \ref bcmos_timer_rc |
| */ |
| typedef bcmos_timer_rc (*F_bcmos_timer_handler)(bcmos_timer *timer, long data); |
| |
| typedef enum |
| { |
| BCMOS_TIMER_PARM_FLAGS_URGENT = 0, /**< Default behavior. If the timer owner is set, timer expiration |
| will be delivered as an urgent message. */ |
| BCMOS_TIMER_PARM_FLAGS_NON_URGENT = 1 << 0, /**< If the timer owner is set, timer expiration will be delivered as |
| a normal (non-urgent) message. */ |
| } bcmos_timer_parm_flags; |
| |
| /** Timer parameters */ |
| typedef struct |
| { |
| const char *name; /**< Timer name */ |
| bcmos_module_id owner; /**< Timer owner. If set, timer expiration is delivered to the module |
| as a message */ |
| bcmos_bool periodic; /**< TRUE=periodic */ |
| F_bcmos_timer_handler handler; /**< Timer handler. Called in context of owner module |
| if set or timer ISR if owner==BCMOS_MODULE_ID_NONE */ |
| long data; /**< data to pass to the handler */ |
| bcmos_timer_parm_flags flags; /**< Flags to change the behavior of the timer */ |
| } bcmos_timer_parm; |
| |
| #ifndef BCMOS_TIMESTAMP_INLINE |
| |
| /** Get current timestamp |
| * \returns the current system timestamp (us) |
| */ |
| uint32_t bcmos_timestamp(void); |
| |
| /** Get current 64 bit timestamp |
| * \returns the current system timestamp (us) |
| * \note There is no guarantee that all 64 bit carry information. |
| * However, it is guaranteed that the timestamp wraps around |
| * not oftener than every 50 days (ms resolution) |
| */ |
| uint64_t bcmos_timestamp64(void); |
| |
| #endif /* #ifndef BCMOS_TIMESTAMP_INLINE */ |
| |
| /** Create timer |
| * |
| * \param[in,out] timer timer control block |
| * \param[in] parm timer parameters |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_timer_create(bcmos_timer *timer, bcmos_timer_parm *parm); |
| |
| /** Destroy timer |
| * The timer is stopped if running and destroyed |
| * \param[in] timer timer handle |
| */ |
| void bcmos_timer_destroy(bcmos_timer *timer); |
| |
| /** Set timer handler |
| * |
| * \param[in,out] timer timer control block |
| * \param[in] handler timer handler |
| * \param[in] data data to be passed to the handler |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_timer_handler_set(bcmos_timer *timer, F_bcmos_timer_handler handler, long data); |
| |
| /** (Re)start timer |
| * Stop timer if running and start it. |
| * |
| * \param[in] timer timer handle |
| * \param[in] delay delay in us |
| */ |
| void bcmos_timer_start(bcmos_timer *timer, uint32_t delay); |
| |
| /** Stop timer if running |
| * |
| * \param[in] timer timer handle |
| */ |
| void bcmos_timer_stop(bcmos_timer *timer); |
| |
| /** Suspend current task for a time |
| * |
| * \param[in] us sleep time (us) |
| */ |
| #ifndef BCMOS_USLEEP_INLINE |
| void bcmos_usleep(uint32_t us); |
| #endif /* #ifndef BCMOS_USLEEP_INLINE */ |
| |
| /** @} system_timer */ |
| |
| /** \addtogroup system_fastlock |
| * @{ |
| */ |
| |
| /** Fast lock control block */ |
| typedef struct bcmos_fastlock bcmos_fastlock; |
| |
| #ifndef BCMOS_FASTLOCK_INLINE |
| |
| /** Init fastlock |
| * \param[in, out] lock fast lock control block |
| * \param[in] flags flags - TBD. E.g., single core / SMP |
| */ |
| void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags); |
| |
| /** Take fast lock |
| * \param[in] lock fast lock |
| * \returns value of interrupt flags that should be used in unlock |
| */ |
| long bcmos_fastlock_lock(bcmos_fastlock *lock); |
| |
| /** Release fast lock |
| * \param[in] lock fast lock |
| * \param[in] flags interrupt flags |
| */ |
| void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags); |
| |
| #endif /* #ifndef BCMOS_FASTLOCK_INLINE */ |
| |
| /** @} system_fastlock */ |
| |
| /** \addtogroup system_mutex |
| * @{ |
| */ |
| |
| /** Mutex control block */ |
| typedef struct bcmos_mutex bcmos_mutex; |
| |
| #ifdef BCMOS_MUTEX_INLINE |
| #define BCMOS_MUTEX_CREATE_DESTROY_INLINE |
| #define BCMOS_MUTEX_LOCK_UNLOCK_INLINE |
| #endif |
| |
| #ifndef BCMOS_MUTEX_CREATE_DESTROY_INLINE |
| |
| /** Create recursive mutex |
| * \param[in, out] mutex Mutex control block |
| * \param[in] flags flags - TBD. E.g., single core / SMP |
| * \param[in] name name of the mutex (if OS supports), NULL means it will be auto-generated |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name); |
| |
| /** Destroy mutex |
| * \param[in] mutex Mutex control block |
| */ |
| void bcmos_mutex_destroy(bcmos_mutex *mutex); |
| |
| #endif /* BCMOS_MUTEX_CREATE_DESTROY_INLINE */ |
| |
| |
| #ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE |
| |
| /** Lock mutex |
| * \param[in] mutex Mutex control block |
| */ |
| void bcmos_mutex_lock(bcmos_mutex *mutex); |
| |
| /** Release mutex |
| * \param[in] mutex Mutex control block |
| */ |
| void bcmos_mutex_unlock(bcmos_mutex *mutex); |
| |
| #endif /* #ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE */ |
| |
| /** @} system_mutex */ |
| |
| /** \addtogroup system_sem |
| * @{ |
| */ |
| |
| /** Semaphore control block */ |
| typedef struct bcmos_sem bcmos_sem; |
| |
| #ifdef BCMOS_SEM_INLINE |
| #define BCMOS_SEM_CREATE_DESTROY_INLINE |
| #define BCMOS_SEM_WAIT_INLINE |
| #define BCMOS_SEM_POST_INLINE |
| #endif |
| |
| #ifndef BCMOS_SEM_CREATE_DESTROY_INLINE |
| |
| /** Create semaphore |
| * \param[in, out] sem semaphore control block |
| * \param[in] count initial value of semaphore counter |
| * \param[in] flags flags - TBD. E.g., single core / SMP |
| * \param[in] name name of the semaphore (if OS supports), NULL means it will be auto-generated |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name); |
| |
| /** Destroy semaphore |
| * \param[in] sem semaphore control block |
| */ |
| void bcmos_sem_destroy(bcmos_sem *sem); |
| |
| #endif /* BCMOS_SEM_CREATE_DESTROY_INLINE */ |
| |
| #ifndef BCMOS_SEM_WAIT_INLINE |
| |
| /** Decrement semaphore counter. Wait if the counter is 0 |
| * |
| * \param[in] sem semaphore control block |
| * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER |
| * \returns 0=OK or error code <0 |
| */ |
| bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout); |
| |
| #endif /* #ifndef BCMOS_SEM_WAIT_INLINE */ |
| |
| #ifndef BCMOS_SEM_POST_INLINE |
| /** Increment semaphore counter |
| * \param[in] sem semaphore control block |
| */ |
| void bcmos_sem_post(bcmos_sem *sem); |
| |
| #endif /* #ifndef BCMOS_SEM_POST_INLINE */ |
| |
| /** @} system_sem */ |
| |
| /* |
| * print support |
| */ |
| |
| /** Print cloning/redirection mode */ |
| typedef enum |
| { |
| BCMOS_PRINT_REDIRECT_MODE_NONE, /**< No cloning, redirection */ |
| BCMOS_PRINT_REDIRECT_MODE_REDIRECT, /**< Redirect console output. Do not print on the serial console */ |
| BCMOS_PRINT_REDIRECT_MODE_CLONE /**< Clone console output to redirection callback */ |
| } bcmos_print_redirect_mode; |
| |
| /** Print re-direction/cloning callback */ |
| typedef int (*bcmos_print_redirect_cb)(void *data, const char *format, va_list ap); |
| |
| /** Set up print redirection/cloning |
| * \param[in] mode redirection/cloning mode |
| * \param[in] cb redirection callback |
| * \param[in] data opaque data to be passed to cb |
| * \returns 0=OK or error <0 |
| */ |
| bcmos_errno bcmos_print_redirect(bcmos_print_redirect_mode mode, bcmos_print_redirect_cb cb, void *data); |
| |
| /* Print on the console with optional cloning / redirection |
| * \param[in] format printf format |
| * \param[in] ap argument list |
| * \returns number of characters printed >= 0 or error < 0 |
| */ |
| int bcmos_vprintf(const char *format, va_list ap); |
| |
| /* Print on the console with optional cloning / redirection |
| * \param[in] format printf format |
| * \returns number of characters printed >= 0 or error < 0 |
| */ |
| int bcmos_printf(const char *format, ...); |
| |
| |
| /** \addtogroup system_trace |
| * @{ |
| */ |
| |
| /** Trace level */ |
| typedef enum |
| { |
| BCMOS_TRACE_LEVEL_NONE, /**< No trace output */ |
| BCMOS_TRACE_LEVEL_ERROR, /**< Trace errors */ |
| BCMOS_TRACE_LEVEL_WARNING, /**< Trace errors + warnings */ |
| BCMOS_TRACE_LEVEL_INFO, /**< Trace errors + warnings + info */ |
| BCMOS_TRACE_LEVEL_VERBOSE, /**< Trace errors + warnings + info + verbose info */ |
| BCMOS_TRACE_LEVEL_DEBUG, /**< Trace everything */ |
| } bcmos_trace_level; |
| |
| extern bcmos_trace_level bcmos_sys_trace_level; |
| |
| #ifdef BCMOS_TRACE_PRINTF |
| #define BCMOS_TRACE_INLINE |
| #endif |
| |
| #ifndef BCMOS_TRACE_INLINE |
| /** Print trace |
| * |
| * \param[in] level Record trace at level |
| * \param[in] format printf-like format |
| */ |
| void bcmos_trace(bcmos_trace_level level, const char *format, ...); |
| #endif |
| |
| |
| /* Print trace */ |
| #ifdef BCMOS_TRACE_PRINTF |
| #define bcmos_trace(level, fmt, args...) bcmos_printf(fmt, ## args) |
| #endif |
| |
| /** Set current trace level |
| * \param[in] level New trace level |
| * \returns old trace level |
| */ |
| static inline bcmos_trace_level bcmos_trace_level_set(bcmos_trace_level level) |
| { |
| bcmos_trace_level old_level = bcmos_sys_trace_level; |
| bcmos_sys_trace_level = level; |
| return old_level; |
| } |
| |
| /** Get current trace level |
| * \returns trace level |
| */ |
| static inline bcmos_trace_level bcmos_trace_level_get(void) |
| { |
| return bcmos_sys_trace_level; |
| } |
| |
| /** Print trace conditionally, depending on the current trace level |
| * \param[in] level Record trace at level |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| */ |
| #define BCMOS_TRACE(level, fmt, args...) \ |
| do \ |
| { \ |
| if (level <= bcmos_sys_trace_level) \ |
| bcmos_trace(level, "%s#%d> " fmt, __FUNCTION__, __LINE__, ## args); \ |
| } while (0) |
| |
| /** Print error trace conditionally, depending on the current trace level |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| */ |
| |
| extern f_bcmolt_sw_error_handler sw_error_handler; |
| |
| #define BCMOS_TRACE_ERR(fmt, args...) \ |
| do \ |
| { \ |
| BCMOS_TRACE(BCMOS_TRACE_LEVEL_ERROR, "ERR: " fmt, ## args); \ |
| if (sw_error_handler != NULL) \ |
| { \ |
| sw_error_handler(0xff, __FILE__, __LINE__); \ |
| } \ |
| _bcmos_backtrace(); \ |
| } while (0) |
| |
| |
| /** Print info trace conditionally, depending on the current trace level |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| */ |
| #define BCMOS_TRACE_INFO(fmt, args...) \ |
| BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "INF: " fmt, ## args) |
| |
| /** Print verbose info trace conditionally, depending on the current trace level |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| */ |
| #define BCMOS_TRACE_VERBOSE(fmt, args...) \ |
| BCMOS_TRACE(BCMOS_TRACE_LEVEL_VERBOSE, "VRB: " fmt, ## args) |
| |
| /** Print debug trace conditionally, depending on the current trace level |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| */ |
| #define BCMOS_TRACE_DEBUG(fmt, args...) \ |
| BCMOS_TRACE(BCMOS_TRACE_LEVEL_DEBUG, "DBG: " fmt, ## args) |
| |
| /** Print trace conditionally based on return code and return |
| * \param[in] rc return code |
| * \param[in] fmt printf-like format |
| * \param[in] args printf-like arguments |
| * \returns rc |
| */ |
| #define BCMOS_TRACE_RETURN(rc, fmt, args...) \ |
| do { \ |
| if (rc) \ |
| BCMOS_TRACE_ERR("status:%s :" fmt, bcmos_strerror(rc), ## args); \ |
| else \ |
| BCMOS_TRACE_INFO("success: " fmt, ## args); \ |
| return rc; \ |
| } while (0) |
| |
| #define BCMOS_TRACE_CHECK_RETURN(cond,rc,fmt,args...) \ |
| do { \ |
| if (cond) \ |
| {\ |
| BCMOS_TRACE_ERR( #cond ": status:%s :" fmt, bcmos_strerror(rc), ## args); \ |
| return rc; \ |
| }\ |
| } while (0) |
| #define BCMOS_CHECK_RETURN(cond,err,ret) \ |
| do { \ |
| if (cond) \ |
| {\ |
| BCMOS_TRACE_ERR( #cond ": status:%s\n", bcmos_strerror(err)); \ |
| return ret; \ |
| }\ |
| } while (0) |
| #define BCMOS_CHECK_RETURN_ERROR(cond,err) BCMOS_CHECK_RETURN(cond,err,err) |
| #define BCMOS_RETURN_ON_ERROR(err) BCMOS_CHECK_RETURN(BCM_ERR_OK != err, err, /*this space intentionally left blank*/) |
| #define BCMOS_RETURN_IF_ERROR(err) BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err) |
| |
| /** @} system_trace */ |
| |
| /* |
| * Low level services |
| */ |
| |
| /** \addtogroup system_buf |
| * @{ |
| */ |
| |
| /** Transport/network buffer */ |
| typedef struct bcmos_buf bcmos_buf; |
| |
| /** @} system_buf */ |
| |
| /** Round a number up to the specified power of 2 */ |
| #define BCMOS_ROUND_UP(n, m) (((n) + (m) - 1) & ~((m) - 1)) |
| |
| /** Round a number up to the nearest word multiple */ |
| #define BCMOS_ROUND_TO_WORD(n) BCMOS_ROUND_UP(n, sizeof(size_t)) |
| |
| /* BCMOS_DIVIDE_ROUND_UP(integer_dividend / integer_divisor) == (integer_dividend + integer_divisor - 1) / integer_divisor */ |
| #define BCMOS_DIVIDE_ROUND_UP(n, m) (((n) + (m) - 1) / (m)) |
| |
| #endif /* BCMOS_SYSTEM_COMMON_H_ */ |