Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / include / asm-v850 / checksum.h
1 /*
2  * include/asm-v850/checksum.h -- Checksum ops
3  *
4  *  Copyright (C) 2001  NEC Corporation
5  *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
6  *
7  * This file is subject to the terms and conditions of the GNU General
8  * Public License.  See the file COPYING in the main directory of this
9  * archive for more details.
10  *
11  * Written by Miles Bader <miles@gnu.org>
12  */
13
14 #ifndef __V850_CHECKSUM_H__
15 #define __V850_CHECKSUM_H__
16
17 /*
18  * computes the checksum of a memory block at buff, length len,
19  * and adds in "sum" (32-bit)
20  *
21  * returns a 32-bit number suitable for feeding into itself
22  * or csum_tcpudp_magic
23  *
24  * this function must be called with even lengths, except
25  * for the last fragment, which may be odd
26  *
27  * it's best to have buff aligned on a 32-bit boundary
28  */
29 extern unsigned int csum_partial (const unsigned char * buff, int len,
30                                   unsigned int sum);
31
32 /*
33  * the same as csum_partial, but copies from src while it
34  * checksums
35  *
36  * here even more important to align src and dst on a 32-bit (or even
37  * better 64-bit) boundary
38  */
39 extern unsigned csum_partial_copy (const char *src, char *dst, int len,
40                                    unsigned sum);
41
42
43 /*
44  * the same as csum_partial_copy, but copies from user space.
45  *
46  * here even more important to align src and dst on a 32-bit (or even
47  * better 64-bit) boundary
48  */
49 extern unsigned csum_partial_copy_from_user (const char *src, char *dst,
50                                              int len, unsigned sum,
51                                              int *csum_err);
52
53 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
54         csum_partial_copy ((src), (dst), (len), (sum))
55
56 unsigned short ip_fast_csum (unsigned char *iph, unsigned int ihl);
57
58 /*
59  *      Fold a partial checksum
60  */
61 static inline unsigned int csum_fold (unsigned long sum)
62 {
63         unsigned int result;
64         /*
65                                 %0              %1
66               hsw %1, %0        H     L         L     H
67               add %1, %0        H     L         H+L+C H+L
68         */
69         asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
70         return (~result) >> 16;
71 }
72
73
74 /*
75  * computes the checksum of the TCP/UDP pseudo-header
76  * returns a 16-bit checksum, already complemented
77  */
78 static inline unsigned int
79 csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr,
80                     unsigned short len,
81                     unsigned short proto, unsigned int sum)
82 {
83         int __carry;
84         __asm__ ("add %2, %0;"
85                  "setf c, %1;"
86                  "add %1, %0;"
87                  "add %3, %0;"
88                  "setf c, %1;"
89                  "add %1, %0;"
90                  "add %4, %0;"
91                  "setf c, %1;"
92                  "add %1, %0"
93                  : "=&r" (sum), "=&r" (__carry)
94                  : "r" (daddr), "r" (saddr),
95                  "r" (ntohs (len) + (proto << 8)),
96                  "0" (sum));
97         return sum;
98 }
99
100 static inline unsigned short int
101 csum_tcpudp_magic (unsigned long saddr, unsigned long daddr,
102                    unsigned short len,
103                    unsigned short proto, unsigned int sum)
104 {
105         return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum));
106 }
107
108 /*
109  * this routine is used for miscellaneous IP-like checksums, mainly
110  * in icmp.c
111  */
112 extern unsigned short ip_compute_csum (const unsigned char * buff, int len);
113
114
115 #endif /* __V850_CHECKSUM_H__ */