OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [alpha/] [lib/] [checksum.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * arch/alpha/lib/checksum.c
3
 *
4
 * This file contains network checksum routines that are better done
5
 * in an architecture-specific manner due to speed..
6
 */
7
 
8
#include <linux/string.h>
9
 
10
#include <asm/byteorder.h>
11
 
12
static inline unsigned short from64to16(unsigned long x)
13
{
14
        /* add up 32-bit words for 33 bits */
15
        x = (x & 0xffffffff) + (x >> 32);
16
        /* add up 16-bit and 17-bit words for 17+c bits */
17
        x = (x & 0xffff) + (x >> 16);
18
        /* add up 16-bit and 2-bit for 16+c bit */
19
        x = (x & 0xffff) + (x >> 16);
20
        /* add up carry.. */
21
        x = (x & 0xffff) + (x >> 16);
22
        return x;
23
}
24
 
25
/*
26
 * computes the checksum of the TCP/UDP pseudo-header
27
 * returns a 16-bit checksum, already complemented.
28
 */
29
unsigned short int csum_tcpudp_magic(unsigned long saddr,
30
                                   unsigned long daddr,
31
                                   unsigned short len,
32
                                   unsigned short proto,
33
                                   unsigned int sum)
34
{
35
        return ~from64to16(saddr + daddr + sum +
36
                ((unsigned long) ntohs(len) << 16) +
37
                ((unsigned long) proto << 8));
38
}
39
 
40
/*
41
 * Do a 64-bit checksum on an arbitrary memory area..
42
 *
43
 * This isn't a great routine, but it's not _horrible_ either. The
44
 * inner loop could be unrolled a bit further, and there are better
45
 * ways to do the carry, but this is reasonable.
46
 */
47
static inline unsigned long do_csum(unsigned char * buff, int len)
48
{
49
        int odd, count;
50
        unsigned long result = 0;
51
 
52
        if (len <= 0)
53
                goto out;
54
        odd = 1 & (unsigned long) buff;
55
        if (odd) {
56
                result = *buff << 8;
57
                len--;
58
                buff++;
59
        }
60
        count = len >> 1;               /* nr of 16-bit words.. */
61
        if (count) {
62
                if (2 & (unsigned long) buff) {
63
                        result += *(unsigned short *) buff;
64
                        count--;
65
                        len -= 2;
66
                        buff += 2;
67
                }
68
                count >>= 1;            /* nr of 32-bit words.. */
69
                if (count) {
70
                        if (4 & (unsigned long) buff) {
71
                                result += *(unsigned int *) buff;
72
                                count--;
73
                                len -= 4;
74
                                buff += 4;
75
                        }
76
                        count >>= 1;    /* nr of 64-bit words.. */
77
                        if (count) {
78
                                unsigned long carry = 0;
79
                                do {
80
                                        unsigned long w = *(unsigned long *) buff;
81
                                        count--;
82
                                        buff += 8;
83
                                        result += carry;
84
                                        result += w;
85
                                        carry = (w > result);
86
                                } while (count);
87
                                result += carry;
88
                                result = (result & 0xffffffff) + (result >> 32);
89
                        }
90
                        if (len & 4) {
91
                                result += *(unsigned int *) buff;
92
                                buff += 4;
93
                        }
94
                }
95
                if (len & 2) {
96
                        result += *(unsigned short *) buff;
97
                        buff += 2;
98
                }
99
        }
100
        if (len & 1)
101
                result += *buff;
102
        result = from64to16(result);
103
        if (odd)
104
                result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
105
out:
106
        return result;
107
}
108
 
109
/*
110
 *      This is a version of ip_compute_csum() optimized for IP headers,
111
 *      which always checksum on 4 octet boundaries.
112
 */
113
unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
114
{
115
        return ~do_csum(iph,ihl*4);
116
}
117
 
118
/*
119
 * computes the checksum of a memory block at buff, length len,
120
 * and adds in "sum" (32-bit)
121
 *
122
 * returns a 32-bit number suitable for feeding into itself
123
 * or csum_tcpudp_magic
124
 *
125
 * this function must be called with even lengths, except
126
 * for the last fragment, which may be odd
127
 *
128
 * it's best to have buff aligned on a 32-bit boundary
129
 */
130
unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum)
131
{
132
        unsigned long result = do_csum(buff, len);
133
 
134
        /* add in old sum, and carry.. */
135
        result += sum;
136
        /* 32+c bits -> 32 bits */
137
        result = (result & 0xffffffff) + (result >> 32);
138
        return result;
139
}
140
 
141
/*
142
 * this routine is used for miscellaneous IP-like checksums, mainly
143
 * in icmp.c
144
 */
145
unsigned short ip_compute_csum(unsigned char * buff, int len)
146
{
147
        return ~from64to16(do_csum(buff,len));
148
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.