checksum.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _S390_CHECKSUM_H
  2. #define _S390_CHECKSUM_H
  3. /*
  4.  *  include/asm-s390/checksum.h
  5.  *    S390 fast network checksum routines
  6.  *    see also arch/S390/lib/checksum.c
  7.  *
  8.  *  S390 version
  9.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  10.  *    Author(s): Ulrich Hild        (first version)
  11.  *               Martin Schwidefsky (heavily optimized CKSM version)
  12.  *               D.J. Barrow        (third attempt) 
  13.  */
  14. #include <asm/uaccess.h>
  15. /*
  16.  * computes the checksum of a memory block at buff, length len,
  17.  * and adds in "sum" (32-bit)
  18.  *
  19.  * returns a 32-bit number suitable for feeding into itself
  20.  * or csum_tcpudp_magic
  21.  *
  22.  * this function must be called with even lengths, except
  23.  * for the last fragment, which may be odd
  24.  *
  25.  * it's best to have buff aligned on a 32-bit boundary
  26.  */
  27. unsigned int
  28. csum_partial(const unsigned char * buff, int len, unsigned int sum);
  29. /*
  30.  * csum_partial as an inline function
  31.  */
  32. extern inline unsigned int 
  33. csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
  34. {
  35. __asm__ __volatile__ (
  36. "    lgr  2,%1n"    /* address in gpr 2 */
  37. "    lgfr 3,%2n"    /* length in gpr 3 */
  38. "0:  cksm %0,2n"    /* do checksum on longs */
  39. "    jo   0bn"
  40.                 : "+&d" (sum)
  41. : "d" (buff), "d" (len)
  42.                 : "cc", "2", "3" );
  43. return sum;
  44. }
  45. /*
  46.  * the same as csum_partial, but copies from src while it
  47.  * checksums
  48.  *
  49.  * here even more important to align src and dst on a 32-bit (or even
  50.  * better 64-bit) boundary
  51.  */
  52. extern inline unsigned int 
  53. csum_partial_copy(const char *src, char *dst, int len,unsigned int sum)
  54. {
  55. memcpy(dst,src,len);
  56.         return csum_partial_inline(dst, len, sum);
  57. }
  58. /*
  59.  * the same as csum_partial_copy, but copies from user space.
  60.  *
  61.  * here even more important to align src and dst on a 32-bit (or even
  62.  * better 64-bit) boundary
  63.  *
  64.  * Copy from userspace and compute checksum.  If we catch an exception
  65.  * then zero the rest of the buffer.
  66.  */
  67. extern inline unsigned int 
  68. csum_partial_copy_from_user (const char *src, char *dst,
  69.                                           int len, unsigned int sum,
  70.                                           int *err_ptr)
  71. {
  72. int missing;
  73. missing = copy_from_user(dst, src, len);
  74. if (missing) {
  75. memset(dst + len - missing, 0, missing);
  76. *err_ptr = -EFAULT;
  77. }
  78. return csum_partial(dst, len, sum);
  79. }
  80. extern inline unsigned int
  81. csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
  82. {
  83.         memcpy(dst,src,len);
  84.         return csum_partial_inline(dst, len, sum);
  85. }
  86. /*
  87.  *      Fold a partial checksum without adding pseudo headers
  88.  */
  89. extern inline unsigned short
  90. csum_fold(unsigned int sum)
  91. {
  92. __asm__ __volatile__ (
  93. "    sr   3,3n"   /* %0 = H*65536 + L */
  94. "    lr   2,%0n"  /* %0 = H L, R2/R3 = H L / 0 0 */
  95. "    srdl 2,16n"  /* %0 = H L, R2/R3 = 0 H / L 0 */
  96. "    alr  2,3n"   /* %0 = H L, R2/R3 = L H / L 0 */
  97. "    alr  %0,2n"  /* %0 = H+L+C L+H */
  98.                 "    srl  %0,16n" /* %0 = H+L+C */
  99. : "+&d" (sum) : : "cc", "2", "3");
  100. return ((unsigned short) ~sum);
  101. }
  102. /*
  103.  * This is a version of ip_compute_csum() optimized for IP headers,
  104.  * which always checksum on 4 octet boundaries.
  105.  *
  106.  */
  107. extern inline unsigned short
  108. ip_fast_csum(unsigned char *iph, unsigned int ihl)
  109. {
  110. unsigned long sum;
  111.         __asm__ __volatile__ (
  112. "    slgr %0,%0n"   /* set sum to zero */
  113.                 "    lgr  2,%1n"    /* address in gpr 2 */
  114.                 "    lgfr 3,%2n"    /* length in gpr 3 */
  115.                 "0:  cksm %0,2n"    /* do checksum on ints */
  116.                 "    jo   0bn"
  117.                 : "=&d" (sum)
  118.                 : "d" (iph), "d" (ihl*4)
  119.                 : "cc", "2", "3" );
  120.         return csum_fold(sum);
  121. }
  122. /*
  123.  * computes the checksum of the TCP/UDP pseudo-header
  124.  * returns a 32-bit checksum
  125.  */
  126. extern inline unsigned int 
  127. csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
  128.                    unsigned short len, unsigned short proto,
  129.                    unsigned int sum)
  130. {
  131. __asm__ __volatile__ (
  132.                 "    lgfr  %0,%0n"
  133.                 "    algr  %0,%1n"  /* sum += saddr */
  134.                 "    brc   12,0fn"
  135. "    aghi  %0,1n"   /* add carry */
  136. "0:  algr  %0,%2n"  /* sum += daddr */
  137.                 "    brc   12,1fn"
  138.                 "    aghi  %0,1n"   /* add carry */
  139. "1:  algfr %0,%3n"  /* sum += (len<<16) + proto */
  140. "    brc   12,2fn"
  141. "    aghi  %0,1n"   /* add carry */
  142. "2:  srlg  0,%0,32n"
  143.                 "    alr   %0,0n"   /* fold to 32 bits */
  144.                 "    brc   12,3fn"
  145.                 "    ahi   %0,1n"   /* add carry */
  146.                 "3:  llgfr %0,%0"
  147. : "+&d" (sum)
  148. : "d" (saddr), "d" (daddr),
  149.   "d" (((unsigned int) len<<16) + (unsigned int) proto)
  150. : "cc", "0" );
  151. return sum;
  152. }
  153. /*
  154.  * computes the checksum of the TCP/UDP pseudo-header
  155.  * returns a 16-bit checksum, already complemented
  156.  */
  157. extern inline unsigned short int
  158. csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
  159.                   unsigned short len, unsigned short proto,
  160.                   unsigned int sum)
  161. {
  162. return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  163. }
  164. /*
  165.  * this routine is used for miscellaneous IP-like checksums, mainly
  166.  * in icmp.c
  167.  */
  168. extern inline unsigned short
  169. ip_compute_csum(unsigned char * buff, int len)
  170. {
  171. return csum_fold(csum_partial_inline(buff, len, 0));
  172. }
  173. #endif /* _S390_CHECKSUM_H */