www.pudn.com > uCOSII上实现的tcpip.rar > zbuffer.c
#include "include/zbuffer.h"
#include "include/zstats.h"
#define ZBUFFER_LEN 128
#define ZBUFFER_NUM 256
/*this two point as the free zbuffer chain's head and tail*/
static volatile zbuffer_t *zbuffer_head = NULL;
static volatile zbuffer_t *zbuffer_tail = NULL;
/*free buffer memory's pool , we use a huge arrary*/
static u8_t zbuffer_memory[ ZBUFFER_NUM * MEM_ALIGN_SIZE( sizeof(zbuffer_t) + ZBUFFER_LEN )];
static zbuffer_t * zbuffer_alloc(void)
{
zbuffer_t *pzbuffer;
sys_enter_critical();
pzbuffer = (zbuffer_t *)zbuffer_head;
if ( pzbuffer )
zbuffer_head = (volatile zbuffer_t *)pzbuffer->next;
#ifdef ZSTATS
if ( pzbuffer != NULL)
zstats.memory_used --;
#endif
sys_exit_critical();
return pzbuffer;
}
static u8_t zbuffer_free(zbuffer_t *pzbuffer)
{
if ( ( ((u8_t *)pzbuffer - zbuffer_memory) % MEM_ALIGN_SIZE( sizeof(zbuffer_t) + ZBUFFER_LEN) ) == 0)
{
pzbuffer->tot_len = 0;
pzbuffer->len = 0;
pzbuffer->next = NULL;
pzbuffer->pdata = (void *)( (u8_t *)pzbuffer + MEM_ALIGN_SIZE( sizeof(zbuffer_t) ));
sys_enter_critical();
zbuffer_tail->next = pzbuffer;
zbuffer_tail =(volatile zbuffer_t *)pzbuffer;
#ifdef ZSTATS
zstats.memory_used ++;
#endif
sys_exit_critical();
return 0;
}
return -1;
}
/****************************************************
*
* Init zbuffer's memory and free buffer chain
* set zbuffer head's pointer and tail's pointer
*
****************************************************/
void zbuffer_init(void)
{
zbuffer_t *pzbuffer, *p;
u16_t i;
u16_t align_len;
align_len = MEM_ALIGN_SIZE( sizeof(zbuffer_t) + ZBUFFER_LEN );
zbuffer_head = (zbuffer_t *)zbuffer_memory;
pzbuffer = (zbuffer_t *)zbuffer_head;
for ( i = 0 ; i < ZBUFFER_NUM; i ++)
{
pzbuffer->next = (zbuffer_t *)( (u8_t *)pzbuffer + align_len );
pzbuffer->len = 0; /*because this zbuffer is in free chain*/
pzbuffer->tot_len = 0;
pzbuffer->pdata = (void *)( (u8_t *)pzbuffer + MEM_ALIGN_SIZE( sizeof(zbuffer_t) ));
p = pzbuffer;
pzbuffer = p->next;
}
p->next = NULL;
#ifdef ZSTATS
zstats.memory_used = ZBUFFER_NUM;
#endif
zbuffer_tail = p;
}
/*******************************************
*
* alloc a zbuffer chain
* called by INT and TASK
*******************************************/
zbuffer_t* zbuffer_new(u16_t tot_len)
{
zbuffer_t *pzbuffer;
zbuffer_t *p, *q;
s32_t rsize;
pzbuffer = zbuffer_alloc();
if ( !pzbuffer )
return NULL;
q = pzbuffer;
pzbuffer->tot_len = tot_len;
pzbuffer->len = tot_len > ZBUFFER_LEN? ZBUFFER_LEN: tot_len;
pzbuffer->next = NULL;
rsize = tot_len - ZBUFFER_LEN;
while( rsize > 0)
{
p = zbuffer_alloc();
if (!p)
{
zbuffer_delete(pzbuffer);
return NULL;
}
p->len = rsize > ZBUFFER_LEN? ZBUFFER_LEN: rsize;
p->next = NULL;
p->tot_len = 0;
pzbuffer->next = p;
pzbuffer = p;
rsize -= ZBUFFER_LEN;
}
return q;
}
/*******************************************
*
* free a zbuffer chain to main free chain
* called by INT and TASK
*******************************************/
void zbuffer_delete(zbuffer_t *pzbuffer)
{
zbuffer_t *p;
while( pzbuffer != NULL)
{
p = pzbuffer->next;
if ( zbuffer_free(pzbuffer) != 0)
return;
pzbuffer = p;
}
}
/*******************************************
*
* addjust a buffer chain's head or tail
* called by INT
*******************************************/
zbuffer_t * zbuffer_adjust(zbuffer_t *pzbuffer, s16_t flen, s16_t blen)
{
zbuffer_t *new_head, *new_tail;
zbuffer_t *p,*q;
if ( flen == 0)
{
new_head = pzbuffer;
}
else if ( flen > 0)
{
new_head = zbuffer_new(flen);
p = new_head;
if (!p)
{
zbuffer_delete(pzbuffer);
return NULL;
}
while( p->next != NULL) p = p->next;
p->next = pzbuffer;
new_head->tot_len += pzbuffer->tot_len;
pzbuffer->tot_len = 0; /*bacause this is not head of chain*/
}
else if ( flen < 0)
{
s32_t rsize;
if ( ((-1)*flen) >= pzbuffer->tot_len )
{
zbuffer_delete(pzbuffer);
return NULL;
}
rsize = (-1)*flen;
rsize -= pzbuffer->len;
p = pzbuffer;
q = NULL;
while( rsize > 0 )
{
q = p;
p = p->next;
rsize -= p->len;
}
rsize += p->len;
p->len -= rsize;
p->pdata = (void *)((u8_t *)p->pdata + rsize);
p->tot_len = pzbuffer->tot_len + flen; /*this is new head of chain*/
if ( q != NULL)
{
q->next = NULL;
zbuffer_delete(pzbuffer);
}
new_head = p;
}
if ( blen == 0)
{
return new_head;
}
else if ( blen > 0)
{
new_tail = zbuffer_new(blen);
if ( new_tail == NULL )
{
zbuffer_delete( new_head );
return NULL;
}
new_head->tot_len += blen;
p = new_head;
while( p->next != NULL) p = p->next;
p->next = new_tail;
new_tail->tot_len = 0; /*bacause this is not head*/
return new_head;
}
else if ( blen < 0)
{
s32_t rsize = new_head->tot_len + blen;
p = new_head;
if ( rsize < 0)
{
zbuffer_delete(new_head);
return NULL;
}
rsize -= p->len;
while( rsize > 0)
{
p = p->next;
rsize -= p->len;
}
rsize += p->len;
if ( p->next != NULL)
{
zbuffer_delete(p->next);
}
p->len = rsize;
p->next = NULL;
new_head->tot_len += blen;
return new_head;
}
return NULL;
}
/************************************
* Read from zbuffer's pdata and length
* is min of zbuffer's and len
***********************************/
void zbuffer_read(zbuffer_t *pzbuffer, u8_t *pdata, u16_t *len)
{
zbuffer_t *p;
u16_t i, count;
if ( pzbuffer == NULL)
{
*len = 0;
}
if ( *len >= pzbuffer->tot_len)
{
*len = pzbuffer->tot_len;
p = pzbuffer;
while( p != NULL)
{
for ( i = 0; i < p->len; i++)
{
*pdata = *(u8_t *)((u8_t *)p->pdata + i);
pdata ++;
}
p = p->next;
}
return;
}
count = 0;
p = pzbuffer;
while( p != NULL)
{
for ( i = 0; i < p->len; i++)
{
*pdata = *(u8_t *)((u8_t *)p->pdata + i);
pdata ++;
count ++;
if ( count >= *len)
{
return;
}
}
p = p->next;
}
return;
}
void zbuffer_write(zbuffer_t *pzbuffer, u8_t *pdata, u16_t *len)
{
zbuffer_t *p;
u16_t i, count;
if ( pzbuffer == NULL)
{
*len = 0;
}
if ( *len >= pzbuffer->tot_len)
{
*len = pzbuffer->tot_len;
p = pzbuffer;
while( p != NULL)
{
for ( i = 0; i < p->len; i++)
{
*(u8_t *)((u8_t *)p->pdata + i) = *pdata;
pdata ++;
}
p = p->next;
}
return;
}
count = 0;
p = pzbuffer;
while( p != NULL)
{
for ( i = 0; i < p->len; i++)
{
*(u8_t *)((u8_t *)p->pdata + i) = *pdata;
pdata ++;
count ++;
if ( count >= *len)
{
return;
}
}
p = p->next;
}
return;
}
zbuffer_t *zbuffer_add(zbuffer_t *pzbuffer1, zbuffer_t *pzbuffer2)
{
zbuffer_t *p;
if ( pzbuffer1 == NULL || pzbuffer2 == NULL )
return NULL;
p = pzbuffer1;
while(p->next != NULL) p = p->next;
p->next = pzbuffer2;
pzbuffer1->tot_len += pzbuffer2->tot_len;
pzbuffer2->tot_len = 0;
return pzbuffer1;
}
zbuffer_t * zbuffer_copy(zbuffer_t *pzbuffer1, zbuffer_t *pzbuffer2)
{
u16_t i, j;
zbuffer_t *pzbuffer, *p, *p2;
p = pzbuffer = zbuffer_new( pzbuffer2->tot_len);
p2 = pzbuffer1;
if ( pzbuffer == NULL)
{
return NULL;
}
i = 0; j = 0;
while(1)
{
if ( pzbuffer2 == NULL || pzbuffer == NULL)
{
break;
}
*((u8_t *)pzbuffer->pdata + i) = *((u8_t *)pzbuffer2->pdata + j);
i++;
j++;
if ( i >= pzbuffer->len)
{
i = 0;
pzbuffer = pzbuffer->next;
}
if ( j >= pzbuffer2->len)
{
j = 0;
pzbuffer2 = pzbuffer2->next;
}
}
if ( p2 != NULL )
return zbuffer_add(p2, p);
else
return p;
return NULL;
}
u16_t zbuffer_chain(zbuffer_t *pzbuffer)
{
u16_t i;
zbuffer_t *p;
if ( pzbuffer == NULL)
return 0;
p = pzbuffer;
i = 1;
while( p->next != NULL)
{
p = p->next;
i++;
}
return i;
}
u8_t zbuffer_head_adjust(zbuffer_t *pbuffer, s16_t offset)
{
void *p;
p = (void *)( (u8_t *)pbuffer + MEM_ALIGN_SIZE( sizeof(zbuffer_t) ));
if ( offset > 0)
{
if ( ((u8_t *)(pbuffer->pdata) - (u8_t *)p) < offset )
{
return -1;
}
pbuffer->pdata = (void *)( (u8_t *)(pbuffer->pdata) - offset);
pbuffer->len += offset;
pbuffer->tot_len += offset;
return 0;
}
else
{
p = (void *)((u8_t *)p + pbuffer->len);
offset *= -1;
if ( ((u8_t *)p - (u8_t *)pbuffer->pdata) < offset )
return -1;
pbuffer->pdata = (void *)((u8_t *)pbuffer->pdata + offset);
pbuffer->len -= offset;
pbuffer->tot_len -= offset;
return 0;
}
return -1;
}
void zbuffer_dump(zbuffer_t *pbuffer)
{
u16_t i;
u16_t count = 0;
zbuffer_t *p;
p = pbuffer;
printf("\n");
while( p != NULL)
{
for ( i = 0; i < p->len; i++)
{
printf("%2x ", *(u8_t *)((u8_t *)p->pdata + i));
count ++;
if ( count % 20 == 0)
printf("\n");
}
p = p->next;
}
printf("\n");
return;
}