diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /gki/common | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'gki/common')
-rw-r--r-- | gki/common/gki.h | 490 | ||||
-rw-r--r-- | gki/common/gki_buffer.c | 1474 | ||||
-rw-r--r-- | gki/common/gki_common.h | 384 | ||||
-rw-r--r-- | gki/common/gki_debug.c | 348 | ||||
-rw-r--r-- | gki/common/gki_inet.h | 42 | ||||
-rw-r--r-- | gki/common/gki_time.c | 1016 |
6 files changed, 3754 insertions, 0 deletions
diff --git a/gki/common/gki.h b/gki/common/gki.h new file mode 100644 index 0000000..a3272d5 --- /dev/null +++ b/gki/common/gki.h @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Name gki.h +** +** Function This file contains GKI public definitions +** +** +** Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ +#ifndef GKI_H +#define GKI_H + +#ifdef BUILDCFG +#include "buildcfg.h" +#endif + +/* Include platform-specific over-rides */ +#if (defined(NFC_STANDALONE) && (NFC_STANDALONE == TRUE)) + #include "gki_target.h" +#else + /* For non-nfc_standalone, include Bluetooth definitions */ + #include "bt_target.h" +#endif + + + +#include "bt_types.h" + +/* Error codes */ +#define GKI_SUCCESS 0x00 +#define GKI_FAILURE 0x01 +#define GKI_INVALID_TASK 0xF0 +#define GKI_INVALID_POOL 0xFF + + +/************************************************************************ +** Mailbox definitions. Each task has 4 mailboxes that are used to +** send buffers to the task. +*/ +#define TASK_MBOX_0 0 +#define TASK_MBOX_1 1 +#define TASK_MBOX_2 2 +#define TASK_MBOX_3 3 + +#define NUM_TASK_MBOX 4 + +/************************************************************************ +** Event definitions. +** +** There are 4 reserved events used to signal messages rcvd in task mailboxes. +** There are 4 reserved events used to signal timeout events. +** There are 8 general purpose events available for applications. +*/ +#define MAX_EVENTS 16 + +#define TASK_MBOX_0_EVT_MASK 0x0001 +#define TASK_MBOX_1_EVT_MASK 0x0002 +#define TASK_MBOX_2_EVT_MASK 0x0004 +#define TASK_MBOX_3_EVT_MASK 0x0008 + + +#define TIMER_0 0 +#define TIMER_1 1 +#define TIMER_2 2 +#define TIMER_3 3 + +#define TIMER_0_EVT_MASK 0x0010 +#define TIMER_1_EVT_MASK 0x0020 +#define TIMER_2_EVT_MASK 0x0040 +#define TIMER_3_EVT_MASK 0x0080 + +#define APPL_EVT_0 8 +#define APPL_EVT_1 9 +#define APPL_EVT_2 10 +#define APPL_EVT_3 11 +#define APPL_EVT_4 12 +#define APPL_EVT_5 13 +#define APPL_EVT_6 14 +#define APPL_EVT_7 15 + +#define EVENT_MASK(evt) ((UINT16)(0x0001 << (evt))) + +/************************************************************************ +** Max Time Queue +**/ +#ifndef GKI_MAX_TIMER_QUEUES +#define GKI_MAX_TIMER_QUEUES 3 +#endif + +/************************************************************************ +** Macro to determine the pool buffer size based on the GKI POOL ID at compile time. +** Pool IDs index from 0 to GKI_NUM_FIXED_BUF_POOLS - 1 +*/ + +#if (GKI_NUM_FIXED_BUF_POOLS < 1) + +#ifndef GKI_POOL_ID_0 +#define GKI_POOL_ID_0 0 +#endif /* ifndef GKI_POOL_ID_0 */ + +#ifndef GKI_BUF0_SIZE +#define GKI_BUF0_SIZE 0 +#endif /* ifndef GKI_BUF0_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 1 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 2) + +#ifndef GKI_POOL_ID_1 +#define GKI_POOL_ID_1 0 +#endif /* ifndef GKI_POOL_ID_1 */ + +#ifndef GKI_BUF1_SIZE +#define GKI_BUF1_SIZE 0 +#endif /* ifndef GKI_BUF1_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 2 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 3) + +#ifndef GKI_POOL_ID_2 +#define GKI_POOL_ID_2 0 +#endif /* ifndef GKI_POOL_ID_2 */ + +#ifndef GKI_BUF2_SIZE +#define GKI_BUF2_SIZE 0 +#endif /* ifndef GKI_BUF2_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 3 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 4) + +#ifndef GKI_POOL_ID_3 +#define GKI_POOL_ID_3 0 +#endif /* ifndef GKI_POOL_ID_4 */ + +#ifndef GKI_BUF3_SIZE +#define GKI_BUF3_SIZE 0 +#endif /* ifndef GKI_BUF3_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 4 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 5) + +#ifndef GKI_POOL_ID_4 +#define GKI_POOL_ID_4 0 +#endif /* ifndef GKI_POOL_ID_4 */ + +#ifndef GKI_BUF4_SIZE +#define GKI_BUF4_SIZE 0 +#endif /* ifndef GKI_BUF4_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 5 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 6) + +#ifndef GKI_POOL_ID_5 +#define GKI_POOL_ID_5 0 +#endif /* ifndef GKI_POOL_ID_5 */ + +#ifndef GKI_BUF5_SIZE +#define GKI_BUF5_SIZE 0 +#endif /* ifndef GKI_BUF5_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 6 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 7) + +#ifndef GKI_POOL_ID_6 +#define GKI_POOL_ID_6 0 +#endif /* ifndef GKI_POOL_ID_6 */ + +#ifndef GKI_BUF6_SIZE +#define GKI_BUF6_SIZE 0 +#endif /* ifndef GKI_BUF6_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 7 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 8) + +#ifndef GKI_POOL_ID_7 +#define GKI_POOL_ID_7 0 +#endif /* ifndef GKI_POOL_ID_7 */ + +#ifndef GKI_BUF7_SIZE +#define GKI_BUF7_SIZE 0 +#endif /* ifndef GKI_BUF7_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 8 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 9) + +#ifndef GKI_POOL_ID_8 +#define GKI_POOL_ID_8 0 +#endif /* ifndef GKI_POOL_ID_8 */ + +#ifndef GKI_BUF8_SIZE +#define GKI_BUF8_SIZE 0 +#endif /* ifndef GKI_BUF8_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 9 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 10) + +#ifndef GKI_POOL_ID_9 +#define GKI_POOL_ID_9 0 +#endif /* ifndef GKI_POOL_ID_9 */ + +#ifndef GKI_BUF9_SIZE +#define GKI_BUF9_SIZE 0 +#endif /* ifndef GKI_BUF9_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 10 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 11) + +#ifndef GKI_POOL_ID_10 +#define GKI_POOL_ID_10 0 +#endif /* ifndef GKI_POOL_ID_10 */ + +#ifndef GKI_BUF10_SIZE +#define GKI_BUF10_SIZE 0 +#endif /* ifndef GKI_BUF10_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 11 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 12) + +#ifndef GKI_POOL_ID_11 +#define GKI_POOL_ID_11 0 +#endif /* ifndef GKI_POOL_ID_11 */ + +#ifndef GKI_BUF11_SIZE +#define GKI_BUF11_SIZE 0 +#endif /* ifndef GKI_BUF11_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 12 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 13) + +#ifndef GKI_POOL_ID_12 +#define GKI_POOL_ID_12 0 +#endif /* ifndef GKI_POOL_ID_12 */ + +#ifndef GKI_BUF12_SIZE +#define GKI_BUF12_SIZE 0 +#endif /* ifndef GKI_BUF12_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 13 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 14) + +#ifndef GKI_POOL_ID_13 +#define GKI_POOL_ID_13 0 +#endif /* ifndef GKI_POOL_ID_13 */ + +#ifndef GKI_BUF13_SIZE +#define GKI_BUF13_SIZE 0 +#endif /* ifndef GKI_BUF13_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 14 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 15) + +#ifndef GKI_POOL_ID_14 +#define GKI_POOL_ID_14 0 +#endif /* ifndef GKI_POOL_ID_14 */ + +#ifndef GKI_BUF14_SIZE +#define GKI_BUF14_SIZE 0 +#endif /* ifndef GKI_BUF14_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 15 */ + + +#if (GKI_NUM_FIXED_BUF_POOLS < 16) + +#ifndef GKI_POOL_ID_15 +#define GKI_POOL_ID_15 0 +#endif /* ifndef GKI_POOL_ID_15 */ + +#ifndef GKI_BUF15_SIZE +#define GKI_BUF15_SIZE 0 +#endif /* ifndef GKI_BUF15_SIZE */ + +#endif /* GKI_NUM_FIXED_BUF_POOLS < 16 */ + + +/* Timer list entry callback type +*/ +typedef void (TIMER_CBACK)(void *p_tle); +#ifndef TIMER_PARAM_TYPE +#ifdef WIN2000 +#define TIMER_PARAM_TYPE void * +#else +#define TIMER_PARAM_TYPE UINT32 +#endif +#endif +/* Define a timer list entry +*/ +typedef struct _tle +{ + struct _tle *p_next; + struct _tle *p_prev; + TIMER_CBACK *p_cback; + INT32 ticks; + TIMER_PARAM_TYPE param; + UINT16 event; + UINT8 in_use; +} TIMER_LIST_ENT; + +/* Define a timer list queue +*/ +typedef struct +{ + TIMER_LIST_ENT *p_first; + TIMER_LIST_ENT *p_last; + INT32 last_ticks; +} TIMER_LIST_Q; + + +/*********************************************************************** +** This queue is a general purpose buffer queue, for application use. +*/ +typedef struct +{ + void *p_first; + void *p_last; + UINT16 count; +} BUFFER_Q; + +#define GKI_IS_QUEUE_EMPTY(p_q) ((p_q)->count == 0) + +/* Task constants +*/ +#ifndef TASKPTR +typedef void (*TASKPTR)(UINT32); +#endif + + +#define GKI_PUBLIC_POOL 0 /* General pool accessible to GKI_getbuf() */ +#define GKI_RESTRICTED_POOL 1 /* Inaccessible pool to GKI_getbuf() */ + +/*********************************************************************** +** Function prototypes +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Task management +*/ +GKI_API extern UINT8 GKI_create_task (TASKPTR, UINT8, INT8 *, UINT16 *, UINT16); +GKI_API extern void GKI_destroy_task(UINT8 task_id); +GKI_API extern void GKI_exit_task(UINT8); +GKI_API extern UINT8 GKI_get_taskid(void); +GKI_API extern void GKI_init(void); +GKI_API extern void GKI_shutdown(void); +GKI_API extern INT8 *GKI_map_taskname(UINT8); +GKI_API extern UINT8 GKI_resume_task(UINT8); +GKI_API extern void GKI_run(void *); +GKI_API extern void GKI_freeze(void); +GKI_API extern void GKI_stop(void); +GKI_API extern UINT8 GKI_suspend_task(UINT8); +GKI_API extern UINT8 GKI_is_task_running(UINT8); + +/* memory management +*/ +GKI_API extern void GKI_shiftdown (UINT8 *p_mem, UINT32 len, UINT32 shift_amount); +GKI_API extern void GKI_shiftup (UINT8 *p_dest, UINT8 *p_src, UINT32 len); + +/* To send buffers and events between tasks +*/ +GKI_API extern UINT8 GKI_isend_event (UINT8, UINT16); +GKI_API extern void GKI_isend_msg (UINT8, UINT8, void *); +GKI_API extern void *GKI_read_mbox (UINT8); +GKI_API extern void GKI_send_msg (UINT8, UINT8, void *); +GKI_API extern UINT8 GKI_send_event (UINT8, UINT16); + + +/* To get and release buffers, change owner and get size +*/ +GKI_API extern void GKI_change_buf_owner (void *, UINT8); +GKI_API extern UINT8 GKI_create_pool (UINT16, UINT16, UINT8, void *); +GKI_API extern void GKI_delete_pool (UINT8); +GKI_API extern void *GKI_find_buf_start (void *); +GKI_API extern void GKI_freebuf (void *); +GKI_API extern void *GKI_getbuf (UINT16); +GKI_API extern UINT16 GKI_get_buf_size (void *); +GKI_API extern void *GKI_getpoolbuf (UINT8); +GKI_API extern UINT16 GKI_poolcount (UINT8); +GKI_API extern UINT16 GKI_poolfreecount (UINT8); +GKI_API extern UINT16 GKI_poolutilization (UINT8); +GKI_API extern void GKI_register_mempool (void *p_mem); +GKI_API extern UINT8 GKI_set_pool_permission(UINT8, UINT8); + + +/* User buffer queue management +*/ +GKI_API extern void *GKI_dequeue (BUFFER_Q *); +GKI_API extern void GKI_enqueue (BUFFER_Q *, void *); +GKI_API extern void GKI_enqueue_head (BUFFER_Q *, void *); +GKI_API extern void *GKI_getfirst (BUFFER_Q *); +GKI_API extern void *GKI_getlast (BUFFER_Q *); +GKI_API extern void *GKI_getnext (void *); +GKI_API extern void GKI_init_q (BUFFER_Q *); +GKI_API extern BOOLEAN GKI_queue_is_empty(BUFFER_Q *); +GKI_API extern void *GKI_remove_from_queue (BUFFER_Q *, void *); +GKI_API extern UINT16 GKI_get_pool_bufsize (UINT8); + +/* Timer management +*/ +GKI_API extern void GKI_add_to_timer_list (TIMER_LIST_Q *, TIMER_LIST_ENT *); +GKI_API extern void GKI_delay(UINT32); +GKI_API extern UINT32 GKI_get_tick_count(void); +GKI_API extern INT8 *GKI_get_time_stamp(INT8 *); +GKI_API extern void GKI_init_timer_list (TIMER_LIST_Q *); +GKI_API extern void GKI_init_timer_list_entry (TIMER_LIST_ENT *); +GKI_API extern INT32 GKI_ready_to_sleep (void); +GKI_API extern void GKI_remove_from_timer_list (TIMER_LIST_Q *, TIMER_LIST_ENT *); +GKI_API extern void GKI_start_timer(UINT8, INT32, BOOLEAN); +GKI_API extern void GKI_stop_timer (UINT8); +GKI_API extern void GKI_timer_update(INT32); +GKI_API extern UINT16 GKI_update_timer_list (TIMER_LIST_Q *, INT32); +GKI_API extern UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *, TIMER_LIST_ENT *); +GKI_API extern UINT16 GKI_wait(UINT16, UINT32); + +/* Start and Stop system time tick callback + * true for start system tick if time queue is not empty + * false to stop system tick if time queue is empty +*/ +typedef void (SYSTEM_TICK_CBACK)(BOOLEAN); + +/* Time queue management for system ticks +*/ +GKI_API extern BOOLEAN GKI_timer_queue_empty (void); +GKI_API extern void GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK *); + +/* Disable Interrupts, Enable Interrupts +*/ +GKI_API extern void GKI_enable(void); +GKI_API extern void GKI_disable(void); +GKI_API extern void GKI_sched_lock(void); +GKI_API extern void GKI_sched_unlock(void); + +/* Allocate (Free) memory from an OS +*/ +GKI_API extern void *GKI_os_malloc (UINT32); +GKI_API extern void GKI_os_free (void *); + +/* os timer operation */ +GKI_API extern UINT32 GKI_get_os_tick_count(void); + +/* Exception handling +*/ +GKI_API extern void GKI_exception (UINT16, char *); + +#if GKI_DEBUG == TRUE +GKI_API extern void GKI_PrintBufferUsage(UINT8 *p_num_pools, UINT16 *p_cur_used); +GKI_API extern void GKI_PrintBuffer(void); +GKI_API extern void GKI_print_task(void); +#else +#undef GKI_PrintBufferUsage +#define GKI_PrintBuffer() NULL +#endif + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/gki/common/gki_buffer.c b/gki/common/gki_buffer.c new file mode 100644 index 0000000..a32c275 --- /dev/null +++ b/gki/common/gki_buffer.c @@ -0,0 +1,1474 @@ +/******************************************************************************** +** * +** Name gki_buffer.c * +** * +** Function this file contains GKI buffer handling functions * +** * +** * +** Copyright (c) 1999-2009, Broadcom Corp., All Rights Reserved. * +** Proprietary and confidential. * +** * +*********************************************************************************/ +#include "gki_int.h" + +#if (GKI_NUM_TOTAL_BUF_POOLS > 16) +#error Number of pools out of range (16 Max)! +#endif + +static void gki_add_to_pool_list(UINT8 pool_id); +static void gki_remove_from_pool_list(UINT8 pool_id); + +/******************************************************************************* +** +** Function gki_init_free_queue +** +** Description Internal function called at startup to initialize a free +** queue. It is called once for each free queue. +** +** Returns void +** +*******************************************************************************/ +static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem) +{ + UINT16 i; + UINT16 act_size; + BUFFER_HDR_T *hdr; + BUFFER_HDR_T *hdr1 = NULL; + UINT32 *magic; + INT32 tempsize = size; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* Ensure an even number of longwords */ + tempsize = (INT32)ALIGN_POOL(size); + act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE); + + /* Remember pool start and end addresses */ +// btla-specific ++ + if(p_mem) + { + p_cb->pool_start[id] = (UINT8 *)p_mem; + p_cb->pool_end[id] = (UINT8 *)p_mem + (act_size * total); + } +// btla-specific -- + + p_cb->pool_size[id] = act_size; + + p_cb->freeq[id].size = (UINT16) tempsize; + p_cb->freeq[id].total = total; + p_cb->freeq[id].cur_cnt = 0; + p_cb->freeq[id].max_cnt = 0; + + /* Initialize index table */ +// btla-specific ++ + if(p_mem) + { + hdr = (BUFFER_HDR_T *)p_mem; + p_cb->freeq[id].p_first = hdr; + for (i = 0; i < total; i++) + { + hdr->task_id = GKI_INVALID_TASK; + hdr->q_id = id; + hdr->status = BUF_STATUS_FREE; + magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize); + *magic = MAGIC_NO; + hdr1 = hdr; + hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size); + hdr1->p_next = hdr; + } + hdr1->p_next = NULL; + p_cb->freeq[id].p_last = hdr1; + } +// btla-specific -- + return; +} + +// btla-specific ++ +#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS +static BOOLEAN gki_alloc_free_queue(UINT8 id) +{ + FREE_QUEUE_T *Q; + tGKI_COM_CB *p_cb = &gki_cb.com; + GKI_TRACE("\ngki_alloc_free_queue in, id:%d \n", id); + + Q = &p_cb->freeq[p_cb->pool_list[id]]; + + if(Q->p_first == 0) + { + void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total); + if(p_mem) + { + //re-initialize the queue with allocated memory + GKI_TRACE("\ngki_alloc_free_queue calling gki_init_free_queue, id:%d size:%d, totol:%d\n", id, Q->size, Q->total); + gki_init_free_queue(id, Q->size, Q->total, p_mem); + GKI_TRACE("\ngki_alloc_free_queue ret OK, id:%d size:%d, totol:%d\n", id, Q->size, Q->total); + return TRUE; + } + GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "gki_alloc_free_queue: Not enough memory"); + } + GKI_TRACE("\ngki_alloc_free_queue out failed, id:%d\n", id); + return FALSE; +} + +void gki_dealloc_free_queue(void) +{ + UINT8 i; + tGKI_COM_CB *p_cb = &gki_cb.com; + + for (i=0; i < p_cb->curr_total_no_of_pools; i++) + { + if ( 0 < p_cb->freeq[i].max_cnt ) + { + GKI_os_free(p_cb->pool_start[i]); + + p_cb->freeq[i].cur_cnt = 0; + p_cb->freeq[i].max_cnt = 0; + p_cb->freeq[i].p_first = NULL; + p_cb->freeq[i].p_last = NULL; + + p_cb->pool_start[i] = NULL; + p_cb->pool_end[i] = NULL; + p_cb->pool_size[i] = 0; + } + } +} + +#endif +// btla-specific -- + +/******************************************************************************* +** +** Function gki_buffer_init +** +** Description Called once internally by GKI at startup to initialize all +** buffers and free buffer pools. +** +** Returns void +** +*******************************************************************************/ +void gki_buffer_init(void) +{ + UINT8 i, tt, mb; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* Initialize mailboxes */ + for (tt = 0; tt < GKI_MAX_TASKS; tt++) + { + for (mb = 0; mb < NUM_TASK_MBOX; mb++) + { + p_cb->OSTaskQFirst[tt][mb] = NULL; + p_cb->OSTaskQLast [tt][mb] = NULL; + } + } + + for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++) + { + p_cb->pool_start[tt] = NULL; + p_cb->pool_end[tt] = NULL; + p_cb->pool_size[tt] = 0; + + p_cb->freeq[tt].p_first = 0; + p_cb->freeq[tt].p_last = 0; + p_cb->freeq[tt].size = 0; + p_cb->freeq[tt].total = 0; + p_cb->freeq[tt].cur_cnt = 0; + p_cb->freeq[tt].max_cnt = 0; + } + + /* Use default from target.h */ + p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK; + +// btla-specific ++ +#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == TRUE)) +// btla-specific -- + +#if (GKI_NUM_FIXED_BUF_POOLS > 0) + p_cb->bufpool0 = (UINT8 *)GKI_os_malloc ((GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 1) + p_cb->bufpool1 = (UINT8 *)GKI_os_malloc ((GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 2) + p_cb->bufpool2 = (UINT8 *)GKI_os_malloc ((GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 3) + p_cb->bufpool3 = (UINT8 *)GKI_os_malloc ((GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 4) + p_cb->bufpool4 = (UINT8 *)GKI_os_malloc ((GKI_BUF4_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 5) + p_cb->bufpool5 = (UINT8 *)GKI_os_malloc ((GKI_BUF5_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 6) + p_cb->bufpool6 = (UINT8 *)GKI_os_malloc ((GKI_BUF6_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 7) + p_cb->bufpool7 = (UINT8 *)GKI_os_malloc ((GKI_BUF7_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 8) + p_cb->bufpool8 = (UINT8 *)GKI_os_malloc ((GKI_BUF8_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 9) + p_cb->bufpool9 = (UINT8 *)GKI_os_malloc ((GKI_BUF9_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 10) + p_cb->bufpool10 = (UINT8 *)GKI_os_malloc ((GKI_BUF10_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 11) + p_cb->bufpool11 = (UINT8 *)GKI_os_malloc ((GKI_BUF11_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 12) + p_cb->bufpool12 = (UINT8 *)GKI_os_malloc ((GKI_BUF12_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 13) + p_cb->bufpool13 = (UINT8 *)GKI_os_malloc ((GKI_BUF13_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 14) + p_cb->bufpool14 = (UINT8 *)GKI_os_malloc ((GKI_BUF14_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 15) + p_cb->bufpool15 = (UINT8 *)GKI_os_malloc ((GKI_BUF15_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX); +#endif + +#endif + + +#if (GKI_NUM_FIXED_BUF_POOLS > 0) + gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 1) + gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 2) + gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 3) + gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 4) + gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 5) + gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 6) + gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 7) + gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 8) + gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 9) + gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 10) + gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 11) + gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 12) + gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 13) + gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 14) + gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14); +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 15) + gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15); +#endif + + /* add pools to the pool_list which is arranged in the order of size */ + for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++) + { + p_cb->pool_list[i] = i; + } + + p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS; + + return; +} + + +/******************************************************************************* +** +** Function GKI_init_q +** +** Description Called by an application to initialize a buffer queue. +** +** Returns void +** +*******************************************************************************/ +void GKI_init_q (BUFFER_Q *p_q) +{ + p_q->p_first = p_q->p_last = NULL; + p_q->count = 0; + + return; +} + + +/******************************************************************************* +** +** Function GKI_getbuf +** +** Description Called by an application to get a free buffer which +** is of size greater or equal to the requested size. +** +** Note: This routine only takes buffers from public pools. +** It will not use any buffers from pools +** marked GKI_RESTRICTED_POOL. +** +** Parameters size - (input) number of bytes needed. +** +** Returns A pointer to the buffer, or NULL if none available +** +*******************************************************************************/ +void *GKI_getbuf (UINT16 size) +{ + UINT8 i; + FREE_QUEUE_T *Q; + BUFFER_HDR_T *p_hdr; + tGKI_COM_CB *p_cb = &gki_cb.com; + + if (size == 0) + { + GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero"); + return (NULL); + } + + /* Find the first buffer pool that is public that can hold the desired size */ + for (i=0; i < p_cb->curr_total_no_of_pools; i++) + { + if ( size <= p_cb->freeq[p_cb->pool_list[i]].size ) + break; + } + + if(i == p_cb->curr_total_no_of_pools) + { + GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big"); + return (NULL); + } + + /* Make sure the buffers aren't disturbed til finished with allocation */ + GKI_disable(); + + /* search the public buffer pools that are big enough to hold the size + * until a free buffer is found */ + for ( ; i < p_cb->curr_total_no_of_pools; i++) + { + /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */ + if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask) + continue; + + Q = &p_cb->freeq[p_cb->pool_list[i]]; + if(Q->cur_cnt < Q->total) + { +// btla-specific ++ + #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS + if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE) + return NULL; + #endif +// btla-specific -- + p_hdr = Q->p_first; + Q->p_first = p_hdr->p_next; + + if (!Q->p_first) + Q->p_last = NULL; + + if(++Q->cur_cnt > Q->max_cnt) + Q->max_cnt = Q->cur_cnt; + + GKI_enable(); + + p_hdr->task_id = GKI_get_taskid(); + + p_hdr->status = BUF_STATUS_UNLINKED; + p_hdr->p_next = NULL; + p_hdr->Type = 0; + + return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); + } + } + + GKI_enable(); + + return (NULL); +} + + +/******************************************************************************* +** +** Function GKI_getpoolbuf +** +** Description Called by an application to get a free buffer from +** a specific buffer pool. +** +** Note: If there are no more buffers available from the pool, +** the public buffers are searched for an available buffer. +** +** Parameters pool_id - (input) pool ID to get a buffer out of. +** +** Returns A pointer to the buffer, or NULL if none available +** +*******************************************************************************/ +void *GKI_getpoolbuf (UINT8 pool_id) +{ + FREE_QUEUE_T *Q; + BUFFER_HDR_T *p_hdr; + tGKI_COM_CB *p_cb = &gki_cb.com; + + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) + return (NULL); + + /* Make sure the buffers aren't disturbed til finished with allocation */ + GKI_disable(); + + Q = &p_cb->freeq[pool_id]; + if(Q->cur_cnt < Q->total) + { +// btla-specific ++ +#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS + if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE) + return NULL; +#endif +// btla-specific -- + p_hdr = Q->p_first; + Q->p_first = p_hdr->p_next; + + if (!Q->p_first) + Q->p_last = NULL; + + if(++Q->cur_cnt > Q->max_cnt) + Q->max_cnt = Q->cur_cnt; + + GKI_enable(); + + + p_hdr->task_id = GKI_get_taskid(); + + p_hdr->status = BUF_STATUS_UNLINKED; + p_hdr->p_next = NULL; + p_hdr->Type = 0; + + return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); + } + + /* If here, no buffers in the specified pool */ + GKI_enable(); + + /* try for free buffers in public pools */ + return (GKI_getbuf(p_cb->freeq[pool_id].size)); + +} + +/******************************************************************************* +** +** Function GKI_freebuf +** +** Description Called by an application to return a buffer to the free pool. +** +** Parameters p_buf - (input) address of the beginning of a buffer. +** +** Returns void +** +*******************************************************************************/ +void GKI_freebuf (void *p_buf) +{ + FREE_QUEUE_T *Q; + BUFFER_HDR_T *p_hdr; + +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + if (!p_buf || gki_chk_buf_damage(p_buf)) + { + GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted"); + return; + } +#endif + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE); + + if (p_hdr->status != BUF_STATUS_UNLINKED) + { + GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf"); + return; + } + + if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS) + { + GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId"); + return; + } + + GKI_disable(); + + /* + ** Release the buffer + */ + Q = &gki_cb.com.freeq[p_hdr->q_id]; + if (Q->p_last) + Q->p_last->p_next = p_hdr; + else + Q->p_first = p_hdr; + + Q->p_last = p_hdr; + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_FREE; + p_hdr->task_id = GKI_INVALID_TASK; + if (Q->cur_cnt > 0) + Q->cur_cnt--; + + GKI_enable(); + + return; +} + + +/******************************************************************************* +** +** Function GKI_get_buf_size +** +** Description Called by an application to get the size of a buffer. +** +** Parameters p_buf - (input) address of the beginning of a buffer. +** +** Returns the size of the buffer +** +*******************************************************************************/ +UINT16 GKI_get_buf_size (void *p_buf) +{ + BUFFER_HDR_T *p_hdr; + + p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE); + + if ((UINT32)p_hdr & 1) + return (0); + + if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS) + { + return (gki_cb.com.freeq[p_hdr->q_id].size); + } + + return (0); +} + +/******************************************************************************* +** +** Function gki_chk_buf_damage +** +** Description Called internally by OSS to check for buffer corruption. +** +** Returns TRUE if there is a problem, else FALSE +** +*******************************************************************************/ +BOOLEAN gki_chk_buf_damage(void *p_buf) +{ +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + + UINT32 *magic; + magic = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf)); + + if ((UINT32)magic & 1) + return (TRUE); + + if (*magic == MAGIC_NO) + return (FALSE); + + return (TRUE); + +#else + + return (FALSE); + +#endif +} + +/******************************************************************************* +** +** Function GKI_send_msg +** +** Description Called by applications to send a buffer to a task +** +** Returns Nothing +** +*******************************************************************************/ +void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg) +{ + BUFFER_HDR_T *p_hdr; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* If task non-existant or not started, drop buffer */ + if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) + { + GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest"); + GKI_freebuf (msg); + return; + } + +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + if (gki_chk_buf_damage(msg)) + { + GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted"); + return; + } +#endif + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE); + + if (p_hdr->status != BUF_STATUS_UNLINKED) + { + GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked"); + return; + } + + GKI_disable(); + + if (p_cb->OSTaskQFirst[task_id][mbox]) + p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr; + else + p_cb->OSTaskQFirst[task_id][mbox] = p_hdr; + + p_cb->OSTaskQLast[task_id][mbox] = p_hdr; + + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_QUEUED; + p_hdr->task_id = task_id; + + + GKI_enable(); + + GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox)); + + return; +} + +/******************************************************************************* +** +** Function GKI_read_mbox +** +** Description Called by applications to read a buffer from one of +** the task mailboxes. A task can only read its own mailbox. +** +** Parameters: mbox - (input) mailbox ID to read (0, 1, 2, or 3) +** +** Returns NULL if the mailbox was empty, else the address of a buffer +** +*******************************************************************************/ +void *GKI_read_mbox (UINT8 mbox) +{ + UINT8 task_id = GKI_get_taskid(); + void *p_buf = NULL; + BUFFER_HDR_T *p_hdr; + + if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX)) + return (NULL); + + GKI_disable(); + + if (gki_cb.com.OSTaskQFirst[task_id][mbox]) + { + p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox]; + gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next; + + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_UNLINKED; + + p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE; + } + + GKI_enable(); + + return (p_buf); +} + + + +/******************************************************************************* +** +** Function GKI_enqueue +** +** Description Enqueue a buffer at the tail of the queue +** +** Parameters: p_q - (input) pointer to a queue. +** p_buf - (input) address of the buffer to enqueue +** +** Returns void +** +*******************************************************************************/ +void GKI_enqueue (BUFFER_Q *p_q, void *p_buf) +{ + BUFFER_HDR_T *p_hdr; + +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + if (gki_chk_buf_damage(p_buf)) + { + GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted"); + return; + } +#endif + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); + + if (p_hdr->status != BUF_STATUS_UNLINKED) + { + GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked"); + return; + } + + GKI_disable(); + + /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */ + if (p_q->p_last) + { + BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE); + p_last_hdr->p_next = p_hdr; + } + else + p_q->p_first = p_buf; + + p_q->p_last = p_buf; + p_q->count++; + + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_QUEUED; + + GKI_enable(); + + return; +} + + +/******************************************************************************* +** +** Function GKI_enqueue_head +** +** Description Enqueue a buffer at the head of the queue +** +** Parameters: p_q - (input) pointer to a queue. +** p_buf - (input) address of the buffer to enqueue +** +** Returns void +** +*******************************************************************************/ +void GKI_enqueue_head (BUFFER_Q *p_q, void *p_buf) +{ + BUFFER_HDR_T *p_hdr; + +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + if (gki_chk_buf_damage(p_buf)) + { + GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted"); + return; + } +#endif + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); + + if (p_hdr->status != BUF_STATUS_UNLINKED) + { + GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue head - buf already linked"); + return; + } + + GKI_disable(); + + if (p_q->p_first) + { + p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE); + p_q->p_first = p_buf; + } + else + { + p_q->p_first = p_buf; + p_q->p_last = p_buf; + p_hdr->p_next = NULL; + } + p_q->count++; + + p_hdr->status = BUF_STATUS_QUEUED; + + GKI_enable(); + + return; +} + + +/******************************************************************************* +** +** Function GKI_dequeue +** +** Description Dequeues a buffer from the head of a queue +** +** Parameters: p_q - (input) pointer to a queue. +** +** Returns NULL if queue is empty, else buffer +** +*******************************************************************************/ +void *GKI_dequeue (BUFFER_Q *p_q) +{ + BUFFER_HDR_T *p_hdr; + + GKI_disable(); + + if (!p_q || !p_q->count) + { + GKI_enable(); + return (NULL); + } + + p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE); + + /* Keep buffers such that GKI header is invisible + */ + if (p_hdr->p_next) + p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE); + else + { + p_q->p_first = NULL; + p_q->p_last = NULL; + } + + p_q->count--; + + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_UNLINKED; + + GKI_enable(); + + return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE); +} + + +/******************************************************************************* +** +** Function GKI_remove_from_queue +** +** Description Dequeue a buffer from the middle of the queue +** +** Parameters: p_q - (input) pointer to a queue. +** p_buf - (input) address of the buffer to enqueue +** +** Returns NULL if queue is empty, else buffer +** +*******************************************************************************/ +void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf) +{ + BUFFER_HDR_T *p_prev; + BUFFER_HDR_T *p_buf_hdr; + + GKI_disable(); + + if (p_buf == p_q->p_first) + { + GKI_enable(); + return (GKI_dequeue (p_q)); + } + + p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE); + p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE); + + for ( ; p_prev; p_prev = p_prev->p_next) + { + /* If the previous points to this one, move the pointers around */ + if (p_prev->p_next == p_buf_hdr) + { + p_prev->p_next = p_buf_hdr->p_next; + + /* If we are removing the last guy in the queue, update p_last */ + if (p_buf == p_q->p_last) + p_q->p_last = p_prev + 1; + + /* One less in the queue */ + p_q->count--; + + /* The buffer is now unlinked */ + p_buf_hdr->p_next = NULL; + p_buf_hdr->status = BUF_STATUS_UNLINKED; + + GKI_enable(); + return (p_buf); + } + } + + GKI_enable(); + return (NULL); +} + +/******************************************************************************* +** +** Function GKI_getfirst +** +** Description Return a pointer to the first buffer in a queue +** +** Parameters: p_q - (input) pointer to a queue. +** +** Returns NULL if queue is empty, else buffer address +** +*******************************************************************************/ +void *GKI_getfirst (BUFFER_Q *p_q) +{ + return (p_q->p_first); +} + + +/******************************************************************************* +** +** Function GKI_getlast +** +** Description Return a pointer to the last buffer in a queue +** +** Parameters: p_q - (input) pointer to a queue. +** +** Returns NULL if queue is empty, else buffer address +** +*******************************************************************************/ +void *GKI_getlast (BUFFER_Q *p_q) +{ + return (p_q->p_last); +} + +/******************************************************************************* +** +** Function GKI_getnext +** +** Description Return a pointer to the next buffer in a queue +** +** Parameters: p_buf - (input) pointer to the buffer to find the next one from. +** +** Returns NULL if no more buffers in the queue, else next buffer address +** +*******************************************************************************/ +void *GKI_getnext (void *p_buf) +{ + BUFFER_HDR_T *p_hdr; + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); + + if (p_hdr->p_next) + return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE); + else + return (NULL); +} + + + +/******************************************************************************* +** +** Function GKI_queue_is_empty +** +** Description Check the status of a queue. +** +** Parameters: p_q - (input) pointer to a queue. +** +** Returns TRUE if queue is empty, else FALSE +** +*******************************************************************************/ +BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q) +{ + return ((BOOLEAN) (p_q->count == 0)); +} + +/******************************************************************************* +** +** Function GKI_find_buf_start +** +** Description This function is called with an address inside a buffer, +** and returns the start address ofthe buffer. +** +** The buffer should be one allocated from one of GKI's pools. +** +** Parameters: p_user_area - (input) address of anywhere in a GKI buffer. +** +** Returns void * - Address of the beginning of the specified buffer if successful, +** otherwise NULL if unsuccessful +** +*******************************************************************************/ +void *GKI_find_buf_start (void *p_user_area) +{ + UINT16 xx, size; + UINT32 yy; + tGKI_COM_CB *p_cb = &gki_cb.com; + UINT8 *p_ua = (UINT8 *)p_user_area; + + for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) + { + if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx])) + { + yy = (UINT32)(p_ua - p_cb->pool_start[xx]); + + size = p_cb->pool_size[xx]; + + yy = (yy / size) * size; + + return ((void *) (p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)) ); + } + } + + /* If here, invalid address - not in one of our buffers */ + GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr"); + + return (NULL); +} + + +/******************************************************************************* +** +** Function GKI_set_pool_permission +** +** Description This function is called to set or change the permissions for +** the specified pool ID. +** +** Parameters pool_id - (input) pool ID to be set or changed +** permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL +** +** Returns GKI_SUCCESS if successful +** GKI_INVALID_POOL if unsuccessful +** +*******************************************************************************/ +UINT8 GKI_set_pool_permission(UINT8 pool_id, UINT8 permission) +{ + tGKI_COM_CB *p_cb = &gki_cb.com; + + if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) + { + if (permission == GKI_RESTRICTED_POOL) + p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask | (1 << pool_id)); + + else /* mark the pool as public */ + p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask & ~(1 << pool_id)); + + return (GKI_SUCCESS); + } + else + return (GKI_INVALID_POOL); +} + +/******************************************************************************* +** +** Function gki_add_to_pool_list +** +** Description Adds pool to the pool list which is arranged in the +** order of size +** +** Returns void +** +*******************************************************************************/ +static void gki_add_to_pool_list(UINT8 pool_id) +{ + + INT32 i, j; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* Find the position where the specified pool should be inserted into the list */ + for(i=0; i < p_cb->curr_total_no_of_pools; i++) + { + + if(p_cb->freeq[pool_id].size <= p_cb->freeq[ p_cb->pool_list[i] ].size) + break; + } + + /* Insert the new buffer pool ID into the list of pools */ + for(j = p_cb->curr_total_no_of_pools; j > i; j--) + { + p_cb->pool_list[j] = p_cb->pool_list[j-1]; + } + + p_cb->pool_list[i] = pool_id; + + return; +} + +/******************************************************************************* +** +** Function gki_remove_from_pool_list +** +** Description Removes pool from the pool list. Called when a pool is deleted +** +** Returns void +** +*******************************************************************************/ +static void gki_remove_from_pool_list(UINT8 pool_id) +{ + tGKI_COM_CB *p_cb = &gki_cb.com; + UINT8 i; + + for(i=0; i < p_cb->curr_total_no_of_pools; i++) + { + if(pool_id == p_cb->pool_list[i]) + break; + } + + while (i < (p_cb->curr_total_no_of_pools - 1)) + { + p_cb->pool_list[i] = p_cb->pool_list[i+1]; + i++; + } + + return; +} + +/******************************************************************************* +** +** Function GKI_igetpoolbuf +** +** Description Called by an interrupt service routine to get a free buffer from +** a specific buffer pool. +** +** Parameters pool_id - (input) pool ID to get a buffer out of. +** +** Returns A pointer to the buffer, or NULL if none available +** +*******************************************************************************/ +void *GKI_igetpoolbuf (UINT8 pool_id) +{ + FREE_QUEUE_T *Q; + BUFFER_HDR_T *p_hdr; + + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) + return (NULL); + + + Q = &gki_cb.com.freeq[pool_id]; + if(Q->cur_cnt < Q->total) + { + p_hdr = Q->p_first; + Q->p_first = p_hdr->p_next; + + if (!Q->p_first) + Q->p_last = NULL; + + if(++Q->cur_cnt > Q->max_cnt) + Q->max_cnt = Q->cur_cnt; + + p_hdr->task_id = GKI_get_taskid(); + + p_hdr->status = BUF_STATUS_UNLINKED; + p_hdr->p_next = NULL; + p_hdr->Type = 0; + + return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); + } + + return (NULL); +} + +/******************************************************************************* +** +** Function GKI_poolcount +** +** Description Called by an application to get the total number of buffers +** in the specified buffer pool. +** +** Parameters pool_id - (input) pool ID to get the free count of. +** +** Returns the total number of buffers in the pool +** +*******************************************************************************/ +UINT16 GKI_poolcount (UINT8 pool_id) +{ + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) + return (0); + + return (gki_cb.com.freeq[pool_id].total); +} + +/******************************************************************************* +** +** Function GKI_poolfreecount +** +** Description Called by an application to get the number of free buffers +** in the specified buffer pool. +** +** Parameters pool_id - (input) pool ID to get the free count of. +** +** Returns the number of free buffers in the pool +** +*******************************************************************************/ +UINT16 GKI_poolfreecount (UINT8 pool_id) +{ + FREE_QUEUE_T *Q; + + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) + return (0); + + Q = &gki_cb.com.freeq[pool_id]; + + return ((UINT16)(Q->total - Q->cur_cnt)); +} + +/******************************************************************************* +** +** Function GKI_change_buf_owner +** +** Description Called to change the task ownership of a buffer. +** +** Parameters: p_buf - (input) pointer to the buffer +** task_id - (input) task id to change ownership to +** +** Returns void +** +*******************************************************************************/ +void GKI_change_buf_owner (void *p_buf, UINT8 task_id) +{ + BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); + + p_hdr->task_id = task_id; + + return; +} + +#if (defined(GKI_SEND_MSG_FROM_ISR) && GKI_SEND_MSG_FROM_ISR == TRUE) +/******************************************************************************* +** +** Function GKI_isend_msg +** +** Description Called from interrupt context to send a buffer to a task +** +** Returns Nothing +** +*******************************************************************************/ +void GKI_isend_msg (UINT8 task_id, UINT8 mbox, void *msg) +{ + BUFFER_HDR_T *p_hdr; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* If task non-existant or not started, drop buffer */ + if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) + { + GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest"); + GKI_freebuf (msg); + return; + } + +#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) + if (gki_chk_buf_damage(msg)) + { + GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted"); + return; + } +#endif + +#if (GKI_ENABLE_OWNER_CHECK == TRUE) + if (gki_chk_buf_owner(msg)) + { + GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner"); + return; + } +#endif + + p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE); + + if (p_hdr->status != BUF_STATUS_UNLINKED) + { + GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked"); + return; + } + + if (p_cb->OSTaskQFirst[task_id][mbox]) + p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr; + else + p_cb->OSTaskQFirst[task_id][mbox] = p_hdr; + + p_cb->OSTaskQLast[task_id][mbox] = p_hdr; + + p_hdr->p_next = NULL; + p_hdr->status = BUF_STATUS_QUEUED; + p_hdr->task_id = task_id; + + GKI_isend_event(task_id, (UINT16)EVENT_MASK(mbox)); + + return; +} +#endif + +/******************************************************************************* +** +** Function GKI_create_pool +** +** Description Called by applications to create a buffer pool. +** +** Parameters: size - (input) length (in bytes) of each buffer in the pool +** count - (input) number of buffers to allocate for the pool +** permission - (input) restricted or public access? +** (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL) +** p_mem_pool - (input) pointer to an OS memory pool, NULL if not provided +** +** Returns the buffer pool ID, which should be used in calls to +** GKI_getpoolbuf(). If a pool could not be created, this +** function returns 0xff. +** +*******************************************************************************/ +UINT8 GKI_create_pool (UINT16 size, UINT16 count, UINT8 permission, void *p_mem_pool) +{ + UINT8 xx; + UINT32 mem_needed; + INT32 tempsize = size; + tGKI_COM_CB *p_cb = &gki_cb.com; + + /* First make sure the size of each pool has a valid size with room for the header info */ + if (size > MAX_USER_BUF_SIZE) + return (GKI_INVALID_POOL); + + /* First, look for an unused pool */ + for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) + { + if (!p_cb->pool_start[xx]) + break; + } + + if (xx == GKI_NUM_TOTAL_BUF_POOLS) + return (GKI_INVALID_POOL); + + /* Ensure an even number of longwords */ + tempsize = (INT32)ALIGN_POOL(size); + + mem_needed = (tempsize + BUFFER_PADDING_SIZE) * count; + + if (!p_mem_pool) + p_mem_pool = GKI_os_malloc(mem_needed); + + if (p_mem_pool) + { + /* Initialize the new pool */ + gki_init_free_queue (xx, size, count, p_mem_pool); + gki_add_to_pool_list(xx); + (void) GKI_set_pool_permission (xx, permission); + p_cb->curr_total_no_of_pools++; + + return (xx); + } + else + return (GKI_INVALID_POOL); +} + +/******************************************************************************* +** +** Function GKI_delete_pool +** +** Description Called by applications to delete a buffer pool. The function +** calls the operating specific function to free the actual memory. +** An exception is generated if an error is detected. +** +** Parameters: pool_id - (input) Id of the poll being deleted. +** +** Returns void +** +*******************************************************************************/ +void GKI_delete_pool (UINT8 pool_id) +{ + FREE_QUEUE_T *Q; + tGKI_COM_CB *p_cb = &gki_cb.com; + + if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id])) + return; + + GKI_disable(); + Q = &p_cb->freeq[pool_id]; + + if (!Q->cur_cnt) + { + Q->size = 0; + Q->total = 0; + Q->cur_cnt = 0; + Q->max_cnt = 0; + Q->p_first = NULL; + Q->p_last = NULL; + + GKI_os_free (p_cb->pool_start[pool_id]); + + p_cb->pool_start[pool_id] = NULL; + p_cb->pool_end[pool_id] = NULL; + p_cb->pool_size[pool_id] = 0; + + gki_remove_from_pool_list(pool_id); + p_cb->curr_total_no_of_pools--; + } + else + GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool"); + + GKI_enable(); + + return; +} + + +/******************************************************************************* +** +** Function GKI_get_pool_bufsize +** +** Description Called by an application to get the size of buffers in a pool +** +** Parameters Pool ID. +** +** Returns the size of buffers in the pool +** +*******************************************************************************/ +UINT16 GKI_get_pool_bufsize (UINT8 pool_id) +{ + if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) + return (gki_cb.com.freeq[pool_id].size); + + return (0); +} + +/******************************************************************************* +** +** Function GKI_poolutilization +** +** Description Called by an application to get the buffer utilization +** in the specified buffer pool. +** +** Parameters pool_id - (input) pool ID to get the free count of. +** +** Returns % of buffers used from 0 to 100 +** +*******************************************************************************/ +UINT16 GKI_poolutilization (UINT8 pool_id) +{ + FREE_QUEUE_T *Q; + + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) + return (100); + + Q = &gki_cb.com.freeq[pool_id]; + + if (Q->total == 0) + return (100); + + return ((Q->cur_cnt * 100) / Q->total); +} + diff --git a/gki/common/gki_common.h b/gki/common/gki_common.h new file mode 100644 index 0000000..6093abf --- /dev/null +++ b/gki/common/gki_common.h @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** Name gki_common.h +** +** Function This file contains GKI private definitions +** +** +** Copyright (c) 1999-2006, Broadcom Corp., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ +#ifndef GKI_COMMON_H +#define GKI_COMMON_H + +#include "gki.h" +#include "dyn_mem.h" + +/* Task States: (For OSRdyTbl) */ +#define TASK_DEAD 0 /* b0000 */ +#define TASK_READY 1 /* b0001 */ +#define TASK_WAIT 2 /* b0010 */ +#define TASK_DELAY 4 /* b0100 */ +#define TASK_SUSPEND 8 /* b1000 */ + + +/******************************************************************** +** Internal Error codes +*********************************************************************/ +#define GKI_ERROR_BUF_CORRUPTED 0xFFFF +#define GKI_ERROR_NOT_BUF_OWNER 0xFFFE +#define GKI_ERROR_FREEBUF_BAD_QID 0xFFFD +#define GKI_ERROR_FREEBUF_BUF_LINKED 0xFFFC +#define GKI_ERROR_SEND_MSG_BAD_DEST 0xFFFB +#define GKI_ERROR_SEND_MSG_BUF_LINKED 0xFFFA +#define GKI_ERROR_ENQUEUE_BUF_LINKED 0xFFF9 +#define GKI_ERROR_DELETE_POOL_BAD_QID 0xFFF8 +#define GKI_ERROR_BUF_SIZE_TOOBIG 0xFFF7 +#define GKI_ERROR_BUF_SIZE_ZERO 0xFFF6 +#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5 + + +/******************************************************************** +** Misc constants +*********************************************************************/ + +#define GKI_MAX_INT32 (0x7fffffffL) +#define GKI_MAX_TIMESTAMP (0xffffffffL) + +/******************************************************************** +** Buffer Management Data Structures +*********************************************************************/ + +typedef struct _buffer_hdr +{ + struct _buffer_hdr *p_next; /* next buffer in the queue */ + UINT8 q_id; /* id of the queue */ + UINT8 task_id; /* task which allocated the buffer*/ + UINT8 status; /* FREE, UNLINKED or QUEUED */ + UINT8 Type; +} BUFFER_HDR_T; + +typedef struct _free_queue +{ + BUFFER_HDR_T *p_first; /* first buffer in the queue */ + BUFFER_HDR_T *p_last; /* last buffer in the queue */ + UINT16 size; /* size of the buffers in the pool */ + UINT16 total; /* toatal number of buffers */ + UINT16 cur_cnt; /* number of buffers currently allocated */ + UINT16 max_cnt; /* maximum number of buffers allocated at any time */ +} FREE_QUEUE_T; + + +/* Buffer related defines +*/ +#define ALIGN_POOL(pl_size) ( (((pl_size) + 3) / sizeof(UINT32)) * sizeof(UINT32)) +#define BUFFER_HDR_SIZE (sizeof(BUFFER_HDR_T)) /* Offset past header */ +#define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */ +#define MAX_USER_BUF_SIZE ((UINT16)0xffff - BUFFER_PADDING_SIZE) /* pool size must allow for header */ +#define MAGIC_NO 0xDDBADDBA + +#define BUF_STATUS_FREE 0 +#define BUF_STATUS_UNLINKED 1 +#define BUF_STATUS_QUEUED 2 + +// btla-specific ++ +#define GKI_USE_DEFERED_ALLOC_BUF_POOLS +// btla-specific -- + +/* Exception related structures (Used in debug mode only) +*/ +#if (GKI_DEBUG == TRUE) +typedef struct +{ + UINT16 type; + UINT8 taskid; + UINT8 msg[GKI_MAX_EXCEPTION_MSGLEN]; +} EXCEPTION_T; +#endif + + +/* Put all GKI variables into one control block +*/ +typedef struct +{ + /* Task management variables + */ + /* The stack and stack size are not used on Windows + */ +// btla-specific ++ +#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == FALSE)) +// btla-specific -- + +#if (GKI_NUM_FIXED_BUF_POOLS > 0) + UINT8 bufpool0[(ALIGN_POOL(GKI_BUF0_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 1) + UINT8 bufpool1[(ALIGN_POOL(GKI_BUF1_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 2) + UINT8 bufpool2[(ALIGN_POOL(GKI_BUF2_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 3) + UINT8 bufpool3[(ALIGN_POOL(GKI_BUF3_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 4) + UINT8 bufpool4[(ALIGN_POOL(GKI_BUF4_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 5) + UINT8 bufpool5[(ALIGN_POOL(GKI_BUF5_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 6) + UINT8 bufpool6[(ALIGN_POOL(GKI_BUF6_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 7) + UINT8 bufpool7[(ALIGN_POOL(GKI_BUF7_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 8) + UINT8 bufpool8[(ALIGN_POOL(GKI_BUF8_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 9) + UINT8 bufpool9[(ALIGN_POOL(GKI_BUF9_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 10) + UINT8 bufpool10[(ALIGN_POOL(GKI_BUF10_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 11) + UINT8 bufpool11[(ALIGN_POOL(GKI_BUF11_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 12) + UINT8 bufpool12[(ALIGN_POOL(GKI_BUF12_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 13) + UINT8 bufpool13[(ALIGN_POOL(GKI_BUF13_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 14) + UINT8 bufpool14[(ALIGN_POOL(GKI_BUF14_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX]; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 15) + UINT8 bufpool15[(ALIGN_POOL(GKI_BUF15_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX]; +#endif + +#else +/* Definitions for dynamic buffer use */ +#if (GKI_NUM_FIXED_BUF_POOLS > 0) + UINT8 *bufpool0; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 1) + UINT8 *bufpool1; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 2) + UINT8 *bufpool2; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 3) + UINT8 *bufpool3; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 4) + UINT8 *bufpool4; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 5) + UINT8 *bufpool5; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 6) + UINT8 *bufpool6; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 7) + UINT8 *bufpool7; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 8) + UINT8 *bufpool8; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 9) + UINT8 *bufpool9; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 10) + UINT8 *bufpool10; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 11) + UINT8 *bufpool11; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 12) + UINT8 *bufpool12; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 13) + UINT8 *bufpool13; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 14) + UINT8 *bufpool14; +#endif + +#if (GKI_NUM_FIXED_BUF_POOLS > 15) + UINT8 *bufpool15; +#endif + +#endif + + UINT8 *OSStack[GKI_MAX_TASKS]; /* pointer to beginning of stack */ + UINT16 OSStackSize[GKI_MAX_TASKS]; /* stack size available to each task */ + + + INT8 *OSTName[GKI_MAX_TASKS]; /* name of the task */ + + UINT8 OSRdyTbl[GKI_MAX_TASKS]; /* current state of the task */ + UINT16 OSWaitEvt[GKI_MAX_TASKS]; /* events that have to be processed by the task */ + UINT16 OSWaitForEvt[GKI_MAX_TASKS]; /* events the task is waiting for*/ + + UINT32 OSTicks; /* system ticks from start */ + UINT32 OSIdleCnt; /* idle counter */ + INT16 OSDisableNesting; /* counter to keep track of interrupt disable nesting */ + INT16 OSLockNesting; /* counter to keep track of sched lock nesting */ + INT16 OSIntNesting; /* counter to keep track of interrupt nesting */ + + /* Timer related variables + */ + INT32 OSTicksTilExp; /* Number of ticks till next timer expires */ +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + UINT32 OSTicksTilStop; /* inactivity delay timer; OS Ticks till stopping system tick */ +#endif + INT32 OSNumOrigTicks; /* Number of ticks between last timer expiration to the next one */ + + INT32 OSWaitTmr [GKI_MAX_TASKS]; /* ticks the task has to wait, for specific events */ + + /* Only take up space timers used in the system (GKI_NUM_TIMERS defined in target.h) */ +#if (GKI_NUM_TIMERS > 0) + INT32 OSTaskTmr0 [GKI_MAX_TASKS]; + INT32 OSTaskTmr0R [GKI_MAX_TASKS]; +#endif + +#if (GKI_NUM_TIMERS > 1) + INT32 OSTaskTmr1 [GKI_MAX_TASKS]; + INT32 OSTaskTmr1R [GKI_MAX_TASKS]; +#endif + +#if (GKI_NUM_TIMERS > 2) + INT32 OSTaskTmr2 [GKI_MAX_TASKS]; + INT32 OSTaskTmr2R [GKI_MAX_TASKS]; +#endif + +#if (GKI_NUM_TIMERS > 3) + INT32 OSTaskTmr3 [GKI_MAX_TASKS]; + INT32 OSTaskTmr3R [GKI_MAX_TASKS]; +#endif + + + + /* Buffer related variables + */ + BUFFER_HDR_T *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */ + BUFFER_HDR_T *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */ + + /* Define the buffer pool management variables + */ + FREE_QUEUE_T freeq[GKI_NUM_TOTAL_BUF_POOLS]; + + UINT16 pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS]; + UINT16 pool_max_count[GKI_NUM_TOTAL_BUF_POOLS]; + UINT16 pool_additions[GKI_NUM_TOTAL_BUF_POOLS]; + + /* Define the buffer pool start addresses + */ + UINT8 *pool_start[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the start of each buffer pool */ + UINT8 *pool_end[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the end of each buffer pool */ + UINT16 pool_size[GKI_NUM_TOTAL_BUF_POOLS]; /* actual size of the buffers in a pool */ + + /* Define the buffer pool access control variables */ + void *p_user_mempool; /* User O/S memory pool */ + UINT16 pool_access_mask; /* Bits are set if the corresponding buffer pool is a restricted pool */ + UINT8 pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */ + UINT8 curr_total_no_of_pools; /* number of fixed buf pools + current number of dynamic pools */ + + BOOLEAN timer_nesting; /* flag to prevent timer interrupt nesting */ + + /* Time queue arrays */ + TIMER_LIST_Q *timer_queues[GKI_MAX_TIMER_QUEUES]; + /* System tick callback */ + SYSTEM_TICK_CBACK *p_tick_cb; + BOOLEAN system_tick_running; /* TRUE if system tick is running. Valid only if p_tick_cb is not NULL */ + +#if (GKI_DEBUG == TRUE) + UINT16 ExceptionCnt; /* number of GKI exceptions that have happened */ + EXCEPTION_T Exception[GKI_MAX_EXCEPTION]; +#endif + +} tGKI_COM_CB; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal GKI function prototypes +*/ +GKI_API extern BOOLEAN gki_chk_buf_damage(void *); +extern BOOLEAN gki_chk_buf_owner(void *); +extern void gki_buffer_init (void); +extern void gki_timers_init(void); +extern void gki_adjust_timer_count (INT32); + +#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS +extern void gki_dealloc_free_queue(void); +#endif + +extern void OSStartRdy(void); +extern void OSCtxSw(void); +extern void OSIntCtxSw(void); +extern void OSSched(void); +extern void OSIntEnter(void); +extern void OSIntExit(void); + + +/* Debug aids +*/ +typedef void (*FP_PRINT)(char *, ...); + +#if (GKI_DEBUG == TRUE) + +typedef void (*PKT_PRINT)(UINT8 *, UINT16); + +extern void gki_print_task(FP_PRINT); +extern void gki_print_exception(FP_PRINT); +extern void gki_print_timer(FP_PRINT); +extern void gki_print_stack(FP_PRINT); +extern void gki_print_buffer(FP_PRINT); +extern void gki_print_buffer_statistics(FP_PRINT, INT16); +GKI_API extern void gki_print_used_bufs (FP_PRINT, UINT8); +extern void gki_dump(UINT8 *, UINT16, FP_PRINT); +extern void gki_dump2(UINT16 *, UINT16, FP_PRINT); +extern void gki_dump4(UINT32 *, UINT16, FP_PRINT); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gki/common/gki_debug.c b/gki/common/gki_debug.c new file mode 100644 index 0000000..3ec8fc5 --- /dev/null +++ b/gki/common/gki_debug.c @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Name gki_debug.c +** +** Function this file contains some sample GKI debug aid functions +** +** +** Copyright (c) 1999-2004, WIDCOMM Inc., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ + +#include "gki_int.h" + +#if (GKI_DEBUG == TRUE) + +const INT8 * const OSTaskStates[] = +{ + (INT8 *)"DEAD", /* 0 */ + (INT8 *)"REDY", /* 1 */ + (INT8 *)"WAIT", /* 2 */ + (INT8 *)"", + (INT8 *)"DELY", /* 4 */ + (INT8 *)"", + (INT8 *)"", + (INT8 *)"", + (INT8 *)"SUSP", /* 8 */ +}; + + +/******************************************************************************* +** +** Function GKI_PrintBufferUsage +** +** Description Displays Current Buffer Pool summary +** +** Returns void +** +*******************************************************************************/ +void GKI_PrintBufferUsage(UINT8 *p_num_pools, UINT16 *p_cur_used) +{ + int i; + FREE_QUEUE_T *p; + UINT8 num = gki_cb.com.curr_total_no_of_pools; + UINT16 cur[GKI_NUM_TOTAL_BUF_POOLS]; + + GKI_TRACE_0(""); + GKI_TRACE_0("--- GKI Buffer Pool Summary (R - restricted, P - public) ---"); + + GKI_TRACE_0("POOL SIZE USED MAXU TOTAL"); + GKI_TRACE_0("------------------------------"); + for (i = 0; i < gki_cb.com.curr_total_no_of_pools; i++) + { + p = &gki_cb.com.freeq[i]; + if ((1 << i) & gki_cb.com.pool_access_mask) + { + GKI_TRACE_5("%02d: (R), %4d, %3d, %3d, %3d", + i, p->size, p->cur_cnt, p->max_cnt, p->total); + } + else + { + GKI_TRACE_5("%02d: (P), %4d, %3d, %3d, %3d", + i, p->size, p->cur_cnt, p->max_cnt, p->total); + } + cur[i] = p->cur_cnt; + } + if (p_num_pools) + *p_num_pools = num; + if (p_cur_used) + memcpy(p_cur_used, cur, num*2); +} + +/******************************************************************************* +** +** Function GKI_PrintBuffer +** +** Description Called internally by OSS to print the buffer pools +** +** Returns void +** +*******************************************************************************/ +void GKI_PrintBuffer(void) +{ + UINT16 i; + for(i=0; i<GKI_NUM_TOTAL_BUF_POOLS; i++) + { + GKI_TRACE_5("pool:%4u free %4u cur %3u max %3u total%3u", i, gki_cb.com.freeq[i].size, + gki_cb.com.freeq[i].cur_cnt, gki_cb.com.freeq[i].max_cnt, gki_cb.com.freeq[i].total); + } +} + +/******************************************************************************* +** +** Function gki_calc_stack +** +** Description This function tries to calculate the amount of +** stack used by looking non magic num. Magic num is consider +** the first byte in the stack. +** +** Returns the number of unused byte on the stack. 4 in case of stack overrun +** +*******************************************************************************/ +UINT16 gki_calc_stack (UINT8 task) +{ + int j, stacksize; + UINT32 MagicNum; + UINT32 *p; + + stacksize = (int) gki_cb.com.OSStackSize[task]; + p = (UINT32 *)gki_cb.com.OSStack[task]; /* assume stack is aligned, */ + MagicNum = *p; + + for(j = 0; j < stacksize; j++) + { + if(*p++ != MagicNum) break; + } + + return (j * sizeof(UINT32)); +} + +/******************************************************************************* +** +** Function GKI_print_task +** +** Description Print task stack usage. +** +** Returns void +** +*******************************************************************************/ +void GKI_print_task(void) +{ +#ifdef _BT_WIN32 + GKI_TRACE_0("Service not available under insight"); +#else + UINT8 TaskId; + + GKI_TRACE_0("TID TASKNAME STATE FREE_STACK STACK"); + for(TaskId=0; TaskId < GKI_MAX_TASKS; TaskId++) + { + if (gki_cb.com.OSRdyTbl[TaskId] != TASK_DEAD) + { + GKI_TRACE_5("%2u %-8s %-5s 0x%04X 0x%04X Bytes", + (UINT16)TaskId, gki_cb.com.OSTName[TaskId], + OSTaskStates[gki_cb.com.OSRdyTbl[TaskId]], + gki_calc_stack(TaskId), gki_cb.com.OSStackSize[TaskId]); + + } + } +#endif +} + + +/******************************************************************************* +** +** Function gki_print_buffer_statistics +** +** Description Called internally by OSS to print the buffer pools statistics +** +** Returns void +** +*******************************************************************************/ +void gki_print_buffer_statistics(FP_PRINT print, INT16 pool) +{ + UINT16 i; + BUFFER_HDR_T *hdr; + UINT16 size,act_size,maxbuffs; + UINT32 *magic; + + if (pool > GKI_NUM_TOTAL_BUF_POOLS || pool < 0) + { + print("Not a valid Buffer pool\n"); + return; + } + + size = gki_cb.com.freeq[pool].size; + maxbuffs = gki_cb.com.freeq[pool].total; + act_size = size + BUFFER_PADDING_SIZE; + print("Buffer Pool[%u] size=%u cur_cnt=%u max_cnt=%u total=%u\n", + pool, gki_cb.com.freeq[pool].size, + gki_cb.com.freeq[pool].cur_cnt, gki_cb.com.freeq[pool].max_cnt, gki_cb.com.freeq[pool].total); + + print(" Owner State Sanity\n"); + print("----------------------------\n"); + hdr = (BUFFER_HDR_T *)(gki_cb.com.pool_start[pool]); + for(i=0; i<maxbuffs; i++) + { + magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + size); + print("%3d: 0x%02x %4d %10s\n", i, hdr->task_id, hdr->status, (*magic == MAGIC_NO)?"OK":"CORRUPTED"); + hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size); + } + return; +} + + +/******************************************************************************* +** +** Function gki_print_used_bufs +** +** Description Dumps used buffers in the particular pool +** +*******************************************************************************/ +GKI_API void gki_print_used_bufs (FP_PRINT print, UINT8 pool_id) +{ + UINT8 *p_start; + UINT16 buf_size; + UINT16 num_bufs; + BUFFER_HDR_T *p_hdr; + UINT16 i; + UINT32 *magic; + UINT16 *p; + + + if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS && gki_cb.com.pool_start[pool_id] != 0) + { + print("Not a valid Buffer pool\n"); + return; + } + + p_start = gki_cb.com.pool_start[pool_id]; + buf_size = gki_cb.com.freeq[pool_id].size + BUFFER_PADDING_SIZE; + num_bufs = gki_cb.com.freeq[pool_id].total; + + for (i = 0; i < num_bufs; i++, p_start += buf_size) + { + p_hdr = (BUFFER_HDR_T *)p_start; + magic = (UINT32 *)((UINT8 *)p_hdr + buf_size - sizeof(UINT32)); + p = (UINT16 *) p_hdr; + + if (p_hdr->status != BUF_STATUS_FREE) + { + print ("%d:0x%x (Q:%d,Task:%s,Stat:%d,%s) %04x %04x %04x %04x %04x %04x %04x %04x\n", + i, p_hdr, + p_hdr->q_id, + GKI_map_taskname(p_hdr->task_id), + p_hdr->status, + (*magic == MAGIC_NO)? "OK" : "CORRUPTED", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + } + } +} + + +/******************************************************************************* +** +** Function gki_print_task +** +** Description This function prints the task states. +** +** Returns void +** +*******************************************************************************/ +void gki_print_task (FP_PRINT print) +{ + UINT8 i; + + print("TID VID TASKNAME STATE WAIT WAITFOR TIMEOUT STACK\n"); + print("-------------------------------------------------\n"); + for(i=0; i<GKI_MAX_TASKS; i++) + { + if (gki_cb.com.OSRdyTbl[i] != TASK_DEAD) + { + print("%2u %-8s %-5s %04X %04X %7u %u/%u Bytes\n", + (UINT16)i, gki_cb.com.OSTName[i], + OSTaskStates[gki_cb.com.OSRdyTbl[i]], + gki_cb.com.OSWaitEvt[i], gki_cb.com.OSWaitForEvt[i], + gki_cb.com.OSWaitTmr[i], gki_calc_stack(i), gki_cb.com.OSStackSize[i]); + } + } +} + + +/******************************************************************************* +** +** Function gki_print_exception +** +** Description This function prints the exception information. +** +** Returns void +** +*******************************************************************************/ +void gki_print_exception(FP_PRINT print) +{ + UINT16 i; + EXCEPTION_T *pExp; + + print ("GKI Exceptions:\n"); + for (i = 0; i < gki_cb.com.ExceptionCnt; i++) + { + pExp = &gki_cb.com.Exception[i]; + print("%d: Type=%d, Task=%d: %s\n", i, + (INT32)pExp->type, (INT32)pExp->taskid, (INT8 *)pExp->msg); + } +} + + +/*****************************************************************************/ +void gki_dump (UINT8 *s, UINT16 len, FP_PRINT print) +{ + UINT16 i, j; + + for(i=0, j=0; i<len; i++) + { + if(j == 0) + print("\n%lX: %02X, ", &s[i], s[i]); + else if(j == 7) + print("%02X, ", s[i]); + else + print("%02X, ", s[i]); + if(++j == 16) + j=0; + } + print("\n"); +} + +void gki_dump2 (UINT16 *s, UINT16 len, FP_PRINT print) +{ + UINT16 i, j; + + for(i=0, j=0; i<len; i++) + { + if(j == 0) + print("\n%lX: %04X, ", &s[i], s[i]); + else + print("%04X, ", s[i]); + if(++j == 8) + j=0; + } + print("\n"); +} + +void gki_dump4 (UINT32 *s, UINT16 len, FP_PRINT print) +{ + UINT16 i, j; + + for(i=0, j=0; i<len; i++) + { + if(j == 0) + print("\n%lX: %08lX, ", &s[i], s[i]); + else + print("%08lX, ", s[i]); + if(++j == 4) + j=0; + } + print("\n"); +} + + +#endif diff --git a/gki/common/gki_inet.h b/gki/common/gki_inet.h new file mode 100644 index 0000000..780e9a0 --- /dev/null +++ b/gki/common/gki_inet.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Name gki_inet.h +** +** Function This file contains macros and interfaces for host-to-network +** conversions used in Internet operations. +** +** +** Copyright (c) 2002-2004, WIDCOMM Inc., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ +#ifndef GKI_INET_H +#define GKI_INET_H + +#include "data_types.h" + +#define htons ntohs +#define htonl ntohl + +#define htonets nettohs +#define htonetl nettohl + +#if BIG_ENDIAN == TRUE +#define ntohs(n) (n) +#define ntohl(n) (n) +#define ntoh6(n) (n) + +#define nettohs(n) (n) +#define nettohl(n) (n) +#else +extern UINT16 ntohs(UINT16 n); +extern UINT32 ntohl(UINT32 n); +extern UINT8 *ntoh6(UINT8 *p); + +#define nettohs(n) ((UINT16)((((n) << 8) & 0xff00) | (((n) >> 8) & 0x00ff))) +#define nettohl(n) ((((n) & 0x000000ff) << 24) | (((n) << 8) & 0x00ff0000) | \ + (((n) >> 8) & 0x0000ff00) | (((n) >> 24) & 0x000000ff)) +#endif + +#endif /* GKI_INET_H */ + diff --git a/gki/common/gki_time.c b/gki/common/gki_time.c new file mode 100644 index 0000000..8121654 --- /dev/null +++ b/gki/common/gki_time.c @@ -0,0 +1,1016 @@ + +/**************************************************************************** +** +** Name GKI_time.c +** +** Function this file contains GKI time related functions +** +** Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ + +#include "gki_int.h" + +#ifndef BT_ERROR_TRACE_0 +#define BT_ERROR_TRACE_0(l,m) +#endif + +/* Make sure that this has been defined in target.h */ +#ifndef GKI_NUM_TIMERS +#error NO TIMERS: Must define at least 1 timer in the system! +#endif + + +#define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL) /* Largest signed positive timer count */ +#define GKI_UNUSED_LIST_ENTRY (0x80000000L) /* Marks an unused timer list entry (initial value) */ +#define GKI_MAX_INT32 (0x7fffffffL) + +/******************************************************************************* +** +** Function gki_timers_init +** +** Description This internal function is called once at startup to initialize +** all the timer structures. +** +** Returns void +** +*******************************************************************************/ +void gki_timers_init(void) +{ + UINT8 tt; + + gki_cb.com.OSTicksTilExp = 0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */ + gki_cb.com.OSNumOrigTicks = 0; +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */ +#endif + + for (tt = 0; tt < GKI_MAX_TASKS; tt++) + { + gki_cb.com.OSWaitTmr [tt] = 0; + +#if (GKI_NUM_TIMERS > 0) + gki_cb.com.OSTaskTmr0 [tt] = 0; + gki_cb.com.OSTaskTmr0R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 1) + gki_cb.com.OSTaskTmr1 [tt] = 0; + gki_cb.com.OSTaskTmr1R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 2) + gki_cb.com.OSTaskTmr2 [tt] = 0; + gki_cb.com.OSTaskTmr2R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 3) + gki_cb.com.OSTaskTmr3 [tt] = 0; + gki_cb.com.OSTaskTmr3R [tt] = 0; +#endif + } + + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + gki_cb.com.timer_queues[tt] = NULL; + } + + gki_cb.com.p_tick_cb = NULL; + gki_cb.com.system_tick_running = FALSE; + + return; +} + +/******************************************************************************* +** +** Function gki_timers_is_timer_running +** +** Description This internal function is called to test if any gki timer are running +** +** +** Returns TRUE if at least one time is running in the system, FALSE else. +** +*******************************************************************************/ +BOOLEAN gki_timers_is_timer_running(void) +{ + UINT8 tt; + for (tt = 0; tt < GKI_MAX_TASKS; tt++) + { + +#if (GKI_NUM_TIMERS > 0) + if(gki_cb.com.OSTaskTmr0 [tt]) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 1) + if(gki_cb.com.OSTaskTmr1 [tt] ) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 2) + if(gki_cb.com.OSTaskTmr2 [tt] ) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 3) + if(gki_cb.com.OSTaskTmr3 [tt] ) + { + return TRUE; + } +#endif + } + + return FALSE; + +} + +/******************************************************************************* +** +** Function GKI_get_tick_count +** +** Description This function returns the current system ticks +** +** Returns The current number of system ticks +** +*******************************************************************************/ +UINT32 GKI_get_tick_count(void) +{ + return gki_cb.com.OSTicks; +} + + +/******************************************************************************* +** +** Function GKI_ready_to_sleep +** +** Description This function returns the number of system ticks until the +** next timer will expire. It is typically called by a power +** savings manager to find out how long it can have the system +** sleep before it needs to service the next entry. +** +** Parameters: None +** +** Returns Number of ticks til the next timer expires +** Note: the value is a signed value. This value should be +** compared to x > 0, to avoid misinterpreting negative tick +** values. +** +*******************************************************************************/ +INT32 GKI_ready_to_sleep (void) +{ + return (gki_cb.com.OSTicksTilExp); +} + + +/******************************************************************************* +** +** Function GKI_start_timer +** +** Description An application can call this function to start one of +** it's four general purpose timers. Any of the four timers +** can be 1-shot or continuous. If a timer is already running, +** it will be reset to the new parameters. +** +** Parameters tnum - (input) timer number to be started (TIMER_0, +** TIMER_1, TIMER_2, or TIMER_3) +** ticks - (input) the number of system ticks til the +** timer expires. +** is_continuous - (input) TRUE if timer restarts automatically, +** else FALSE if it is a 'one-shot'. +** +** Returns void +** +*******************************************************************************/ +void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous) +{ + INT32 reload; + INT32 orig_ticks; + UINT8 task_id = GKI_get_taskid(); + BOOLEAN bad_timer = FALSE; + + if (ticks <= 0) + ticks = 1; + + orig_ticks = ticks; /* save the ticks in case adjustment is necessary */ + + + /* If continuous timer, set reload, else set it to 0 */ + if (is_continuous) + reload = ticks; + else + reload = 0; + + GKI_disable(); + + if(gki_timers_is_timer_running() == FALSE) + { +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is not running, start system tick */ + if(gki_cb.com.OSTicksTilStop == 0) + { +#endif + if(gki_cb.com.p_tick_cb) + { + /* start system tick */ + gki_cb.com.system_tick_running = TRUE; + (gki_cb.com.p_tick_cb) (TRUE); + } +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + } + else + { + /* clear inactivity delay timer */ + gki_cb.com.OSTicksTilStop = 0; + } +#endif + } + /* Add the time since the last task timer update. + ** Note that this works when no timers are active since + ** both OSNumOrigTicks and OSTicksTilExp are 0. + */ + if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks) + { + ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp; + } + else + ticks = GKI_MAX_INT32; + + switch (tnum) + { +#if (GKI_NUM_TIMERS > 0) + case TIMER_0: + gki_cb.com.OSTaskTmr0R[task_id] = reload; + gki_cb.com.OSTaskTmr0 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 1) + case TIMER_1: + gki_cb.com.OSTaskTmr1R[task_id] = reload; + gki_cb.com.OSTaskTmr1 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 2) + case TIMER_2: + gki_cb.com.OSTaskTmr2R[task_id] = reload; + gki_cb.com.OSTaskTmr2 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 3) + case TIMER_3: + gki_cb.com.OSTaskTmr3R[task_id] = reload; + gki_cb.com.OSTaskTmr3 [task_id] = ticks; + break; +#endif + default: + bad_timer = TRUE; /* Timer number is bad, so do not use */ + } + + /* Update the expiration timeout if a legitimate timer */ + if (!bad_timer) + { + /* Only update the timeout value if it is less than any other newly started timers */ + gki_adjust_timer_count (orig_ticks); + } + + GKI_enable(); + +} + +/******************************************************************************* +** +** Function GKI_stop_timer +** +** Description An application can call this function to stop one of +** it's four general purpose timers. There is no harm in +** stopping a timer that is already stopped. +** +** Parameters tnum - (input) timer number to be started (TIMER_0, +** TIMER_1, TIMER_2, or TIMER_3) +** Returns void +** +*******************************************************************************/ +void GKI_stop_timer (UINT8 tnum) +{ + UINT8 task_id = GKI_get_taskid(); + + switch (tnum) + { +#if (GKI_NUM_TIMERS > 0) + case TIMER_0: + gki_cb.com.OSTaskTmr0R[task_id] = 0; + gki_cb.com.OSTaskTmr0 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 1) + case TIMER_1: + gki_cb.com.OSTaskTmr1R[task_id] = 0; + gki_cb.com.OSTaskTmr1 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 2) + case TIMER_2: + gki_cb.com.OSTaskTmr2R[task_id] = 0; + gki_cb.com.OSTaskTmr2 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 3) + case TIMER_3: + gki_cb.com.OSTaskTmr3R[task_id] = 0; + gki_cb.com.OSTaskTmr3 [task_id] = 0; + break; +#endif + } + + GKI_disable(); + + if (gki_timers_is_timer_running() == FALSE) + { + if (gki_cb.com.p_tick_cb) + { +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is not running */ + if ((gki_cb.com.system_tick_running)&&(gki_cb.com.OSTicksTilStop == 0)) + { + /* set inactivity delay timer */ + /* when timer expires, system tick will be stopped */ + gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK; + } +#else + gki_cb.com.system_tick_running = FALSE; + gki_cb.com.p_tick_cb(FALSE); /* stop system tick */ +#endif + } + } + + GKI_enable(); + + +} + + +/******************************************************************************* +** +** Function GKI_timer_update +** +** Description This function is called by an OS to drive the GKI's timers. +** It is typically called at every system tick to +** update the timers for all tasks, and check for timeouts. +** +** Note: It has been designed to also allow for variable tick updates +** so that systems with strict power savings requirements can +** have the update occur at variable intervals. +** +** Parameters: ticks_since_last_update - (input) This is the number of TICKS that have +** occurred since the last time GKI_timer_update was called. +** +** Returns void +** +*******************************************************************************/ +void GKI_timer_update (INT32 ticks_since_last_update) +{ + UINT8 task_id; + long next_expiration; /* Holds the next soonest expiration time after this update */ + + /* Increment the number of ticks used for time stamps */ + gki_cb.com.OSTicks += ticks_since_last_update; + + /* If any timers are running in any tasks, decrement the remaining time til + * the timer updates need to take place (next expiration occurs) + */ + gki_cb.com.OSTicksTilExp -= ticks_since_last_update; + + /* Don't allow timer interrupt nesting */ + if (gki_cb.com.timer_nesting) + return; + + gki_cb.com.timer_nesting = 1; + +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is set and expired */ + if (gki_cb.com.OSTicksTilStop) + { + if( gki_cb.com.OSTicksTilStop <= (UINT32)ticks_since_last_update ) + { + if(gki_cb.com.p_tick_cb) + { + gki_cb.com.system_tick_running = FALSE; + (gki_cb.com.p_tick_cb) (FALSE); /* stop system tick */ + } + gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */ + gki_cb.com.timer_nesting = 0; + return; + } + else + gki_cb.com.OSTicksTilStop -= ticks_since_last_update; + } +#endif + + /* No need to update the ticks if no timeout has occurred */ + if (gki_cb.com.OSTicksTilExp > 0) + { + gki_cb.com.timer_nesting = 0; + return; + } + + next_expiration = GKI_NO_NEW_TMRS_STARTED; + + /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks + to account for the difference so timer updates below are decremented by the full number + of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this + value only affects the timer updates below + */ + gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp; + +#if GKI_TIMER_LIST_NOPREEMPT == TRUE + /* Protect this section because if a GKI_timer_stop happens between: + * - gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; + * - gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; + * then the timer may appear stopped while it is about to be reloaded. + * Note: Not needed if this function cannot be preempted (typical). + */ + GKI_disable(); +#endif + + /* Check for OS Task Timers */ + for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) + { + if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */ + { + gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks; + if (gki_cb.com.OSWaitTmr[task_id] <= 0) + { + /* Timer Expired */ + gki_cb.com.OSRdyTbl[task_id] = TASK_READY; + } + } + +#if (GKI_NUM_TIMERS > 0) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr0[task_id] > 0) + { + gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr0[task_id] <= 0) + { + /* Reload timer and set Timer 0 Expired event mask */ + gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_0_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_0_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr0[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 1) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr1[task_id] > 0) + { + gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr1[task_id] <= 0) + { + /* Reload timer and set Timer 1 Expired event mask */ + gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_1_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_1_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr1[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 2) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr2[task_id] > 0) + { + gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr2[task_id] <= 0) + { + /* Reload timer and set Timer 2 Expired event mask */ + gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_2_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_2_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr2[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 3) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr3[task_id] > 0) + { + gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr3[task_id] <= 0) + { + /* Reload timer and set Timer 3 Expired event mask */ + gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_3_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_3_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr3[task_id]; +#endif + + } + +#if GKI_TIMER_LIST_NOPREEMPT == TRUE + /* End the critical section */ + GKI_enable(); +#endif + + /* Set the next timer experation value if there is one to start */ + if (next_expiration < GKI_NO_NEW_TMRS_STARTED) + { + gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration; + } + else + { + gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0; + } + + gki_cb.com.timer_nesting = 0; + + return; +} + + +/******************************************************************************* +** +** Function GKI_timer_queue_empty +** +** Description This function is called by applications to see whether the timer +** queue is empty +** +** Parameters +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN GKI_timer_queue_empty (void) +{ + UINT8 tt; + + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt]) + return FALSE; + } + + return TRUE; +} + +/******************************************************************************* +** +** Function GKI_timer_queue_register_callback +** +** Description This function is called by applications to register system tick +** start/stop callback for time queues +** +** +** Parameters p_callback - (input) pointer to the system tick callback +** +** Returns BOOLEAN +** +*******************************************************************************/ +void GKI_timer_queue_register_callback (SYSTEM_TICK_CBACK *p_callback) +{ + gki_cb.com.p_tick_cb = p_callback; + + return; +} + +/******************************************************************************* +** +** Function GKI_init_timer_list +** +** Description This function is called by applications when they +** want to initialize a timer list. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** +** Returns void +** +*******************************************************************************/ +void GKI_init_timer_list (TIMER_LIST_Q *p_timer_listq) +{ + p_timer_listq->p_first = NULL; + p_timer_listq->p_last = NULL; + p_timer_listq->last_ticks = 0; + + return; +} + +/******************************************************************************* +** +** Function GKI_init_timer_list_entry +** +** Description This function is called by the applications when they +** want to initialize a timer list entry. This must be +** done prior to first use of the entry. +** +** Parameters p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_init_timer_list_entry (TIMER_LIST_ENT *p_tle) +{ + p_tle->p_next = NULL; + p_tle->p_prev = NULL; + p_tle->ticks = GKI_UNUSED_LIST_ENTRY; + p_tle->in_use = FALSE; +} + + +/******************************************************************************* +** +** Function GKI_update_timer_list +** +** Description This function is called by the applications when they +** want to update a timer list. This should be at every +** timer list unit tick, e.g. once per sec, once per minute etc. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** num_units_since_last_update - (input) number of units since the last update +** (allows for variable unit update) +** +** NOTE: The following timer list update routines should not be used for exact time +** critical purposes. The timer tasks should be used when exact timing is needed. +** +** Returns the number of timers that have expired +** +*******************************************************************************/ +UINT16 GKI_update_timer_list (TIMER_LIST_Q *p_timer_listq, INT32 num_units_since_last_update) +{ + TIMER_LIST_ENT *p_tle; + UINT16 num_time_out = 0; + INT32 rem_ticks; + INT32 temp_ticks; + + p_tle = p_timer_listq->p_first; + + /* First, get the guys who have previously timed out */ + /* Note that the tick value of the timers should always be '0' */ + while ((p_tle) && (p_tle->ticks <= 0)) + { + num_time_out++; + p_tle = p_tle->p_next; + } + + /* Timer entriy tick values are relative to the preceeding entry */ + rem_ticks = num_units_since_last_update; + + /* Now, adjust remaining timer entries */ + while ((p_tle != NULL) && (rem_ticks > 0)) + { + temp_ticks = p_tle->ticks; + p_tle->ticks -= rem_ticks; + + /* See if this timer has just timed out */ + if (p_tle->ticks <= 0) + { + /* We set the number of ticks to '0' so that the legacy code + * that assumes a '0' or nonzero value will still work as coded. */ + p_tle->ticks = 0; + + num_time_out++; + } + + rem_ticks -= temp_ticks; /* Decrement the remaining ticks to process */ + p_tle = p_tle->p_next; + } + + if (p_timer_listq->last_ticks > 0) + { + p_timer_listq->last_ticks -= num_units_since_last_update; + + /* If the last timer has expired set last_ticks to 0 so that other list update + * functions will calculate correctly + */ + if (p_timer_listq->last_ticks < 0) + p_timer_listq->last_ticks = 0; + } + + return (num_time_out); +} + +/******************************************************************************* +** +** Function GKI_get_remaining_ticks +** +** Description This function is called by an application to get remaining +** ticks to expire +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_target_tle - (input) pointer to a timer list queue entry +** +** Returns 0 if timer is not used or timer is not in the list +** remaining ticks if success +** +*******************************************************************************/ +UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_target_tle) +{ + TIMER_LIST_ENT *p_tle; + UINT32 rem_ticks = 0; + + if (p_target_tle->in_use) + { + p_tle = p_timer_listq->p_first; + + /* adding up all of ticks in previous entries */ + while ((p_tle)&&(p_tle != p_target_tle)) + { + rem_ticks += p_tle->ticks; + p_tle = p_tle->p_next; + } + + /* if found target entry */ + if (p_tle == p_target_tle) + { + rem_ticks += p_tle->ticks; + } + else + { + BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: No timer entry in the list"); + return(0); + } + } + else + { + BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: timer entry is not active"); + } + + return (rem_ticks); +} + +/******************************************************************************* +** +** Function GKI_add_to_timer_list +** +** Description This function is called by an application to add a timer +** entry to a timer list. +** +** Note: A timer value of '0' will effectively insert an already +** expired event. Negative tick values will be ignored. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_add_to_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle) +{ + UINT32 nr_ticks_total; + UINT8 tt; + TIMER_LIST_ENT *p_temp; + + /* Only process valid tick values */ + if (p_tle->ticks >= 0) + { + /* If this entry is the last in the list */ + if (p_tle->ticks >= p_timer_listq->last_ticks) + { + /* If this entry is the only entry in the list */ + if (p_timer_listq->p_first == NULL) + p_timer_listq->p_first = p_tle; + else + { + /* Insert the entry onto the end of the list */ + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = p_tle; + + p_tle->p_prev = p_timer_listq->p_last; + } + + p_tle->p_next = NULL; + p_timer_listq->p_last = p_tle; + nr_ticks_total = p_tle->ticks; + p_tle->ticks -= p_timer_listq->last_ticks; + + p_timer_listq->last_ticks = nr_ticks_total; + } + else /* This entry needs to be inserted before the last entry */ + { + /* Find the entry that the new one needs to be inserted in front of */ + p_temp = p_timer_listq->p_first; + while (p_tle->ticks > p_temp->ticks) + { + /* Update the tick value if looking at an unexpired entry */ + if (p_temp->ticks > 0) + p_tle->ticks -= p_temp->ticks; + + p_temp = p_temp->p_next; + } + + /* The new entry is the first in the list */ + if (p_temp == p_timer_listq->p_first) + { + p_tle->p_next = p_timer_listq->p_first; + p_timer_listq->p_first->p_prev = p_tle; + p_timer_listq->p_first = p_tle; + } + else + { + p_temp->p_prev->p_next = p_tle; + p_tle->p_prev = p_temp->p_prev; + p_temp->p_prev = p_tle; + p_tle->p_next = p_temp; + } + p_temp->ticks -= p_tle->ticks; + } + + p_tle->in_use = TRUE; + + /* if we already add this timer queue to the array */ + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == p_timer_listq) + return; + } + /* add this timer queue to the array */ + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == NULL) + break; + } + if (tt < GKI_MAX_TIMER_QUEUES) + { + gki_cb.com.timer_queues[tt] = p_timer_listq; + } + } + + return; +} + + +/******************************************************************************* +** +** Function GKI_remove_from_timer_list +** +** Description This function is called by an application to remove a timer +** entry from a timer list. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_remove_from_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle) +{ + UINT8 tt; + + /* Verify that the entry is valid */ + if (p_tle == NULL || p_tle->in_use == FALSE || p_timer_listq->p_first == NULL) + { + return; + } + + /* Add the ticks remaining in this timer (if any) to the next guy in the list. + ** Note: Expired timers have a tick value of '0'. + */ + if (p_tle->p_next != NULL) + { + p_tle->p_next->ticks += p_tle->ticks; + } + else + { + p_timer_listq->last_ticks -= p_tle->ticks; + } + + /* Unlink timer from the list. + */ + if (p_timer_listq->p_first == p_tle) + { + p_timer_listq->p_first = p_tle->p_next; + + if (p_timer_listq->p_first != NULL) + p_timer_listq->p_first->p_prev = NULL; + + if (p_timer_listq->p_last == p_tle) + p_timer_listq->p_last = NULL; + } + else + { + if (p_timer_listq->p_last == p_tle) + { + p_timer_listq->p_last = p_tle->p_prev; + + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = NULL; + } + else + { + if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle) + p_tle->p_next->p_prev = p_tle->p_prev; + else + { + /* Error case - chain messed up ?? */ + return; + } + + if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle) + p_tle->p_prev->p_next = p_tle->p_next; + else + { + /* Error case - chain messed up ?? */ + return; + } + } + } + + p_tle->p_next = p_tle->p_prev = NULL; + p_tle->ticks = GKI_UNUSED_LIST_ENTRY; + p_tle->in_use = FALSE; + + /* if timer queue is empty */ + if (p_timer_listq->p_first == NULL && p_timer_listq->p_last == NULL) + { + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == p_timer_listq) + { + gki_cb.com.timer_queues[tt] = NULL; + break; + } + } + } + + return; +} + + +/******************************************************************************* +** +** Function gki_adjust_timer_count +** +** Description This function is called whenever a new timer or GKI_wait occurs +** to adjust (if necessary) the current time til the first expiration. +** This only needs to make an adjustment if the new timer (in ticks) is +** less than the number of ticks remaining on the current timer. +** +** Parameters: ticks - (input) number of system ticks of the new timer entry +** +** NOTE: This routine MUST be called while interrupts are disabled to +** avoid updates while adjusting the timer variables. +** +** Returns void +** +*******************************************************************************/ +void gki_adjust_timer_count (INT32 ticks) +{ + if (ticks > 0) + { + /* See if the new timer expires before the current first expiration */ + if (gki_cb.com.OSNumOrigTicks == 0 || (ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0)) + { + gki_cb.com.OSNumOrigTicks = (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks; + gki_cb.com.OSTicksTilExp = ticks; + } + } + + return; +} |