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

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

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

  1 /* $Id: checksum.h,v 1.6 2000/02/18 22:06:19 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, 1999 by Ralf Baechle
  8  * Copyright (C) 1999 Silicon Graphics, Inc.
  9  */
 10 #ifndef _ASM_CHECKSUM_H
 11 #define _ASM_CHECKSUM_H
 12 
 13 /*
 14  * computes the checksum of a memory block at buff, length len,
 15  * and adds in "sum" (32-bit)
 16  *
 17  * returns a 32-bit number suitable for feeding into itself
 18  * or csum_tcpudp_magic
 19  *
 20  * this function must be called with even lengths, except
 21  * for the last fragment, which may be odd
 22  *
 23  * it's best to have buff aligned on a 32-bit boundary
 24  */
 25 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 26 
 27 /*
 28  * this is a new version of the above that records errors it finds in *errp,
 29  * but continues and zeros the rest of the buffer.
 30  */
 31 #define csum_partial_copy_nocheck csum_partial_copy
 32 
 33 /*
 34  * this is a new version of the above that records errors it finds in *errp,
 35  * but continues and zeros the rest of the buffer.
 36  */
 37 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
 38                                          unsigned int sum, int *errp);
 39 
 40 /*
 41  * Copy and checksum to user
 42  */
 43 #define HAVE_CSUM_COPY_USER
 44 extern inline unsigned int
 45 csum_and_copy_to_user (const char *src, char *dst,
 46                        int len, int sum, int *err_ptr)
 47 {
 48         sum = csum_partial(src, len, sum);
 49 
 50         if (copy_to_user(dst, src, len)) {
 51                 *err_ptr = -EFAULT;
 52                 return -1;
 53         }
 54 
 55         return sum;
 56 }
 57 
 58 /*
 59  * the same as csum_partial, but copies from user space (but on MIPS
 60  * we have just one address space, so this is identical to the above)
 61  *
 62  * this is obsolete and will go away.
 63  */
 64 #define csum_partial_copy_fromuser csum_partial_copy
 65 unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
 66   
 67 /*
 68  *      Fold a partial checksum without adding pseudo headers
 69  */
 70 static inline unsigned short int
 71 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
 97 ip_fast_csum(unsigned char * iph, unsigned int ihl)
 98 {
 99         unsigned int sum;
100         unsigned long dummy;
101 
102         /*
103          * This is for 32-bit processors ...  but works just fine for 64-bit
104          * processors for now ...  XXX
105          */
106         __asm__ __volatile__("
107         .set    noreorder
108         .set    noat
109         lw      %0, (%1)
110         subu    %2, 4
111         dsll    %2, 2
112 
113         lw      %3, 4(%1)
114         daddu   %2, %1
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         daddiu  %1, 4
129         addu    %0, %3
130         sltu    $1, %0, %3
131         bne     %2, %1, 1b
132          addu   %0, $1
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
148 csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
149                    unsigned short len, unsigned short proto, unsigned int sum)
150 {
151     __asm__("
152         .set    noat
153         daddu   %0, %2
154         daddu   %0, %3
155         daddu   %0, %4
156         dsll32  $1, %0, 0
157         daddu   %0, $1          # never results in an overflow
158         dsrl32  %0, %0, 0
159         .set    at"
160         : "=r" (sum)
161         : "" (sum), "r"(saddr), "r" (daddr),
162 #ifdef __MIPSEL__
163             "r" ((ntohs(len)<<16)+proto*256)
164 #else
165             "r" (((proto)<<16)+len)
166 #endif
167         : "$1");
168 
169         return sum;
170 }
171 
172 /*
173  * computes the checksum of the TCP/UDP pseudo-header
174  * returns a 16-bit checksum, already complemented
175  */
176 static inline unsigned short int
177 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
178                   unsigned short proto, unsigned int sum)
179 {
180         return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
181 }
182 
183 /*
184  * this routine is used for miscellaneous IP-like checksums, mainly
185  * in icmp.c
186  */
187 static inline unsigned short
188 ip_compute_csum(unsigned char * buff, int len)
189 {
190         return csum_fold(csum_partial(buff, len, 0));
191 }
192 
193 #define _HAVE_ARCH_IPV6_CSUM
194 static inline unsigned short int
195 csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
196                 unsigned short proto, unsigned int sum) 
197 {
198         __asm__("
199                 .set    noreorder
200                 .set    noat
201                 addu    %0, %5          # proto (long in network byte order)
202                 sltu    $1, %0, %5
203                 addu    %0, $1
204 
205                 addu    %0, %6          # csum
206                 sltu    $1, %0, %6
207                 lw      %1, 0(%2)       # four words source address
208                 addu    %0, $1
209                 addu    %0, %1
210                 sltu    $1, %0, $1
211 
212                 lw      %1, 4(%2)
213                 addu    %0, $1
214                 addu    %0, %1
215                 sltu    $1, %0, $1
216 
217                 lw      %1, 8(%2)
218                 addu    %0, $1
219                 addu    %0, %1
220                 sltu    $1, %0, $1
221 
222                 lw      %1, 12(%2)
223                 addu    %0, $1
224                 addu    %0, %1
225                 sltu    $1, %0, $1
226 
227                 lw      %1, 0(%3)
228                 addu    %0, $1
229                 addu    %0, %1
230                 sltu    $1, %0, $1
231 
232                 lw      %1, 4(%3)
233                 addu    %0, $1
234                 addu    %0, %1
235                 sltu    $1, %0, $1
236 
237                 lw      %1, 8(%3)
238                 addu    %0, $1
239                 addu    %0, %1
240                 sltu    $1, %0, $1
241 
242                 lw      %1, 12(%3)
243                 addu    %0, $1
244                 addu    %0, %1
245                 sltu    $1, %0, $1
246                 .set    noat
247                 .set    noreorder"
248                 : "=r" (sum), "=r" (proto)
249                 : "r" (saddr), "r" (daddr),
250                   "" (htonl(len)), "1" (htonl(proto)), "r"(sum)
251                 : "$1");
252 
253         return csum_fold(sum);
254 }
255 
256 #endif /* _ASM_CHECKSUM_H */
257 

~ [ 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.