~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-mips/checksum.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* $Id: checksum.h,v 1.8 2000/02/18 00:24:48 ralf Exp $
  2  *
  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.
  6  *
  7  * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
  8  */
  9 #ifndef _ASM_CHECKSUM_H
 10 #define _ASM_CHECKSUM_H
 11 
 12 #include <asm/uaccess.h>
 13 
 14 /*
 15  * computes the checksum of a memory block at buff, length len,
 16  * and adds in "sum" (32-bit)
 17  *
 18  * returns a 32-bit number suitable for feeding into itself
 19  * or csum_tcpudp_magic
 20  *
 21  * this function must be called with even lengths, except
 22  * for the last fragment, which may be odd
 23  *
 24  * it's best to have buff aligned on a 32-bit boundary
 25  */
 26 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 27 
 28 /*
 29  * this is a new version of the above that records errors it finds in *errp,
 30  * but continues and zeros the rest of the buffer.
 31  */
 32 #define csum_partial_copy_nocheck csum_partial_copy
 33 
 34 /*
 35  * this is a new version of the above that records errors it finds in *errp,
 36  * but continues and zeros the rest of the buffer.
 37  */
 38 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
 39                                          unsigned int sum, int *errp);
 40 
 41 /*
 42  * Copy and checksum to user
 43  */
 44 #define HAVE_CSUM_COPY_USER
 45 extern inline unsigned int
 46 csum_and_copy_to_user (const char *src, char *dst,
 47                        int len, int sum, int *err_ptr)
 48 {
 49         sum = csum_partial(src, len, sum);
 50 
 51         if (copy_to_user(dst, src, len)) {
 52                 *err_ptr = -EFAULT;
 53                 return -1;
 54         }
 55 
 56         return sum;
 57 }
 58 
 59 /*
 60  * the same as csum_partial, but copies from user space (but on MIPS
 61  * we have just one address space, so this is identical to the above)
 62  *
 63  * this is obsolete and will go away.
 64  */
 65 #define csum_partial_copy_fromuser csum_partial_copy
 66 unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
 67   
 68 /*
 69  *      Fold a partial checksum without adding pseudo headers
 70  */
 71 static inline unsigned short int csum_fold(unsigned int sum)
 72 {
 73         __asm__("
 74         .set    noat            
 75         sll     $1,%0,16
 76         addu    %0,$1
 77         sltu    $1,%0,$1
 78         srl     %0,%0,16
 79         addu    %0,$1
 80         xori    %0,0xffff
 81         .set    at"
 82         : "=r" (sum)
 83         : "" (sum)
 84         : "$1");
 85 
 86         return sum;
 87 }
 88  
 89 /*
 90  *      This is a version of ip_compute_csum() optimized for IP headers,
 91  *      which always checksum on 4 octet boundaries.
 92  *
 93  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
 94  *      Arnt Gulbrandsen.
 95  */
 96 static inline unsigned short ip_fast_csum(unsigned char * iph,
 97                                           unsigned int ihl)
 98 {
 99         unsigned int sum;
100         unsigned long dummy;
101 
102         /*
103          * This is for 32-bit MIPS processors.
104          */
105         __asm__ __volatile__("
106         .set    noreorder
107         .set    noat
108         lw      %0,(%1)
109         subu    %2,4
110         #blez   %2,2f
111         sll     %2,2                    # delay slot
112 
113         lw      %3,4(%1)
114         addu    %2,%1                   # delay slot
115         addu    %0,%3
116         sltu    $1,%0,%3
117         lw      %3,8(%1)
118         addu    %0,$1
119         addu    %0,%3
120         sltu    $1,%0,%3
121         lw      %3,12(%1)
122         addu    %0,$1
123         addu    %0,%3
124         sltu    $1,%0,%3
125         addu    %0,$1
126 
127 1:      lw      %3,16(%1)
128         addiu   %1,4
129         addu    %0,%3
130         sltu    $1,%0,%3
131         bne     %2,%1,1b
132         addu    %0,$1                   # delay slot
133 
134 2:      .set    at
135         .set    reorder"
136         : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
137         : "1" (iph), "2" (ihl)
138         : "$1");
139 
140         return csum_fold(sum);
141 }
142 
143 /*
144  * computes the checksum of the TCP/UDP pseudo-header
145  * returns a 16-bit checksum, already complemented
146  */
147 static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
148                                                unsigned long daddr,
149                                                unsigned short len,
150                                                unsigned short proto,
151                                                unsigned int sum)
152 {
153     __asm__("
154         .set    noat
155         addu    %0,%2
156         sltu    $1,%0,%2
157         addu    %0,$1
158 
159         addu    %0,%3
160         sltu    $1,%0,%3
161         addu    %0,$1
162 
163         addu    %0,%4
164         sltu    $1,%0,%4
165         addu    %0,$1
166         .set    at"
167         : "=r" (sum)
168         : "" (daddr), "r"(saddr),
169 #ifdef __MIPSEL__
170             "r" ((ntohs(len)<<16)+proto*256),
171 #else
172             "r" (((proto)<<16)+len),
173 #endif
174             "r"(sum)
175         : "$1");
176 
177         return sum;
178 }
179 
180 /*
181  * computes the checksum of the TCP/UDP pseudo-header
182  * returns a 16-bit checksum, already complemented
183  */
184 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
185                                                    unsigned long daddr,
186                                                    unsigned short len,
187                                                    unsigned short proto,
188                                                    unsigned int sum)
189 {
190         return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
191 }
192 
193 /*
194  * this routine is used for miscellaneous IP-like checksums, mainly
195  * in icmp.c
196  */
197 static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
198 {
199         return csum_fold(csum_partial(buff, len, 0));
200 }
201 
202 #define _HAVE_ARCH_IPV6_CSUM
203 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
204                                                      struct in6_addr *daddr,
205                                                      __u32 len,
206                                                      unsigned short proto,
207                                                      unsigned int sum) 
208 {
209         __asm__("
210                 .set    noreorder
211                 .set    noat
212                 addu    %0,%5           # proto (long in network byte order)
213                 sltu    $1,%0,%5
214                 addu    %0,$1
215 
216                 addu    %0,%6           # csum
217                 sltu    $1,%0,%6
218                 lw      %1,0(%2)        # four words source address
219                 addu    %0,$1
220                 addu    %0,%1
221                 sltu    $1,%0,$1
222 
223                 lw      %1,4(%2)
224                 addu    %0,$1
225                 addu    %0,%1
226                 sltu    $1,%0,$1
227 
228                 lw      %1,8(%2)
229                 addu    %0,$1
230                 addu    %0,%1
231                 sltu    $1,%0,$1
232 
233                 lw      %1,12(%2)
234                 addu    %0,$1
235                 addu    %0,%1
236                 sltu    $1,%0,$1
237 
238                 lw      %1,0(%3)
239                 addu    %0,$1
240                 addu    %0,%1
241                 sltu    $1,%0,$1
242 
243                 lw      %1,4(%3)
244                 addu    %0,$1
245                 addu    %0,%1
246                 sltu    $1,%0,$1
247 
248                 lw      %1,8(%3)
249                 addu    %0,$1
250                 addu    %0,%1
251                 sltu    $1,%0,$1
252 
253                 lw      %1,12(%3)
254                 addu    %0,$1
255                 addu    %0,%1
256                 sltu    $1,%0,$1
257                 .set    noat
258                 .set    noreorder"
259                 : "=r" (sum),
260                   "=r" (proto)
261                 : "r" (saddr),
262                   "r" (daddr),
263                   "" (htonl(len)),
264                   "1" (htonl(proto)),
265                   "r"(sum)
266                 : "$1");
267 
268         return csum_fold(sum);
269 }
270 
271 #endif /* _ASM_CHECKSUM_H */
272 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.