home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-mips / checksum.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  5.6 KB  |  256 lines

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