blob: da09c1ce11d83260199ee2317197240c76843e61 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#ifndef BCMOS_COMMON_H_
31#define BCMOS_COMMON_H_
32
33#ifndef BCMOS_SYSTEM_H_
34#error Please do not include bcmos_common.h directly. Include bcmos_system.h
35#endif
36
37#include "bcmos_errno.h"
38#include "bcmos_types.h"
39#include "bcmos_queue.h"
40#include "bcmos_tree.h"
41/* Get constants, such as task, module, event id lists */
42#include "bcmos_platform.h"
43#include "bcmos_pack.h"
44#include "bcmos_sysif.h"
45
46#define MAX_TASK_NAME_SIZE 64
47#define MAX_MODULE_NAME_SIZE 64
48#define MAX_MSG_QUEUE_NAME_SIZE 64
49#define MAX_TIMER_NAME_SIZE 64
50#define MAX_POOL_NAME_SIZE 64
51#define MAX_EVENT_NAME_SIZE 64
52#define MAX_MUTEX_NAME_SIZE 64
53#define BCMOS_MSG_POOL_DEFAULT_SIZE 512
54
55/* Define bcmos_bool - the boolean type for bcmos - based on C99 standard boolean type */
56#ifndef BCMOS_BOOLEAN
57typedef _Bool bcmos_bool;
58#define BCMOS_FALSE 0
59#define BCMOS_TRUE 1
60#endif
61
62#define BCM_SIZEOFARRAY(arr) (sizeof(arr)/sizeof(*arr))
63#define BCM_SIZEOFFIELD(s, f) (sizeof(((s*)NULL)->f))
64#define BCM_MEMZERO_STRUCT(ptr) memset(ptr, 0, sizeof(*(ptr)))
65#define BCM_MEMCPY_ARRAY(dst, src) memcpy(dst, src, sizeof(dst))
66#define TAB " "
67#define TAB2 TAB TAB
68#define TAB3 TAB2 TAB
69#define TAB4 TAB2 TAB2
70
71#define CHIP_REVISION_A0 0xA0
72#define CHIP_REVISION_B0 0xB0
73
74#ifdef SIMULATION_BUILD
75#define GET_CHIP_REVISION CHIP_REVISION_A0
76#else
77extern uint32_t chip_revision;
78#define GET_CHIP_REVISION (chip_revision != 0 ? chip_revision : (chip_revision = get_chip_revision()))
79#endif
80
81typedef void (*f_bcmolt_sw_error_handler)(uint8_t pon_id, const char *file_name, uint32_t line_number);
82
83/* Similar to BUG_ON(), with the following features:
84 * 1. The condition is checked against BCM_ERR_OK.
85 * 2. In case on an error, the macro returns from the calling function with the error code. */
86#define BUG_ON_ERR_RET(f) \
87 do \
88 { \
89 bcmos_errno _err; \
90 _err = f; \
91 BUG_ON(_err != BCM_ERR_OK); \
92 return _err; \
93 } \
94 while (0)
95
96/** \addtogroup system_init
97 * @{
98 */
99
100/** Initialize system library
101 * Must be called before any other system function
102 * \returns 0=OK or error code <0
103 */
104bcmos_errno bcmos_init(void);
105
106/** Cleanup system library
107 */
108void bcmos_exit(void);
109
110/** @} system_init */
111
112/** \addtogroup system_mem
113 * @{
114 */
115
116#ifndef BCMOS_MALLOC_FREE_INLINE
117
118/** \defgroup system_heap Default Heap
119 * @{
120 */
121
122/** Allocate memory from the main heap
123 * \param[in] size
124 * \returns memory block pointer or NULL
125 */
126void *bcmos_alloc(uint32_t size);
127
128/** Release memory to the main pool
129 * \param[in] ptr
130 */
131void bcmos_free(void *ptr);
132
133/** @} system_heap */
134
135#endif /* #ifndef BCMOS_MALLOC_FREE_INLINE */
136
137/** \defgroup blk_pool Block Memory Pool
138 * \ingroup system_mem
139 * @{
140 */
141
142/** Block memory pool parameters */
143typedef struct
144{
145 const char *name; /**< Pool name */
146 uint32_t blk_size; /**< Memory block size > 0 */
147 uint32_t num_blks; /**< Number of blocks in the pool. If not set - it is derived from pool_size */
148 void *start; /**< Start address. Can be NULL */
149 uint32_t pool_size; /**< Total pool size in bytes. Only 1 of pool_size, num_blks must be set */
150 uint32_t flags; /**< TBD flags */
151#define BCMOS_BLK_POOL_FLAG_MSG_POOL 0x80000000 /* Used by message pool */
152} bcmos_blk_pool_parm;
153
154/** Block memory pool statistics */
155typedef struct bcmos_blk_pool_stat
156{
157 uint32_t allocated; /**< Number of blocks allocated */
158 uint32_t released; /**< Number of blocks released */
159 uint32_t free; /**< Number of free blocks in the pool */
160 uint32_t alloc_failed; /**< Number of allocation failures */
161} bcmos_blk_pool_stat;
162
163/** Block memory pool info */
164typedef struct bcmos_blk_pool_info
165{
166 bcmos_blk_pool_parm parm; /**< Pool parameters */
167 bcmos_blk_pool_stat stat; /**< Pool statistics */
168} bcmos_blk_pool_info;
169
170/** Block memory pool control block */
171typedef struct bcmos_blk_pool bcmos_blk_pool;
172
173/** Create block memory pool
174 * \param[in,out] pool pool control block
175 * \param[in] parm pool parameters
176 * \returns 0=OK or error code <0
177 */
178bcmos_errno bcmos_blk_pool_create(bcmos_blk_pool *pool, const bcmos_blk_pool_parm *parm);
179
180/** Destroy block memory pool
181 * \param[in] pool pool handle
182 * \returns 0=OK or error code <0
183 */
184bcmos_errno bcmos_blk_pool_destroy(bcmos_blk_pool *pool);
185
186/** Allocate block from block memory pool
187 *
188 * This allocates a single unit (unit_size bytes)
189 * \param[in] pool Pool handle
190 * \return memory block pointer or NULL.
191 * It is guaranteed that the returned pointer is aligned to pointer size
192 */
193void *bcmos_blk_pool_alloc(bcmos_blk_pool *pool);
194
195/** Allocate block from block memory pool and zero the block
196 *
197 * This allocates a single unit (unit_size bytes)
198 * \param[in] pool Pool handle
199 * \return memory block pointer or NULL.
200 * It is guaranteed that the returned pointer is aligned to pointer size
201 */
202void *bcmos_blk_pool_calloc(bcmos_blk_pool *pool);
203
204/** Release memory allocated using bcmos_blk_pool_alloc()
205 *
206 * \param[in] ptr pointer
207 */
208void bcmos_blk_pool_free(void *ptr);
209
210/** Release all blocks in memory pool. Block content is not affected
211 * This function is useful when application wants to pre-initialize
212 * some portion of each memory block at init time
213 *
214 * \param[in] pool Pool handle
215 */
216void bcmos_blk_pool_reset(bcmos_blk_pool *pool);
217
218/** Get pool info
219 *
220 * The pool must be created using bcmos_blk_pool_create()
221 * \param[in] pool Block memory pool handle
222 * \param[out] info Block memory pool info
223 * \returns 0=OK or error code <0
224 */
225bcmos_errno bcmos_blk_pool_query(const bcmos_blk_pool *pool, bcmos_blk_pool_info *info);
226
227/** Block pool iterator
228 * \param[in] prev Previous block pool. *prev==NULL - get first
229 * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
230 */
231bcmos_errno bcmos_blk_pool_get_next(const bcmos_blk_pool **prev);
232
233/** @} blk_pool */
234
235/** \defgroup byte_pool Byte Memory Pool
236 * \ingroup system_mem
237 * @{
238 */
239
240/** Byte memory pool parameters */
241typedef struct
242{
243 const char *name; /**< Pool name */
244 uint32_t size; /**< Pool size (bytes) */
245 void *start; /**< Start address. Can be NULL */
246} bcmos_byte_pool_parm;
247
248/** Byte memory pool control block */
249typedef struct bcmos_byte_pool bcmos_byte_pool;
250
251/** Create byte memory pool
252 * \param[in,out] pool pool control block
253 * \param[in] parm pool parameters
254 * \returns 0=OK or error code <0
255 */
256bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm);
257
258/** Destroy byte memory pool
259 * \param[in] pool pool handle
260 * \returns 0=OK or error code <0
261 */
262bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool);
263
264#ifndef BCMOS_BYTE_POOL_ALLOC_FREE_INLINE
265/** Allocate memory from byte memory pool
266 *
267 * This function can only be used with byte memory pools created
268 * with unit_size==1
269 * \param[in] pool Pool handle
270 * \param[in] size Block size (bytes)
271 * \return memory block pointer or NULL
272 */
273void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size);
274
275/** Release memory allocated using bcmos_pool_byte_alloc()
276 *
277 * \param[in] ptr pointer
278 */
279void bcmos_byte_pool_free(void *ptr);
280
281#endif /* BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */
282
283/** @} byte_pool */
284
285/** @} system_mem */
286
287/** \addtogroup system_task
288 * @{
289 */
290#ifndef BCMOS_WAIT_FOREVER
291#define BCMOS_WAIT_FOREVER 0xFFFFFFFF /**< Wait timeout. Wait forever */
292#endif
293#ifndef BCMOS_NO_WAIT
294#define BCMOS_NO_WAIT 0 /**< Wait timeout. Don't wait */
295#endif
296#define BCMOS_MICROSECONDS_IN_SECONDS (1000000)
297
298/** Task priority */
299typedef enum
300{
301 BCMOS_TASK_PRIORITY_0, /**< Priority 0 - highest */
302 BCMOS_TASK_PRIORITY_1, /**< Priority 1 */
303 BCMOS_TASK_PRIORITY_2, /**< Priority 2 */
304 BCMOS_TASK_PRIORITY_3, /**< Priority 3 */
305 BCMOS_TASK_PRIORITY_4, /**< Priority 4 */
306 BCMOS_TASK_PRIORITY_5, /**< Priority 5 */
307 BCMOS_TASK_PRIORITY_6, /**< Priority 6 */
308 BCMOS_TASK_PRIORITY_7, /**< Priority 7 */
309 BCMOS_TASK_PRIORITY_8, /**< Priority 8 */
310 BCMOS_TASK_PRIORITY_9, /**< Priority 9 */
311 BCMOS_TASK_PRIORITY_10,/**< Priority 10 */
312 BCMOS_TASK_PRIORITY_11,/**< Priority 11 */
313 BCMOS_TASK_PRIORITY_12,/**< Priority 12 */
314 BCMOS_TASK_PRIORITY_13,/**< Priority 13 */
315 BCMOS_TASK_PRIORITY_14,/**< Priority 14 */
316 BCMOS_TASK_PRIORITY_15,/**< Priority 15 */
317 BCMOS_TASK_PRIORITY_16,/**< Priority 16 */
318 BCMOS_TASK_PRIORITY_17,/**< Priority 17 */
319 BCMOS_TASK_PRIORITY_18,/**< Priority 18 */
320 BCMOS_TASK_PRIORITY_19,/**< Priority 19 */
321 BCMOS_TASK_PRIORITY_20,/**< Priority 20 */
322 BCMOS_TASK_PRIORITY_21,/**< Priority 21 */
323 BCMOS_TASK_PRIORITY_22,/**< Priority 22 */
324 BCMOS_TASK_PRIORITY_23,/**< Priority 23 */
325 BCMOS_TASK_PRIORITY_24,/**< Priority 24 */
326 BCMOS_TASK_PRIORITY_25,/**< Priority 25 */
327 BCMOS_TASK_PRIORITY_26,/**< Priority 26 */
328 BCMOS_TASK_PRIORITY_27,/**< Priority 27 */
329 BCMOS_TASK_PRIORITY_28,/**< Priority 28 */
330 BCMOS_TASK_PRIORITY_29,/**< Priority 29 */
331 BCMOS_TASK_PRIORITY_30,/**< Priority 30 */
332 BCMOS_TASK_PRIORITY_31,/**< Priority 31 - lowest */
333} bcmos_task_priority;
334
335/** Task handler */
336typedef int (*F_bcmos_task_handler)(long data);
337
338/* Default task handler */
339extern int bcmos_dft_task_handler(long data);
340
341/* This flags determines whether a task is to be suspended upon OOPS condition. */
342#define BCMOS_TASK_FLAG_NO_SUSPEND_ON_OOPS (1 << 0)
343
344/** Task parameters */
345typedef struct
346{
347 const char *name; /**< Task name */
348 bcmos_task_priority priority; /**< Task priority */
349 bcmos_core core; /**< CPU core the task is locked to */
350 uint32_t stack_size; /**< Task stack size */
351 void *stack; /**< Stack location. NULL=allocate automatically */
352 F_bcmos_task_handler init_handler; /**< Optional "init" handler. Called once in the task context when it is created.
353 This callback is only supported in integration mode (handler==NULL).
354 init_handler returns bcmos_errno. If it returns value other than BCM_ERR_OK,
355 the task is destroyed */
356 F_bcmos_task_handler handler; /**< Task handler. NULL=default (integration mode) */
357 F_bcmos_task_handler timeout_handler;/**< This function is used only in integration mode (handler==NULL) if
358 msg_wait_timeout is > 0. It is called if there were no messages for the task
359 for longer than msg_wait_timeout us.
360 If timeout handler returns value other than BCM_ERR_OK, task terminates.
361 */
362 uint32_t msg_wait_timeout; /**< This parameter is used only in integration mode (handler==NULL) together with
363 timeout_handler. If > 0 and there were no messages for longer than
364 msg_wait_timeout us, timeout_handler is called.
365 */
366 long data; /**< Data passed to the task handler */
367 uint32_t flags; /**< flags */
368} bcmos_task_parm;
369
370/** Task control block */
371typedef struct bcmos_task bcmos_task;
372
373/** Create a new task
374 *
375 * \param[in,out] task Task control block
376 * \param[in] parm Task parameters
377 * \returns 0=OK or error code <0
378 */
379bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm);
380
381/** Set task timeout
382 *
383 * This function is only used in integration mode (handler==NULL).
384 * It sets max time the default task handler waits for message directed to one of the
385 * task's modules.
386 *
387 * \param[in,out] task Task control block
388 * \param[in] timeout Max time (us) to wait for messages. 0=FOREVER
389 * Changing timeout from infinite to finite only takes effect
390 * after message is received by any task module.
391 * \param[in] timeout_handler Handler to be called upon timeout. Must be != NULL if timeout > 0.
392 * If the handler returns error (!= BCM_ERR_OK), task terminates.
393 * \returns 0=OK or error code <0
394 */
395bcmos_errno bcmos_task_timeout_set(bcmos_task *task, uint32_t timeout, F_bcmos_task_handler timeout_handler);
396
397/** Destroy task
398 *
399 * \param[in] task Task handle
400 * \returns 0=OK or error code <0
401 */
402bcmos_errno bcmos_task_destroy(bcmos_task *task);
403
404/** Get current task
405 * \returns task handle or NULL if not in task context
406 */
407bcmos_task *bcmos_task_current(void);
408
409/** Query task info
410 * \param[in] task Task control block
411 * \param[out] parm Task parameters
412 * \returns 0=OK or error code <0
413 */
414bcmos_errno bcmos_task_query(const bcmos_task *task, bcmos_task_parm *parm);
415
416/** Task iterator
417 * \param[in] prev Previous task. *prev==NULL - get first
418 * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
419 */
420bcmos_errno bcmos_task_get_next(bcmos_task **prev);
421
422
423/** @} system_task */
424
425/** \addtogroup system_msg
426 * @{
427 */
428
429/** Message header */
430typedef struct bcmos_msg bcmos_msg;
431
432/** Message queue control block */
433typedef struct bcmos_msg_queue bcmos_msg_queue;
434
435/** Message queue group control block */
436typedef struct bcmos_msg_qgroup bcmos_msg_qgroup;
437
438#if defined(BCMOS_MSG_QUEUE_DOMAIN_SOCKET) || defined(BCMOS_MSG_QUEUE_UDP_SOCKET) || defined(BCMOS_MSG_QUEUE_USER_DEFINED)
439#define BCMOS_MSG_QUEUE_REMOTE_SUPPORT
440#endif
441
442/** Message queue endpoint type */
443typedef enum
444{
445 BCMOS_MSG_QUEUE_EP_LOCAL, /**< Local endpoint (inter-thread communication) */
446#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
447 BCMOS_MSG_QUEUE_EP_DOMAIN_SOCKET, /**< Domain-socket based endpoint */
448#endif
449#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
450 BCMOS_MSG_QUEUE_EP_UDP_SOCKET, /**< UDP socket-based endpoint */
451#endif
452#ifdef BCMOS_MSG_QUEUE_USER_DEFINED
453 BCMOS_MSG_QUEUE_EP_USER_DEFINED /**< User-defined endpoint */
454#endif
455} bcmos_msg_queue_ep_type;
456
457
458/** Message queue parameters */
459typedef struct
460{
461 const char *name; /**< Queue name (for logging and debugging) */
462 uint32_t size; /**< Max queue size. 0=unlimited */
463 uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */
464 uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */
465 uint32_t flags; /**< TBD flags. For example, single-core, m-core */
466 void (*notify)(bcmos_msg_queue *q, const char *txt); /***< Called when queue congestion state changes */
467 bcmos_msg_queue_ep_type ep_type; /**< Queue endpoint type */
468
469#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
470 /* Remote message queue support allows queue endpoints to be located in
471 * different processes or even processors.
472 */
473 const char *local_ep_address; /**< Queue local endpoint address */
474 const char *remote_ep_address; /**< Queue local endpoint address */
475
476 uint32_t max_mtu; /**< Max MTU size */
477#define BCMOS_MSG_QUEUE_DEFAULT_MAX_MTU (64*1024)
478
479 /** Optional "pack" callback. Not needed if 2 processes are on the same core. */
480 bcmos_errno (*pack)(bcmos_msg_queue *queue, bcmos_msg *msg, uint8_t **buf, uint32_t *buf_length);
481
482 /** Optional "unpack" callback. Not needed if 2 processes are on the same core. */
483 bcmos_errno (*unpack)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length, bcmos_msg **msg);
484
485 /** Optional callback that releases packed buffer */
486 void (*free_packed)(bcmos_msg_queue *queue, uint8_t *buf);
487
488 /** Optional "open" callback. Must be set for user-defined queue, NULL otherwise */
489 bcmos_errno (*open)(bcmos_msg_queue *queue);
490
491 /** Optional "close" callback. Must be set for user-defined queue, NULL otherwise */
492 bcmos_errno (*close)(bcmos_msg_queue *queue);
493
494 /** Optional "send" callback. Must be set for user-defined queue, NULL otherwise */
495 bcmos_errno (*send)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length);
496
497 /** Optional "recv" callback. Must be set for user-defined queue, NULL otherwise */
498 bcmos_errno (*recv)(bcmos_msg_queue *queue, uint32_t timeout, uint8_t **buf, uint32_t *buf_length);
499#endif
500
501} bcmos_msg_queue_parm;
502
503/** Message queue statistics */
504typedef struct
505{
506 uint32_t msg_in; /**< Number of messages currently in the queue */
507 uint32_t msg_sent; /**< Number of messages successfully submitted into the queue */
508 uint32_t msg_received; /**< Number of messages received from the queue */
509 uint32_t msg_discarded; /**< Number of messages discarded because of queue overflow */
510 uint32_t msg_almost_full; /**< Number of messages submitted to queue when it was above high water mark */
511 bcmos_bool is_congested; /**< True=the queue is currently congested */
512} bcmos_msg_queue_stat;
513
514/** Message queue info */
515typedef struct
516{
517 bcmos_msg_queue_parm parm; /**< Queue parameters */
518 bcmos_msg_queue_stat stat; /**< Queue statistics */
519} bcmos_msg_queue_info;
520
521/** Message priority in queue group */
522typedef uint32_t bcmos_qgroup_prty;
523
524/** Message queue group parameters */
525typedef struct
526{
527 const char *name; /**< Queue group name (for logging and debugging) */
528 bcmos_qgroup_prty nqueues; /**< Number of queues in the group */
529 uint32_t size; /**< Total number of messages that can be stored in queue group. 0=unlimited */
530 uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */
531 uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */
532 uint32_t flags; /**< TBD flags. For example, single-core, m-core */
533 void (*notify)(bcmos_msg_qgroup *qgrp, const char *txt); /***< Called when queue group congestion state changes */
534} bcmos_msg_qgroup_parm;
535
536/** Message queue group info */
537typedef struct
538{
539 bcmos_msg_qgroup_parm parm; /**< Queue group parameters */
540 bcmos_msg_queue_stat stat; /**< Queue group statistics */
541} bcmos_msg_qgroup_info;
542
543/** Message recipient instance (e.g., optical link id) */
544typedef uint16_t bcmos_msg_instance;
545
546/** Message send flags */
547typedef enum
548{
549 BCMOS_MSG_SEND_AUTO_FREE = 0x00000000, /**< Automatically release message in case of error. This is the default behaviour */
550 BCMOS_MSG_SEND_NO_FREE_ON_ERROR =0x00000001,/**< Do NOT free message in case of transmit error */
551 BCMOS_MSG_SEND_URGENT = 0x00000002, /**< Urgent message */
552 BCMOS_MSG_SEND_NOLIMIT = 0x00000004, /**< Ignore destination queue size limit */
553} bcmos_msg_send_flags;
554
555/** Registered message handler */
556typedef void (*F_bcmos_msg_handler)(bcmos_module_id module_id, bcmos_msg *msg);
557typedef bcmos_errno (*F_bcmos_module_init)(long data);
558typedef void (*F_bcmos_module_exit)(long data);
559
560/** Message header */
561struct bcmos_msg
562{
563 bcmos_msg_id type; /**< Message type */
564 bcmos_msg_instance instance;/**< Message recipient instance (e.g., optical link id) */
565 F_bcmos_msg_handler handler;/**< Message handler. Can be set by the sender or message dispatcher */
566 bcmos_module_id sender; /**< Sender module */
567 STAILQ_ENTRY(bcmos_msg) next; /**< Next message pointer */
568 void *data; /**< Message data pointer */
569 void *start; /**< Message data block start (for release) */
570 uint32_t size; /**< Message data size */
571 bcmos_msg_send_flags send_flags; /**< Flags the message was sent with */
572#define BCMOS_MSG_QUEUE_SIZE_UNLIMITED 0xFFFFFFFF /**< Unlimited queue */
573 void (*release)(bcmos_msg *); /**< Release callback */
574 void (*data_release)(bcmos_msg *); /**< Data release callback. Used when message is released to message pool */
575};
576
577/* Helper functions that pack / unpack message header for IPC */
578#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
579
580/** Size of message header on the line for IPC */
581#define BCMOS_MSG_HDR_SIZE 8
582
583void bcmos_msg_hdr_pack(const bcmos_msg *msg, uint8_t *buf, uint32_t data_size);
584void bcmos_msg_hdr_unpack(const uint8_t *buf, bcmos_msg *msg);
585
586#endif
587
588/** Create message queue.
589 *
590 * This function can be called explicitly in "traditional" mode
591 * or implicitly by bcmos_module_create().
592 * \param[in,out] queue Queue control block
593 * \param[in] parm Queue parameters
594 * \returns 0=OK or error code <0
595 */
596bcmos_errno bcmos_msg_queue_create(bcmos_msg_queue *queue, const bcmos_msg_queue_parm *parm);
597
598/** Destroy queue
599 *
600 * \param[in] queue Queue handle
601 * \returns 0=OK or error code <0
602 */
603bcmos_errno bcmos_msg_queue_destroy(bcmos_msg_queue *queue);
604
605/** Get queue info
606 *
607 * \param[in] queue Queue handle
608 * \param[out] info Queue information
609 * \returns 0=OK or error code <0
610 */
611bcmos_errno bcmos_msg_queue_query(const bcmos_msg_queue *queue, bcmos_msg_queue_info *info);
612
613/** Message queue iterator
614 * \param[in] prev Previous queue. *prev==NULL - get first
615 * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
616 */
617bcmos_errno bcmos_msg_queue_get_next(const bcmos_msg_queue **prev);
618
619/** Create message queue group.
620 *
621 * Queue group contains configurable number of queues. The queues are drained
622 * in strict priority. Priority 0 is the highest.
623 *
624 * \param[in,out] qgroup Queue group control block
625 * \param[in] parm Queue group parameters
626 * \returns 0=OK or error code <0
627 */
628bcmos_errno bcmos_msg_qgroup_create(bcmos_msg_qgroup *qgroup, const bcmos_msg_qgroup_parm *parm);
629
630/** Destroy queue group
631 *
632 * \param[in] qgroup Queue group handle
633 * \returns 0=OK or error code <0
634 */
635bcmos_errno bcmos_msg_qgroup_destroy(bcmos_msg_qgroup *qgroup);
636
637/** Get queue group info
638 *
639 * \param[in] qgroup Queue group handle
640 * \param[out] info Queue group information
641 * \returns 0=OK or error code <0
642 */
643bcmos_errno bcmos_msg_qgroup_query(const bcmos_msg_qgroup *qgroup, bcmos_msg_qgroup_info *info);
644
645/** Message queue group iterator
646 * \param[in] prev Previous queue group. *prev==NULL - get first
647 * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
648 */
649bcmos_errno bcmos_msg_qgroup_get_next(const bcmos_msg_qgroup **prev);
650
651/** Send message to queue
652 *
653 * \param[in] queue Queue handle
654 * \param[in] msg Message
655 * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
656 *
657 * msg is released automatically regardless of bcmos_msg_send() outcome, unless
658 * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
659 *
660 * \returns 0=OK or error code <0
661 */
662bcmos_errno bcmos_msg_send(bcmos_msg_queue *queue, bcmos_msg *msg, bcmos_msg_send_flags flags);
663
664/** Send message to module
665 *
666 * For module to be able to receive the message, it must be registered
667 * using bcmos_msg_register()
668 *
669 * \param[in] module_id Module id
670 * \param[in] msg Message. msg->handler must be set
671 * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
672 *
673 * msg is released automatically regardless of bcmos_msg_send_to_module() outcome, unless
674 * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
675 *
676 * \returns 0=OK or error code <0
677 */
678bcmos_errno bcmos_msg_send_to_module(bcmos_module_id module_id, bcmos_msg *msg, bcmos_msg_send_flags flags);
679
680/** Send message to queue group
681 *
682 * \param[in] qgroup Queue group handle
683 * \param[in] msg Message
684 * \param[in] prty Message priority in range 0-nqueues_in_group-1.
685 * 0 priority is the highest. If MAX number of messages are already queues
686 * in the queue group, sending message can leave to discard of the head message
687 * queued at lower priority
688 * \param[in] flags BCMOS_MSG_SEND_AUTO_FREE or BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag
689 *
690 *
691 * msg is released automatically regardless of bcmos_msg_send_to_qgroup() outcome, unless
692 * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
693 *
694 * \returns 0=OK or error code <0
695 */
696bcmos_errno bcmos_msg_send_to_qgroup(bcmos_msg_qgroup *qgroup, bcmos_msg *msg, bcmos_qgroup_prty prty,
697 bcmos_msg_send_flags flags);
698
699/** Get message from the head of message queue
700 *
701 * The function can lead to the calling task being suspended for a period
702 * of time or indefinitely, until message is submitted to the queue.\n
703 * The function is only used in "traditional tasks" (see \ref system_model).
704 *
705 * \param[in] queue Queue handle
706 * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
707 * \param[out] msg Message handle
708 * \returns 0=OK or error code <0
709 */
710bcmos_errno bcmos_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, bcmos_msg **msg);
711
712/** Get highest priority message from queue group
713 *
714 * The function can lead to the calling task being suspended for a period
715 * of time or indefinitely, until message is submitted to the queue group.\n
716 * The function is only used in "traditional tasks" (see \ref system_model).
717 *
718 * \param[in] qgroup Queue group handle
719 * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
720 * \param[out] msg Message handle
721 * \returns 0=OK or error code <0
722 */
723bcmos_errno bcmos_msg_recv_from_qgroup(bcmos_msg_qgroup *qgroup, uint32_t timeout, bcmos_msg **msg);
724
725/** Dispatch message. Send to module that registered for it.
726 *
727 * The message must be registered using bcmos_msg_register()
728 *
729 * This function should be used if the message sender doesn't know the target module and/or
730 * message handling callback.
731 *
732 * \param[in] msg Message handle
733 * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
734 *
735 * msg is released automatically regardless of bcmos_msg_dispatch() outcome, unless
736 * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
737 *
738 * \returns 0=OK or error code <0
739 */
740bcmos_errno bcmos_msg_dispatch(bcmos_msg *msg, bcmos_msg_send_flags flags);
741
742/** Register message for "push-mode" delivery.
743 *
744 * When registered message is sent to the target module and
745 * the module's task wakes up, message handler is called in the module's context.
746 *
747 * \param[in] msg_type Message type
748 * \param[in] instance Message type instance
749 * \param[in] module_id Target module id
750 * \param[in] handler Message handler
751 * \returns 0=OK or error code <0
752 */
753bcmos_errno bcmos_msg_register(bcmos_msg_id msg_type, bcmos_msg_instance instance,
754 bcmos_module_id module_id, F_bcmos_msg_handler handler);
755
756/** Un-register message registered by bcmos_msg_register()
757 *
758 * \param[in] msg_type Message type
759 * \param[in] instance Message type instance
760 * \param[in] module_id Target module id
761 * \returns 0=OK or error code <0
762 */
763bcmos_errno bcmos_msg_unregister(bcmos_msg_id msg_type, bcmos_msg_instance instance,
764 bcmos_module_id module_id);
765
766/** Put the OS message infrastructure in "shutdown mode".
767 *
768 * When in shutdown mode, bcmos_msg_dispatch() will return BCM_ERR_OK instead of BCM_ERR_NOENT when a handler is not
769 * found for the message. Additionally, bcmos_msg_dispatch() becomes safe to call concurrently with
770 * bcmos_msg_unregister() (this is not true in normal operation).
771 *
772 * \param[in] shutdown_mode Whether or not to enable shutdown mode
773 */
774void bcmos_msg_shutdown_mode_set(bcmos_bool shutdown_mode);
775
776/** Gets whether or not the OS message infrastructure is currently in "shutdown mode".
777 * \returns BCMOS_TRUE if we are in shutdown mode, BCMOS_FALSE otherwise
778 */
779bcmos_bool bcmos_msg_shutdown_mode_get(void);
780
781/** Helper type for storing message types alongside their handlers. */
782typedef struct
783{
784 bcmos_msg_id msg_type;
785 F_bcmos_msg_handler handler;
786} bcmos_msg_id2handler;
787
788/** Message pool */
789typedef struct bcmos_msg_pool bcmos_msg_pool;
790
791/** Message pool parameters */
792typedef struct bcmos_msg_pool_parm
793{
794 const char *name; /**< Pool name */
795 uint32_t size; /**< Number of messages in the pool */
796 uint32_t data_size; /**< Message data size */
797 uint32_t flags; /**< TBD flags */
798 void (*data_release)(bcmos_msg *msg); /**< Optional data release callback. Called when message is released to the pool */
799} bcmos_msg_pool_parm;
800
801/** Message pool statistics */
802typedef bcmos_blk_pool_stat bcmos_msg_pool_stat;
803
804/** Message pool info */
805typedef struct bcmos_msg_pool_info
806{
807 bcmos_msg_pool_parm parm; /**< Pool parameters */
808 bcmos_msg_pool_stat stat; /**< Pool statistics */
809} bcmos_msg_pool_info;
810
811/** Create message pool
812 *
813 * Create pool containing pre-allocated messages with specified data size
814 * \param[in] pool Message pool handle
815 * \param[in] parm Message pool parameters
816 * \returns 0=OK or error code <0
817 */
818bcmos_errno bcmos_msg_pool_create(bcmos_msg_pool *pool, const bcmos_msg_pool_parm *parm);
819
820/** Destroy message pool
821 *
822 * All messages must be released to the pool before it can be destroyed.
823 *
824 * \param[in] pool Message pool handle
825 * \returns 0=OK or error code <0
826 */
827bcmos_errno bcmos_msg_pool_destroy(bcmos_msg_pool *pool);
828
829/** Allocate message from pool
830 *
831 * The pool must be created using bcmos_pool_create()
832 * \param[in] pool Message pool handle
833 * \returns msg pointer or NULL if the pool is empty.
834 * "data" and "release" fields in the returned message are pre-set
835 * Once no longer needed, the message must be released using bcmos_msg_free()
836 */
837bcmos_msg *bcmos_msg_pool_alloc(bcmos_msg_pool *pool);
838
839/** Allocate message from pool and clear data
840 *
841 * The pool must be created using bcmos_pool_create()
842 * \param[in] pool Message pool handle
843 * \returns msg pointer or NULL if the pool is empty.
844 * "data" and "release" fields in the returned message are pre-set
845 * Once no longer needed, the message must be released using bcmos_msg_free()
846 */
847static inline bcmos_msg *bcmos_msg_pool_calloc(bcmos_msg_pool *pool)
848{
849 bcmos_msg *msg = bcmos_msg_pool_alloc(pool);
850 if (msg)
851 {
852 memset(msg->data, 0, msg->size);
853 }
854 return msg;
855}
856
857/** Get pool info
858 *
859 * The pool must be created using bcmos_pool_create()
860 * \param[in] pool Message pool handle
861 * \param[out] info Message pool info
862 * \returns 0=OK or error code <0
863 */
864bcmos_errno bcmos_msg_pool_query(const bcmos_msg_pool *pool, bcmos_msg_pool_info *info);
865
866/** Message pool iterator
867 * \param[in] prev Previous message pool. *prev==NULL - get first
868 * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
869 */
870bcmos_errno bcmos_msg_pool_get_next(const bcmos_msg_pool **prev);
871
872/** @} system_msg */
873
874/** \addtogroup system_module
875 * @{
876 */
877
878/** Max number of modules per task. Must be <= 32 */
879#define BCMOS_MAX_MODULES_PER_TASK 8
880
881/** Module parameters */
882typedef struct
883{
884 bcmos_msg_queue_parm qparm; /**< Message queue paramaters */
885 F_bcmos_module_init init; /**< Init callback */
886 F_bcmos_module_exit exit; /**< Exit callback */
887 long data; /**< Module context initial value. Also passed to init and exit callbacks */
888} bcmos_module_parm;
889
890/** Module control block */
891typedef struct bcmos_module bcmos_module;
892
893/** Register module
894 *
895 * \param[in] module_id Module id
896 * \param[in] task Owner task ID
897 * \param[in] parm Module parameters
898 * \returns 0=OK or error code <0
899 */
900bcmos_errno bcmos_module_create(bcmos_module_id module_id, bcmos_task *task, bcmos_module_parm *parm);
901
902/** Un-register module
903 *
904 * \param[in] module_id Module id
905 * \returns 0=OK or error code <0
906 */
907bcmos_errno bcmos_module_destroy(bcmos_module_id module_id);
908
909/** Get current module id in the current task
910 *
911 * \returns module_id
912 */
913bcmos_module_id bcmos_module_current(void);
914
915/** Get module context
916 *
917 * Module context is initialized as module_parm.data and can be modified using
918 * bcmos_module_context_set()
919 *
920 * \param[in] module_id Module_id
921 * \returns context pointer set by bcmos_module_context_set() or
922 *
923 * NULL if module_id is invalid or context is not set.
924 */
925void *bcmos_module_context(bcmos_module_id module_id);
926
927/** Set module context
928 *
929 * Context is an arbitrary structure used to store module-specific data.
930 * Usually this function is called from module init() callback
931 *
932 * \param[in] module_id Module_id
933 * \param[in] context Module context pointer
934 * \returns 0=OK or error code <0
935 */
936bcmos_errno bcmos_module_context_set(bcmos_module_id module_id, void *context);
937
938/* module control blocks */
939extern bcmos_module *bcmos_modules[BCMOS_MODULE_ID__NUM_OF];
940
941static inline bcmos_module *_bcmos_module_get(bcmos_module_id module_id)
942{
943 bcmos_module *module = bcmos_modules[module_id];
944 if ((unsigned)module_id >= BCMOS_MODULE_ID__NUM_OF)
945 return NULL;
946 return module;
947}
948
949/** Query module
950 *
951 * \param[in] module_id Module_id
952 * \param[out] task Task that owns the module
953 * \param[out] info Module queue info
954 * \returns 0=OK or error code <0
955 */
956bcmos_errno bcmos_module_query(bcmos_module_id module_id, const bcmos_task **task, bcmos_msg_queue_info *info);
957
958/** @} system_module */
959
960/** \addtogroup system_event
961 * @{
962 */
963
964/** Registered event handler */
965typedef void (*F_bcmos_event_handler)(bcmos_event_id event_id, uint32_t active_bits);
966
967/** Event parameters */
968typedef struct
969{
970 const char *name; /**< Event set name */
971 bcmos_module_id module_id; /**< Module id. The module must be registered */
972 uint32_t mask; /**< Event bits module is interested in */
973 F_bcmos_event_handler handler; /**< Event handler. Called in module's context */
974 uint32_t flags; /**< TBD flags. E.g., inter-core */
975} bcmos_event_parm;
976
977/** Event control block */
978typedef struct bcmos_event bcmos_event;
979
980/** Create event set
981 *
982 * \param[in] event_id Event set id
983 * \param[in] parm Event parameters. Used in "integration" mode. NULL in "traditional" mode
984 * \returns 0=OK or error code <0
985 */
986bcmos_errno bcmos_event_create(bcmos_event_id event_id, bcmos_event_parm *parm);
987
988/** Destroy event set created by bcmos_event_create()
989 *
990 * \param[in] event_id Event set id
991 * \returns 0=OK or error code <0
992 */
993bcmos_errno bcmos_event_destroy(bcmos_event_id event_id);
994
995/** Raise event
996 *
997 * Raised event is delivered to module(s) that registered for it
998 * using bcmos_event_register() or to the task waiting for event
999 * using bcmos_event_recv()
1000 *
1001 * \param[in] event_id Event set id
1002 * \param[in] active_bits Active bit mask
1003 * \returns 0=OK or error code <0. Can only fail if event is not registered
1004 */
1005bcmos_errno bcmos_event_raise(bcmos_event_id event_id, uint32_t active_bits);
1006
1007/** Wait for event
1008 *
1009 * This function is used in "traditional" mode.\n
1010 * The caller can block for a time or indefinitely
1011 *
1012 * \param[in] event_id Event set id
1013 * \param[in] mask Interesting bits. The functions returns when
1014 * - timeout expires
1015 * - event with (active_bits & mask) != 0 is raised
1016 * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
1017 * \param[out] active_bits active bits in the event set. valid only if the function returns 0
1018 * \returns 0=OK or error code <0
1019 */
1020bcmos_errno bcmos_event_recv(bcmos_event_id event_id, uint32_t mask,
1021 uint32_t timeout, uint32_t *active_bits);
1022
1023/* Event set array */
1024extern bcmos_event *bcmos_events[BCMOS_EVENT_ID__NUM_OF];
1025
1026/* Get event givern the event id */
1027static inline bcmos_event *_bcmos_event_get(bcmos_event_id event_id)
1028{
1029 bcmos_event *ev = bcmos_events[event_id];
1030 if ((unsigned)event_id >= BCMOS_EVENT_ID__NUM_OF)
1031 return NULL;
1032 return ev;
1033}
1034
1035/** @} system_event */
1036
1037/** \addtogroup system_timer
1038 * @{
1039 */
1040
1041/** Max timer duration (us) */
1042#define BCMOS_MAX_TIMER_DURATION 0x80000000
1043
1044/** Timer control block */
1045typedef struct bcmos_timer bcmos_timer;
1046
1047/** Timer handler completion code */
1048typedef enum
1049{
1050 BCMOS_TIMER_OK, /**< Restart timer if periodic or keep stopped if not */
1051 BCMOS_TIMER_STOP /**< Do not restart periodic timer */
1052} bcmos_timer_rc;
1053
1054/** Timer handler
1055 * \param[in] timer Expired timer handle
1056 * \param[in] data User data supplied at timer creation time
1057 * \returns \ref bcmos_timer_rc
1058 */
1059typedef bcmos_timer_rc (*F_bcmos_timer_handler)(bcmos_timer *timer, long data);
1060
1061typedef enum
1062{
1063 BCMOS_TIMER_PARM_FLAGS_URGENT = 0, /**< Default behavior. If the timer owner is set, timer expiration
1064 will be delivered as an urgent message. */
1065 BCMOS_TIMER_PARM_FLAGS_NON_URGENT = 1 << 0, /**< If the timer owner is set, timer expiration will be delivered as
1066 a normal (non-urgent) message. */
1067} bcmos_timer_parm_flags;
1068
1069/** Timer parameters */
1070typedef struct
1071{
1072 const char *name; /**< Timer name */
1073 bcmos_module_id owner; /**< Timer owner. If set, timer expiration is delivered to the module
1074 as a message */
1075 bcmos_bool periodic; /**< TRUE=periodic */
1076 F_bcmos_timer_handler handler; /**< Timer handler. Called in context of owner module
1077 if set or timer ISR if owner==BCMOS_MODULE_ID_NONE */
1078 long data; /**< data to pass to the handler */
1079 bcmos_timer_parm_flags flags; /**< Flags to change the behavior of the timer */
1080} bcmos_timer_parm;
1081
1082#ifndef BCMOS_TIMESTAMP_INLINE
1083
1084/** Get current timestamp
1085 * \returns the current system timestamp (us)
1086 */
1087uint32_t bcmos_timestamp(void);
1088
1089/** Get current 64 bit timestamp
1090 * \returns the current system timestamp (us)
1091 * \note There is no guarantee that all 64 bit carry information.
1092 * However, it is guaranteed that the timestamp wraps around
1093 * not oftener than every 50 days (ms resolution)
1094 */
1095uint64_t bcmos_timestamp64(void);
1096
1097#endif /* #ifndef BCMOS_TIMESTAMP_INLINE */
1098
1099/** Create timer
1100 *
1101 * \param[in,out] timer timer control block
1102 * \param[in] parm timer parameters
1103 * \returns 0=OK or error code <0
1104 */
1105bcmos_errno bcmos_timer_create(bcmos_timer *timer, bcmos_timer_parm *parm);
1106
1107/** Destroy timer
1108 * The timer is stopped if running and destroyed
1109 * \param[in] timer timer handle
1110 */
1111void bcmos_timer_destroy(bcmos_timer *timer);
1112
1113/** Set timer handler
1114 *
1115 * \param[in,out] timer timer control block
1116 * \param[in] handler timer handler
1117 * \param[in] data data to be passed to the handler
1118 * \returns 0=OK or error code <0
1119 */
1120bcmos_errno bcmos_timer_handler_set(bcmos_timer *timer, F_bcmos_timer_handler handler, long data);
1121
1122/** (Re)start timer
1123 * Stop timer if running and start it.
1124 *
1125 * \param[in] timer timer handle
1126 * \param[in] delay delay in us
1127 */
1128void bcmos_timer_start(bcmos_timer *timer, uint32_t delay);
1129
1130/** Stop timer if running
1131 *
1132 * \param[in] timer timer handle
1133 */
1134void bcmos_timer_stop(bcmos_timer *timer);
1135
1136/** Suspend current task for a time
1137 *
1138 * \param[in] us sleep time (us)
1139 */
1140#ifndef BCMOS_USLEEP_INLINE
1141void bcmos_usleep(uint32_t us);
1142#endif /* #ifndef BCMOS_USLEEP_INLINE */
1143
1144/** @} system_timer */
1145
1146/** \addtogroup system_fastlock
1147 * @{
1148 */
1149
1150/** Fast lock control block */
1151typedef struct bcmos_fastlock bcmos_fastlock;
1152
1153#ifndef BCMOS_FASTLOCK_INLINE
1154
1155/** Init fastlock
1156 * \param[in, out] lock fast lock control block
1157 * \param[in] flags flags - TBD. E.g., single core / SMP
1158 */
1159void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags);
1160
1161/** Take fast lock
1162 * \param[in] lock fast lock
1163 * \returns value of interrupt flags that should be used in unlock
1164 */
1165long bcmos_fastlock_lock(bcmos_fastlock *lock);
1166
1167/** Release fast lock
1168 * \param[in] lock fast lock
1169 * \param[in] flags interrupt flags
1170 */
1171void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags);
1172
1173#endif /* #ifndef BCMOS_FASTLOCK_INLINE */
1174
1175/** @} system_fastlock */
1176
1177/** \addtogroup system_mutex
1178 * @{
1179 */
1180
1181/** Mutex control block */
1182typedef struct bcmos_mutex bcmos_mutex;
1183
1184#ifdef BCMOS_MUTEX_INLINE
1185#define BCMOS_MUTEX_CREATE_DESTROY_INLINE
1186#define BCMOS_MUTEX_LOCK_UNLOCK_INLINE
1187#endif
1188
1189#ifndef BCMOS_MUTEX_CREATE_DESTROY_INLINE
1190
1191/** Create recursive mutex
1192 * \param[in, out] mutex Mutex control block
1193 * \param[in] flags flags - TBD. E.g., single core / SMP
1194 * \param[in] name name of the mutex (if OS supports), NULL means it will be auto-generated
1195 * \returns 0=OK or error code <0
1196 */
1197bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name);
1198
1199/** Destroy mutex
1200 * \param[in] mutex Mutex control block
1201 */
1202void bcmos_mutex_destroy(bcmos_mutex *mutex);
1203
1204#endif /* BCMOS_MUTEX_CREATE_DESTROY_INLINE */
1205
1206
1207#ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE
1208
1209/** Lock mutex
1210 * \param[in] mutex Mutex control block
1211 */
1212void bcmos_mutex_lock(bcmos_mutex *mutex);
1213
1214/** Release mutex
1215 * \param[in] mutex Mutex control block
1216 */
1217void bcmos_mutex_unlock(bcmos_mutex *mutex);
1218
1219#endif /* #ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE */
1220
1221/** @} system_mutex */
1222
1223/** \addtogroup system_sem
1224 * @{
1225 */
1226
1227/** Semaphore control block */
1228typedef struct bcmos_sem bcmos_sem;
1229
1230#ifdef BCMOS_SEM_INLINE
1231#define BCMOS_SEM_CREATE_DESTROY_INLINE
1232#define BCMOS_SEM_WAIT_INLINE
1233#define BCMOS_SEM_POST_INLINE
1234#endif
1235
1236#ifndef BCMOS_SEM_CREATE_DESTROY_INLINE
1237
1238/** Create semaphore
1239 * \param[in, out] sem semaphore control block
1240 * \param[in] count initial value of semaphore counter
1241 * \param[in] flags flags - TBD. E.g., single core / SMP
1242 * \param[in] name name of the semaphore (if OS supports), NULL means it will be auto-generated
1243 * \returns 0=OK or error code <0
1244 */
1245bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name);
1246
1247/** Destroy semaphore
1248 * \param[in] sem semaphore control block
1249 */
1250void bcmos_sem_destroy(bcmos_sem *sem);
1251
1252#endif /* BCMOS_SEM_CREATE_DESTROY_INLINE */
1253
1254#ifndef BCMOS_SEM_WAIT_INLINE
1255
1256/** Decrement semaphore counter. Wait if the counter is 0
1257 *
1258 * \param[in] sem semaphore control block
1259 * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
1260 * \returns 0=OK or error code <0
1261 */
1262bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout);
1263
1264#endif /* #ifndef BCMOS_SEM_WAIT_INLINE */
1265
1266#ifndef BCMOS_SEM_POST_INLINE
1267/** Increment semaphore counter
1268 * \param[in] sem semaphore control block
1269 */
1270void bcmos_sem_post(bcmos_sem *sem);
1271
1272#endif /* #ifndef BCMOS_SEM_POST_INLINE */
1273
1274/** @} system_sem */
1275
1276/*
1277 * print support
1278 */
1279
1280/** Print cloning/redirection mode */
1281typedef enum
1282{
1283 BCMOS_PRINT_REDIRECT_MODE_NONE, /**< No cloning, redirection */
1284 BCMOS_PRINT_REDIRECT_MODE_REDIRECT, /**< Redirect console output. Do not print on the serial console */
1285 BCMOS_PRINT_REDIRECT_MODE_CLONE /**< Clone console output to redirection callback */
1286} bcmos_print_redirect_mode;
1287
1288/** Print re-direction/cloning callback */
1289typedef int (*bcmos_print_redirect_cb)(void *data, const char *format, va_list ap);
1290
1291/** Set up print redirection/cloning
1292 * \param[in] mode redirection/cloning mode
1293 * \param[in] cb redirection callback
1294 * \param[in] data opaque data to be passed to cb
1295 * \returns 0=OK or error <0
1296 */
1297bcmos_errno bcmos_print_redirect(bcmos_print_redirect_mode mode, bcmos_print_redirect_cb cb, void *data);
1298
1299/* Print on the console with optional cloning / redirection
1300 * \param[in] format printf format
1301 * \param[in] ap argument list
1302 * \returns number of characters printed >= 0 or error < 0
1303 */
1304int bcmos_vprintf(const char *format, va_list ap);
1305
1306/* Print on the console with optional cloning / redirection
1307 * \param[in] format printf format
1308 * \returns number of characters printed >= 0 or error < 0
1309 */
1310int bcmos_printf(const char *format, ...);
1311
1312
1313/** \addtogroup system_trace
1314 * @{
1315 */
1316
1317/** Trace level */
1318typedef enum
1319{
1320 BCMOS_TRACE_LEVEL_NONE, /**< No trace output */
1321 BCMOS_TRACE_LEVEL_ERROR, /**< Trace errors */
1322 BCMOS_TRACE_LEVEL_WARNING, /**< Trace errors + warnings */
1323 BCMOS_TRACE_LEVEL_INFO, /**< Trace errors + warnings + info */
1324 BCMOS_TRACE_LEVEL_VERBOSE, /**< Trace errors + warnings + info + verbose info */
1325 BCMOS_TRACE_LEVEL_DEBUG, /**< Trace everything */
1326} bcmos_trace_level;
1327
1328extern bcmos_trace_level bcmos_sys_trace_level;
1329
1330#ifdef BCMOS_TRACE_PRINTF
1331#define BCMOS_TRACE_INLINE
1332#endif
1333
1334#ifndef BCMOS_TRACE_INLINE
1335/** Print trace
1336 *
1337 * \param[in] level Record trace at level
1338 * \param[in] format printf-like format
1339 */
1340void bcmos_trace(bcmos_trace_level level, const char *format, ...);
1341#endif
1342
1343
1344/* Print trace */
1345#ifdef BCMOS_TRACE_PRINTF
1346#define bcmos_trace(level, fmt, args...) bcmos_printf(fmt, ## args)
1347#endif
1348
1349/** Set current trace level
1350 * \param[in] level New trace level
1351 * \returns old trace level
1352 */
1353static inline bcmos_trace_level bcmos_trace_level_set(bcmos_trace_level level)
1354{
1355 bcmos_trace_level old_level = bcmos_sys_trace_level;
1356 bcmos_sys_trace_level = level;
1357 return old_level;
1358}
1359
1360/** Get current trace level
1361 * \returns trace level
1362 */
1363static inline bcmos_trace_level bcmos_trace_level_get(void)
1364{
1365 return bcmos_sys_trace_level;
1366}
1367
1368/** Print trace conditionally, depending on the current trace level
1369 * \param[in] level Record trace at level
1370 * \param[in] fmt printf-like format
1371 * \param[in] args printf-like arguments
1372 */
1373#define BCMOS_TRACE(level, fmt, args...) \
1374 do \
1375 { \
1376 if (level <= bcmos_sys_trace_level) \
1377 bcmos_trace(level, "%s#%d> " fmt, __FUNCTION__, __LINE__, ## args); \
1378 } while (0)
1379
1380/** Print error trace conditionally, depending on the current trace level
1381 * \param[in] fmt printf-like format
1382 * \param[in] args printf-like arguments
1383 */
1384
1385extern f_bcmolt_sw_error_handler sw_error_handler;
1386
1387#define BCMOS_TRACE_ERR(fmt, args...) \
1388 do \
1389 { \
1390 BCMOS_TRACE(BCMOS_TRACE_LEVEL_ERROR, "ERR: " fmt, ## args); \
1391 if (sw_error_handler != NULL) \
1392 { \
1393 sw_error_handler(0xff, __FILE__, __LINE__); \
1394 } \
1395 _bcmos_backtrace(); \
1396 } while (0)
1397
1398
1399/** Print info trace conditionally, depending on the current trace level
1400 * \param[in] fmt printf-like format
1401 * \param[in] args printf-like arguments
1402 */
1403#define BCMOS_TRACE_INFO(fmt, args...) \
1404 BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "INF: " fmt, ## args)
1405
1406/** Print verbose info trace conditionally, depending on the current trace level
1407 * \param[in] fmt printf-like format
1408 * \param[in] args printf-like arguments
1409 */
1410#define BCMOS_TRACE_VERBOSE(fmt, args...) \
1411 BCMOS_TRACE(BCMOS_TRACE_LEVEL_VERBOSE, "VRB: " fmt, ## args)
1412
1413/** Print debug trace conditionally, depending on the current trace level
1414 * \param[in] fmt printf-like format
1415 * \param[in] args printf-like arguments
1416 */
1417#define BCMOS_TRACE_DEBUG(fmt, args...) \
1418 BCMOS_TRACE(BCMOS_TRACE_LEVEL_DEBUG, "DBG: " fmt, ## args)
1419
1420/** Print trace conditionally based on return code and return
1421 * \param[in] rc return code
1422 * \param[in] fmt printf-like format
1423 * \param[in] args printf-like arguments
1424 * \returns rc
1425 */
1426#define BCMOS_TRACE_RETURN(rc, fmt, args...) \
1427 do { \
1428 if (rc) \
1429 BCMOS_TRACE_ERR("status:%s :" fmt, bcmos_strerror(rc), ## args); \
1430 else \
1431 BCMOS_TRACE_INFO("success: " fmt, ## args); \
1432 return rc; \
1433 } while (0)
1434
1435#define BCMOS_TRACE_CHECK_RETURN(cond,rc,fmt,args...) \
1436 do { \
1437 if (cond) \
1438 {\
1439 BCMOS_TRACE_ERR( #cond ": status:%s :" fmt, bcmos_strerror(rc), ## args); \
1440 return rc; \
1441 }\
1442 } while (0)
1443#define BCMOS_CHECK_RETURN(cond,err,ret) \
1444 do { \
1445 if (cond) \
1446 {\
1447 BCMOS_TRACE_ERR( #cond ": status:%s\n", bcmos_strerror(err)); \
1448 return ret; \
1449 }\
1450 } while (0)
1451#define BCMOS_CHECK_RETURN_ERROR(cond,err) BCMOS_CHECK_RETURN(cond,err,err)
1452#define BCMOS_RETURN_ON_ERROR(err) BCMOS_CHECK_RETURN(BCM_ERR_OK != err, err, /*this space intentionally left blank*/)
1453#define BCMOS_RETURN_IF_ERROR(err) BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err)
1454
1455/** @} system_trace */
1456
1457/*
1458 * Low level services
1459 */
1460
1461/** \addtogroup system_buf
1462 * @{
1463 */
1464
1465/** Transport/network buffer */
1466typedef struct bcmos_buf bcmos_buf;
1467
1468/** @} system_buf */
1469
1470/** Round a number up to the specified power of 2 */
1471#define BCMOS_ROUND_UP(n, m) (((n) + (m) - 1) & ~((m) - 1))
1472
1473/** Round a number up to the nearest word multiple */
1474#define BCMOS_ROUND_TO_WORD(n) BCMOS_ROUND_UP(n, sizeof(size_t))
1475
1476/* BCMOS_DIVIDE_ROUND_UP(integer_dividend / integer_divisor) == (integer_dividend + integer_divisor - 1) / integer_divisor */
1477#define BCMOS_DIVIDE_ROUND_UP(n, m) (((n) + (m) - 1) / (m))
1478
1479#endif /* BCMOS_SYSTEM_COMMON_H_ */