Fixed frame buffer allocation for AA modes
[libogc.git] / libdb / uIP / uip_pbuf.c
blobbb7612488a8fb4cb19b392e093257fd16185dca2
1 #include <stdlib.h>
2 #include <string.h>
4 #include "memb.h"
5 #include "memr.h"
6 #include "uip_pbuf.h"
8 #if UIP_LOGGING == 1
9 #include <stdio.h>
10 #define UIP_LOG(m) uip_log(__FILE__,__LINE__,m)
11 #else
12 #define UIP_LOG(m)
13 #endif /* UIP_LOGGING == 1 */
15 #if UIP_ERRORING == 1
16 #include <stdio.h>
17 #define UIP_ERROR(m) uip_log(__FILE__,__LINE__,m)
18 #else
19 #define UIP_ERROR(m)
20 #endif /* UIP_ERRORING == 1 */
22 #if UIP_STATISTICS == 1
23 struct uip_stats uip_stat;
24 #define UIP_STAT(s) s
25 #else
26 #define UIP_STAT(s)
27 #endif /* UIP_STATISTICS == 1 */
29 MEMB(uip_pool_pbufs,sizeof(struct uip_pbuf)+UIP_PBUF_POOL_BUFSIZE,UIP_PBUF_POOL_NUM);
30 MEMB(uip_rom_pbufs,sizeof(struct uip_pbuf),UIP_PBUF_ROM_NUM);
32 void uip_pbuf_init()
34 memb_init(&uip_pool_pbufs);
35 memb_init(&uip_rom_pbufs);
38 struct uip_pbuf* uip_pbuf_alloc(uip_pbuf_layer layer,u16_t len,uip_pbuf_flag flag)
40 u16_t offset;
41 s32_t rem_len;
42 struct uip_pbuf *p,*q,*r;
44 offset = 0;
45 switch(layer) {
46 case UIP_PBUF_TRANSPORT:
47 offset += UIP_TRANSPORT_HLEN;
48 case UIP_PBUF_IP:
49 offset += UIP_IP_HLEN;
50 case UIP_PBUF_LINK:
51 offset += UIP_LL_HLEN;
52 break;
53 case UIP_PBUF_RAW:
54 break;
55 default:
56 UIP_ERROR("uip_pbuf_alloc: bad pbuf layer.\n");
57 return NULL;
60 switch(flag) {
61 case UIP_PBUF_POOL:
62 p = memb_alloc(&uip_pool_pbufs);
63 if(p==NULL) {
64 UIP_ERROR("uip_pbuf_alloc: couldn't allocate pbuf(p) from pool\n");
65 return NULL;
68 p->next = NULL;
69 p->payload = MEM_ALIGN((void*)((u8_t*)p+(sizeof(struct uip_pbuf)+offset)));
70 p->tot_len = len;
71 p->len = (len>(UIP_PBUF_POOL_BUFSIZE-offset)?(UIP_PBUF_POOL_BUFSIZE-offset):len);
72 p->flags = UIP_PBUF_FLAG_POOL;
73 p->ref = 1;
75 r = p;
76 rem_len = len - p->len;
77 while(rem_len>0) {
78 q = memb_alloc(&uip_pool_pbufs);
79 if(q==NULL) {
80 UIP_ERROR("uip_pbuf_alloc: couldn't allocate pbuf(q) from pool\n");
81 uip_pbuf_free(p);
82 return NULL;
85 q->next = NULL;
86 r->next = q;
87 q->tot_len = rem_len;
88 q->len = (rem_len>UIP_PBUF_POOL_BUFSIZE?UIP_PBUF_POOL_BUFSIZE:rem_len);
89 q->payload = (void*)((u8_t*)q+sizeof(struct uip_pbuf));
90 q->flags = UIP_PBUF_FLAG_POOL;
91 q->ref = 1;
93 rem_len -= q->len;
94 r = q;
96 break;
97 case UIP_PBUF_RAM:
98 p = memr_malloc(MEM_ALIGN_SIZE(sizeof(struct uip_pbuf)+offset)+MEM_ALIGN_SIZE(len));
99 if(p==NULL) {
100 UIP_ERROR("uip_pbuf_alloc: couldn't allocate pbuf from ram\n");
101 return NULL;
103 p->payload = MEM_ALIGN((u8_t*)p+sizeof(struct uip_pbuf)+offset);
104 p->len = p->tot_len = len;
105 p->next = NULL;
106 p->flags = UIP_PBUF_FLAG_RAM;
107 break;
108 case UIP_PBUF_ROM:
109 case UIP_PBUF_REF:
110 p = memb_alloc(&uip_rom_pbufs);
111 if(p==NULL) {
112 UIP_ERROR("uip_pbuf_alloc: couldn't allocate pbuf from rom/ref\n");
113 return NULL;
115 p->payload = NULL;
116 p->next = NULL;
117 p->len = p->tot_len = len;
118 p->flags = (flag==UIP_PBUF_ROM?UIP_PBUF_FLAG_ROM:UIP_PBUF_FLAG_REF);
119 break;
120 default:
121 UIP_ERROR("uip_pbuf_alloc: bad flag value.\n");
122 return NULL;
125 p->ref = 1;
126 return p;
129 u8_t uip_pbuf_free(struct uip_pbuf *p)
131 u8_t cnt;
132 struct uip_pbuf *q;
134 if(p==NULL) return 0;
136 cnt = 0;
137 while(p!=NULL) {
138 p->ref--;
139 if(p->ref==0) {
140 q = p->next;
141 if(p->flags==UIP_PBUF_FLAG_POOL) {
142 memb_free(&uip_pool_pbufs,p);
143 } else if(p->flags==UIP_PBUF_FLAG_ROM || p->flags==UIP_PBUF_FLAG_REF) {
144 memb_free(&uip_rom_pbufs,p);
145 } else {
146 memr_free(p);
148 cnt++;
149 p = q;
150 } else
151 p = NULL;
153 return cnt;
156 void uip_pbuf_realloc(struct uip_pbuf *p,u16_t new_len)
158 u16_t rem_len;
159 s16_t grow;
160 struct uip_pbuf *q;
162 if(new_len>=p->tot_len) return;
164 grow = new_len - p->tot_len;
165 rem_len = new_len;
166 q = p;
167 while(rem_len>q->len) {
168 rem_len -= q->len;
169 q->tot_len += grow;
170 q = q->next;
173 if(q->flags==UIP_PBUF_FLAG_RAM && rem_len!=q->len)
174 memr_realloc(q,(u8_t*)q->payload-(u8_t*)q+rem_len);
176 q->len = rem_len;
177 q->tot_len = q->len;
179 if(q->next!=NULL) uip_pbuf_free(q->next);
180 q->next = NULL;
183 u8_t uip_pbuf_header(struct uip_pbuf *p,s16_t hdr_size_inc)
185 void *payload;
187 if(hdr_size_inc==0 || p==NULL) return 0;
190 payload = p->payload;
191 if(p->flags==UIP_PBUF_FLAG_POOL || p->flags==UIP_PBUF_FLAG_RAM) {
192 p->payload = (u8_t*)p->payload-hdr_size_inc;
193 if((u8_t*)p->payload<(u8_t*)p+sizeof(struct uip_pbuf)) {
194 p->payload = payload;
195 return 1;
197 } else if(p->flags==UIP_PBUF_FLAG_ROM || p->flags==UIP_PBUF_FLAG_REF) {
198 if(hdr_size_inc<0 && hdr_size_inc-p->len<=0) p->payload = (u8_t*)p->payload-hdr_size_inc;
199 else return 1;
201 p->tot_len += hdr_size_inc;
202 p->len += hdr_size_inc;
204 return 0;
207 u8_t uip_pbuf_clen(struct uip_pbuf *p)
209 u8_t len;
211 len = 0;
212 while(p!=NULL) {
213 len++;
214 p = p->next;
216 return len;
219 void uip_pbuf_ref(struct uip_pbuf *p)
221 if(p!=NULL) {
222 ++(p->ref);
226 void uip_pbuf_cat(struct uip_pbuf *h,struct uip_pbuf *t)
228 struct uip_pbuf *p;
230 if(h==NULL || t==NULL) return;
232 for(p=h;p->next!=NULL;p=p->next) {
233 p->tot_len += t->tot_len;
235 p->tot_len += t->tot_len;
236 p->next = t;
239 void uip_pbuf_queue(struct uip_pbuf *p,struct uip_pbuf *n)
241 if(p==NULL || n==NULL || p==n) return;
243 while(p->next!=NULL) p = p->next;
245 p->next = n;
246 uip_pbuf_ref(n);
249 struct uip_pbuf* uip_pbuf_dequeue(struct uip_pbuf *p)
251 struct uip_pbuf *q;
252 u8_t tail_gone = 1;
254 if(p==NULL) return NULL;
256 while(p->tot_len!=p->len) p = p->next;
258 q = p->next;
259 if(q!=NULL) {
260 p->next = NULL;
261 tail_gone = uip_pbuf_free(q);
263 return (tail_gone>0?NULL:q);
266 void uip_pbuf_chain(struct uip_pbuf *h,struct uip_pbuf *t)
268 uip_pbuf_cat(h,t);
269 uip_pbuf_ref(t);
272 struct uip_pbuf* uip_pbuf_dechain(struct uip_pbuf *p)
274 struct uip_pbuf *q;
275 u8_t tail_gone = 1;
277 q = p->next;
278 if(q!=NULL) {
279 q->tot_len = p->tot_len - p->len;
280 p->next = NULL;
281 p->tot_len = p->len;
283 tail_gone = uip_pbuf_free(q);
286 return (tail_gone>0?NULL:q);