TERES/SOFTWARE/A64-TERES/u-boot_new/usb_sunxi/buf_queue.c
Dimitar Gamishev 093685c7d8 u-boot
2017-10-13 14:02:55 +03:00

222 lines
5.4 KiB
C

/*
* (C) Copyright 2007-2013
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* wangwei <wangwei@allwinnertech.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include "buf_queue.h"
#include <malloc.h>
//extern __u32 NAND_GetPageSize(void);
extern __u32 NAND_GetLogicPageSize(void);
int buf_queue_init_flag = 0;
int buf_queue_max_len = 80;
int buf_queue_page_size = 8*1024;
int buf_queue_current_len = 0;
u8* buf_queue_base_buf = NULL;
buf_node_t * buf_queue_head = NULL;
buf_node_t * buf_queue_tail = NULL;
int buf_queue_init(void)
{
int i = 0;
if(buf_queue_init_flag)
{
printf("sunxi efex queue error: already init\n");
return -1;
}
//init queue page size and max len by storage type
int storage_type = uboot_spare_head.boot_data.storage_type;
if(storage_type == 0)
{
buf_queue_page_size = NAND_GetLogicPageSize();
buf_queue_max_len = 80;
}
else
{
buf_queue_page_size = 64*1024;
buf_queue_max_len = 20;
}
printf("buf queue page size = %d\n", buf_queue_page_size);
buf_queue_base_buf = NULL;
buf_queue_head = buf_queue_tail = NULL;
//malloc queue base buff
buf_queue_base_buf = ( u8*) malloc(buf_queue_page_size*buf_queue_max_len);
if(buf_queue_base_buf == NULL)
{
printf("sunxi usb efex queue error: malloc memory fail size 0x%x\n",
buf_queue_page_size*buf_queue_max_len);
return -1;
}
//create cycle queue
buf_element_t element;
memset(&element, 0 , sizeof(element));
for(i = 0; i < buf_queue_max_len ; i++)
{
//malloc page memory from queue base_buf
element.buff = buf_queue_base_buf+i*buf_queue_page_size ;
//malloc node memory
buf_node_t *node = ( buf_node_t*) malloc(sizeof(buf_node_t));
if(node == NULL)
{
printf("sunxi usb efex queue error: malloc memory fail size 0x%zu\n",sizeof(buf_node_t));
return -1;
}
node->element= element;
node->next = NULL;
if(buf_queue_tail == NULL)
{
//queue is empty
buf_queue_head = buf_queue_tail = node ;
}
else
{
buf_queue_tail->next = node;
buf_queue_tail = buf_queue_tail->next;
}
}
//set cycle queue
buf_queue_tail->next = buf_queue_head;
//set head and tail point to the same node when begin
buf_queue_head = buf_queue_tail;
//set current len to zero
buf_queue_current_len = 0;
//set init flag
buf_queue_init_flag = 1;
return 0;
}
int buf_queue_exit(void)
{
buf_node_t *tmp = NULL;
int free_cnt = buf_queue_max_len;
//free base buf
if(buf_queue_base_buf)
{
free(buf_queue_base_buf);
buf_queue_base_buf = NULL;
}
//free node buf
while(buf_queue_head != NULL)
{
tmp = buf_queue_head;
//move to next node
buf_queue_head = buf_queue_head->next;
//free queue node memory
free(tmp);
//check
free_cnt--;
if(free_cnt == 0) break;
}
buf_queue_head = buf_queue_tail = NULL;
buf_queue_current_len = 0;
buf_queue_init_flag = 0;
return 0;
}
int buf_queue_empty(void)
{
return buf_queue_current_len == 0 ?1:0;
}
int buf_queue_full(void)
{
return buf_queue_current_len == buf_queue_max_len?1:0;
}
int buf_queue_free_size(void)
{
return buf_queue_max_len-buf_queue_current_len;
}
int buf_queue_get_page_size(void)
{
return buf_queue_page_size;
}
int buf_enqueue(buf_element_t* element)
{
if(buf_queue_full())
{
//printf("efex queue: full");
//full queue
return -1;
}
buf_element_t *pelem = NULL;
if(buf_queue_empty())
{
pelem = &(buf_queue_head->element);
}
else
{
pelem = &(buf_queue_tail->element);
}
memcpy(pelem->buff,element->buff, element->sector_num*512);
pelem->addr = element->addr ;
pelem->sector_num = element->sector_num;
buf_queue_tail = buf_queue_tail->next;
buf_queue_current_len++;
return 0;
}
int buf_dequeue(buf_element_t* pelement)
{
if(buf_queue_empty()) return -1; //empty queue
//get value
buf_element_t *ptmp = &buf_queue_head->element;
pelement->addr = ptmp->addr;
pelement->sector_num = ptmp->sector_num;
memcpy(pelement->buff,ptmp->buff,ptmp->sector_num*512);
//move head
buf_queue_head = buf_queue_head->next;
buf_queue_current_len--;
//printf("efex dequeue ok: addr0x%x, sector 0x%x \n",pelement->addr,pelement->sector_num);
return 0;
}