blob: bae557bbd9ab7f4adfb0374e2c0384570be9524e [file] [log] [blame]
adamdunkels70c4c342003-04-24 17:01:17 +00001/*
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.
adamdunkels9fe9ae92004-09-12 20:28:47 +000013 * 3. The name of the author may not be used to endorse or promote
adamdunkels70c4c342003-04-24 17:01:17 +000014 * 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 *
oliverschmidtb30bf5a2005-02-24 22:04:53 +000031 * $Id: uip_arch.c,v 1.7 2005/02/24 22:04:53 oliverschmidt Exp $
adamdunkels70c4c342003-04-24 17:01:17 +000032 *
33 */
34
35
36#include "uip.h"
37#include "uip_arch.h"
38
39#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
40#define IP_PROTO_TCP 6
adamdunkels6968dcb2004-09-19 19:01:12 +000041#define IP_PROTO_UDP 17
adamdunkels70c4c342003-04-24 17:01:17 +000042
43/*-----------------------------------------------------------------------------------*/
oliverschmidt11740ed2004-07-18 13:21:05 +000044#pragma optimize(push, off)
adamdunkels70c4c342003-04-24 17:01:17 +000045void
46uip_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}
oliverschmidt11740ed2004-07-18 13:21:05 +000072#pragma optimize(pop)
adamdunkels70c4c342003-04-24 17:01:17 +000073/*-----------------------------------------------------------------------------------*/
adamdunkels70c4c342003-04-24 17:01:17 +000074static u16_t chksum_ptr, chksum_len, chksum_tmp;
adamdunkels6968dcb2004-09-19 19:01:12 +000075static u8_t chksum_protocol;
adamdunkels70c4c342003-04-24 17:01:17 +000076static u16_t chksum(void);
77/*-----------------------------------------------------------------------------------*/
oliverschmidt11740ed2004-07-18 13:21:05 +000078#pragma optimize(push, off)
adamdunkels70c4c342003-04-24 17:01:17 +000079u16_t
80chksum(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}
oliverschmidt11740ed2004-07-18 13:21:05 +0000173#pragma optimize(pop)
adamdunkels70c4c342003-04-24 17:01:17 +0000174/*-----------------------------------------------------------------------------------*/
175u16_t
176uip_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/*-----------------------------------------------------------------------------------*/
206u16_t
207uip_ipchksum(void)
208{
209 chksum_ptr = (u16_t)uip_buf + UIP_LLH_LEN;
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000210 chksum_len = UIP_IPH_LEN;
adamdunkels70c4c342003-04-24 17:01:17 +0000211 return chksum();
212}
213/*-----------------------------------------------------------------------------------*/
oliverschmidt11740ed2004-07-18 13:21:05 +0000214#pragma optimize(push, off)
adamdunkels6968dcb2004-09-19 19:01:12 +0000215static u16_t
216transport_chksum(u8_t protocol)
217{
218 chksum_protocol = protocol;
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000219 chksum_ptr = (u16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
220 chksum_len = UIP_TCPH_LEN;
adamdunkels70c4c342003-04-24 17:01:17 +0000221 chksum_tmp = chksum();
222
223 chksum_ptr = (u16_t)uip_appdata;
adamdunkels6968dcb2004-09-19 19:01:12 +0000224 asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000225 asm("sec");
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000226 asm("sbc #%b", UIP_IPTCPH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000227 asm("sta _chksum_len");
adamdunkels6968dcb2004-09-19 19:01:12 +0000228 asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000229 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
adamdunkels6968dcb2004-09-19 19:01:12 +0000256 asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000257 asm("sec");
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000258 asm("sbc #%b", UIP_IPH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000259 asm("sta _chksum_len");
adamdunkels6968dcb2004-09-19 19:01:12 +0000260 asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000261 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");
adamdunkels6968dcb2004-09-19 19:01:12 +0000270 asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
adamdunkels70c4c342003-04-24 17:01:17 +0000271 asm("adc _chksum_tmp");
272 asm("sta _chksum_tmp");
273 asm("iny");
adamdunkels6968dcb2004-09-19 19:01:12 +0000274 asm("lda _uip_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/*-----------------------------------------------------------------------------------*/
316u16_t
317uip_tcpchksum(void)
318{
319 return transport_chksum(IP_PROTO_TCP);
320#if 0
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000321 chksum_ptr = (u16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
322 chksum_len = UIP_TCPH_LEN;
adamdunkels6968dcb2004-09-19 19:01:12 +0000323 chksum_tmp = chksum();
324
325 chksum_ptr = (u16_t)uip_appdata;
326 asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
327 asm("sec");
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000328 asm("sbc #%b", UIP_IPTCPH_LEN);
adamdunkels6968dcb2004-09-19 19:01:12 +0000329 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");
oliverschmidtb30bf5a2005-02-24 22:04:53 +0000360 asm("sbc #%b", UIP_IPH_LEN);
adamdunkels6968dcb2004-09-19 19:01:12 +0000361 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);
adamdunkels70c4c342003-04-24 17:01:17 +0000377 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;
adamdunkels6968dcb2004-09-19 19:01:12 +0000414#endif
adamdunkels70c4c342003-04-24 17:01:17 +0000415}
adamdunkels6968dcb2004-09-19 19:01:12 +0000416
417/*-----------------------------------------------------------------------------------*/
418#if UIP_UDP_CHECKSUMS
419u16_t
420uip_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 */
adamdunkels70c4c342003-04-24 17:01:17 +0000520/*-----------------------------------------------------------------------------------*/