The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/include/asm-mips64/checksum.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: bd455b1c928b37f821bb84c0ef09280a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.