Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2001, Adam Dunkels. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. The name of the author may not be used to endorse or promote 00014 * products derived from this software without specific prior 00015 * written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00018 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00021 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00023 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00025 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00026 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00027 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 * 00029 * This file is part of the uIP TCP/IP stack. 00030 * 00031 * $Id: uip_arch.c,v 1.2 2010/05/30 10:12:30 oliverschmidt Exp $ 00032 * 00033 */ 00034 00035 00036 #include "net/uip.h" 00037 #include "net/uip_arch.h" 00038 00039 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) 00040 #define IP_PROTO_TCP 6 00041 #define IP_PROTO_UDP 17 00042 00043 /*-----------------------------------------------------------------------------------*/ 00044 #pragma optimize(push, off) 00045 void 00046 uip_add32(uint8_t *op32, uint16_t op16) 00047 { 00048 asm("ldy #3"); 00049 asm("jsr ldaxysp"); 00050 asm("sta ptr1"); 00051 asm("stx ptr1+1"); 00052 asm("ldy #0"); 00053 asm("lda (sp),y"); 00054 asm("ldy #3"); 00055 asm("clc"); 00056 asm("adc (ptr1),y"); 00057 asm("sta _uip_acc32+3"); 00058 asm("dey"); 00059 asm("lda (ptr1),y"); 00060 asm("ldy #1"); 00061 asm("adc (sp),y"); 00062 asm("sta _uip_acc32+2"); 00063 asm("ldy #1"); 00064 asm("lda (ptr1),y"); 00065 asm("adc #0"); 00066 asm("sta _uip_acc32+1"); 00067 asm("dey"); 00068 asm("lda (ptr1),y"); 00069 asm("adc #0"); 00070 asm("sta _uip_acc32+0"); 00071 } 00072 #pragma optimize(pop) 00073 /*-----------------------------------------------------------------------------------*/ 00074 static uint16_t chksum_ptr, chksum_len, chksum_tmp; 00075 static uint8_t chksum_protocol; 00076 static uint16_t chksum(void); 00077 /*-----------------------------------------------------------------------------------*/ 00078 #pragma optimize(push, off) 00079 uint16_t 00080 chksum(void) { 00081 00082 asm("lda #0"); 00083 asm("sta tmp1"); 00084 asm("sta tmp1+1"); 00085 asm("lda _chksum_ptr"); 00086 asm("sta ptr1"); 00087 asm("lda _chksum_ptr+1"); 00088 asm("sta ptr1+1"); 00089 00090 00091 asm("lda _chksum_len+1"); 00092 asm("beq chksumlast"); 00093 00094 00095 /* If checksum is > 256, do the first runs. */ 00096 asm("ldy #0"); 00097 asm("clc"); 00098 asm("chksumloop_256:"); 00099 asm("lda (ptr1),y"); 00100 asm("adc tmp1"); 00101 asm("sta tmp1"); 00102 asm("iny"); 00103 asm("lda (ptr1),y"); 00104 asm("adc tmp1+1"); 00105 asm("sta tmp1+1"); 00106 asm("iny"); 00107 asm("bne chksumloop_256"); 00108 asm("inc ptr1+1"); 00109 asm("dec _chksum_len+1"); 00110 asm("bne chksumloop_256"); 00111 00112 asm("chksum_endloop_256:"); 00113 asm("lda tmp1"); 00114 asm("adc #0"); 00115 asm("sta tmp1"); 00116 asm("lda tmp1+1"); 00117 asm("adc #0"); 00118 asm("sta tmp1+1"); 00119 asm("bcs chksum_endloop_256"); 00120 00121 asm("chksumlast:"); 00122 asm("lda _chksum_len"); 00123 asm("lsr"); 00124 asm("bcc chksum_noodd"); 00125 asm("ldy _chksum_len"); 00126 asm("dey"); 00127 asm("lda (ptr1),y"); 00128 asm("clc"); 00129 asm("adc tmp1"); 00130 asm("sta tmp1"); 00131 asm("bcc noinc1"); 00132 asm("inc tmp1+1"); 00133 asm("bne noinc1"); 00134 asm("inc tmp1"); 00135 asm("noinc1:"); 00136 asm("dec _chksum_len"); 00137 00138 asm("chksum_noodd:"); 00139 asm("clc"); 00140 asm("php"); 00141 asm("ldy _chksum_len"); 00142 asm("chksum_loop1:"); 00143 asm("cpy #0"); 00144 asm("beq chksum_loop1_end"); 00145 asm("plp"); 00146 asm("dey"); 00147 asm("dey"); 00148 asm("lda (ptr1),y"); 00149 asm("adc tmp1"); 00150 asm("sta tmp1"); 00151 asm("iny"); 00152 asm("lda (ptr1),y"); 00153 asm("adc tmp1+1"); 00154 asm("sta tmp1+1"); 00155 asm("dey"); 00156 asm("php"); 00157 asm("jmp chksum_loop1"); 00158 asm("chksum_loop1_end:"); 00159 asm("plp"); 00160 00161 asm("chksum_endloop:"); 00162 asm("lda tmp1"); 00163 asm("adc #0"); 00164 asm("sta tmp1"); 00165 asm("lda tmp1+1"); 00166 asm("adc #0"); 00167 asm("sta tmp1+1"); 00168 asm("bcs chksum_endloop"); 00169 00170 asm("lda tmp1"); 00171 asm("ldx tmp1+1"); 00172 } 00173 #pragma optimize(pop) 00174 /*-----------------------------------------------------------------------------------*/ 00175 uint16_t 00176 uip_chksum(uint16_t *buf, uint16_t len) 00177 { 00178 /* unsigned long sum; 00179 00180 sum = 0; 00181 00182 chksum_ptr = (uint16_t)buf; 00183 while(len >= 256) { 00184 chksum_len = 256; 00185 sum += chksum(); 00186 len -= 256; 00187 chksum_ptr += 256; 00188 } 00189 00190 if(len < 256) { 00191 chksum_len = len; 00192 sum += chksum(); 00193 } 00194 00195 while((sum >> 16) != 0) { 00196 sum = (sum >> 16) + (sum & 0xffff); 00197 } 00198 00199 return sum;*/ 00200 00201 chksum_len = len; 00202 chksum_ptr = (uint16_t)buf; 00203 return chksum(); 00204 } 00205 /*-----------------------------------------------------------------------------------*/ 00206 uint16_t 00207 uip_ipchksum(void) 00208 { 00209 chksum_ptr = (uint16_t)uip_buf + UIP_LLH_LEN; 00210 chksum_len = UIP_IPH_LEN; 00211 return chksum(); 00212 } 00213 /*-----------------------------------------------------------------------------------*/ 00214 #pragma optimize(push, off) 00215 static uint16_t 00216 transport_chksum(uint8_t protocol) 00217 { 00218 chksum_protocol = protocol; 00219 chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]; 00220 chksum_len = UIP_TCPH_LEN; 00221 chksum_tmp = chksum(); 00222 00223 chksum_ptr = (uint16_t)uip_appdata; 00224 asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN); 00225 asm("sec"); 00226 asm("sbc #%b", UIP_IPTCPH_LEN); 00227 asm("sta _chksum_len"); 00228 asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN); 00229 asm("sbc #0"); 00230 asm("sta _chksum_len+1"); 00231 00232 asm("jsr %v", chksum); 00233 00234 asm("clc"); 00235 asm("adc _chksum_tmp"); 00236 asm("sta _chksum_tmp"); 00237 asm("txa"); 00238 asm("adc _chksum_tmp+1"); 00239 asm("sta _chksum_tmp+1"); 00240 00241 /* Fold carry */ 00242 /* asm("bcc noinc"); 00243 asm("inc _chksum_tmp"); 00244 asm("noinc:");*/ 00245 00246 asm("tcpchksum_loop1:"); 00247 asm("lda _chksum_tmp"); 00248 asm("adc #0"); 00249 asm("sta _chksum_tmp"); 00250 asm("lda _chksum_tmp+1"); 00251 asm("adc #0"); 00252 asm("sta _chksum_tmp+1"); 00253 asm("bcs tcpchksum_loop1"); 00254 00255 00256 asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN); 00257 asm("sec"); 00258 asm("sbc #%b", UIP_IPH_LEN); 00259 asm("sta _chksum_len"); 00260 asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN); 00261 asm("sbc #0"); 00262 asm("sta _chksum_len+1"); 00263 00264 00265 asm("ldy #$0c"); 00266 asm("clc"); 00267 asm("php"); 00268 asm("tcpchksum_loop2:"); 00269 asm("plp"); 00270 asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN); 00271 asm("adc _chksum_tmp"); 00272 asm("sta _chksum_tmp"); 00273 asm("iny"); 00274 asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN); 00275 asm("adc _chksum_tmp+1"); 00276 asm("sta _chksum_tmp+1"); 00277 asm("iny"); 00278 asm("php"); 00279 asm("cpy #$14"); 00280 asm("bne tcpchksum_loop2"); 00281 00282 asm("plp"); 00283 00284 asm("lda _chksum_tmp"); 00285 asm("adc #0"); 00286 asm("sta _chksum_tmp"); 00287 asm("lda _chksum_tmp+1"); 00288 asm("adc %v", chksum_protocol); 00289 asm("sta _chksum_tmp+1"); 00290 00291 00292 asm("lda _chksum_tmp"); 00293 asm("adc _chksum_len+1"); 00294 asm("sta _chksum_tmp"); 00295 asm("lda _chksum_tmp+1"); 00296 asm("adc _chksum_len"); 00297 asm("sta _chksum_tmp+1"); 00298 00299 00300 00301 asm("tcpchksum_loop3:"); 00302 asm("lda _chksum_tmp"); 00303 asm("adc #0"); 00304 asm("sta _chksum_tmp"); 00305 asm("lda _chksum_tmp+1"); 00306 asm("adc #0"); 00307 asm("sta _chksum_tmp+1"); 00308 asm("bcs tcpchksum_loop3"); 00309 00310 00311 return chksum_tmp; 00312 } 00313 #pragma optimize(pop) 00314 00315 /*-----------------------------------------------------------------------------------*/ 00316 uint16_t 00317 uip_tcpchksum(void) 00318 { 00319 return transport_chksum(IP_PROTO_TCP); 00320 #if 0 00321 chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]; 00322 chksum_len = UIP_TCPH_LEN; 00323 chksum_tmp = chksum(); 00324 00325 chksum_ptr = (uint16_t)uip_appdata; 00326 asm("lda _uip_buf+3+%b", UIP_LLH_LEN); 00327 asm("sec"); 00328 asm("sbc #%b", UIP_IPTCPH_LEN); 00329 asm("sta _chksum_len"); 00330 asm("lda _uip_buf+2+%b", UIP_LLH_LEN); 00331 asm("sbc #0"); 00332 asm("sta _chksum_len+1"); 00333 00334 asm("jsr %v", chksum); 00335 00336 asm("clc"); 00337 asm("adc _chksum_tmp"); 00338 asm("sta _chksum_tmp"); 00339 asm("txa"); 00340 asm("adc _chksum_tmp+1"); 00341 asm("sta _chksum_tmp+1"); 00342 00343 /* Fold carry */ 00344 /* asm("bcc noinc"); 00345 asm("inc _chksum_tmp"); 00346 asm("noinc:");*/ 00347 00348 asm("tcpchksum_loop1:"); 00349 asm("lda _chksum_tmp"); 00350 asm("adc #0"); 00351 asm("sta _chksum_tmp"); 00352 asm("lda _chksum_tmp+1"); 00353 asm("adc #0"); 00354 asm("sta _chksum_tmp+1"); 00355 asm("bcs tcpchksum_loop1"); 00356 00357 00358 asm("lda _uip_buf+3+%b", UIP_LLH_LEN); 00359 asm("sec"); 00360 asm("sbc #%b", UIP_IPH_LEN); 00361 asm("sta _chksum_len"); 00362 asm("lda _uip_buf+2+%b", UIP_LLH_LEN); 00363 asm("sbc #0"); 00364 asm("sta _chksum_len+1"); 00365 00366 00367 asm("ldy #$0c"); 00368 asm("clc"); 00369 asm("php"); 00370 asm("tcpchksum_loop2:"); 00371 asm("plp"); 00372 asm("lda _uip_buf+%b,y", UIP_LLH_LEN); 00373 asm("adc _chksum_tmp"); 00374 asm("sta _chksum_tmp"); 00375 asm("iny"); 00376 asm("lda _uip_buf+%b,y", UIP_LLH_LEN); 00377 asm("adc _chksum_tmp+1"); 00378 asm("sta _chksum_tmp+1"); 00379 asm("iny"); 00380 asm("php"); 00381 asm("cpy #$14"); 00382 asm("bne tcpchksum_loop2"); 00383 00384 asm("plp"); 00385 00386 asm("lda _chksum_tmp"); 00387 asm("adc #0"); 00388 asm("sta _chksum_tmp"); 00389 asm("lda _chksum_tmp+1"); 00390 asm("adc #6"); /* IP_PROTO_TCP */ 00391 asm("sta _chksum_tmp+1"); 00392 00393 00394 asm("lda _chksum_tmp"); 00395 asm("adc _chksum_len+1"); 00396 asm("sta _chksum_tmp"); 00397 asm("lda _chksum_tmp+1"); 00398 asm("adc _chksum_len"); 00399 asm("sta _chksum_tmp+1"); 00400 00401 00402 00403 asm("tcpchksum_loop3:"); 00404 asm("lda _chksum_tmp"); 00405 asm("adc #0"); 00406 asm("sta _chksum_tmp"); 00407 asm("lda _chksum_tmp+1"); 00408 asm("adc #0"); 00409 asm("sta _chksum_tmp+1"); 00410 asm("bcs tcpchksum_loop3"); 00411 00412 00413 return chksum_tmp; 00414 #endif 00415 } 00416 00417 /*-----------------------------------------------------------------------------------*/ 00418 #if UIP_UDP_CHECKSUMS 00419 uint16_t 00420 uip_udpchksum(void) 00421 { 00422 return transport_chksum(IP_PROTO_UDP); 00423 #if 0 00424 chksum_ptr = (uint16_t)&uip_buf[20 + UIP_LLH_LEN]; 00425 chksum_len = 20; 00426 chksum_tmp = chksum(); 00427 00428 chksum_ptr = (uint16_t)uip_appdata; 00429 asm("lda _uip_buf+3+%b", UIP_LLH_LEN); 00430 asm("sec"); 00431 asm("sbc #40"); 00432 asm("sta _chksum_len"); 00433 asm("lda _uip_buf+2+%b", UIP_LLH_LEN); 00434 asm("sbc #0"); 00435 asm("sta _chksum_len+1"); 00436 00437 asm("jsr %v", chksum); 00438 00439 asm("clc"); 00440 asm("adc _chksum_tmp"); 00441 asm("sta _chksum_tmp"); 00442 asm("txa"); 00443 asm("adc _chksum_tmp+1"); 00444 asm("sta _chksum_tmp+1"); 00445 00446 /* Fold carry */ 00447 /* asm("bcc noinc"); 00448 asm("inc _chksum_tmp"); 00449 asm("noinc:");*/ 00450 00451 asm("tcpchksum_loop1:"); 00452 asm("lda _chksum_tmp"); 00453 asm("adc #0"); 00454 asm("sta _chksum_tmp"); 00455 asm("lda _chksum_tmp+1"); 00456 asm("adc #0"); 00457 asm("sta _chksum_tmp+1"); 00458 asm("bcs tcpchksum_loop1"); 00459 00460 00461 asm("lda _uip_buf+3+%b", UIP_LLH_LEN); 00462 asm("sec"); 00463 asm("sbc #20"); 00464 asm("sta _chksum_len"); 00465 asm("lda _uip_buf+2+%b", UIP_LLH_LEN); 00466 asm("sbc #0"); 00467 asm("sta _chksum_len+1"); 00468 00469 00470 asm("ldy #$0c"); 00471 asm("clc"); 00472 asm("php"); 00473 asm("tcpchksum_loop2:"); 00474 asm("plp"); 00475 asm("lda _uip_buf+%b,y", UIP_LLH_LEN); 00476 asm("adc _chksum_tmp"); 00477 asm("sta _chksum_tmp"); 00478 asm("iny"); 00479 asm("lda _uip_buf+%b,y", UIP_LLH_LEN); 00480 asm("adc _chksum_tmp+1"); 00481 asm("sta _chksum_tmp+1"); 00482 asm("iny"); 00483 asm("php"); 00484 asm("cpy #$14"); 00485 asm("bne tcpchksum_loop2"); 00486 00487 asm("plp"); 00488 00489 asm("lda _chksum_tmp"); 00490 asm("adc #0"); 00491 asm("sta _chksum_tmp"); 00492 asm("lda _chksum_tmp+1"); 00493 asm("adc #17"); /* IP_PROTO_UDP */ 00494 asm("sta _chksum_tmp+1"); 00495 00496 00497 asm("lda _chksum_tmp"); 00498 asm("adc _chksum_len+1"); 00499 asm("sta _chksum_tmp"); 00500 asm("lda _chksum_tmp+1"); 00501 asm("adc _chksum_len"); 00502 asm("sta _chksum_tmp+1"); 00503 00504 00505 00506 asm("tcpchksum_loop3:"); 00507 asm("lda _chksum_tmp"); 00508 asm("adc #0"); 00509 asm("sta _chksum_tmp"); 00510 asm("lda _chksum_tmp+1"); 00511 asm("adc #0"); 00512 asm("sta _chksum_tmp+1"); 00513 asm("bcs tcpchksum_loop3"); 00514 00515 00516 return chksum_tmp; 00517 #endif 00518 } 00519 #endif /* UIP_UDP_CHECKSUMS */ 00520 /*-----------------------------------------------------------------------------------*/