// Copyright 2022-2023 Beken // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "bk_sdio.h" //#include "sdio.h" #include "sdio_utils.h" #include "sdio_slave_driver.h" #include #include "driver/sdio_types.h" #if CONFIG_SDIO_SLAVE #ifdef CONFIG_SDIO_DEBUG_EN int32_t sdio_list_dump_info(sdio_node_t *head, sdio_node_t *tail, uint32_t count) { sdio_node_t *cur_p = head; sdio_node_t *next_p = NULL; //TODO:log out each node info. for(uint32_t i = 0; i < count; i++) { if(cur_p) { SDIO_LOG_INFO("nd%d=0x%x,next=0x%x len=%d", i, cur_p, cur_p->next, cur_p->len); next_p = cur_p->next; } if(next_p == NULL) break; cur_p = next_p; } if(tail && (tail != cur_p)) { SDIO_LOG_ERR("list err:tail=0x%x, len=%d", tail, tail->len); } return 0; } #endif /** * @brief Init a sdio single link list which includes the buffers. * * This API init a sdio single link list which includes the buffers. * - Malloc buffers * - Reserved the header for SDIO * - Linked the buffers with single list * - * @param count How many buffers will be malloced. * @param size Each buffer size for data which doesn't include SDIO header,it should be 4 bytes align * @param head Saved the list head * @param tail Saved the list tail * * @attention * * @return * - BK_OK: succeed * - others: other errors. */ bk_err_t sdio_list_init(uint32_t count, uint32_t size, sdio_node_ptr_t *head_p, sdio_node_ptr_t *tail_p) { uint32_t i = 0; sdio_node_t *cur_p = NULL, *next_p; uint32_t buf_len = 0; if(head_p == NULL || tail_p == NULL) { SDIO_LOG_ERR("list init"); return BK_ERR_SDIO_LIST_INIT; } size = ((size + 3) / 4) * 4; //align to 4 bytes buf_len = sizeof(sdio_node_t) + size; #ifdef CONFIG_SDIO_DEBUG_EN buf_len += SDIO_DEBUG_BUFFER_TAIL_LEN; #endif //first node { cur_p = *head_p = *tail_p = (sdio_node_t *)os_malloc(buf_len); if(*head_p == NULL) { SDIO_LOG_ERR("mem malloc,len=%d", buf_len); return BK_ERR_SDIO_NO_MEM; } cur_p->len = 0; #ifdef CONFIG_SDIO_DEBUG_EN //TODO:log info *(uint32_t *)(((uint8_t *)cur_p+buf_len-SDIO_DEBUG_BUFFER_TAIL_LEN)) = SDIO_DEBUG_MAGIC_VALUE; #endif } for(i = 1; i < count; i++) { next_p = (sdio_node_t *)os_malloc(buf_len); if(next_p == NULL) { SDIO_LOG_ERR("mem malloc,i=%d,len=%d", i, buf_len); return BK_ERR_SDIO_NO_MEM; } next_p->len = 0; #ifdef CONFIG_SDIO_DEBUG_EN *(uint32_t *)((uint8_t *)(cur_p+buf_len-SDIO_DEBUG_BUFFER_TAIL_LEN)) = SDIO_DEBUG_MAGIC_VALUE; #endif cur_p->next = next_p; cur_p = cur_p->next; } cur_p->next = NULL; *tail_p = cur_p; #ifdef CONFIG_SDIO_DEBUG_EN sdio_list_dump_info(*head_p, *tail_p, count); #endif return BK_OK; } /** * @brief Deinit a sdio single link list which includes the buffers. * * This API deinit a sdio single link list which includes the buffers. * - Free buffers * - * @param list_p The list will be deinited * * @attention * * @return * - BK_OK: succeed * - others: other errors. */ bk_err_t sdio_list_deinit(sdio_list_t *list_p) { uint32_t count = 0; sdio_node_t *cur_p = NULL, *next_p; if(list_p) { cur_p = list_p->head; while(cur_p) { next_p = cur_p->next; os_free(cur_p); cur_p = next_p; count++; } if(count == list_p->count) { return BK_OK; } } return BK_FAIL; } static bk_err_t sdio_list_check(sdio_node_t *push_head, sdio_node_t *push_tail, uint32_t count) { sdio_node_t *cur_p = push_head; uint32_t compute = 1; if(push_head == NULL) { SDIO_LOG_ERR("head null"); return BK_ERR_SDIO_LIST; } if(push_tail && push_tail->next != NULL) { SDIO_LOG_ERR("tail invalid"); return BK_ERR_SDIO_LIST; } while(cur_p) { if(compute == count) { if(cur_p == push_tail) { return BK_OK; } else { SDIO_LOG_ERR("list is invalid"); return BK_ERR_SDIO_LIST; } } cur_p = cur_p->next; compute++; } SDIO_LOG_ERR("list invalid really node cnt=%d, set count=%d", compute-1, count); return BK_ERR_SDIO_LIST; } /** * @brief Pop a node from the selected list. * * This API Pop a node from the selected list. * - Pop out a node from the selected list * - Update the list info * - * @param list_p Selected pop node list * @param node_p Save the pop out node * * @attention * * @return * - BK_OK: succeed * - others: other errors. */ bk_err_t sdio_list_pop_node(sdio_list_t *list_p, sdio_node_ptr_t *node_p) { bk_err_t ret = BK_OK; ret = sdio_list_check(list_p->head, list_p->tail, list_p->count); if(ret != BK_OK) { SDIO_LOG_ERR("list fail"); *node_p = NULL; return BK_FAIL; } if(list_p->count) { sdio_node_ptr_t tmp_node_p = list_p->head; *node_p = tmp_node_p; if(list_p->head == list_p->tail) //last one { list_p->head = list_p->tail = NULL; } else { list_p->head = list_p->head->next; } tmp_node_p->next = NULL; list_p->count--; } #ifdef CONFIG_SDIO_DEBUG_EN sdio_list_dump_info(list_p->head, list_p->tail, list_p->count); #endif return ret; } /** * @brief Push a source list to target list. * * This API Push a source list to target list. * - Check list is whether valid * - Link two list together * - Update the list info * - * @param list_p Selected target list * @param head_p Source list header node * @param tail_p Source list tail node * @param count How many nodes of source list * * @attention * * @return * - BK_OK: succeed * - others: other errors. */ bk_err_t sdio_list_push_list(sdio_list_t *list_p, sdio_node_t *head_p, sdio_node_t *tail_p, uint32_t count) { bk_err_t ret = BK_OK; ret = sdio_list_check(head_p, tail_p, count); if(ret != BK_OK) { SDIO_LOG_ERR("list fail"); return ret; } if(list_p->head == NULL) //ongoing is null, first in { list_p->head = head_p; list_p->tail = tail_p; list_p->count = count; } else { ret = sdio_list_check(list_p->head, list_p->tail, list_p->count); if(ret != BK_OK) { SDIO_LOG_ERR("list fail"); return ret; } list_p->tail->next = head_p; list_p->tail = tail_p; list_p->tail->next = NULL; list_p->count += count; } //TODO:Just debug ret = sdio_list_check(list_p->head, list_p->tail, list_p->count); if(ret != BK_OK) { SDIO_LOG_ERR("list fail"); return ret; } return ret; } sdio_node_t *sdio_list_pop_list(sdio_node_t *head, uint32_t count) { return 0; } uint32_t sdio_list_get_node_count(sdio_list_t *list_p) { return list_p->count; } uint32_t sdio_list_compute_total_length(sdio_list_t *list_p) { sdio_node_ptr_t cur_p = list_p->head; uint32_t total_length = 0; for(uint32_t i = 0; i < list_p->count; i++) { if(cur_p) { total_length += cur_p->len; } cur_p = cur_p->next; } return total_length; } #endif // EOF