Contiki 2.5
uip_arch.c
1 /*
2  * Copyright (c) 2001, Adam Dunkels.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote
14  * products derived from this software without specific prior
15  * written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * This file is part of the uIP TCP/IP stack.
30  *
31  * $Id: uip_arch.c,v 1.2 2010/05/30 10:12:30 oliverschmidt Exp $
32  *
33  */
34 
35 
36 #include "net/uip.h"
37 #include "net/uip_arch.h"
38 
39 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
40 #define IP_PROTO_TCP 6
41 #define IP_PROTO_UDP 17
42 
43 /*-----------------------------------------------------------------------------------*/
44 #pragma optimize(push, off)
45 void
46 uip_add32(u8_t *op32, u16_t op16)
47 {
48  asm("ldy #3");
49  asm("jsr ldaxysp");
50  asm("sta ptr1");
51  asm("stx ptr1+1");
52  asm("ldy #0");
53  asm("lda (sp),y");
54  asm("ldy #3");
55  asm("clc");
56  asm("adc (ptr1),y");
57  asm("sta _uip_acc32+3");
58  asm("dey");
59  asm("lda (ptr1),y");
60  asm("ldy #1");
61  asm("adc (sp),y");
62  asm("sta _uip_acc32+2");
63  asm("ldy #1");
64  asm("lda (ptr1),y");
65  asm("adc #0");
66  asm("sta _uip_acc32+1");
67  asm("dey");
68  asm("lda (ptr1),y");
69  asm("adc #0");
70  asm("sta _uip_acc32+0");
71 }
72 #pragma optimize(pop)
73 /*-----------------------------------------------------------------------------------*/
74 static u16_t chksum_ptr, chksum_len, chksum_tmp;
75 static u8_t chksum_protocol;
76 static u16_t chksum(void);
77 /*-----------------------------------------------------------------------------------*/
78 #pragma optimize(push, off)
79 u16_t
80 chksum(void) {
81 
82  asm("lda #0");
83  asm("sta tmp1");
84  asm("sta tmp1+1");
85  asm("lda _chksum_ptr");
86  asm("sta ptr1");
87  asm("lda _chksum_ptr+1");
88  asm("sta ptr1+1");
89 
90 
91  asm("lda _chksum_len+1");
92  asm("beq chksumlast");
93 
94 
95  /* If checksum is > 256, do the first runs. */
96  asm("ldy #0");
97  asm("clc");
98  asm("chksumloop_256:");
99  asm("lda (ptr1),y");
100  asm("adc tmp1");
101  asm("sta tmp1");
102  asm("iny");
103  asm("lda (ptr1),y");
104  asm("adc tmp1+1");
105  asm("sta tmp1+1");
106  asm("iny");
107  asm("bne chksumloop_256");
108  asm("inc ptr1+1");
109  asm("dec _chksum_len+1");
110  asm("bne chksumloop_256");
111 
112  asm("chksum_endloop_256:");
113  asm("lda tmp1");
114  asm("adc #0");
115  asm("sta tmp1");
116  asm("lda tmp1+1");
117  asm("adc #0");
118  asm("sta tmp1+1");
119  asm("bcs chksum_endloop_256");
120 
121  asm("chksumlast:");
122  asm("lda _chksum_len");
123  asm("lsr");
124  asm("bcc chksum_noodd");
125  asm("ldy _chksum_len");
126  asm("dey");
127  asm("lda (ptr1),y");
128  asm("clc");
129  asm("adc tmp1");
130  asm("sta tmp1");
131  asm("bcc noinc1");
132  asm("inc tmp1+1");
133  asm("bne noinc1");
134  asm("inc tmp1");
135  asm("noinc1:");
136  asm("dec _chksum_len");
137 
138  asm("chksum_noodd:");
139  asm("clc");
140  asm("php");
141  asm("ldy _chksum_len");
142  asm("chksum_loop1:");
143  asm("cpy #0");
144  asm("beq chksum_loop1_end");
145  asm("plp");
146  asm("dey");
147  asm("dey");
148  asm("lda (ptr1),y");
149  asm("adc tmp1");
150  asm("sta tmp1");
151  asm("iny");
152  asm("lda (ptr1),y");
153  asm("adc tmp1+1");
154  asm("sta tmp1+1");
155  asm("dey");
156  asm("php");
157  asm("jmp chksum_loop1");
158  asm("chksum_loop1_end:");
159  asm("plp");
160 
161  asm("chksum_endloop:");
162  asm("lda tmp1");
163  asm("adc #0");
164  asm("sta tmp1");
165  asm("lda tmp1+1");
166  asm("adc #0");
167  asm("sta tmp1+1");
168  asm("bcs chksum_endloop");
169 
170  asm("lda tmp1");
171  asm("ldx tmp1+1");
172 }
173 #pragma optimize(pop)
174 /*-----------------------------------------------------------------------------------*/
175 u16_t
176 uip_chksum(u16_t *buf, u16_t len)
177 {
178  /* unsigned long sum;
179 
180  sum = 0;
181 
182  chksum_ptr = (u16_t)buf;
183  while(len >= 256) {
184  chksum_len = 256;
185  sum += chksum();
186  len -= 256;
187  chksum_ptr += 256;
188  }
189 
190  if(len < 256) {
191  chksum_len = len;
192  sum += chksum();
193  }
194 
195  while((sum >> 16) != 0) {
196  sum = (sum >> 16) + (sum & 0xffff);
197  }
198 
199  return sum;*/
200 
201  chksum_len = len;
202  chksum_ptr = (u16_t)buf;
203  return chksum();
204 }
205 /*-----------------------------------------------------------------------------------*/
206 u16_t
208 {
209  chksum_ptr = (u16_t)uip_buf + UIP_LLH_LEN;
210  chksum_len = UIP_IPH_LEN;
211  return chksum();
212 }
213 /*-----------------------------------------------------------------------------------*/
214 #pragma optimize(push, off)
215 static u16_t
216 transport_chksum(u8_t protocol)
217 {
218  chksum_protocol = protocol;
219  chksum_ptr = (u16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
220  chksum_len = UIP_TCPH_LEN;
221  chksum_tmp = chksum();
222 
223  chksum_ptr = (u16_t)uip_appdata;
224  asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
225  asm("sec");
226  asm("sbc #%b", UIP_IPTCPH_LEN);
227  asm("sta _chksum_len");
228  asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
229  asm("sbc #0");
230  asm("sta _chksum_len+1");
231 
232  asm("jsr %v", chksum);
233 
234  asm("clc");
235  asm("adc _chksum_tmp");
236  asm("sta _chksum_tmp");
237  asm("txa");
238  asm("adc _chksum_tmp+1");
239  asm("sta _chksum_tmp+1");
240 
241  /* Fold carry */
242  /* asm("bcc noinc");
243  asm("inc _chksum_tmp");
244  asm("noinc:");*/
245 
246  asm("tcpchksum_loop1:");
247  asm("lda _chksum_tmp");
248  asm("adc #0");
249  asm("sta _chksum_tmp");
250  asm("lda _chksum_tmp+1");
251  asm("adc #0");
252  asm("sta _chksum_tmp+1");
253  asm("bcs tcpchksum_loop1");
254 
255 
256  asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
257  asm("sec");
258  asm("sbc #%b", UIP_IPH_LEN);
259  asm("sta _chksum_len");
260  asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
261  asm("sbc #0");
262  asm("sta _chksum_len+1");
263 
264 
265  asm("ldy #$0c");
266  asm("clc");
267  asm("php");
268  asm("tcpchksum_loop2:");
269  asm("plp");
270  asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
271  asm("adc _chksum_tmp");
272  asm("sta _chksum_tmp");
273  asm("iny");
274  asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
275  asm("adc _chksum_tmp+1");
276  asm("sta _chksum_tmp+1");
277  asm("iny");
278  asm("php");
279  asm("cpy #$14");
280  asm("bne tcpchksum_loop2");
281 
282  asm("plp");
283 
284  asm("lda _chksum_tmp");
285  asm("adc #0");
286  asm("sta _chksum_tmp");
287  asm("lda _chksum_tmp+1");
288  asm("adc %v", chksum_protocol);
289  asm("sta _chksum_tmp+1");
290 
291 
292  asm("lda _chksum_tmp");
293  asm("adc _chksum_len+1");
294  asm("sta _chksum_tmp");
295  asm("lda _chksum_tmp+1");
296  asm("adc _chksum_len");
297  asm("sta _chksum_tmp+1");
298 
299 
300 
301  asm("tcpchksum_loop3:");
302  asm("lda _chksum_tmp");
303  asm("adc #0");
304  asm("sta _chksum_tmp");
305  asm("lda _chksum_tmp+1");
306  asm("adc #0");
307  asm("sta _chksum_tmp+1");
308  asm("bcs tcpchksum_loop3");
309 
310 
311  return chksum_tmp;
312 }
313 #pragma optimize(pop)
314 
315 /*-----------------------------------------------------------------------------------*/
316 u16_t
318 {
319  return transport_chksum(IP_PROTO_TCP);
320 #if 0
321  chksum_ptr = (u16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
322  chksum_len = UIP_TCPH_LEN;
323  chksum_tmp = chksum();
324 
325  chksum_ptr = (u16_t)uip_appdata;
326  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
327  asm("sec");
328  asm("sbc #%b", UIP_IPTCPH_LEN);
329  asm("sta _chksum_len");
330  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
331  asm("sbc #0");
332  asm("sta _chksum_len+1");
333 
334  asm("jsr %v", chksum);
335 
336  asm("clc");
337  asm("adc _chksum_tmp");
338  asm("sta _chksum_tmp");
339  asm("txa");
340  asm("adc _chksum_tmp+1");
341  asm("sta _chksum_tmp+1");
342 
343  /* Fold carry */
344  /* asm("bcc noinc");
345  asm("inc _chksum_tmp");
346  asm("noinc:");*/
347 
348  asm("tcpchksum_loop1:");
349  asm("lda _chksum_tmp");
350  asm("adc #0");
351  asm("sta _chksum_tmp");
352  asm("lda _chksum_tmp+1");
353  asm("adc #0");
354  asm("sta _chksum_tmp+1");
355  asm("bcs tcpchksum_loop1");
356 
357 
358  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
359  asm("sec");
360  asm("sbc #%b", UIP_IPH_LEN);
361  asm("sta _chksum_len");
362  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
363  asm("sbc #0");
364  asm("sta _chksum_len+1");
365 
366 
367  asm("ldy #$0c");
368  asm("clc");
369  asm("php");
370  asm("tcpchksum_loop2:");
371  asm("plp");
372  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
373  asm("adc _chksum_tmp");
374  asm("sta _chksum_tmp");
375  asm("iny");
376  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
377  asm("adc _chksum_tmp+1");
378  asm("sta _chksum_tmp+1");
379  asm("iny");
380  asm("php");
381  asm("cpy #$14");
382  asm("bne tcpchksum_loop2");
383 
384  asm("plp");
385 
386  asm("lda _chksum_tmp");
387  asm("adc #0");
388  asm("sta _chksum_tmp");
389  asm("lda _chksum_tmp+1");
390  asm("adc #6"); /* IP_PROTO_TCP */
391  asm("sta _chksum_tmp+1");
392 
393 
394  asm("lda _chksum_tmp");
395  asm("adc _chksum_len+1");
396  asm("sta _chksum_tmp");
397  asm("lda _chksum_tmp+1");
398  asm("adc _chksum_len");
399  asm("sta _chksum_tmp+1");
400 
401 
402 
403  asm("tcpchksum_loop3:");
404  asm("lda _chksum_tmp");
405  asm("adc #0");
406  asm("sta _chksum_tmp");
407  asm("lda _chksum_tmp+1");
408  asm("adc #0");
409  asm("sta _chksum_tmp+1");
410  asm("bcs tcpchksum_loop3");
411 
412 
413  return chksum_tmp;
414 #endif
415 }
416 
417 /*-----------------------------------------------------------------------------------*/
418 #if UIP_UDP_CHECKSUMS
419 u16_t
420 uip_udpchksum(void)
421 {
422  return transport_chksum(IP_PROTO_UDP);
423 #if 0
424  chksum_ptr = (u16_t)&uip_buf[20 + UIP_LLH_LEN];
425  chksum_len = 20;
426  chksum_tmp = chksum();
427 
428  chksum_ptr = (u16_t)uip_appdata;
429  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
430  asm("sec");
431  asm("sbc #40");
432  asm("sta _chksum_len");
433  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
434  asm("sbc #0");
435  asm("sta _chksum_len+1");
436 
437  asm("jsr %v", chksum);
438 
439  asm("clc");
440  asm("adc _chksum_tmp");
441  asm("sta _chksum_tmp");
442  asm("txa");
443  asm("adc _chksum_tmp+1");
444  asm("sta _chksum_tmp+1");
445 
446  /* Fold carry */
447  /* asm("bcc noinc");
448  asm("inc _chksum_tmp");
449  asm("noinc:");*/
450 
451  asm("tcpchksum_loop1:");
452  asm("lda _chksum_tmp");
453  asm("adc #0");
454  asm("sta _chksum_tmp");
455  asm("lda _chksum_tmp+1");
456  asm("adc #0");
457  asm("sta _chksum_tmp+1");
458  asm("bcs tcpchksum_loop1");
459 
460 
461  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
462  asm("sec");
463  asm("sbc #20");
464  asm("sta _chksum_len");
465  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
466  asm("sbc #0");
467  asm("sta _chksum_len+1");
468 
469 
470  asm("ldy #$0c");
471  asm("clc");
472  asm("php");
473  asm("tcpchksum_loop2:");
474  asm("plp");
475  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
476  asm("adc _chksum_tmp");
477  asm("sta _chksum_tmp");
478  asm("iny");
479  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
480  asm("adc _chksum_tmp+1");
481  asm("sta _chksum_tmp+1");
482  asm("iny");
483  asm("php");
484  asm("cpy #$14");
485  asm("bne tcpchksum_loop2");
486 
487  asm("plp");
488 
489  asm("lda _chksum_tmp");
490  asm("adc #0");
491  asm("sta _chksum_tmp");
492  asm("lda _chksum_tmp+1");
493  asm("adc #17"); /* IP_PROTO_UDP */
494  asm("sta _chksum_tmp+1");
495 
496 
497  asm("lda _chksum_tmp");
498  asm("adc _chksum_len+1");
499  asm("sta _chksum_tmp");
500  asm("lda _chksum_tmp+1");
501  asm("adc _chksum_len");
502  asm("sta _chksum_tmp+1");
503 
504 
505 
506  asm("tcpchksum_loop3:");
507  asm("lda _chksum_tmp");
508  asm("adc #0");
509  asm("sta _chksum_tmp");
510  asm("lda _chksum_tmp+1");
511  asm("adc #0");
512  asm("sta _chksum_tmp+1");
513  asm("bcs tcpchksum_loop3");
514 
515 
516  return chksum_tmp;
517 #endif
518 }
519 #endif /* UIP_UDP_CHECKSUMS */
520 /*-----------------------------------------------------------------------------------*/