1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18#include "gki_int.h"
19#include <cutils/log.h>
20
21#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
22#error Number of pools out of range (16 Max)!
23#endif
24
25static void gki_add_to_pool_list(UINT8 pool_id);
26static void gki_remove_from_pool_list(UINT8 pool_id);
27
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// btla-specific ++
54    if(p_mem)
55    {
56        p_cb->pool_start[id] = (UINT8 *)p_mem;
57        p_cb->pool_end[id]   = (UINT8 *)p_mem + (act_size * total);
58    }
59// btla-specific --
60
61    p_cb->pool_size[id]  = act_size;
62
63    p_cb->freeq[id].size      = (UINT16) tempsize;
64    p_cb->freeq[id].total     = total;
65    p_cb->freeq[id].cur_cnt   = 0;
66    p_cb->freeq[id].max_cnt   = 0;
67
68    /* Initialize  index table */
69// btla-specific ++
70    if(p_mem)
71    {
72        hdr = (BUFFER_HDR_T *)p_mem;
73        p_cb->freeq[id].p_first = hdr;
74        for (i = 0; i < total; i++)
75        {
76            hdr->task_id = GKI_INVALID_TASK;
77            hdr->q_id    = id;
78            hdr->status  = BUF_STATUS_FREE;
79            magic        = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
80            *magic       = MAGIC_NO;
81            hdr1         = hdr;
82            hdr          = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
83            hdr1->p_next = hdr;
84        }
85        hdr1->p_next = NULL;
86        p_cb->freeq[id].p_last = hdr1;
87    }
88// btla-specific --
89    return;
90}
91
92// btla-specific ++
93#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
94static BOOLEAN gki_alloc_free_queue(UINT8 id)
95{
96    FREE_QUEUE_T  *Q;
97    tGKI_COM_CB *p_cb = &gki_cb.com;
98    GKI_TRACE("\ngki_alloc_free_queue in, id:%d \n", (int)id );
99
100    Q = &p_cb->freeq[p_cb->pool_list[id]];
101
102    if(Q->p_first == 0)
103    {
104        void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total);
105        if(p_mem)
106        {
107            //re-initialize the queue with allocated memory
108            GKI_TRACE("\ngki_alloc_free_queue calling  gki_init_free_queue, id:%d  size:%d, totol:%d\n", id, Q->size, Q->total);
109            gki_init_free_queue(id, Q->size, Q->total, p_mem);
110            GKI_TRACE("\ngki_alloc_free_queue ret OK, id:%d  size:%d, totol:%d\n", id, Q->size, Q->total);
111            return TRUE;
112        }
113        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "gki_alloc_free_queue: Not enough memory");
114    }
115    GKI_TRACE("\ngki_alloc_free_queue out failed, id:%d\n", id);
116    return FALSE;
117}
118
119void gki_dealloc_free_queue(void)
120{
121    UINT8   i;
122    tGKI_COM_CB *p_cb = &gki_cb.com;
123
124    for (i=0; i < p_cb->curr_total_no_of_pools; i++)
125    {
126        if ( 0 < p_cb->freeq[i].max_cnt )
127        {
128            GKI_os_free(p_cb->pool_start[i]);
129
130            p_cb->freeq[i].cur_cnt   = 0;
131            p_cb->freeq[i].max_cnt   = 0;
132            p_cb->freeq[i].p_first   = NULL;
133            p_cb->freeq[i].p_last    = NULL;
134
135            p_cb->pool_start[i] = NULL;
136            p_cb->pool_end[i]   = NULL;
137            p_cb->pool_size[i]  = 0;
138        }
139    }
140}
141
142#endif
143// btla-specific --
144
145/*******************************************************************************
146**
147** Function         gki_buffer_init
148**
149** Description      Called once internally by GKI at startup to initialize all
150**                  buffers and free buffer pools.
151**
152** Returns          void
153**
154*******************************************************************************/
155void gki_buffer_init(void)
156{
157    UINT8   i, tt, mb;
158    tGKI_COM_CB *p_cb = &gki_cb.com;
159
160    /* Initialize mailboxes */
161    for (tt = 0; tt < GKI_MAX_TASKS; tt++)
162    {
163        for (mb = 0; mb < NUM_TASK_MBOX; mb++)
164        {
165            p_cb->OSTaskQFirst[tt][mb] = NULL;
166            p_cb->OSTaskQLast [tt][mb] = NULL;
167        }
168    }
169
170    for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)
171    {
172        p_cb->pool_start[tt] = NULL;
173        p_cb->pool_end[tt]   = NULL;
174        p_cb->pool_size[tt]  = 0;
175
176        p_cb->freeq[tt].p_first = 0;
177        p_cb->freeq[tt].p_last  = 0;
178        p_cb->freeq[tt].size    = 0;
179        p_cb->freeq[tt].total   = 0;
180        p_cb->freeq[tt].cur_cnt = 0;
181        p_cb->freeq[tt].max_cnt = 0;
182    }
183
184    /* Use default from target.h */
185    p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
186
187// btla-specific ++
188#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == TRUE))
189// btla-specific --
190
191#if (GKI_NUM_FIXED_BUF_POOLS > 0)
192    p_cb->bufpool0 = (UINT8 *)GKI_os_malloc ((GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX);
193#endif
194
195#if (GKI_NUM_FIXED_BUF_POOLS > 1)
196    p_cb->bufpool1 = (UINT8 *)GKI_os_malloc ((GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX);
197#endif
198
199#if (GKI_NUM_FIXED_BUF_POOLS > 2)
200    p_cb->bufpool2 = (UINT8 *)GKI_os_malloc ((GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX);
201#endif
202
203#if (GKI_NUM_FIXED_BUF_POOLS > 3)
204    p_cb->bufpool3 = (UINT8 *)GKI_os_malloc ((GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX);
205#endif
206
207#if (GKI_NUM_FIXED_BUF_POOLS > 4)
208    p_cb->bufpool4 = (UINT8 *)GKI_os_malloc ((GKI_BUF4_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX);
209#endif
210
211#if (GKI_NUM_FIXED_BUF_POOLS > 5)
212    p_cb->bufpool5 = (UINT8 *)GKI_os_malloc ((GKI_BUF5_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX);
213#endif
214
215#if (GKI_NUM_FIXED_BUF_POOLS > 6)
216    p_cb->bufpool6 = (UINT8 *)GKI_os_malloc ((GKI_BUF6_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX);
217#endif
218
219#if (GKI_NUM_FIXED_BUF_POOLS > 7)
220    p_cb->bufpool7 = (UINT8 *)GKI_os_malloc ((GKI_BUF7_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX);
221#endif
222
223#if (GKI_NUM_FIXED_BUF_POOLS > 8)
224    p_cb->bufpool8 = (UINT8 *)GKI_os_malloc ((GKI_BUF8_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX);
225#endif
226
227#if (GKI_NUM_FIXED_BUF_POOLS > 9)
228    p_cb->bufpool9 = (UINT8 *)GKI_os_malloc ((GKI_BUF9_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX);
229#endif
230
231#if (GKI_NUM_FIXED_BUF_POOLS > 10)
232    p_cb->bufpool10 = (UINT8 *)GKI_os_malloc ((GKI_BUF10_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX);
233#endif
234
235#if (GKI_NUM_FIXED_BUF_POOLS > 11)
236    p_cb->bufpool11 = (UINT8 *)GKI_os_malloc ((GKI_BUF11_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX);
237#endif
238
239#if (GKI_NUM_FIXED_BUF_POOLS > 12)
240    p_cb->bufpool12 = (UINT8 *)GKI_os_malloc ((GKI_BUF12_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX);
241#endif
242
243#if (GKI_NUM_FIXED_BUF_POOLS > 13)
244    p_cb->bufpool13 = (UINT8 *)GKI_os_malloc ((GKI_BUF13_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX);
245#endif
246
247#if (GKI_NUM_FIXED_BUF_POOLS > 14)
248    p_cb->bufpool14 = (UINT8 *)GKI_os_malloc ((GKI_BUF14_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX);
249#endif
250
251#if (GKI_NUM_FIXED_BUF_POOLS > 15)
252    p_cb->bufpool15 = (UINT8 *)GKI_os_malloc ((GKI_BUF15_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX);
253#endif
254
255#endif
256
257
258#if (GKI_NUM_FIXED_BUF_POOLS > 0)
259    gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0);
260#endif
261
262#if (GKI_NUM_FIXED_BUF_POOLS > 1)
263    gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1);
264#endif
265
266#if (GKI_NUM_FIXED_BUF_POOLS > 2)
267    gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2);
268#endif
269
270#if (GKI_NUM_FIXED_BUF_POOLS > 3)
271    gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3);
272#endif
273
274#if (GKI_NUM_FIXED_BUF_POOLS > 4)
275    gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4);
276#endif
277
278#if (GKI_NUM_FIXED_BUF_POOLS > 5)
279    gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5);
280#endif
281
282#if (GKI_NUM_FIXED_BUF_POOLS > 6)
283    gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6);
284#endif
285
286#if (GKI_NUM_FIXED_BUF_POOLS > 7)
287    gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7);
288#endif
289
290#if (GKI_NUM_FIXED_BUF_POOLS > 8)
291    gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8);
292#endif
293
294#if (GKI_NUM_FIXED_BUF_POOLS > 9)
295    gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9);
296#endif
297
298#if (GKI_NUM_FIXED_BUF_POOLS > 10)
299    gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10);
300#endif
301
302#if (GKI_NUM_FIXED_BUF_POOLS > 11)
303    gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11);
304#endif
305
306#if (GKI_NUM_FIXED_BUF_POOLS > 12)
307    gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12);
308#endif
309
310#if (GKI_NUM_FIXED_BUF_POOLS > 13)
311    gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13);
312#endif
313
314#if (GKI_NUM_FIXED_BUF_POOLS > 14)
315    gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14);
316#endif
317
318#if (GKI_NUM_FIXED_BUF_POOLS > 15)
319    gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
320#endif
321
322    /* add pools to the pool_list which is arranged in the order of size */
323    for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++)
324    {
325        p_cb->pool_list[i] = i;
326    }
327
328    p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
329
330    return;
331}
332
333
334/*******************************************************************************
335**
336** Function         GKI_init_q
337**
338** Description      Called by an application to initialize a buffer queue.
339**
340** Returns          void
341**
342*******************************************************************************/
343void GKI_init_q (BUFFER_Q *p_q)
344{
345    p_q->p_first = p_q->p_last = NULL;
346    p_q->count = 0;
347
348    return;
349}
350
351
352/*******************************************************************************
353**
354** Function         GKI_getbuf
355**
356** Description      Called by an application to get a free buffer which
357**                  is of size greater or equal to the requested size.
358**
359**                  Note: This routine only takes buffers from public pools.
360**                        It will not use any buffers from pools
361**                        marked GKI_RESTRICTED_POOL.
362**
363** Parameters       size - (input) number of bytes needed.
364**
365** Returns          A pointer to the buffer, or NULL if none available
366**
367*******************************************************************************/
368void *GKI_getbuf (UINT16 size)
369{
370    UINT8         i;
371    FREE_QUEUE_T  *Q;
372    BUFFER_HDR_T  *p_hdr;
373    tGKI_COM_CB *p_cb = &gki_cb.com;
374
375    if (size == 0)
376    {
377        GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
378        return (NULL);
379    }
380
381    /* Find the first buffer pool that is public that can hold the desired size */
382    for (i=0; i < p_cb->curr_total_no_of_pools; i++)
383    {
384        if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
385            break;
386    }
387
388    if(i == p_cb->curr_total_no_of_pools)
389    {
390        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
391        return (NULL);
392    }
393
394    /* Make sure the buffers aren't disturbed til finished with allocation */
395    GKI_disable();
396
397    /* search the public buffer pools that are big enough to hold the size
398     * until a free buffer is found */
399    for ( ; i < p_cb->curr_total_no_of_pools; i++)
400    {
401        /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
402        if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask)
403            continue;
404        if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
405             Q = &p_cb->freeq[p_cb->pool_list[i]];
406        else
407             continue;
408
409        if(Q->cur_cnt < Q->total)
410        {
411// btla-specific ++
412        #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
413            if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
414                return NULL;
415        #endif
416// btla-specific --
417            p_hdr = Q->p_first;
418            Q->p_first = p_hdr->p_next;
419
420            if (!Q->p_first)
421                Q->p_last = NULL;
422
423            if(++Q->cur_cnt > Q->max_cnt)
424                Q->max_cnt = Q->cur_cnt;
425
426            GKI_enable();
427
428            p_hdr->task_id = GKI_get_taskid();
429
430            p_hdr->status  = BUF_STATUS_UNLINKED;
431            p_hdr->p_next  = NULL;
432            p_hdr->Type    = 0;
433
434            return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
435        }
436    }
437
438    GKI_enable();
439
440    GKI_exception (GKI_ERROR_OUT_OF_BUFFERS, "getbuf: out of buffers");
441    return (NULL);
442}
443
444
445/*******************************************************************************
446**
447** Function         GKI_getpoolbuf
448**
449** Description      Called by an application to get a free buffer from
450**                  a specific buffer pool.
451**
452**                  Note: If there are no more buffers available from the pool,
453**                        the public buffers are searched for an available buffer.
454**
455** Parameters       pool_id - (input) pool ID to get a buffer out of.
456**
457** Returns          A pointer to the buffer, or NULL if none available
458**
459*******************************************************************************/
460void *GKI_getpoolbuf (UINT8 pool_id)
461{
462    FREE_QUEUE_T  *Q;
463    BUFFER_HDR_T  *p_hdr;
464    tGKI_COM_CB *p_cb = &gki_cb.com;
465
466    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
467    {
468        GKI_exception(GKI_ERROR_GETPOOLBUF_BAD_QID, "getpoolbuf bad pool");
469        return (NULL);
470    }
471
472    /* Make sure the buffers aren't disturbed til finished with allocation */
473    GKI_disable();
474
475    Q = &p_cb->freeq[pool_id];
476    if(Q->cur_cnt < Q->total)
477    {
478// btla-specific ++
479#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
480        if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
481            return NULL;
482#endif
483// btla-specific --
484        p_hdr = Q->p_first;
485        Q->p_first = p_hdr->p_next;
486
487        if (!Q->p_first)
488            Q->p_last = NULL;
489
490        if(++Q->cur_cnt > Q->max_cnt)
491            Q->max_cnt = Q->cur_cnt;
492
493        GKI_enable();
494
495
496        p_hdr->task_id = GKI_get_taskid();
497
498        p_hdr->status  = BUF_STATUS_UNLINKED;
499        p_hdr->p_next  = NULL;
500        p_hdr->Type    = 0;
501
502        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
503    }
504
505    /* If here, no buffers in the specified pool */
506    GKI_enable();
507
508    /* try for free buffers in public pools */
509    return (GKI_getbuf(p_cb->freeq[pool_id].size));
510
511}
512
513/*******************************************************************************
514**
515** Function         GKI_freebuf
516**
517** Description      Called by an application to return a buffer to the free pool.
518**
519** Parameters       p_buf - (input) address of the beginning of a buffer.
520**
521** Returns          void
522**
523*******************************************************************************/
524void GKI_freebuf (void *p_buf)
525{
526    FREE_QUEUE_T    *Q;
527    BUFFER_HDR_T    *p_hdr;
528
529#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
530    if (!p_buf || gki_chk_buf_damage(p_buf))
531    {
532        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
533        return;
534    }
535#endif
536
537    p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
538
539    if (p_hdr->status != BUF_STATUS_UNLINKED)
540    {
541        GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
542        return;
543    }
544
545    if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS)
546    {
547        GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
548        return;
549    }
550
551    GKI_disable();
552
553    /*
554    ** Release the buffer
555    */
556    Q  = &gki_cb.com.freeq[p_hdr->q_id];
557    if (Q->p_last)
558        Q->p_last->p_next = p_hdr;
559    else
560        Q->p_first = p_hdr;
561
562    Q->p_last      = p_hdr;
563    p_hdr->p_next  = NULL;
564    p_hdr->status  = BUF_STATUS_FREE;
565    p_hdr->task_id = GKI_INVALID_TASK;
566    if (Q->cur_cnt > 0)
567        Q->cur_cnt--;
568
569    GKI_enable();
570
571    return;
572}
573
574
575/*******************************************************************************
576**
577** Function         GKI_get_buf_size
578**
579** Description      Called by an application to get the size of a buffer.
580**
581** Parameters       p_buf - (input) address of the beginning of a buffer.
582**
583** Returns          the size of the buffer
584**
585*******************************************************************************/
586UINT16 GKI_get_buf_size (void *p_buf)
587{
588    BUFFER_HDR_T    *p_hdr;
589
590    p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE);
591
592    if ((UINT32)p_hdr & 1)
593        return (0);
594
595    if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS)
596    {
597        return (gki_cb.com.freeq[p_hdr->q_id].size);
598    }
599
600    return (0);
601}
602
603/*******************************************************************************
604**
605** Function         gki_chk_buf_damage
606**
607** Description      Called internally by OSS to check for buffer corruption.
608**
609** Returns          TRUE if there is a problem, else FALSE
610**
611*******************************************************************************/
612BOOLEAN gki_chk_buf_damage(void *p_buf)
613{
614#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
615
616    UINT32 *magic;
617    magic  = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf));
618
619    if ((UINT32)magic & 1)
620        return (TRUE);
621
622    if (*magic == MAGIC_NO)
623        return (FALSE);
624
625    return (TRUE);
626
627#else
628
629    return (FALSE);
630
631#endif
632}
633
634/*******************************************************************************
635**
636** Function         GKI_send_msg
637**
638** Description      Called by applications to send a buffer to a task
639**
640** Returns          Nothing
641**
642*******************************************************************************/
643void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)
644{
645    BUFFER_HDR_T    *p_hdr;
646    tGKI_COM_CB *p_cb = &gki_cb.com;
647
648    /* If task non-existant or not started, drop buffer */
649    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
650    {
651        GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
652        GKI_freebuf (msg);
653        return;
654    }
655
656#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
657    if (gki_chk_buf_damage(msg))
658    {
659        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
660        return;
661    }
662#endif
663
664    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
665
666    if (p_hdr->status != BUF_STATUS_UNLINKED)
667    {
668        GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
669        return;
670    }
671
672    GKI_disable();
673
674    if (p_cb->OSTaskQFirst[task_id][mbox])
675        p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
676    else
677        p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
678
679    p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
680
681    p_hdr->p_next = NULL;
682    p_hdr->status = BUF_STATUS_QUEUED;
683    p_hdr->task_id = task_id;
684
685
686    GKI_enable();
687
688    GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
689
690    return;
691}
692
693/*******************************************************************************
694**
695** Function         GKI_read_mbox
696**
697** Description      Called by applications to read a buffer from one of
698**                  the task mailboxes.  A task can only read its own mailbox.
699**
700** Parameters:      mbox  - (input) mailbox ID to read (0, 1, 2, or 3)
701**
702** Returns          NULL if the mailbox was empty, else the address of a buffer
703**
704*******************************************************************************/
705void *GKI_read_mbox (UINT8 mbox)
706{
707    UINT8           task_id = GKI_get_taskid();
708    void            *p_buf = NULL;
709    BUFFER_HDR_T    *p_hdr;
710
711    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX))
712        return (NULL);
713
714    GKI_disable();
715
716    if (gki_cb.com.OSTaskQFirst[task_id][mbox])
717    {
718        p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
719        gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
720
721        p_hdr->p_next = NULL;
722        p_hdr->status = BUF_STATUS_UNLINKED;
723
724        p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE;
725    }
726
727    GKI_enable();
728
729    return (p_buf);
730}
731
732
733
734/*******************************************************************************
735**
736** Function         GKI_enqueue
737**
738** Description      Enqueue a buffer at the tail of the queue
739**
740** Parameters:      p_q  -  (input) pointer to a queue.
741**                  p_buf - (input) address of the buffer to enqueue
742**
743** Returns          void
744**
745*******************************************************************************/
746void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
747{
748    BUFFER_HDR_T    *p_hdr;
749
750#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
751    if (gki_chk_buf_damage(p_buf))
752    {
753        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
754        return;
755    }
756#endif
757
758    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
759
760    if (p_hdr->status != BUF_STATUS_UNLINKED)
761    {
762        GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked");
763        return;
764    }
765
766    GKI_disable();
767
768    /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
769    if (p_q->p_last)
770    {
771        BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE);
772        p_last_hdr->p_next = p_hdr;
773    }
774    else
775        p_q->p_first = p_buf;
776
777    p_q->p_last = p_buf;
778    p_q->count++;
779
780    p_hdr->p_next = NULL;
781    p_hdr->status = BUF_STATUS_QUEUED;
782
783    GKI_enable();
784
785    return;
786}
787
788
789/*******************************************************************************
790**
791** Function         GKI_enqueue_head
792**
793** Description      Enqueue a buffer at the head of the queue
794**
795** Parameters:      p_q  -  (input) pointer to a queue.
796**                  p_buf - (input) address of the buffer to enqueue
797**
798** Returns          void
799**
800*******************************************************************************/
801void GKI_enqueue_head (BUFFER_Q *p_q, void *p_buf)
802{
803    BUFFER_HDR_T    *p_hdr;
804
805#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
806    if (gki_chk_buf_damage(p_buf))
807    {
808        GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
809        return;
810    }
811#endif
812
813    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
814
815    if (p_hdr->status != BUF_STATUS_UNLINKED)
816    {
817        GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue head - buf already linked");
818        return;
819    }
820
821    GKI_disable();
822
823    if (p_q->p_first)
824    {
825        p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
826        p_q->p_first = p_buf;
827    }
828    else
829    {
830        p_q->p_first = p_buf;
831        p_q->p_last  = p_buf;
832        p_hdr->p_next = NULL;
833    }
834    p_q->count++;
835
836    p_hdr->status = BUF_STATUS_QUEUED;
837
838    GKI_enable();
839
840    return;
841}
842
843
844/*******************************************************************************
845**
846** Function         GKI_dequeue
847**
848** Description      Dequeues a buffer from the head of a queue
849**
850** Parameters:      p_q  - (input) pointer to a queue.
851**
852** Returns          NULL if queue is empty, else buffer
853**
854*******************************************************************************/
855void *GKI_dequeue (BUFFER_Q *p_q)
856{
857    BUFFER_HDR_T    *p_hdr;
858
859    GKI_disable();
860
861    if (!p_q || !p_q->count)
862    {
863        GKI_enable();
864        return (NULL);
865    }
866
867    p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
868
869    /* Keep buffers such that GKI header is invisible
870    */
871    if (p_hdr->p_next)
872        p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
873    else
874    {
875        p_q->p_first = NULL;
876        p_q->p_last  = NULL;
877    }
878
879    p_q->count--;
880
881    p_hdr->p_next = NULL;
882    p_hdr->status = BUF_STATUS_UNLINKED;
883
884    GKI_enable();
885
886    return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
887}
888
889
890/*******************************************************************************
891**
892** Function         GKI_remove_from_queue
893**
894** Description      Dequeue a buffer from the middle of the queue
895**
896** Parameters:      p_q  - (input) pointer to a queue.
897**                  p_buf - (input) address of the buffer to enqueue
898**
899** Returns          NULL if queue is empty, else buffer
900**
901*******************************************************************************/
902void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
903{
904    BUFFER_HDR_T    *p_prev;
905    BUFFER_HDR_T    *p_buf_hdr;
906
907    GKI_disable();
908
909    if (p_buf == p_q->p_first)
910    {
911        GKI_enable();
912        return (GKI_dequeue (p_q));
913    }
914
915    p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
916    p_prev    = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
917
918    for ( ; p_prev; p_prev = p_prev->p_next)
919    {
920        /* If the previous points to this one, move the pointers around */
921        if (p_prev->p_next == p_buf_hdr)
922        {
923            p_prev->p_next = p_buf_hdr->p_next;
924
925            /* If we are removing the last guy in the queue, update p_last */
926            if (p_buf == p_q->p_last)
927                p_q->p_last = p_prev + 1;
928
929            /* One less in the queue */
930            p_q->count--;
931
932            /* The buffer is now unlinked */
933            p_buf_hdr->p_next = NULL;
934            p_buf_hdr->status = BUF_STATUS_UNLINKED;
935
936            GKI_enable();
937            return (p_buf);
938        }
939    }
940
941    GKI_enable();
942    return (NULL);
943}
944
945/*******************************************************************************
946**
947** Function         GKI_getfirst
948**
949** Description      Return a pointer to the first buffer in a queue
950**
951** Parameters:      p_q  - (input) pointer to a queue.
952**
953** Returns          NULL if queue is empty, else buffer address
954**
955*******************************************************************************/
956void *GKI_getfirst (BUFFER_Q *p_q)
957{
958    return (p_q->p_first);
959}
960
961
962/*******************************************************************************
963**
964** Function         GKI_getlast
965**
966** Description      Return a pointer to the last buffer in a queue
967**
968** Parameters:      p_q  - (input) pointer to a queue.
969**
970** Returns          NULL if queue is empty, else buffer address
971**
972*******************************************************************************/
973void *GKI_getlast (BUFFER_Q *p_q)
974{
975    return (p_q->p_last);
976}
977
978/*******************************************************************************
979**
980** Function         GKI_getnext
981**
982** Description      Return a pointer to the next buffer in a queue
983**
984** Parameters:      p_buf  - (input) pointer to the buffer to find the next one from.
985**
986** Returns          NULL if no more buffers in the queue, else next buffer address
987**
988*******************************************************************************/
989void *GKI_getnext (void *p_buf)
990{
991    BUFFER_HDR_T    *p_hdr;
992
993    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
994
995    if (p_hdr->p_next)
996        return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
997    else
998        return (NULL);
999}
1000
1001
1002
1003/*******************************************************************************
1004**
1005** Function         GKI_queue_is_empty
1006**
1007** Description      Check the status of a queue.
1008**
1009** Parameters:      p_q  - (input) pointer to a queue.
1010**
1011** Returns          TRUE if queue is empty, else FALSE
1012**
1013*******************************************************************************/
1014BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
1015{
1016    return ((BOOLEAN) (p_q->count == 0));
1017}
1018
1019/*******************************************************************************
1020**
1021** Function         gki_add_to_pool_list
1022**
1023** Description      Adds pool to the pool list which is arranged in the
1024**                  order of size
1025**
1026** Returns          void
1027**
1028*******************************************************************************/
1029static void gki_add_to_pool_list(UINT8 pool_id)
1030{
1031
1032    INT32 i, j;
1033    tGKI_COM_CB *p_cb = &gki_cb.com;
1034
1035     /* Find the position where the specified pool should be inserted into the list */
1036    for(i=0; i < p_cb->curr_total_no_of_pools; i++)
1037    {
1038
1039        if(p_cb->freeq[pool_id].size <= p_cb->freeq[ p_cb->pool_list[i] ].size)
1040            break;
1041    }
1042
1043    /* Insert the new buffer pool ID into the list of pools */
1044    for(j = p_cb->curr_total_no_of_pools; j > i; j--)
1045    {
1046        p_cb->pool_list[j] = p_cb->pool_list[j-1];
1047    }
1048
1049    p_cb->pool_list[i] = pool_id;
1050
1051    return;
1052}
1053
1054/*******************************************************************************
1055**
1056** Function         gki_remove_from_pool_list
1057**
1058** Description      Removes pool from the pool list. Called when a pool is deleted
1059**
1060** Returns          void
1061**
1062*******************************************************************************/
1063static void gki_remove_from_pool_list(UINT8 pool_id)
1064{
1065    tGKI_COM_CB *p_cb = &gki_cb.com;
1066    UINT8 i;
1067
1068    for(i=0; i < p_cb->curr_total_no_of_pools; i++)
1069    {
1070        if(pool_id == p_cb->pool_list[i])
1071            break;
1072    }
1073
1074    while (i < (p_cb->curr_total_no_of_pools - 1))
1075    {
1076        p_cb->pool_list[i] = p_cb->pool_list[i+1];
1077        i++;
1078    }
1079
1080    return;
1081}
1082
1083/*******************************************************************************
1084**
1085** Function         GKI_igetpoolbuf
1086**
1087** Description      Called by an interrupt service routine to get a free buffer from
1088**                  a specific buffer pool.
1089**
1090** Parameters       pool_id - (input) pool ID to get a buffer out of.
1091**
1092** Returns          A pointer to the buffer, or NULL if none available
1093**
1094*******************************************************************************/
1095void *GKI_igetpoolbuf (UINT8 pool_id)
1096{
1097    FREE_QUEUE_T  *Q;
1098    BUFFER_HDR_T  *p_hdr;
1099
1100    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1101        return (NULL);
1102
1103
1104    Q = &gki_cb.com.freeq[pool_id];
1105    if(Q->cur_cnt < Q->total)
1106    {
1107        p_hdr = Q->p_first;
1108        Q->p_first = p_hdr->p_next;
1109
1110        if (!Q->p_first)
1111            Q->p_last = NULL;
1112
1113        if(++Q->cur_cnt > Q->max_cnt)
1114            Q->max_cnt = Q->cur_cnt;
1115
1116        p_hdr->task_id = GKI_get_taskid();
1117
1118        p_hdr->status  = BUF_STATUS_UNLINKED;
1119        p_hdr->p_next  = NULL;
1120        p_hdr->Type    = 0;
1121
1122        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
1123    }
1124
1125    return (NULL);
1126}
1127
1128/*******************************************************************************
1129**
1130** Function         GKI_poolcount
1131**
1132** Description      Called by an application to get the total number of buffers
1133**                  in the specified buffer pool.
1134**
1135** Parameters       pool_id - (input) pool ID to get the free count of.
1136**
1137** Returns          the total number of buffers in the pool
1138**
1139*******************************************************************************/
1140UINT16 GKI_poolcount (UINT8 pool_id)
1141{
1142    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1143        return (0);
1144
1145    return (gki_cb.com.freeq[pool_id].total);
1146}
1147
1148/*******************************************************************************
1149**
1150** Function         GKI_poolfreecount
1151**
1152** Description      Called by an application to get the number of free buffers
1153**                  in the specified buffer pool.
1154**
1155** Parameters       pool_id - (input) pool ID to get the free count of.
1156**
1157** Returns          the number of free buffers in the pool
1158**
1159*******************************************************************************/
1160UINT16 GKI_poolfreecount (UINT8 pool_id)
1161{
1162    FREE_QUEUE_T  *Q;
1163
1164    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1165        return (0);
1166
1167    Q  = &gki_cb.com.freeq[pool_id];
1168
1169    return ((UINT16)(Q->total - Q->cur_cnt));
1170}
1171
1172/*******************************************************************************
1173**
1174** Function         GKI_get_pool_bufsize
1175**
1176** Description      Called by an application to get the size of buffers in a pool
1177**
1178** Parameters       Pool ID.
1179**
1180** Returns          the size of buffers in the pool
1181**
1182*******************************************************************************/
1183UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
1184{
1185    if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
1186        return (gki_cb.com.freeq[pool_id].size);
1187
1188    return (0);
1189}
1190
1191/*******************************************************************************
1192**
1193** Function         GKI_poolutilization
1194**
1195** Description      Called by an application to get the buffer utilization
1196**                  in the specified buffer pool.
1197**
1198** Parameters       pool_id - (input) pool ID to get the free count of.
1199**
1200** Returns          % of buffers used from 0 to 100
1201**
1202*******************************************************************************/
1203UINT16 GKI_poolutilization (UINT8 pool_id)
1204{
1205    FREE_QUEUE_T  *Q;
1206
1207    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
1208        return (100);
1209
1210    Q  = &gki_cb.com.freeq[pool_id];
1211
1212    if (Q->total == 0)
1213        return (100);
1214
1215    return ((Q->cur_cnt * 100) / Q->total);
1216}
1217
1218