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-sparc64 / checksum.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.6 KB  |  174 lines

  1. /* $Id: checksum.h,v 1.19 2002/02/09 19:49:31 davem Exp $ */
  2. #ifndef __SPARC64_CHECKSUM_H
  3. #define __SPARC64_CHECKSUM_H
  4.  
  5. /*  checksum.h:  IP/UDP/TCP checksum routines on the V9.
  6.  *
  7.  *  Copyright(C) 1995 Linus Torvalds
  8.  *  Copyright(C) 1995 Miguel de Icaza
  9.  *  Copyright(C) 1996 David S. Miller
  10.  *  Copyright(C) 1996 Eddie C. Dost
  11.  *  Copyright(C) 1997 Jakub Jelinek
  12.  *
  13.  * derived from:
  14.  *    Alpha checksum c-code
  15.  *      ix86 inline assembly
  16.  *      RFC1071 Computing the Internet Checksum
  17.  */
  18.  
  19. #include <linux/in6.h>
  20. #include <asm/uaccess.h>
  21.  
  22. /* computes the checksum of a memory block at buff, length len,
  23.  * and adds in "sum" (32-bit)
  24.  *
  25.  * returns a 32-bit number suitable for feeding into itself
  26.  * or csum_tcpudp_magic
  27.  *
  28.  * this function must be called with even lengths, except
  29.  * for the last fragment, which may be odd
  30.  *
  31.  * it's best to have buff aligned on a 32-bit boundary
  32.  */
  33. extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
  34.  
  35. /* the same as csum_partial, but copies from user space while it
  36.  * checksums
  37.  *
  38.  * here even more important to align src and dst on a 32-bit (or even
  39.  * better 64-bit) boundary
  40.  */
  41. extern unsigned int csum_partial_copy_nocheck(const unsigned char *src,
  42.                           unsigned char *dst,
  43.                           int len, unsigned int sum);
  44.  
  45. extern long __csum_partial_copy_from_user(const unsigned char __user *src,
  46.                       unsigned char *dst, int len,
  47.                       unsigned int sum);
  48.  
  49. static inline unsigned int
  50. csum_partial_copy_from_user(const unsigned char __user *src,
  51.                 unsigned char *dst, int len,
  52.                 unsigned int sum, int *err)
  53. {
  54.     long ret = __csum_partial_copy_from_user(src, dst, len, sum);
  55.     if (ret < 0)
  56.         *err = -EFAULT;
  57.     return (unsigned int) ret;
  58. }
  59.  
  60. /* 
  61.  *    Copy and checksum to user
  62.  */
  63. #define HAVE_CSUM_COPY_USER
  64. extern long __csum_partial_copy_to_user(const unsigned char *src,
  65.                     unsigned char __user *dst, int len,
  66.                       unsigned int sum);
  67.  
  68. static inline unsigned int
  69. csum_and_copy_to_user(const unsigned char *src,
  70.               unsigned char __user *dst, int len,
  71.               unsigned int sum, int *err)
  72. {
  73.     long ret = __csum_partial_copy_to_user(src, dst, len, sum);
  74.     if (ret < 0)
  75.         *err = -EFAULT;
  76.     return (unsigned int) ret;
  77. }
  78.  
  79. /* ihl is always 5 or greater, almost always is 5, and iph is word aligned
  80.  * the majority of the time.
  81.  */
  82. extern unsigned short ip_fast_csum(__const__ unsigned char *iph,
  83.                    unsigned int ihl);
  84.  
  85. /* Fold a partial checksum without adding pseudo headers. */
  86. static inline unsigned short csum_fold(unsigned int sum)
  87. {
  88.     unsigned int tmp;
  89.  
  90.     __asm__ __volatile__(
  91. "    addcc        %0, %1, %1\n"
  92. "    srl        %1, 16, %1\n"
  93. "    addc        %1, %%g0, %1\n"
  94. "    xnor        %%g0, %1, %0\n"
  95.     : "=&r" (sum), "=r" (tmp)
  96.     : "0" (sum), "1" (sum<<16)
  97.     : "cc");
  98.     return (sum & 0xffff);
  99. }
  100.  
  101. static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
  102.                            unsigned long daddr,
  103.                            unsigned int len,
  104.                            unsigned short proto,
  105.                            unsigned int sum)
  106. {
  107.     __asm__ __volatile__(
  108. "    addcc        %1, %0, %0\n"
  109. "    addccc        %2, %0, %0\n"
  110. "    addccc        %3, %0, %0\n"
  111. "    addc        %0, %%g0, %0\n"
  112.     : "=r" (sum), "=r" (saddr)
  113.     : "r" (daddr), "r" ((proto<<16)+len), "0" (sum), "1" (saddr)
  114.     : "cc");
  115.     return sum;
  116. }
  117.  
  118. /*
  119.  * computes the checksum of the TCP/UDP pseudo-header
  120.  * returns a 16-bit checksum, already complemented
  121.  */
  122. static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
  123.                            unsigned long daddr,
  124.                            unsigned short len,
  125.                            unsigned short proto,
  126.                            unsigned int sum) 
  127. {
  128.     return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  129. }
  130.  
  131. #define _HAVE_ARCH_IPV6_CSUM
  132.  
  133. static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  134.                          struct in6_addr *daddr,
  135.                          __u32 len,
  136.                          unsigned short proto,
  137.                          unsigned int sum) 
  138. {
  139.     __asm__ __volatile__ (
  140. "    addcc        %3, %4, %%g7\n"
  141. "    addccc        %5, %%g7, %%g7\n"
  142. "    lduw        [%2 + 0x0c], %%g2\n"
  143. "    lduw        [%2 + 0x08], %%g3\n"
  144. "    addccc        %%g2, %%g7, %%g7\n"
  145. "    lduw        [%2 + 0x04], %%g2\n"
  146. "    addccc        %%g3, %%g7, %%g7\n"
  147. "    lduw        [%2 + 0x00], %%g3\n"
  148. "    addccc        %%g2, %%g7, %%g7\n"
  149. "    lduw        [%1 + 0x0c], %%g2\n"
  150. "    addccc        %%g3, %%g7, %%g7\n"
  151. "    lduw        [%1 + 0x08], %%g3\n"
  152. "    addccc        %%g2, %%g7, %%g7\n"
  153. "    lduw        [%1 + 0x04], %%g2\n"
  154. "    addccc        %%g3, %%g7, %%g7\n"
  155. "    lduw        [%1 + 0x00], %%g3\n"
  156. "    addccc        %%g2, %%g7, %%g7\n"
  157. "    addccc        %%g3, %%g7, %0\n"
  158. "    addc        0, %0, %0\n"
  159.     : "=&r" (sum)
  160.     : "r" (saddr), "r" (daddr), "r"(htonl(len)),
  161.       "r"(htonl(proto)), "r"(sum)
  162.     : "g2", "g3", "g7", "cc");
  163.  
  164.     return csum_fold(sum);
  165. }
  166.  
  167. /* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
  168. static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
  169. {
  170.     return csum_fold(csum_partial(buff, len, 0));
  171. }
  172.  
  173. #endif /* !(__SPARC64_CHECKSUM_H) */
  174.