checksum.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _PARISC_CHECKSUM_H
  2. #define _PARISC_CHECKSUM_H
  3. /*
  4.  * computes the checksum of a memory block at buff, length len,
  5.  * and adds in "sum" (32-bit)
  6.  *
  7.  * returns a 32-bit number suitable for feeding into itself
  8.  * or csum_tcpudp_magic
  9.  *
  10.  * this function must be called with even lengths, except
  11.  * for the last fragment, which may be odd
  12.  *
  13.  * it's best to have buff aligned on a 32-bit boundary
  14.  */
  15. extern unsigned int csum_partial(const unsigned char *, int, unsigned int);
  16. /*
  17.  * the same as csum_partial, but copies from src while it
  18.  * checksums
  19.  *
  20.  * here even more important to align src and dst on a 32-bit (or even
  21.  * better 64-bit) boundary
  22.  */
  23. extern unsigned int csum_partial_copy(const char *, char *, int, unsigned int);
  24. /*
  25.  * the same as csum_partial, but copies from user space
  26.  *
  27.  * this is obsolete and will go away.
  28.  */
  29. #define csum_partial_copy_fromuser csum_partial_copy
  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. unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
  35. /*
  36.  * Note: when you get a NULL pointer exception here this means someone
  37.  * passed in an incorrect kernel address to one of these functions. 
  38.  *
  39.  * If you use these functions directly please don't forget the 
  40.  * verify_area().
  41.  */
  42. extern __inline__
  43. unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
  44. int len, int sum)
  45. {
  46. return csum_partial_copy (src, dst, len, sum);
  47. }
  48. /*
  49.  * Optimized for IP headers, which always checksum on 4 octet boundaries.
  50.  *
  51.  * Written by Randolph Chung <tausq@debian.org>
  52.  */
  53. static inline unsigned short ip_fast_csum(unsigned char * iph,
  54.   unsigned int ihl) {
  55. unsigned int sum;
  56. __asm__ __volatile__ (
  57. " ldws,ma 4(%1), %0n"
  58. " addi -4, %2, %2n"
  59. " comib,>= 0, %2, 2fn"
  60. "n"
  61. " ldws,ma 4(%1), %%r19n"
  62. " add %0, %%r19, %0n"
  63. " ldws,ma 4(%1), %%r19n"
  64. " addc %0, %%r19, %0n"
  65. " ldws,ma 4(%1), %%r19n"
  66. " addc %0, %%r19, %0n"
  67. "1: ldws,ma 4(%1), %%r19n"
  68. " addib,<> -1, %2, 1bn"
  69. " addc %0, %%r19, %0n"
  70. " addc %0, %%r0, %0n"
  71. "n"
  72. " zdepi -1, 31, 16, %%r19n"
  73. " and %0, %%r19, %%r20n"
  74. " extru %0, 15, 16, %%r21n"
  75. " add %%r20, %%r21, %0n"
  76. " and %0, %%r19, %%r20n"
  77. " extru %0, 15, 16, %%r21n"
  78. " add %%r20, %%r21, %0n"
  79. " subi -1, %0, %0n"
  80. "2:n"
  81. : "=r" (sum), "=r" (iph), "=r" (ihl)
  82. : "1" (iph), "2" (ihl)
  83. : "r19", "r20", "r21" );
  84. return(sum);
  85. }
  86. /*
  87.  * Fold a partial checksum
  88.  */
  89. static inline unsigned int csum_fold(unsigned int sum)
  90. {
  91. /* add the swapped two 16-bit halves of sum,
  92.    a possible carry from adding the two 16-bit halves,
  93.    will carry from the lower half into the upper half,
  94.    giving us the correct sum in the upper half. */
  95. sum += (sum << 16) + (sum >> 16);
  96. return (~sum) >> 16;
  97. }
  98.  
  99. static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
  100.        unsigned long daddr,
  101.        unsigned short len,
  102.        unsigned short proto,
  103.        unsigned int sum) 
  104. {
  105. __asm__(
  106. " add  %1, %0, %0n"
  107. " addc %2, %0, %0n"
  108. " addc %3, %0, %0n"
  109. " addc %%r0, %0, %0n"
  110. : "=r" (sum)
  111. : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
  112.     return sum;
  113. }
  114. /*
  115.  * computes the checksum of the TCP/UDP pseudo-header
  116.  * returns a 16-bit checksum, already complemented
  117.  */
  118. static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
  119.    unsigned long daddr,
  120.    unsigned short len,
  121.    unsigned short proto,
  122.    unsigned int sum) 
  123. {
  124. return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  125. }
  126. /*
  127.  * this routine is used for miscellaneous IP-like checksums, mainly
  128.  * in icmp.c
  129.  */
  130. static inline unsigned short ip_compute_csum(unsigned char * buf, int len) {
  131.  return csum_fold (csum_partial(buf, len, 0));
  132. }
  133. #define _HAVE_ARCH_IPV6_CSUM
  134. static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  135.      struct in6_addr *daddr,
  136.      __u16 len,
  137.      unsigned short proto,
  138.      unsigned int sum) 
  139. {
  140. __asm__ __volatile__ (
  141. #if BITS_PER_LONG > 32
  142. /*
  143. ** We can execute two loads and two adds per cycle on PA 8000.
  144. ** But add insn's get serialized waiting for the carry bit.
  145. ** Try to keep 4 registers with "live" values ahead of the ALU.
  146. */
  147. " ldd,ma 8(%1), %%r19n" /* get 1st saddr word */
  148. " ldd,ma 8(%2), %%r20n" /* get 1st daddr word */
  149. " add %8, %3, %3n"/* add 16-bit proto + len */
  150. " add %%r19, %0, %0n"
  151. " ldd,ma 8(%1), %%r21n" /* 2cd saddr */
  152. " ldd,ma 8(%2), %%r22n" /* 2cd daddr */
  153. " add,dc %%r20, %0, %0n"
  154. " add,dc %%r21, %0, %0n"
  155. " add,dc %%r22, %0, %0n"
  156. " add,dc %3, %0, %0n"  /* fold in proto+len | carry bit */
  157. " extrd,u %0, 31, 32, %%r19n" /* copy upper half down */
  158. " depdi 0, 31, 32, %0n" /* clear upper half */
  159. " add %%r19, %0, %0n" /* fold into 32-bits */
  160. " addc 0, %0, %0n" /* add carry */
  161. #else
  162. /*
  163. ** For PA 1.x, the insn order doesn't matter as much.
  164. ** Insn stream is serialized on the carry bit here too.
  165. ** result from the previous operation (eg r0 + x)
  166. */
  167. " ldw,ma 4(%1), %%r19n" /* get 1st saddr word */
  168. " ldw,ma 4(%2), %%r20n" /* get 1st daddr word */
  169. " add %8, %3, %3n" /* add 16-bit proto + len */
  170. " add %%r19, %0, %0n"
  171. " ldw,ma 4(%1), %%r21n" /* 2cd saddr */
  172. " addc %%r20, %0, %0n"
  173. " ldw,ma 4(%2), %%r22n" /* 2cd daddr */
  174. " addc %%r21, %0, %0n"
  175. " ldw,ma 4(%1), %%r19n" /* 3rd saddr */
  176. " addc %%r22, %0, %0n"
  177. " ldw,ma 4(%2), %%r20n" /* 3rd daddr */
  178. " addc %%r19, %0, %0n"
  179. " ldw,ma 4(%1), %%r21n" /* 4th saddr */
  180. " addc %%r20, %0, %0n"
  181. " ldw,ma 4(%2), %%r22n" /* 4th daddr */
  182. " addc %%r21, %0, %0n"
  183. " addc %%r22, %0, %0n"
  184. " addc %3, %0, %0n" /* fold in proto+len, catch carry */
  185. #endif
  186. : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len)
  187. : "0" (sum), "1" (saddr), "2" (daddr), "3" (len), "r" (proto)
  188. : "r19", "r20", "r21", "r22");
  189. return csum_fold(sum);
  190. }
  191. /* 
  192.  * Copy and checksum to user
  193.  */
  194. #define HAVE_CSUM_COPY_USER
  195. static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
  196.     int len, int sum, int *err_ptr)
  197. {
  198. /* code stolen from include/asm-mips64 */
  199. sum = csum_partial(src, len, sum);
  200.  
  201. if (copy_to_user(dst, src, len)) {
  202. *err_ptr = -EFAULT;
  203. return -1;
  204. }
  205. return sum;
  206. }
  207. #endif