make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / include / asm-x86_64 / checksum.h
1 #ifndef _X86_64_CHECKSUM_H
2 #define _X86_64_CHECKSUM_H
3
4 /* 
5  * Checksums for x86-64 
6  * Copyright 2002 by Andi Kleen, SuSE Labs 
7  * with some code from asm-i386/checksum.h
8  */ 
9
10 #include <linux/compiler.h>
11 #include <asm/uaccess.h>
12 #include <asm/byteorder.h>
13
14 /** 
15  * csum_fold - Fold and invert a 32bit checksum.
16  * sum: 32bit unfolded sum
17  * 
18  * Fold a 32bit running checksum to 16bit and invert it. This is usually
19  * the last step before putting a checksum into a packet.
20  * Make sure not to mix with 64bit checksums.
21  */
22 static inline unsigned int csum_fold(unsigned int sum)
23 {
24         __asm__(
25                 "  addl %1,%0\n"
26                 "  adcl $0xffff,%0"
27                 : "=r" (sum)
28                 : "r" (sum << 16), "0" (sum & 0xffff0000)
29         );
30         return (~sum) >> 16;
31 }
32
33 /*
34  *      This is a version of ip_compute_csum() optimized for IP headers,
35  *      which always checksum on 4 octet boundaries.
36  *
37  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
38  *      Arnt Gulbrandsen.
39  */
40
41 /**
42  * ip_fast_csum - Compute the IPv4 header checksum efficiently.
43  * iph: ipv4 header
44  * ihl: length of header / 4
45  */ 
46 static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) 
47 {
48         unsigned int sum;
49
50         asm(    "  movl (%1), %0\n"
51                 "  subl $4, %2\n"
52                 "  jbe 2f\n"
53                 "  addl 4(%1), %0\n"
54                 "  adcl 8(%1), %0\n"
55                 "  adcl 12(%1), %0\n"
56                 "1: adcl 16(%1), %0\n"
57                 "  lea 4(%1), %1\n"
58                 "  decl %2\n"
59                 "  jne  1b\n"
60                 "  adcl $0, %0\n"
61                 "  movl %0, %2\n"
62                 "  shrl $16, %0\n"
63                 "  addw %w2, %w0\n"
64                 "  adcl $0, %0\n"
65                 "  notl %0\n"
66                 "2:"
67         /* Since the input registers which are loaded with iph and ipl
68            are modified, we must also specify them as outputs, or gcc
69            will assume they contain their original values. */
70         : "=r" (sum), "=r" (iph), "=r" (ihl)
71         : "1" (iph), "2" (ihl));
72         return(sum);
73 }
74
75 /** 
76  * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
77  * @saddr: source address
78  * @daddr: destination address
79  * @len: length of packet
80  * @proto: ip protocol of packet
81  * @sum: initial sum to be added in (32bit unfolded) 
82  * 
83  * Returns the pseudo header checksum the input data. Result is 
84  * 32bit unfolded.
85  */
86 static inline unsigned long 
87 csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
88                    unsigned short proto, unsigned int sum) 
89 {
90         asm("  addl %1, %0\n"
91             "  adcl %2, %0\n"
92             "  adcl %3, %0\n"
93             "  adcl $0, %0\n"
94                 : "=r" (sum)
95             : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum));
96     return sum;
97 }
98
99
100 /** 
101  * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
102  * @saddr: source address
103  * @daddr: destination address
104  * @len: length of packet
105  * @proto: ip protocol of packet
106  * @sum: initial sum to be added in (32bit unfolded) 
107  * 
108  * Returns the 16bit pseudo header checksum the input data already
109  * complemented and ready to be filled in.
110  */
111 static inline unsigned short int 
112 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
113                   unsigned short len, unsigned short proto, unsigned int sum) 
114 {
115         return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
116 }
117
118 /** 
119  * csum_partial - Compute an internet checksum.
120  * @buff: buffer to be checksummed
121  * @len: length of buffer.
122  * @sum: initial sum to be added in (32bit unfolded)
123  *
124  * Returns the 32bit unfolded internet checksum of the buffer.
125  * Before filling it in it needs to be csum_fold()'ed.
126  * buff should be aligned to a 64bit boundary if possible.
127  */ 
128 extern unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
129
130 #define  _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
131 #define HAVE_CSUM_COPY_USER 1
132
133
134 /* Do not call this directly. Use the wrappers below */
135 extern unsigned long csum_partial_copy_generic(const char *src, const char *dst, 
136                                                unsigned len,
137                                                unsigned sum, 
138                                                int *src_err_ptr, int *dst_err_ptr);
139
140
141 extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, 
142                                        int len, unsigned int isum, int *errp);
143 extern unsigned int csum_partial_copy_to_user(const char *src, char *dst, 
144                                       int len, unsigned int isum, int *errp);
145 extern unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, 
146                                               unsigned int sum);
147
148 /* Old names. To be removed. */
149 #define csum_and_copy_to_user csum_partial_copy_to_user
150 #define csum_and_copy_from_user csum_partial_copy_from_user
151
152 /** 
153  * ip_compute_csum - Compute an 16bit IP checksum.
154  * @buff: buffer address.
155  * @len: length of buffer.
156  *
157  * Returns the 16bit folded/inverted checksum of the passed buffer.
158  * Ready to fill in.
159  */
160 extern unsigned short ip_compute_csum(unsigned char * buff, int len);
161
162 /**
163  * csum_ipv6_magic - Compute checksum of an IPv6 pseudo header.
164  * @saddr: source address
165  * @daddr: destination address
166  * @len: length of packet
167  * @proto: protocol of packet
168  * @sum: initial sum (32bit unfolded) to be added in
169  *
170  * Computes an IPv6 pseudo header checksum. This sum is added the checksum 
171  * into UDP/TCP packets and contains some link layer information.
172  * Returns the unfolded 32bit checksum.
173  */
174
175 struct in6_addr;
176
177 #define _HAVE_ARCH_IPV6_CSUM 1
178 extern unsigned short 
179 csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
180                 __u32 len, unsigned short proto, unsigned int sum);
181
182 #endif