Contiki 2.6

uip_arch.c

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 /*-----------------------------------------------------------------------------------*/