Contiki 3.x
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  *
32  */
33 
34 
35 #include "net/ip/uip.h"
36 #include "net/ip/uip_arch.h"
37 
38 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
39 #define IP_PROTO_TCP 6
40 #define IP_PROTO_UDP 17
41 
42 /*-----------------------------------------------------------------------------------*/
43 #pragma optimize(push, off)
44 void
45 uip_add32(uint8_t *op32, uint16_t op16)
46 {
47  asm("ldy #3");
48  asm("jsr ldaxysp");
49  asm("sta ptr1");
50  asm("stx ptr1+1");
51  asm("ldy #0");
52  asm("lda (sp),y");
53  asm("ldy #3");
54  asm("clc");
55  asm("adc (ptr1),y");
56  asm("sta _uip_acc32+3");
57  asm("dey");
58  asm("lda (ptr1),y");
59  asm("ldy #1");
60  asm("adc (sp),y");
61  asm("sta _uip_acc32+2");
62  asm("ldy #1");
63  asm("lda (ptr1),y");
64  asm("adc #0");
65  asm("sta _uip_acc32+1");
66  asm("dey");
67  asm("lda (ptr1),y");
68  asm("adc #0");
69  asm("sta _uip_acc32+0");
70 }
71 #pragma optimize(pop)
72 /*-----------------------------------------------------------------------------------*/
73 static uint16_t chksum_ptr, chksum_len, chksum_tmp;
74 static uint8_t chksum_protocol;
75 static uint16_t chksum(void);
76 /*-----------------------------------------------------------------------------------*/
77 #pragma optimize(push, off)
78 uint16_t
79 chksum(void) {
80 
81  asm("lda #0");
82  asm("sta tmp1");
83  asm("sta tmp1+1");
84  asm("lda _chksum_ptr");
85  asm("sta ptr1");
86  asm("lda _chksum_ptr+1");
87  asm("sta ptr1+1");
88 
89  asm("lda _chksum_len+1");
90  asm("beq chksumlast");
91 
92  /* If checksum is > 256, do the first runs. */
93  asm("ldy #0");
94  asm("clc");
95  asm("chksumloop_256:");
96  asm("lda (ptr1),y");
97  asm("adc tmp1");
98  asm("sta tmp1");
99  asm("iny");
100  asm("lda (ptr1),y");
101  asm("adc tmp1+1");
102  asm("sta tmp1+1");
103  asm("iny");
104  asm("bne chksumloop_256");
105  asm("inc ptr1+1");
106  asm("dec _chksum_len+1");
107  asm("bne chksumloop_256");
108 
109  asm("chksum_endloop_256:");
110  asm("lda tmp1");
111  asm("adc #0");
112  asm("sta tmp1");
113  asm("lda tmp1+1");
114  asm("adc #0");
115  asm("sta tmp1+1");
116  asm("bcs chksum_endloop_256");
117 
118  asm("chksumlast:");
119  asm("lda _chksum_len");
120  asm("lsr");
121  asm("bcc chksum_noodd");
122  asm("ldy _chksum_len");
123  asm("dey");
124  asm("lda (ptr1),y");
125  asm("clc");
126  asm("adc tmp1");
127  asm("sta tmp1");
128  asm("bcc noinc1");
129  asm("inc tmp1+1");
130  asm("bne noinc1");
131  asm("inc tmp1");
132  asm("noinc1:");
133  asm("dec _chksum_len");
134 
135  asm("chksum_noodd:");
136  asm("clc");
137  asm("php");
138  asm("ldy _chksum_len");
139  asm("chksum_loop1:");
140  asm("cpy #0");
141  asm("beq chksum_loop1_end");
142  asm("plp");
143  asm("dey");
144  asm("dey");
145  asm("lda (ptr1),y");
146  asm("adc tmp1");
147  asm("sta tmp1");
148  asm("iny");
149  asm("lda (ptr1),y");
150  asm("adc tmp1+1");
151  asm("sta tmp1+1");
152  asm("dey");
153  asm("php");
154  asm("jmp chksum_loop1");
155  asm("chksum_loop1_end:");
156  asm("plp");
157 
158  asm("chksum_endloop:");
159  asm("lda tmp1");
160  asm("adc #0");
161  asm("sta tmp1");
162  asm("lda tmp1+1");
163  asm("adc #0");
164  asm("sta tmp1+1");
165  asm("bcs chksum_endloop");
166 
167  asm("lda tmp1");
168  asm("ldx tmp1+1");
169 
170  return __AX__;
171 }
172 #pragma optimize(pop)
173 /*-----------------------------------------------------------------------------------*/
174 uint16_t
175 uip_chksum(uint16_t *buf, uint16_t len)
176 {
177  /* unsigned long sum;
178 
179  sum = 0;
180 
181  chksum_ptr = (uint16_t)buf;
182  while(len >= 256) {
183  chksum_len = 256;
184  sum += chksum();
185  len -= 256;
186  chksum_ptr += 256;
187  }
188 
189  if(len < 256) {
190  chksum_len = len;
191  sum += chksum();
192  }
193 
194  while((sum >> 16) != 0) {
195  sum = (sum >> 16) + (sum & 0xffff);
196  }
197 
198  return sum;*/
199 
200  chksum_len = len;
201  chksum_ptr = (uint16_t)buf;
202  return chksum();
203 }
204 /*-----------------------------------------------------------------------------------*/
205 uint16_t
207 {
208  chksum_ptr = (uint16_t)uip_buf + UIP_LLH_LEN;
209  chksum_len = UIP_IPH_LEN;
210  return chksum();
211 }
212 /*-----------------------------------------------------------------------------------*/
213 #pragma optimize(push, off)
214 static uint16_t
215 transport_chksum(uint8_t protocol)
216 {
217  chksum_protocol = protocol;
218  chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
219  chksum_len = UIP_TCPH_LEN;
220  chksum_tmp = chksum();
221 
222  chksum_ptr = (uint16_t)uip_appdata;
223  asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
224  asm("sec");
225  asm("sbc #%b", UIP_IPTCPH_LEN);
226  asm("sta _chksum_len");
227  asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
228  asm("sbc #0");
229  asm("sta _chksum_len+1");
230 
231  asm("jsr %v", chksum);
232 
233  asm("clc");
234  asm("adc _chksum_tmp");
235  asm("sta _chksum_tmp");
236  asm("txa");
237  asm("adc _chksum_tmp+1");
238  asm("sta _chksum_tmp+1");
239 
240  /* Fold carry */
241  /* asm("bcc noinc");
242  asm("inc _chksum_tmp");
243  asm("noinc:");*/
244 
245  asm("tcpchksum_loop1:");
246  asm("lda _chksum_tmp");
247  asm("adc #0");
248  asm("sta _chksum_tmp");
249  asm("lda _chksum_tmp+1");
250  asm("adc #0");
251  asm("sta _chksum_tmp+1");
252  asm("bcs tcpchksum_loop1");
253 
254  asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
255  asm("sec");
256  asm("sbc #%b", UIP_IPH_LEN);
257  asm("sta _chksum_len");
258  asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
259  asm("sbc #0");
260  asm("sta _chksum_len+1");
261 
262  asm("ldy #$0c");
263  asm("clc");
264  asm("php");
265  asm("tcpchksum_loop2:");
266  asm("plp");
267  asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
268  asm("adc _chksum_tmp");
269  asm("sta _chksum_tmp");
270  asm("iny");
271  asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
272  asm("adc _chksum_tmp+1");
273  asm("sta _chksum_tmp+1");
274  asm("iny");
275  asm("php");
276  asm("cpy #$14");
277  asm("bne tcpchksum_loop2");
278 
279  asm("plp");
280 
281  asm("lda _chksum_tmp");
282  asm("adc #0");
283  asm("sta _chksum_tmp");
284  asm("lda _chksum_tmp+1");
285  asm("adc %v", chksum_protocol);
286  asm("sta _chksum_tmp+1");
287 
288  asm("lda _chksum_tmp");
289  asm("adc _chksum_len+1");
290  asm("sta _chksum_tmp");
291  asm("lda _chksum_tmp+1");
292  asm("adc _chksum_len");
293  asm("sta _chksum_tmp+1");
294 
295  asm("tcpchksum_loop3:");
296  asm("lda _chksum_tmp");
297  asm("adc #0");
298  asm("sta _chksum_tmp");
299  asm("lda _chksum_tmp+1");
300  asm("adc #0");
301  asm("sta _chksum_tmp+1");
302  asm("bcs tcpchksum_loop3");
303 
304  return chksum_tmp;
305 }
306 #pragma optimize(pop)
307 
308 /*-----------------------------------------------------------------------------------*/
309 uint16_t
311 {
312  return transport_chksum(IP_PROTO_TCP);
313 #if 0
314  chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
315  chksum_len = UIP_TCPH_LEN;
316  chksum_tmp = chksum();
317 
318  chksum_ptr = (uint16_t)uip_appdata;
319  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
320  asm("sec");
321  asm("sbc #%b", UIP_IPTCPH_LEN);
322  asm("sta _chksum_len");
323  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
324  asm("sbc #0");
325  asm("sta _chksum_len+1");
326 
327  asm("jsr %v", chksum);
328 
329  asm("clc");
330  asm("adc _chksum_tmp");
331  asm("sta _chksum_tmp");
332  asm("txa");
333  asm("adc _chksum_tmp+1");
334  asm("sta _chksum_tmp+1");
335 
336  /* Fold carry */
337  /* asm("bcc noinc");
338  asm("inc _chksum_tmp");
339  asm("noinc:");*/
340 
341  asm("tcpchksum_loop1:");
342  asm("lda _chksum_tmp");
343  asm("adc #0");
344  asm("sta _chksum_tmp");
345  asm("lda _chksum_tmp+1");
346  asm("adc #0");
347  asm("sta _chksum_tmp+1");
348  asm("bcs tcpchksum_loop1");
349 
350  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
351  asm("sec");
352  asm("sbc #%b", UIP_IPH_LEN);
353  asm("sta _chksum_len");
354  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
355  asm("sbc #0");
356  asm("sta _chksum_len+1");
357 
358  asm("ldy #$0c");
359  asm("clc");
360  asm("php");
361  asm("tcpchksum_loop2:");
362  asm("plp");
363  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
364  asm("adc _chksum_tmp");
365  asm("sta _chksum_tmp");
366  asm("iny");
367  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
368  asm("adc _chksum_tmp+1");
369  asm("sta _chksum_tmp+1");
370  asm("iny");
371  asm("php");
372  asm("cpy #$14");
373  asm("bne tcpchksum_loop2");
374 
375  asm("plp");
376 
377  asm("lda _chksum_tmp");
378  asm("adc #0");
379  asm("sta _chksum_tmp");
380  asm("lda _chksum_tmp+1");
381  asm("adc #6"); /* IP_PROTO_TCP */
382  asm("sta _chksum_tmp+1");
383 
384  asm("lda _chksum_tmp");
385  asm("adc _chksum_len+1");
386  asm("sta _chksum_tmp");
387  asm("lda _chksum_tmp+1");
388  asm("adc _chksum_len");
389  asm("sta _chksum_tmp+1");
390 
391  asm("tcpchksum_loop3:");
392  asm("lda _chksum_tmp");
393  asm("adc #0");
394  asm("sta _chksum_tmp");
395  asm("lda _chksum_tmp+1");
396  asm("adc #0");
397  asm("sta _chksum_tmp+1");
398  asm("bcs tcpchksum_loop3");
399 
400  return chksum_tmp;
401 #endif
402 }
403 
404 /*-----------------------------------------------------------------------------------*/
405 #if UIP_UDP_CHECKSUMS
406 uint16_t
407 uip_udpchksum(void)
408 {
409  return transport_chksum(IP_PROTO_UDP);
410 #if 0
411  chksum_ptr = (uint16_t)&uip_buf[20 + UIP_LLH_LEN];
412  chksum_len = 20;
413  chksum_tmp = chksum();
414 
415  chksum_ptr = (uint16_t)uip_appdata;
416  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
417  asm("sec");
418  asm("sbc #40");
419  asm("sta _chksum_len");
420  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
421  asm("sbc #0");
422  asm("sta _chksum_len+1");
423 
424  asm("jsr %v", chksum);
425 
426  asm("clc");
427  asm("adc _chksum_tmp");
428  asm("sta _chksum_tmp");
429  asm("txa");
430  asm("adc _chksum_tmp+1");
431  asm("sta _chksum_tmp+1");
432 
433  /* Fold carry */
434  /* asm("bcc noinc");
435  asm("inc _chksum_tmp");
436  asm("noinc:");*/
437 
438  asm("tcpchksum_loop1:");
439  asm("lda _chksum_tmp");
440  asm("adc #0");
441  asm("sta _chksum_tmp");
442  asm("lda _chksum_tmp+1");
443  asm("adc #0");
444  asm("sta _chksum_tmp+1");
445  asm("bcs tcpchksum_loop1");
446 
447  asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
448  asm("sec");
449  asm("sbc #20");
450  asm("sta _chksum_len");
451  asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
452  asm("sbc #0");
453  asm("sta _chksum_len+1");
454 
455  asm("ldy #$0c");
456  asm("clc");
457  asm("php");
458  asm("tcpchksum_loop2:");
459  asm("plp");
460  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
461  asm("adc _chksum_tmp");
462  asm("sta _chksum_tmp");
463  asm("iny");
464  asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
465  asm("adc _chksum_tmp+1");
466  asm("sta _chksum_tmp+1");
467  asm("iny");
468  asm("php");
469  asm("cpy #$14");
470  asm("bne tcpchksum_loop2");
471 
472  asm("plp");
473 
474  asm("lda _chksum_tmp");
475  asm("adc #0");
476  asm("sta _chksum_tmp");
477  asm("lda _chksum_tmp+1");
478  asm("adc #17"); /* IP_PROTO_UDP */
479  asm("sta _chksum_tmp+1");
480 
481  asm("lda _chksum_tmp");
482  asm("adc _chksum_len+1");
483  asm("sta _chksum_tmp");
484  asm("lda _chksum_tmp+1");
485  asm("adc _chksum_len");
486  asm("sta _chksum_tmp+1");
487 
488  asm("tcpchksum_loop3:");
489  asm("lda _chksum_tmp");
490  asm("adc #0");
491  asm("sta _chksum_tmp");
492  asm("lda _chksum_tmp+1");
493  asm("adc #0");
494  asm("sta _chksum_tmp+1");
495  asm("bcs tcpchksum_loop3");
496 
497  return chksum_tmp;
498 #endif
499 }
500 #endif /* UIP_UDP_CHECKSUMS */
501 /*-----------------------------------------------------------------------------------*/
uint16_t uip_udpchksum(void)
Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
uint16_t uip_ipchksum(void)
Calculate the IP header checksum of the packet header in uip_buf.
Definition: uip6.c:343
Header file for the uIP TCP/IP stack.
uint16_t uip_chksum(uint16_t *buf, uint16_t len)
Calculate the Internet checksum over a buffer.
Definition: uip6.c:336
uint16_t uip_tcpchksum(void)
Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
Definition: uip_arch.c:310
#define UIP_LLH_LEN
The link level header length.
Definition: uipopt.h:160
void uip_add32(uint8_t *op32, uint16_t op16)
Carry out a 32-bit addition.
Definition: uip_arch.c:45
Declarations of architecture specific functions.
uip_appdata
Pointer to the application data in the packet buffer.
Definition: tcp_loader.c:74