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