* better
[mascara-docs.git] / i386 / linux-2.3.21 / include / asm-mips / checksum.h
blobad72dc1a611f5ec4799960d70ce4eb6554bdece0
1 /* $Id: checksum.h,v 1.6 1998/09/16 13:30:51 ralf Exp $
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
7 * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
8 */
9 #ifndef __ASM_MIPS_CHECKSUM_H
10 #define __ASM_MIPS_CHECKSUM_H
13 * computes the checksum of a memory block at buff, length len,
14 * and adds in "sum" (32-bit)
16 * returns a 32-bit number suitable for feeding into itself
17 * or csum_tcpudp_magic
19 * this function must be called with even lengths, except
20 * for the last fragment, which may be odd
22 * it's best to have buff aligned on a 32-bit boundary
24 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
27 * this is a new version of the above that records errors it finds in *errp,
28 * but continues and zeros the rest of the buffer.
30 #define csum_partial_copy_nocheck csum_partial_copy
33 * this is a new version of the above that records errors it finds in *errp,
34 * but continues and zeros the rest of the buffer.
36 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
37 unsigned int sum, int *errp);
39 #define HAVE_CSUM_COPY_USER
40 unsigned int csum_and_copy_to_user (const char *src, char *dst,
41 int len, int sum, int *err_ptr);
44 * the same as csum_partial, but copies from user space (but on MIPS
45 * we have just one address space, so this is identical to the above)
47 * this is obsolete and will go away.
49 #define csum_partial_copy_fromuser csum_partial_copy
50 unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
53 * Fold a partial checksum without adding pseudo headers
55 static inline unsigned short int csum_fold(unsigned int sum)
57 __asm__("
58 .set noat
59 sll $1,%0,16
60 addu %0,$1
61 sltu $1,%0,$1
62 srl %0,%0,16
63 addu %0,$1
64 xori %0,0xffff
65 .set at"
66 : "=r" (sum)
67 : "0" (sum)
68 : "$1");
70 return sum;
74 * This is a version of ip_compute_csum() optimized for IP headers,
75 * which always checksum on 4 octet boundaries.
77 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
78 * Arnt Gulbrandsen.
80 static inline unsigned short ip_fast_csum(unsigned char * iph,
81 unsigned int ihl)
83 unsigned int sum;
84 unsigned long dummy;
87 * This is for 32-bit MIPS processors.
89 __asm__ __volatile__("
90 .set noreorder
91 .set noat
92 lw %0,(%1)
93 subu %2,4
94 #blez %2,2f
95 sll %2,2 # delay slot
97 lw %3,4(%1)
98 addu %2,%1 # delay slot
99 addu %0,%3
100 sltu $1,%0,%3
101 lw %3,8(%1)
102 addu %0,$1
103 addu %0,%3
104 sltu $1,%0,%3
105 lw %3,12(%1)
106 addu %0,$1
107 addu %0,%3
108 sltu $1,%0,%3
109 addu %0,$1
111 1: lw %3,16(%1)
112 addiu %1,4
113 addu %0,%3
114 sltu $1,%0,%3
115 bne %2,%1,1b
116 addu %0,$1 # delay slot
118 2: .set at
119 .set reorder"
120 : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
121 : "1" (iph), "2" (ihl)
122 : "$1");
124 return csum_fold(sum);
128 * computes the checksum of the TCP/UDP pseudo-header
129 * returns a 16-bit checksum, already complemented
131 static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
132 unsigned long daddr,
133 unsigned short len,
134 unsigned short proto,
135 unsigned int sum)
137 __asm__("
138 .set noat
139 addu %0,%2
140 sltu $1,%0,%2
141 addu %0,$1
143 addu %0,%3
144 sltu $1,%0,%3
145 addu %0,$1
147 addu %0,%4
148 sltu $1,%0,%4
149 addu %0,$1
150 .set at"
151 : "=r" (sum)
152 : "0" (daddr), "r"(saddr),
153 #ifdef __MIPSEL__
154 "r" ((ntohs(len)<<16)+proto*256),
155 #else
156 "r" (((proto)<<16)+len),
157 #endif
158 "r"(sum)
159 : "$1");
161 return sum;
165 * computes the checksum of the TCP/UDP pseudo-header
166 * returns a 16-bit checksum, already complemented
168 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
169 unsigned long daddr,
170 unsigned short len,
171 unsigned short proto,
172 unsigned int sum)
174 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
178 * this routine is used for miscellaneous IP-like checksums, mainly
179 * in icmp.c
181 static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
183 return csum_fold(csum_partial(buff, len, 0));
186 #define _HAVE_ARCH_IPV6_CSUM
187 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
188 struct in6_addr *daddr,
189 __u16 len,
190 unsigned short proto,
191 unsigned int sum)
193 __asm__("
194 .set noreorder
195 .set noat
196 addu %0,%5 # proto (long in network byte order)
197 sltu $1,%0,%5
198 addu %0,$1
200 addu %0,%6 # csum
201 sltu $1,%0,%6
202 lw %1,0(%2) # four words source address
203 addu %0,$1
204 addu %0,%1
205 sltu $1,%0,$1
207 lw %1,4(%2)
208 addu %0,$1
209 addu %0,%1
210 sltu $1,%0,$1
212 lw %1,8(%2)
213 addu %0,$1
214 addu %0,%1
215 sltu $1,%0,$1
217 lw %1,12(%2)
218 addu %0,$1
219 addu %0,%1
220 sltu $1,%0,$1
222 lw %1,0(%3)
223 addu %0,$1
224 addu %0,%1
225 sltu $1,%0,$1
227 lw %1,4(%3)
228 addu %0,$1
229 addu %0,%1
230 sltu $1,%0,$1
232 lw %1,8(%3)
233 addu %0,$1
234 addu %0,%1
235 sltu $1,%0,$1
237 lw %1,12(%3)
238 addu %0,$1
239 addu %0,%1
240 sltu $1,%0,$1
241 .set noat
242 .set noreorder"
243 : "=r" (sum),
244 "=r" (proto)
245 : "r" (saddr),
246 "r" (daddr),
247 "0" (htonl((__u32) (len))),
248 "1" (htonl(proto)),
249 "r"(sum)
250 : "$1");
252 return csum_fold(sum);
255 #endif /* __ASM_MIPS_CHECKSUM_H */