mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-08-16 22:28:59 +00:00
520 lines
12 KiB
C
520 lines
12 KiB
C
/*
|
|
* Copyright (c) 2001, Adam Dunkels.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote
|
|
* products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* This file is part of the uIP TCP/IP stack.
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#include "net/uip.h"
|
|
#include "net/uip_arch.h"
|
|
|
|
#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
|
#define IP_PROTO_TCP 6
|
|
#define IP_PROTO_UDP 17
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
#pragma optimize(push, off)
|
|
void
|
|
uip_add32(uint8_t *op32, uint16_t op16)
|
|
{
|
|
asm("ldy #3");
|
|
asm("jsr ldaxysp");
|
|
asm("sta ptr1");
|
|
asm("stx ptr1+1");
|
|
asm("ldy #0");
|
|
asm("lda (sp),y");
|
|
asm("ldy #3");
|
|
asm("clc");
|
|
asm("adc (ptr1),y");
|
|
asm("sta _uip_acc32+3");
|
|
asm("dey");
|
|
asm("lda (ptr1),y");
|
|
asm("ldy #1");
|
|
asm("adc (sp),y");
|
|
asm("sta _uip_acc32+2");
|
|
asm("ldy #1");
|
|
asm("lda (ptr1),y");
|
|
asm("adc #0");
|
|
asm("sta _uip_acc32+1");
|
|
asm("dey");
|
|
asm("lda (ptr1),y");
|
|
asm("adc #0");
|
|
asm("sta _uip_acc32+0");
|
|
}
|
|
#pragma optimize(pop)
|
|
/*-----------------------------------------------------------------------------------*/
|
|
static uint16_t chksum_ptr, chksum_len, chksum_tmp;
|
|
static uint8_t chksum_protocol;
|
|
static uint16_t chksum(void);
|
|
/*-----------------------------------------------------------------------------------*/
|
|
#pragma optimize(push, off)
|
|
uint16_t
|
|
chksum(void) {
|
|
|
|
asm("lda #0");
|
|
asm("sta tmp1");
|
|
asm("sta tmp1+1");
|
|
asm("lda _chksum_ptr");
|
|
asm("sta ptr1");
|
|
asm("lda _chksum_ptr+1");
|
|
asm("sta ptr1+1");
|
|
|
|
|
|
asm("lda _chksum_len+1");
|
|
asm("beq chksumlast");
|
|
|
|
|
|
/* If checksum is > 256, do the first runs. */
|
|
asm("ldy #0");
|
|
asm("clc");
|
|
asm("chksumloop_256:");
|
|
asm("lda (ptr1),y");
|
|
asm("adc tmp1");
|
|
asm("sta tmp1");
|
|
asm("iny");
|
|
asm("lda (ptr1),y");
|
|
asm("adc tmp1+1");
|
|
asm("sta tmp1+1");
|
|
asm("iny");
|
|
asm("bne chksumloop_256");
|
|
asm("inc ptr1+1");
|
|
asm("dec _chksum_len+1");
|
|
asm("bne chksumloop_256");
|
|
|
|
asm("chksum_endloop_256:");
|
|
asm("lda tmp1");
|
|
asm("adc #0");
|
|
asm("sta tmp1");
|
|
asm("lda tmp1+1");
|
|
asm("adc #0");
|
|
asm("sta tmp1+1");
|
|
asm("bcs chksum_endloop_256");
|
|
|
|
asm("chksumlast:");
|
|
asm("lda _chksum_len");
|
|
asm("lsr");
|
|
asm("bcc chksum_noodd");
|
|
asm("ldy _chksum_len");
|
|
asm("dey");
|
|
asm("lda (ptr1),y");
|
|
asm("clc");
|
|
asm("adc tmp1");
|
|
asm("sta tmp1");
|
|
asm("bcc noinc1");
|
|
asm("inc tmp1+1");
|
|
asm("bne noinc1");
|
|
asm("inc tmp1");
|
|
asm("noinc1:");
|
|
asm("dec _chksum_len");
|
|
|
|
asm("chksum_noodd:");
|
|
asm("clc");
|
|
asm("php");
|
|
asm("ldy _chksum_len");
|
|
asm("chksum_loop1:");
|
|
asm("cpy #0");
|
|
asm("beq chksum_loop1_end");
|
|
asm("plp");
|
|
asm("dey");
|
|
asm("dey");
|
|
asm("lda (ptr1),y");
|
|
asm("adc tmp1");
|
|
asm("sta tmp1");
|
|
asm("iny");
|
|
asm("lda (ptr1),y");
|
|
asm("adc tmp1+1");
|
|
asm("sta tmp1+1");
|
|
asm("dey");
|
|
asm("php");
|
|
asm("jmp chksum_loop1");
|
|
asm("chksum_loop1_end:");
|
|
asm("plp");
|
|
|
|
asm("chksum_endloop:");
|
|
asm("lda tmp1");
|
|
asm("adc #0");
|
|
asm("sta tmp1");
|
|
asm("lda tmp1+1");
|
|
asm("adc #0");
|
|
asm("sta tmp1+1");
|
|
asm("bcs chksum_endloop");
|
|
|
|
asm("lda tmp1");
|
|
asm("ldx tmp1+1");
|
|
}
|
|
#pragma optimize(pop)
|
|
/*-----------------------------------------------------------------------------------*/
|
|
uint16_t
|
|
uip_chksum(uint16_t *buf, uint16_t len)
|
|
{
|
|
/* unsigned long sum;
|
|
|
|
sum = 0;
|
|
|
|
chksum_ptr = (uint16_t)buf;
|
|
while(len >= 256) {
|
|
chksum_len = 256;
|
|
sum += chksum();
|
|
len -= 256;
|
|
chksum_ptr += 256;
|
|
}
|
|
|
|
if(len < 256) {
|
|
chksum_len = len;
|
|
sum += chksum();
|
|
}
|
|
|
|
while((sum >> 16) != 0) {
|
|
sum = (sum >> 16) + (sum & 0xffff);
|
|
}
|
|
|
|
return sum;*/
|
|
|
|
chksum_len = len;
|
|
chksum_ptr = (uint16_t)buf;
|
|
return chksum();
|
|
}
|
|
/*-----------------------------------------------------------------------------------*/
|
|
uint16_t
|
|
uip_ipchksum(void)
|
|
{
|
|
chksum_ptr = (uint16_t)uip_buf + UIP_LLH_LEN;
|
|
chksum_len = UIP_IPH_LEN;
|
|
return chksum();
|
|
}
|
|
/*-----------------------------------------------------------------------------------*/
|
|
#pragma optimize(push, off)
|
|
static uint16_t
|
|
transport_chksum(uint8_t protocol)
|
|
{
|
|
chksum_protocol = protocol;
|
|
chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
|
|
chksum_len = UIP_TCPH_LEN;
|
|
chksum_tmp = chksum();
|
|
|
|
chksum_ptr = (uint16_t)uip_appdata;
|
|
asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #%b", UIP_IPTCPH_LEN);
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
asm("jsr %v", chksum);
|
|
|
|
asm("clc");
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("txa");
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
/* Fold carry */
|
|
/* asm("bcc noinc");
|
|
asm("inc _chksum_tmp");
|
|
asm("noinc:");*/
|
|
|
|
asm("tcpchksum_loop1:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop1");
|
|
|
|
|
|
asm("lda _uip_aligned_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #%b", UIP_IPH_LEN);
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_aligned_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
|
|
asm("ldy #$0c");
|
|
asm("clc");
|
|
asm("php");
|
|
asm("tcpchksum_loop2:");
|
|
asm("plp");
|
|
asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("iny");
|
|
asm("lda _uip_aligned_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("iny");
|
|
asm("php");
|
|
asm("cpy #$14");
|
|
asm("bne tcpchksum_loop2");
|
|
|
|
asm("plp");
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc %v", chksum_protocol);
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc _chksum_len+1");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc _chksum_len");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
|
|
asm("tcpchksum_loop3:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop3");
|
|
|
|
|
|
return chksum_tmp;
|
|
}
|
|
#pragma optimize(pop)
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
uint16_t
|
|
uip_tcpchksum(void)
|
|
{
|
|
return transport_chksum(IP_PROTO_TCP);
|
|
#if 0
|
|
chksum_ptr = (uint16_t)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
|
|
chksum_len = UIP_TCPH_LEN;
|
|
chksum_tmp = chksum();
|
|
|
|
chksum_ptr = (uint16_t)uip_appdata;
|
|
asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #%b", UIP_IPTCPH_LEN);
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
asm("jsr %v", chksum);
|
|
|
|
asm("clc");
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("txa");
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
/* Fold carry */
|
|
/* asm("bcc noinc");
|
|
asm("inc _chksum_tmp");
|
|
asm("noinc:");*/
|
|
|
|
asm("tcpchksum_loop1:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop1");
|
|
|
|
|
|
asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #%b", UIP_IPH_LEN);
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
|
|
asm("ldy #$0c");
|
|
asm("clc");
|
|
asm("php");
|
|
asm("tcpchksum_loop2:");
|
|
asm("plp");
|
|
asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("iny");
|
|
asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("iny");
|
|
asm("php");
|
|
asm("cpy #$14");
|
|
asm("bne tcpchksum_loop2");
|
|
|
|
asm("plp");
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #6"); /* IP_PROTO_TCP */
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc _chksum_len+1");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc _chksum_len");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
|
|
asm("tcpchksum_loop3:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop3");
|
|
|
|
|
|
return chksum_tmp;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
#if UIP_UDP_CHECKSUMS
|
|
uint16_t
|
|
uip_udpchksum(void)
|
|
{
|
|
return transport_chksum(IP_PROTO_UDP);
|
|
#if 0
|
|
chksum_ptr = (uint16_t)&uip_buf[20 + UIP_LLH_LEN];
|
|
chksum_len = 20;
|
|
chksum_tmp = chksum();
|
|
|
|
chksum_ptr = (uint16_t)uip_appdata;
|
|
asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #40");
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
asm("jsr %v", chksum);
|
|
|
|
asm("clc");
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("txa");
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
/* Fold carry */
|
|
/* asm("bcc noinc");
|
|
asm("inc _chksum_tmp");
|
|
asm("noinc:");*/
|
|
|
|
asm("tcpchksum_loop1:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop1");
|
|
|
|
|
|
asm("lda _uip_buf+3+%b", UIP_LLH_LEN);
|
|
asm("sec");
|
|
asm("sbc #20");
|
|
asm("sta _chksum_len");
|
|
asm("lda _uip_buf+2+%b", UIP_LLH_LEN);
|
|
asm("sbc #0");
|
|
asm("sta _chksum_len+1");
|
|
|
|
|
|
asm("ldy #$0c");
|
|
asm("clc");
|
|
asm("php");
|
|
asm("tcpchksum_loop2:");
|
|
asm("plp");
|
|
asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp");
|
|
asm("sta _chksum_tmp");
|
|
asm("iny");
|
|
asm("lda _uip_buf+%b,y", UIP_LLH_LEN);
|
|
asm("adc _chksum_tmp+1");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("iny");
|
|
asm("php");
|
|
asm("cpy #$14");
|
|
asm("bne tcpchksum_loop2");
|
|
|
|
asm("plp");
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #17"); /* IP_PROTO_UDP */
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
asm("lda _chksum_tmp");
|
|
asm("adc _chksum_len+1");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc _chksum_len");
|
|
asm("sta _chksum_tmp+1");
|
|
|
|
|
|
|
|
asm("tcpchksum_loop3:");
|
|
asm("lda _chksum_tmp");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp");
|
|
asm("lda _chksum_tmp+1");
|
|
asm("adc #0");
|
|
asm("sta _chksum_tmp+1");
|
|
asm("bcs tcpchksum_loop3");
|
|
|
|
|
|
return chksum_tmp;
|
|
#endif
|
|
}
|
|
#endif /* UIP_UDP_CHECKSUMS */
|
|
/*-----------------------------------------------------------------------------------*/
|