gki_buffer.c revision 45faad0ff5deeb0c676356345d99398cc4ab695a
1/****************************************************************************
2**
3**  Name:       gki_buffer.c
4**
5**  Function:   this file contains functions related GKI buffer
6**
7**
8**  Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved.
9**  Broadcom Bluetooth Core. Proprietary and confidential.
10**
11*****************************************************************************/
12#include "gki_int.h"
13#include <stdio.h>
14
15#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
16#error Number of pools out of range (16 Max)!
17#endif
18
19#if (!defined(BTU_STACK_LITE_ENABLED) || BTU_STACK_LITE_ENABLED == FALSE)
20static void gki_add_to_pool_list(UINT8 pool_id);
21static void gki_remove_from_pool_list(UINT8 pool_id);
22#endif /*  BTU_STACK_LITE_ENABLED == FALSE */
23
24#if GKI_BUFFER_DEBUG
25#define LOG_TAG "GKI_DEBUG"
26#define LOGD(format, ...)  LogMsg (TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI | TRACE_TYPE_GENERIC, format, ## __VA_ARGS__)
27#endif
28/*******************************************************************************
29**
30** Function         gki_init_free_queue
31**
32** Description      Internal function called at startup to initialize a free
33**                  queue. It is called once for each free queue.
34**
35** Returns          void
36**
37*******************************************************************************/
38static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
39{
40    UINT16           i;
41    UINT16           act_size;
42    BUFFER_HDR_T    *hdr;
43    BUFFER_HDR_T    *hdr1 = NULL;
44    UINT32          *magic;
45    INT32            tempsize = size;
46    tGKI_COM_CB     *p_cb = &gki_cb.com;
47
48    /* Ensure an even number of longwords */
49    tempsize = (INT32)ALIGN_POOL(size);
50    act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
51
52    /* Remember pool start and end addresses */
53    if(p_mem)
54    {
55        p_cb->pool_start[id] = (UINT8 *)p_mem;
56        p_cb->pool_end[id]   = (UINT8 *)p_mem + (act_size * total);
57    }
58
59    p_cb->pool_size[id]  = act_size;
60
61    p_cb->freeq[id].size      = (UINT16) tempsize;
62    p_cb->freeq[id].total     = total;
63    p_cb->freeq[id].cur_cnt   = 0;
64    p_cb->freeq[id].max_cnt   = 0;
65
66#if GKI_BUFFER_DEBUG
67    LOGD("gki_init_free_queue() init pool=%d, size=%d (aligned=%d) total=%d start=%p\n", id, size, tempsize, total, p_mem);
68#endif
69
70    /* Initialize  index table */
71    if(p_mem)
72    {
73        hdr = (BUFFER_HDR_T *)p_mem;
74        p_cb->freeq[id].p_first = hdr;
75        for (i = 0; i < total; i++)
76        {
77            hdr->task_id = GKI_INVALID_TASK;
78            hdr->q_id    = id;
79            hdr->status  = BUF_STATUS_FREE;
80            magic        = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
81            *magic       = MAGIC_NO;
82            hdr1         = hdr;
83            hdr          = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
84            hdr1->p_next = hdr;
85        }
86        hdr1->p_next = NULL;
87        p_cb->freeq[id].p_last = hdr1;
88    }
89    return;
90}
91
92#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
93static BOOLEAN gki_alloc_free_queue(UINT8 id)
94{
95    FREE_QUEUE_T  *Q;
96    tGKI_COM_CB *p_cb = &gki_cb.com;
97    printf("\ngki_alloc_free_queue in, id:%d \n", id);
98
99    Q = &p_cb->freeq[p_cb->pool_list[id]];
100
101    if(Q->p_first == 0)
102    {
103        void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total);
104        if(p_mem)
105        {
106            //re-initialize the queue with allocated memory
107            printf("\ngki_alloc_free_queue calling  gki_init_free_queue, id:%d  size:%d, totol:%d\n", id, Q->size, Q->total);
108            gki_init_free_queue(id, Q->size, Q->total, p_mem);
109            printf("\ngki_alloc_free_queue ret OK, id:%d  size:%d, totol:%d\n", id, Q->size, Q->total);
110            return TRUE;
111        }
112        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "gki_alloc_free_queue: Not enough memory");
113    }
114    printf("\ngki_alloc_free_queue out failed, id:%d\n", id);
115    return FALSE;
116}
117#endif
118
119/*******************************************************************************
120**
121** Function         gki_buffer_init
122**
123** Description      Called once internally by GKI at startup to initialize all
124**                  buffers and free buffer pools.
125**
126** Returns          void
127**
128*******************************************************************************/
129void gki_buffer_init(void)
130{
131    UINT8   i, tt, mb;
132    tGKI_COM_CB *p_cb = &gki_cb.com;
133
134    /* Initialize mailboxes */
135    for (tt = 0; tt < GKI_MAX_TASKS; tt++)
136    {
137        for (mb = 0; mb < NUM_TASK_MBOX; mb++)
138        {
139            p_cb->OSTaskQFirst[tt][mb] = NULL;
140            p_cb->OSTaskQLast [tt][mb] = NULL;
141        }
142    }
143
144    for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)
145    {
146        p_cb->pool_start[tt] = NULL;
147        p_cb->pool_end[tt]   = NULL;
148        p_cb->pool_size[tt]  = 0;
149
150        p_cb->freeq[tt].p_first = 0;
151        p_cb->freeq[tt].p_last  = 0;
152        p_cb->freeq[tt].size    = 0;
153        p_cb->freeq[tt].total   = 0;
154        p_cb->freeq[tt].cur_cnt = 0;
155        p_cb->freeq[tt].max_cnt = 0;
156    }
157
158    /* Use default from target.h */
159    p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
160
161#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == TRUE))
162
163#if (GKI_NUM_FIXED_BUF_POOLS > 0)
164    p_cb->bufpool0 = (UINT8 *)GKI_os_malloc ((GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX);
165#endif
166
167#if (GKI_NUM_FIXED_BUF_POOLS > 1)
168    p_cb->bufpool1 = (UINT8 *)GKI_os_malloc ((GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX);
169#endif
170
171#if (GKI_NUM_FIXED_BUF_POOLS > 2)
172    p_cb->bufpool2 = (UINT8 *)GKI_os_malloc ((GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX);
173#endif
174
175#if (GKI_NUM_FIXED_BUF_POOLS > 3)
176    p_cb->bufpool3 = (UINT8 *)GKI_os_malloc ((GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX);
177#endif
178
179#if (GKI_NUM_FIXED_BUF_POOLS > 4)
180    p_cb->bufpool4 = (UINT8 *)GKI_os_malloc ((GKI_BUF4_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX);
181#endif
182
183#if (GKI_NUM_FIXED_BUF_POOLS > 5)
184    p_cb->bufpool5 = (UINT8 *)GKI_os_malloc ((GKI_BUF5_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX);
185#endif
186
187#if (GKI_NUM_FIXED_BUF_POOLS > 6)
188    p_cb->bufpool6 = (UINT8 *)GKI_os_malloc ((GKI_BUF6_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX);
189#endif
190
191#if (GKI_NUM_FIXED_BUF_POOLS > 7)
192    p_cb->bufpool7 = (UINT8 *)GKI_os_malloc ((GKI_BUF7_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX);
193#endif
194
195#if (GKI_NUM_FIXED_BUF_POOLS > 8)
196    p_cb->bufpool8 = (UINT8 *)GKI_os_malloc ((GKI_BUF8_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX);
197#endif
198
199#if (GKI_NUM_FIXED_BUF_POOLS > 9)
200    p_cb->bufpool9 = (UINT8 *)GKI_os_malloc ((GKI_BUF9_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX);
201#endif
202
203#if (GKI_NUM_FIXED_BUF_POOLS > 10)
204    p_cb->bufpool10 = (UINT8 *)GKI_os_malloc ((GKI_BUF10_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX);
205#endif
206
207#if (GKI_NUM_FIXED_BUF_POOLS > 11)
208    p_cb->bufpool11 = (UINT8 *)GKI_os_malloc ((GKI_BUF11_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX);
209#endif
210
211#if (GKI_NUM_FIXED_BUF_POOLS > 12)
212    p_cb->bufpool12 = (UINT8 *)GKI_os_malloc ((GKI_BUF12_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX);
213#endif
214
215#if (GKI_NUM_FIXED_BUF_POOLS > 13)
216    p_cb->bufpool13 = (UINT8 *)GKI_os_malloc ((GKI_BUF13_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX);
217#endif
218
219#if (GKI_NUM_FIXED_BUF_POOLS > 14)
220    p_cb->bufpool14 = (UINT8 *)GKI_os_malloc ((GKI_BUF14_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX);
221#endif
222
223#if (GKI_NUM_FIXED_BUF_POOLS > 15)
224    p_cb->bufpool15 = (UINT8 *)GKI_os_malloc ((GKI_BUF15_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX);
225#endif
226
227#endif
228
229
230#if (GKI_NUM_FIXED_BUF_POOLS > 0)
231    gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0);
232#endif
233
234#if (GKI_NUM_FIXED_BUF_POOLS > 1)
235    gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1);
236#endif
237
238#if (GKI_NUM_FIXED_BUF_POOLS > 2)
239    gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2);
240#endif
241
242#if (GKI_NUM_FIXED_BUF_POOLS > 3)
243    gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3);
244#endif
245
246#if (GKI_NUM_FIXED_BUF_POOLS > 4)
247    gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4);
248#endif
249
250#if (GKI_NUM_FIXED_BUF_POOLS > 5)
251    gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5);
252#endif
253
254#if (GKI_NUM_FIXED_BUF_POOLS > 6)
255    gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6);
256#endif
257
258#if (GKI_NUM_FIXED_BUF_POOLS > 7)
259    gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7);
260#endif
261
262#if (GKI_NUM_FIXED_BUF_POOLS > 8)
263    gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8);
264#endif
265
266#if (GKI_NUM_FIXED_BUF_POOLS > 9)
267    gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9);
268#endif
269
270#if (GKI_NUM_FIXED_BUF_POOLS > 10)
271    gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10);
272#endif
273
274#if (GKI_NUM_FIXED_BUF_POOLS > 11)
275    gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11);
276#endif
277
278#if (GKI_NUM_FIXED_BUF_POOLS > 12)
279    gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12);
280#endif
281
282#if (GKI_NUM_FIXED_BUF_POOLS > 13)
283    gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13);
284#endif
285
286#if (GKI_NUM_FIXED_BUF_POOLS > 14)
287    gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14);
288#endif
289
290#if (GKI_NUM_FIXED_BUF_POOLS > 15)
291    gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
292#endif
293
294    /* add pools to the pool_list which is arranged in the order of size */
295    for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++)
296    {
297        p_cb->pool_list[i] = i;
298    }
299
300    p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
301
302    return;
303}
304
305
306/*******************************************************************************
307**
308** Function         GKI_init_q
309**
310** Description      Called by an application to initialize a buffer queue.
311**
312** Returns          void
313**
314*******************************************************************************/
315void GKI_init_q (BUFFER_Q *p_q)
316{
317    p_q->p_first = p_q->p_last = NULL;
318    p_q->count = 0;
319
320    return;
321}
322
323
324/*******************************************************************************
325**
326** Function         GKI_getbuf
327**
328** Description      Called by an application to get a free buffer which
329**                  is of size greater or equal to the requested size.
330**
331**                  Note: This routine only takes buffers from public pools.
332**                        It will not use any buffers from pools
333**                        marked GKI_RESTRICTED_POOL.
334**
335** Parameters       size - (input) number of bytes needed.
336**
337** Returns          A pointer to the buffer, or NULL if none available
338**
339*******************************************************************************/
340#if GKI_BUFFER_DEBUG
341void *GKI_getbuf_debug (UINT16 size, const char * _function_, int _line_)
342#else
343void *GKI_getbuf (UINT16 size)
344#endif
345{
346    UINT8         i;
347    FREE_QUEUE_T  *Q;
348    BUFFER_HDR_T  *p_hdr;
349    tGKI_COM_CB *p_cb = &gki_cb.com;
350#if GKI_BUFFER_DEBUG
351    UINT8         x;
352#endif
353
354    if (size == 0)
355    {
356        GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
357        return (NULL);
358    }
359
360#if GKI_BUFFER_DEBUG
361    LOGD("GKI_getbuf() requesting %d func:%s(line=%d)\n", size, _function_, _line_);
362#endif
363    /* Find the first buffer pool that is public that can hold the desired size */
364    for (i=0; i < p_cb->curr_total_no_of_pools; i++)
365    {
366        if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
367            break;
368    }
369
370    if(i == p_cb->curr_total_no_of_pools)
371    {
372        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
373        return (NULL);
374    }
375
376    /* Make sure the buffers aren't disturbed til finished with allocation */
377    GKI_disable();
378
379    /* search the public buffer pools that are big enough to hold the size
380     * until a free buffer is found */
381    for ( ; i < p_cb->curr_total_no_of_pools; i++)
382    {
383        /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
384        if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask)
385            continue;
386
387        Q = &p_cb->freeq[p_cb->pool_list[i]];
388        if(Q->cur_cnt < Q->total)
389        {
390        #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
391            if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
392                return NULL;
393        #endif
394            p_hdr = Q->p_first;
395            Q->p_first = p_hdr->p_next;
396
397            if (!Q->p_first)
398                Q->p_last = NULL;
399
400            if(++Q->cur_cnt > Q->max_cnt)
401                Q->max_cnt = Q->cur_cnt;
402
403            GKI_enable();
404
405            p_hdr->task_id = GKI_get_taskid();
406
407            p_hdr->status  = BUF_STATUS_UNLINKED;
408            p_hdr->p_next  = NULL;
409            p_hdr->Type    = 0;
410#if GKI_BUFFER_DEBUG
411            LOGD("GKI_getbuf() allocated, %x, %x (%d of %d used) %d\n", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[i].total);
412
413            strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN);
414            p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0';
415            p_hdr->_line = _line_;
416#endif
417            return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
418        }
419    }
420
421#if GKI_BUFFER_DEBUG
422    LOGD("GKI_getbuf() unable to allocated buffer!!!!!\n");
423    LOGD("******************** GKI Memory Pool Dump ********************\n");
424
425    p_cb = &gki_cb.com;
426
427    LOGD("Dumping total of %d buffer pools\n", p_cb->curr_total_no_of_pools);
428
429    for (i=0 ; i < p_cb->curr_total_no_of_pools; i++)
430    {
431        p_hdr = (BUFFER_HDR_T *)p_cb->pool_start[i];
432
433        LOGD("pool %d has a total of %d buffers (start=%p)\n", i, p_cb->freeq[i].total, p_hdr);
434
435        for (x=0; p_hdr && x < p_cb->freeq[i].total; x++)
436        {
437            if (p_hdr->status != BUF_STATUS_FREE)
438            {
439                LOGD("pool:%d, buf[%d]:%x, hdr:%x status=%d func:%s(line=%d)\n", i, x, (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, p_hdr->status, p_hdr->_function, p_hdr->_line);
440            }
441
442            p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_hdr + p_cb->pool_size[i]);
443        }
444    }
445    LOGD("**************************************************************\n");
446#endif
447
448    GKI_enable();
449
450    return (NULL);
451}
452
453
454/*******************************************************************************
455**
456** Function         GKI_getpoolbuf
457**
458** Description      Called by an application to get a free buffer from
459**                  a specific buffer pool.
460**
461**                  Note: If there are no more buffers available from the pool,
462**                        the public buffers are searched for an available buffer.
463**
464** Parameters       pool_id - (input) pool ID to get a buffer out of.
465**
466** Returns          A pointer to the buffer, or NULL if none available
467**
468*******************************************************************************/
469#if GKI_BUFFER_DEBUG
470void *GKI_getpoolbuf_debug (UINT8 pool_id, const char * _function_, int _line_)
471#else
472void *GKI_getpoolbuf (UINT8 pool_id)
473#endif
474{
475    FREE_QUEUE_T  *Q;
476    BUFFER_HDR_T  *p_hdr;
477    tGKI_COM_CB *p_cb = &gki_cb.com;
478
479    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
480        return (NULL);
481
482#if GKI_BUFFER_DEBUG
483    LOGD("GKI_getpoolbuf() requesting from %d func:%s(line=%d)\n", pool_id, _function_, _line_);
484#endif
485    /* Make sure the buffers aren't disturbed til finished with allocation */
486    GKI_disable();
487
488    Q = &p_cb->freeq[pool_id];
489    if(Q->cur_cnt < Q->total)
490    {
491#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
492        if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
493            return NULL;
494#endif
495        p_hdr = Q->p_first;
496        Q->p_first = p_hdr->p_next;
497
498        if (!Q->p_first)
499            Q->p_last = NULL;
500
501        if(++Q->cur_cnt > Q->max_cnt)
502            Q->max_cnt = Q->cur_cnt;
503
504        GKI_enable();
505
506
507        p_hdr->task_id = GKI_get_taskid();
508
509        p_hdr->status  = BUF_STATUS_UNLINKED;
510        p_hdr->p_next  = NULL;
511        p_hdr->Type    = 0;
512
513#if GKI_BUFFER_DEBUG
514        LOGD("GKI_getpoolbuf() allocated, %x, %x (%d of %d used) %d\n", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[pool_id].total);
515
516        strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN);
517        p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0';
518        p_hdr->_line = _line_;
519#endif
520        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
521    }
522
523    /* If here, no buffers in the specified pool */
524    GKI_enable();
525
526#if GKI_BUFFER_DEBUG
527    /* try for free buffers in public pools */
528    return (GKI_getbuf_debug(p_cb->freeq[pool_id].size, _function_, _line_));
529#else
530    /* try for free buffers in public pools */
531    return (GKI_getbuf(p_cb->freeq[pool_id].size));
532#endif
533}
534
535/*******************************************************************************
536**
537** Function         GKI_freebuf
538**
539** Description      Called by an application to return a buffer to the free pool.
540**
541** Parameters       p_buf - (input) address of the beginning of a buffer.
542**
543** Returns          void
544**
545*******************************************************************************/
546void GKI_freebuf (void *p_buf)
547{
548    FREE_QUEUE_T    *Q;
549    BUFFER_HDR_T    *p_hdr;
550
551#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
552    if (!p_buf || gki_chk_buf_damage(p_buf))
553    {
554        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
555        return;
556    }
557#endif
558
559    p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
560
561#if GKI_BUFFER_DEBUG
562    LOGD("GKI_freebuf() freeing, %x, %x, func:%s(line=%d)\n", p_buf, p_hdr, p_hdr->_function, p_hdr->_line);
563#endif
564
565    if (p_hdr->status != BUF_STATUS_UNLINKED)
566    {
567        GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
568        return;
569    }
570
571    if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS)
572    {
573        GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
574        return;
575    }
576
577    GKI_disable();
578
579    /*
580    ** Release the buffer
581    */
582    Q  = &gki_cb.com.freeq[p_hdr->q_id];
583    if (Q->p_last)
584        Q->p_last->p_next = p_hdr;
585    else
586        Q->p_first = p_hdr;
587
588    Q->p_last      = p_hdr;
589    p_hdr->p_next  = NULL;
590    p_hdr->status  = BUF_STATUS_FREE;
591    p_hdr->task_id = GKI_INVALID_TASK;
592    if (Q->cur_cnt > 0)
593        Q->cur_cnt--;
594
595    GKI_enable();
596
597    return;
598}
599
600
601/*******************************************************************************
602**
603** Function         GKI_get_buf_size
604**
605** Description      Called by an application to get the size of a buffer.
606**
607** Parameters       p_buf - (input) address of the beginning of a buffer.
608**
609** Returns          the size of the buffer
610**
611*******************************************************************************/
612UINT16 GKI_get_buf_size (void *p_buf)
613{
614    BUFFER_HDR_T    *p_hdr;
615
616    p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE);
617
618    if ((UINT32)p_hdr & 1)
619        return (0);
620
621    if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS)
622    {
623        return (gki_cb.com.freeq[p_hdr->q_id].size);
624    }
625
626    return (0);
627}
628
629/*******************************************************************************
630**
631** Function         gki_chk_buf_damage
632**
633** Description      Called internally by OSS to check for buffer corruption.
634**
635** Returns          TRUE if there is a problem, else FALSE
636**
637*******************************************************************************/
638BOOLEAN gki_chk_buf_damage(void *p_buf)
639{
640#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
641
642    UINT32 *magic;
643    magic  = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf));
644
645    if ((UINT32)magic & 1)
646        return (TRUE);
647
648    if (*magic == MAGIC_NO)
649        return (FALSE);
650
651    return (TRUE);
652
653#else
654
655    return (FALSE);
656
657#endif
658}
659
660/*******************************************************************************
661**
662** Function         GKI_send_msg
663**
664** Description      Called by applications to send a buffer to a task
665**
666** Returns          Nothing
667**
668*******************************************************************************/
669void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)
670{
671    BUFFER_HDR_T    *p_hdr;
672    tGKI_COM_CB *p_cb = &gki_cb.com;
673
674    /* If task non-existant or not started, drop buffer */
675    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
676    {
677        GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
678        GKI_freebuf (msg);
679        return;
680    }
681
682#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
683    if (gki_chk_buf_damage(msg))
684    {
685        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
686        return;
687    }
688#endif
689
690    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
691
692    if (p_hdr->status != BUF_STATUS_UNLINKED)
693    {
694        GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
695        return;
696    }
697
698    GKI_disable();
699
700    if (p_cb->OSTaskQFirst[task_id][mbox])
701        p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
702    else
703        p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
704
705    p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
706
707    p_hdr->p_next = NULL;
708    p_hdr->status = BUF_STATUS_QUEUED;
709    p_hdr->task_id = task_id;
710
711
712    GKI_enable();
713
714    GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
715
716    return;
717}
718
719/*******************************************************************************
720**
721** Function         GKI_read_mbox
722**
723** Description      Called by applications to read a buffer from one of
724**                  the task mailboxes.  A task can only read its own mailbox.
725**
726** Parameters:      mbox  - (input) mailbox ID to read (0, 1, 2, or 3)
727**
728** Returns          NULL if the mailbox was empty, else the address of a buffer
729**
730*******************************************************************************/
731void *GKI_read_mbox (UINT8 mbox)
732{
733    UINT8           task_id = GKI_get_taskid();
734    void            *p_buf = NULL;
735    BUFFER_HDR_T    *p_hdr;
736
737    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX))
738        return (NULL);
739
740    GKI_disable();
741
742    if (gki_cb.com.OSTaskQFirst[task_id][mbox])
743    {
744        p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
745        gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
746
747        p_hdr->p_next = NULL;
748        p_hdr->status = BUF_STATUS_UNLINKED;
749
750        p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE;
751    }
752
753    GKI_enable();
754
755    return (p_buf);
756}
757
758
759
760/*******************************************************************************
761**
762** Function         GKI_enqueue
763**
764** Description      Enqueue a buffer at the tail of the queue
765**
766** Parameters:      p_q  -  (input) pointer to a queue.
767**                  p_buf - (input) address of the buffer to enqueue
768**
769** Returns          void
770**
771*******************************************************************************/
772void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
773{
774    BUFFER_HDR_T    *p_hdr;
775
776#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
777    if (gki_chk_buf_damage(p_buf))
778    {
779        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
780        return;
781    }
782#endif
783
784    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
785
786    if (p_hdr->status != BUF_STATUS_UNLINKED)
787    {
788        GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked");
789        return;
790    }
791
792    GKI_disable();
793
794    /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
795    if (p_q->p_first)
796    {
797        BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE);
798        p_last_hdr->p_next = p_hdr;
799    }
800    else
801        p_q->p_first = p_buf;
802
803    p_q->p_last = p_buf;
804    p_q->count++;
805
806    p_hdr->p_next = NULL;
807    p_hdr->status = BUF_STATUS_QUEUED;
808
809    GKI_enable();
810
811    return;
812}
813
814
815/*******************************************************************************
816**
817** Function         GKI_enqueue_head
818**
819** Description      Enqueue a buffer at the head of the queue
820**
821** Parameters:      p_q  -  (input) pointer to a queue.
822**                  p_buf - (input) address of the buffer to enqueue
823**
824** Returns          void
825**
826*******************************************************************************/
827void GKI_enqueue_head (BUFFER_Q *p_q, void *p_buf)
828{
829    BUFFER_HDR_T    *p_hdr;
830
831#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
832    if (gki_chk_buf_damage(p_buf))
833    {
834        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
835        return;
836    }
837#endif
838
839    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
840
841    if (p_hdr->status != BUF_STATUS_UNLINKED)
842    {
843        GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue head - buf already linked");
844        return;
845    }
846
847    GKI_disable();
848
849    if (p_q->p_first)
850    {
851        p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
852        p_q->p_first = p_buf;
853    }
854    else
855    {
856        p_q->p_first = p_buf;
857        p_q->p_last  = p_buf;
858        p_hdr->p_next = NULL;
859    }
860    p_q->count++;
861
862    p_hdr->status = BUF_STATUS_QUEUED;
863
864    GKI_enable();
865
866    return;
867}
868
869
870/*******************************************************************************
871**
872** Function         GKI_dequeue
873**
874** Description      Dequeues a buffer from the head of a queue
875**
876** Parameters:      p_q  - (input) pointer to a queue.
877**
878** Returns          NULL if queue is empty, else buffer
879**
880*******************************************************************************/
881void *GKI_dequeue (BUFFER_Q *p_q)
882{
883    BUFFER_HDR_T    *p_hdr;
884
885    GKI_disable();
886
887    if (!p_q || !p_q->count)
888    {
889        GKI_enable();
890        return (NULL);
891    }
892
893    p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
894
895    /* Keep buffers such that GKI header is invisible
896    */
897    if (p_hdr->p_next)
898        p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
899    else
900    {
901        p_q->p_first = NULL;
902        p_q->p_last  = NULL;
903    }
904
905    p_q->count--;
906
907    p_hdr->p_next = NULL;
908    p_hdr->status = BUF_STATUS_UNLINKED;
909
910    GKI_enable();
911
912    return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
913}
914
915
916/*******************************************************************************
917**
918** Function         GKI_remove_from_queue
919**
920** Description      Dequeue a buffer from the middle of the queue
921**
922** Parameters:      p_q  - (input) pointer to a queue.
923**                  p_buf - (input) address of the buffer to enqueue
924**
925** Returns          NULL if queue is empty, else buffer
926**
927*******************************************************************************/
928void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
929{
930    BUFFER_HDR_T    *p_prev;
931    BUFFER_HDR_T    *p_buf_hdr;
932
933    GKI_disable();
934
935    if (p_buf == p_q->p_first)
936    {
937        GKI_enable();
938        return (GKI_dequeue (p_q));
939    }
940
941    p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
942    p_prev    = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
943
944    for ( ; p_prev; p_prev = p_prev->p_next)
945    {
946        /* If the previous points to this one, move the pointers around */
947        if (p_prev->p_next == p_buf_hdr)
948        {
949            p_prev->p_next = p_buf_hdr->p_next;
950
951            /* If we are removing the last guy in the queue, update p_last */
952            if (p_buf == p_q->p_last)
953                p_q->p_last = p_prev + 1;
954
955            /* One less in the queue */
956            p_q->count--;
957
958            /* The buffer is now unlinked */
959            p_buf_hdr->p_next = NULL;
960            p_buf_hdr->status = BUF_STATUS_UNLINKED;
961
962            GKI_enable();
963            return (p_buf);
964        }
965    }
966
967    GKI_enable();
968    return (NULL);
969}
970
971/*******************************************************************************
972**
973** Function         GKI_getfirst
974**
975** Description      Return a pointer to the first buffer in a queue
976**
977** Parameters:      p_q  - (input) pointer to a queue.
978**
979** Returns          NULL if queue is empty, else buffer address
980**
981*******************************************************************************/
982void *GKI_getfirst (BUFFER_Q *p_q)
983{
984    return (p_q->p_first);
985}
986
987/*******************************************************************************
988**
989** Function         GKI_getlast
990**
991** Description      Return a pointer to the last buffer in a queue
992**
993** Parameters:      p_q  - (input) pointer to a queue.
994**
995** Returns          NULL if queue is empty, else buffer address
996**
997*******************************************************************************/
998void *GKI_getlast (BUFFER_Q *p_q)
999{
1000    return (p_q->p_last);
1001}
1002
1003/*******************************************************************************
1004**
1005** Function         GKI_getnext
1006**
1007** Description      Return a pointer to the next buffer in a queue
1008**
1009** Parameters:      p_buf  - (input) pointer to the buffer to find the next one from.
1010**
1011** Returns          NULL if no more buffers in the queue, else next buffer address
1012**
1013*******************************************************************************/
1014void *GKI_getnext (void *p_buf)
1015{
1016    BUFFER_HDR_T    *p_hdr;
1017
1018    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
1019
1020    if (p_hdr->p_next)
1021        return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
1022    else
1023        return (NULL);
1024}
1025
1026
1027
1028/*******************************************************************************
1029**
1030** Function         GKI_queue_is_empty
1031**
1032** Description      Check the status of a queue.
1033**
1034** Parameters:      p_q  - (input) pointer to a queue.
1035**
1036** Returns          TRUE if queue is empty, else FALSE
1037**
1038*******************************************************************************/
1039BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
1040{
1041    return ((BOOLEAN) (p_q->count == 0));
1042}
1043
1044/*******************************************************************************
1045**
1046** Function         GKI_find_buf_start
1047**
1048** Description      This function is called with an address inside a buffer,
1049**                  and returns the start address ofthe buffer.
1050**
1051**                  The buffer should be one allocated from one of GKI's pools.
1052**
1053** Parameters:      p_user_area - (input) address of anywhere in a GKI buffer.
1054**
1055** Returns          void * - Address of the beginning of the specified buffer if successful,
1056**                          otherwise NULL if unsuccessful
1057**
1058*******************************************************************************/
1059void *GKI_find_buf_start (void *p_user_area)
1060{
1061    UINT16       xx, size;
1062    UINT32       yy;
1063    tGKI_COM_CB *p_cb = &gki_cb.com;
1064    UINT8       *p_ua = (UINT8 *)p_user_area;
1065
1066    for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
1067    {
1068        if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx]))
1069        {
1070            yy = (UINT32)(p_ua - p_cb->pool_start[xx]);
1071
1072            size = p_cb->pool_size[xx];
1073
1074            yy = (yy / size) * size;
1075
1076            return ((void *) (p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)) );
1077        }
1078    }
1079
1080    /* If here, invalid address - not in one of our buffers */
1081    GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
1082
1083    return (NULL);
1084}
1085
1086
1087/********************************************************
1088* The following functions are not needed for light stack
1089*********************************************************/
1090#if (!defined(BTU_STACK_LITE_ENABLED) || BTU_STACK_LITE_ENABLED == FALSE)
1091
1092/*******************************************************************************
1093**
1094** Function         GKI_set_pool_permission
1095**
1096** Description      This function is called to set or change the permissions for
1097**                  the specified pool ID.
1098**
1099** Parameters       pool_id -       (input) pool ID to be set or changed
1100**                  permission -    (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
1101**
1102** Returns          GKI_SUCCESS if successful
1103**                  GKI_INVALID_POOL if unsuccessful
1104**
1105*******************************************************************************/
1106UINT8 GKI_set_pool_permission(UINT8 pool_id, UINT8 permission)
1107{
1108    tGKI_COM_CB *p_cb = &gki_cb.com;
1109
1110    if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
1111    {
1112        if (permission == GKI_RESTRICTED_POOL)
1113            p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask | (1 << pool_id));
1114
1115        else    /* mark the pool as public */
1116            p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask & ~(1 << pool_id));
1117
1118        return (GKI_SUCCESS);
1119    }
1120    else
1121        return (GKI_INVALID_POOL);
1122}
1123
1124/*******************************************************************************
1125**
1126** Function         gki_add_to_pool_list
1127**
1128** Description      Adds pool to the pool list which is arranged in the
1129**                  order of size
1130**
1131** Returns          void
1132**
1133*******************************************************************************/
1134static void gki_add_to_pool_list(UINT8 pool_id)
1135{
1136
1137    INT32 i, j;
1138    tGKI_COM_CB *p_cb = &gki_cb.com;
1139
1140     /* Find the position where the specified pool should be inserted into the list */
1141    for(i=0; i < p_cb->curr_total_no_of_pools; i++)
1142    {
1143
1144        if(p_cb->freeq[pool_id].size <= p_cb->freeq[ p_cb->pool_list[i] ].size)
1145            break;
1146    }
1147
1148    /* Insert the new buffer pool ID into the list of pools */
1149    for(j = p_cb->curr_total_no_of_pools; j > i; j--)
1150    {
1151        p_cb->pool_list[j] = p_cb->pool_list[j-1];
1152    }
1153
1154    p_cb->pool_list[i] = pool_id;
1155
1156    return;
1157}
1158
1159/*******************************************************************************
1160**
1161** Function         gki_remove_from_pool_list
1162**
1163** Description      Removes pool from the pool list. Called when a pool is deleted
1164**
1165** Returns          void
1166**
1167*******************************************************************************/
1168static void gki_remove_from_pool_list(UINT8 pool_id)
1169{
1170    tGKI_COM_CB *p_cb = &gki_cb.com;
1171    UINT8 i;
1172
1173    for(i=0; i < p_cb->curr_total_no_of_pools; i++)
1174    {
1175        if(pool_id == p_cb->pool_list[i])
1176            break;
1177    }
1178
1179    while (i < (p_cb->curr_total_no_of_pools - 1))
1180    {
1181        p_cb->pool_list[i] = p_cb->pool_list[i+1];
1182        i++;
1183    }
1184
1185    return;
1186}
1187
1188/*******************************************************************************
1189**
1190** Function         GKI_igetpoolbuf
1191**
1192** Description      Called by an interrupt service routine to get a free buffer from
1193**                  a specific buffer pool.
1194**
1195** Parameters       pool_id - (input) pool ID to get a buffer out of.
1196**
1197** Returns          A pointer to the buffer, or NULL if none available
1198**
1199*******************************************************************************/
1200void *GKI_igetpoolbuf (UINT8 pool_id)
1201{
1202    FREE_QUEUE_T  *Q;
1203    BUFFER_HDR_T  *p_hdr;
1204
1205    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1206        return (NULL);
1207
1208
1209    Q = &gki_cb.com.freeq[pool_id];
1210    if(Q->cur_cnt < Q->total)
1211    {
1212        p_hdr = Q->p_first;
1213        Q->p_first = p_hdr->p_next;
1214
1215        if (!Q->p_first)
1216            Q->p_last = NULL;
1217
1218        if(++Q->cur_cnt > Q->max_cnt)
1219            Q->max_cnt = Q->cur_cnt;
1220
1221        p_hdr->task_id = GKI_get_taskid();
1222
1223        p_hdr->status  = BUF_STATUS_UNLINKED;
1224        p_hdr->p_next  = NULL;
1225        p_hdr->Type    = 0;
1226
1227        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
1228    }
1229
1230    return (NULL);
1231}
1232
1233/*******************************************************************************
1234**
1235** Function         GKI_poolcount
1236**
1237** Description      Called by an application to get the total number of buffers
1238**                  in the specified buffer pool.
1239**
1240** Parameters       pool_id - (input) pool ID to get the free count of.
1241**
1242** Returns          the total number of buffers in the pool
1243**
1244*******************************************************************************/
1245UINT16 GKI_poolcount (UINT8 pool_id)
1246{
1247    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1248        return (0);
1249
1250    return (gki_cb.com.freeq[pool_id].total);
1251}
1252
1253/*******************************************************************************
1254**
1255** Function         GKI_poolfreecount
1256**
1257** Description      Called by an application to get the number of free buffers
1258**                  in the specified buffer pool.
1259**
1260** Parameters       pool_id - (input) pool ID to get the free count of.
1261**
1262** Returns          the number of free buffers in the pool
1263**
1264*******************************************************************************/
1265UINT16 GKI_poolfreecount (UINT8 pool_id)
1266{
1267    FREE_QUEUE_T  *Q;
1268
1269    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1270        return (0);
1271
1272    Q  = &gki_cb.com.freeq[pool_id];
1273
1274    return ((UINT16)(Q->total - Q->cur_cnt));
1275}
1276
1277/*******************************************************************************
1278**
1279** Function         GKI_change_buf_owner
1280**
1281** Description      Called to change the task ownership of a buffer.
1282**
1283** Parameters:      p_buf   - (input) pointer to the buffer
1284**                  task_id - (input) task id to change ownership to
1285**
1286** Returns          void
1287**
1288*******************************************************************************/
1289void GKI_change_buf_owner (void *p_buf, UINT8 task_id)
1290{
1291    BUFFER_HDR_T    *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
1292
1293    p_hdr->task_id = task_id;
1294
1295    return;
1296}
1297
1298#if (defined(GKI_SEND_MSG_FROM_ISR) &&  GKI_SEND_MSG_FROM_ISR == TRUE)
1299/*******************************************************************************
1300**
1301** Function         GKI_isend_msg
1302**
1303** Description      Called from interrupt context to send a buffer to a task
1304**
1305** Returns          Nothing
1306**
1307*******************************************************************************/
1308void GKI_isend_msg (UINT8 task_id, UINT8 mbox, void *msg)
1309{
1310    BUFFER_HDR_T    *p_hdr;
1311    tGKI_COM_CB *p_cb = &gki_cb.com;
1312
1313    /* If task non-existant or not started, drop buffer */
1314    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
1315    {
1316        GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
1317        GKI_freebuf (msg);
1318        return;
1319    }
1320
1321#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
1322    if (gki_chk_buf_damage(msg))
1323    {
1324        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
1325        return;
1326    }
1327#endif
1328
1329#if (GKI_ENABLE_OWNER_CHECK == TRUE)
1330    if (gki_chk_buf_owner(msg))
1331    {
1332        GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner");
1333        return;
1334    }
1335#endif
1336
1337    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
1338
1339    if (p_hdr->status != BUF_STATUS_UNLINKED)
1340    {
1341        GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
1342        return;
1343    }
1344
1345    if (p_cb->OSTaskQFirst[task_id][mbox])
1346        p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
1347    else
1348        p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
1349
1350    p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
1351
1352    p_hdr->p_next = NULL;
1353    p_hdr->status = BUF_STATUS_QUEUED;
1354    p_hdr->task_id = task_id;
1355
1356    GKI_isend_event(task_id, (UINT16)EVENT_MASK(mbox));
1357
1358    return;
1359}
1360#endif
1361
1362/*******************************************************************************
1363**
1364** Function         GKI_create_pool
1365**
1366** Description      Called by applications to create a buffer pool.
1367**
1368** Parameters:      size        - (input) length (in bytes) of each buffer in the pool
1369**                  count       - (input) number of buffers to allocate for the pool
1370**                  permission  - (input) restricted or public access?
1371**                                        (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
1372**                  p_mem_pool  - (input) pointer to an OS memory pool, NULL if not provided
1373**
1374** Returns          the buffer pool ID, which should be used in calls to
1375**                  GKI_getpoolbuf(). If a pool could not be created, this
1376**                  function returns 0xff.
1377**
1378*******************************************************************************/
1379UINT8 GKI_create_pool (UINT16 size, UINT16 count, UINT8 permission, void *p_mem_pool)
1380{
1381    UINT8        xx;
1382    UINT32       mem_needed;
1383    INT32        tempsize = size;
1384    tGKI_COM_CB *p_cb = &gki_cb.com;
1385
1386    /* First make sure the size of each pool has a valid size with room for the header info */
1387    if (size > MAX_USER_BUF_SIZE)
1388        return (GKI_INVALID_POOL);
1389
1390    /* First, look for an unused pool */
1391    for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
1392    {
1393        if (!p_cb->pool_start[xx])
1394            break;
1395    }
1396
1397    if (xx == GKI_NUM_TOTAL_BUF_POOLS)
1398        return (GKI_INVALID_POOL);
1399
1400    /* Ensure an even number of longwords */
1401    tempsize = (INT32)ALIGN_POOL(size);
1402
1403    mem_needed = (tempsize + BUFFER_PADDING_SIZE) * count;
1404
1405    if (!p_mem_pool)
1406        p_mem_pool = GKI_os_malloc(mem_needed);
1407
1408    if (p_mem_pool)
1409    {
1410        /* Initialize the new pool */
1411        gki_init_free_queue (xx, size, count, p_mem_pool);
1412        gki_add_to_pool_list(xx);
1413        (void) GKI_set_pool_permission (xx, permission);
1414        p_cb->curr_total_no_of_pools++;
1415
1416        return (xx);
1417    }
1418    else
1419        return (GKI_INVALID_POOL);
1420}
1421
1422/*******************************************************************************
1423**
1424** Function         GKI_delete_pool
1425**
1426** Description      Called by applications to delete a buffer pool.  The function
1427**                  calls the operating specific function to free the actual memory.
1428**                  An exception is generated if an error is detected.
1429**
1430** Parameters:      pool_id - (input) Id of the poll being deleted.
1431**
1432** Returns          void
1433**
1434*******************************************************************************/
1435void GKI_delete_pool (UINT8 pool_id)
1436{
1437    FREE_QUEUE_T    *Q;
1438    tGKI_COM_CB     *p_cb = &gki_cb.com;
1439
1440    if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id]))
1441        return;
1442
1443    GKI_disable();
1444    Q  = &p_cb->freeq[pool_id];
1445
1446    if (!Q->cur_cnt)
1447    {
1448        Q->size      = 0;
1449        Q->total     = 0;
1450        Q->cur_cnt   = 0;
1451        Q->max_cnt   = 0;
1452        Q->p_first   = NULL;
1453        Q->p_last    = NULL;
1454
1455        GKI_os_free (p_cb->pool_start[pool_id]);
1456
1457        p_cb->pool_start[pool_id] = NULL;
1458        p_cb->pool_end[pool_id]   = NULL;
1459        p_cb->pool_size[pool_id]  = 0;
1460
1461        gki_remove_from_pool_list(pool_id);
1462        p_cb->curr_total_no_of_pools--;
1463    }
1464    else
1465        GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool");
1466
1467    GKI_enable();
1468
1469    return;
1470}
1471
1472#endif /*  BTU_STACK_LITE_ENABLED == FALSE */
1473
1474/*******************************************************************************
1475**
1476** Function         GKI_get_pool_bufsize
1477**
1478** Description      Called by an application to get the size of buffers in a pool
1479**
1480** Parameters       Pool ID.
1481**
1482** Returns          the size of buffers in the pool
1483**
1484*******************************************************************************/
1485UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
1486{
1487    if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
1488        return (gki_cb.com.freeq[pool_id].size);
1489
1490    return (0);
1491}
1492
1493/*******************************************************************************
1494**
1495** Function         GKI_poolutilization
1496**
1497** Description      Called by an application to get the buffer utilization
1498**                  in the specified buffer pool.
1499**
1500** Parameters       pool_id - (input) pool ID to get the free count of.
1501**
1502** Returns          % of buffers used from 0 to 100
1503**
1504*******************************************************************************/
1505UINT16 GKI_poolutilization (UINT8 pool_id)
1506{
1507    FREE_QUEUE_T  *Q;
1508
1509    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1510        return (100);
1511
1512    Q  = &gki_cb.com.freeq[pool_id];
1513
1514    if (Q->total == 0)
1515        return (100);
1516
1517    return ((Q->cur_cnt * 100) / Q->total);
1518}
1519
1520