checksum.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #ifndef _M68K_CHECKSUM_H
  2. #define _M68K_CHECKSUM_H
  3. #include <linux/in6.h>
  4. /*
  5. * computes the checksum of a memory block at buff, length len,
  6. * and adds in "sum" (32-bit)
  7. *
  8. * returns a 32-bit number suitable for feeding into itself
  9. * or csum_tcpudp_magic
  10. *
  11. * this function must be called with even lengths, except
  12. * for the last fragment, which may be odd
  13. *
  14. * it's best to have buff aligned on a 32-bit boundary
  15. */
  16. unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
  17. /*
  18. * the same as csum_partial, but copies from src while it
  19. * checksums
  20. *
  21. * here even more important to align src and dst on a 32-bit (or even
  22. * better 64-bit) boundary
  23. */
  24. unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
  25. int len, int sum);
  26. /*
  27. * the same as csum_partial_copy, but copies from user space.
  28. *
  29. * here even more important to align src and dst on a 32-bit (or even
  30. * better 64-bit) boundary
  31. */
  32. extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
  33. unsigned char *dst, int len, int sum, int *csum_err);
  34. #define csum_partial_copy_nocheck(src, dst, len, sum) \
  35. csum_partial_copy((src), (dst), (len), (sum))
  36. unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl);
  37. /*
  38. * Fold a partial checksum
  39. */
  40. static inline unsigned int csum_fold(unsigned int sum)
  41. {
  42. #ifdef CONFIG_COLDFIRE
  43. sum = (sum & 0xffff) + (sum >> 16);
  44. sum = (sum & 0xffff) + (sum >> 16);
  45. #else
  46. unsigned int tmp = sum;
  47. __asm__("swap %1\n\t"
  48. "addw %1, %0\n\t"
  49. "clrw %1\n\t"
  50. "addxw %1, %0"
  51. : "=&d" (sum), "=&d" (tmp)
  52. : "0" (sum), "1" (sum));
  53. #endif
  54. return ~sum;
  55. }
  56. /*
  57. * computes the checksum of the TCP/UDP pseudo-header
  58. * returns a 16-bit checksum, already complemented
  59. */
  60. static inline unsigned int
  61. csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
  62. unsigned short proto, unsigned int sum)
  63. {
  64. __asm__ ("addl %1,%0\n\t"
  65. "addxl %4,%0\n\t"
  66. "addxl %5,%0\n\t"
  67. "clrl %1\n\t"
  68. "addxl %1,%0"
  69. : "=&d" (sum), "=&d" (saddr)
  70. : "0" (daddr), "1" (saddr), "d" (len + proto),
  71. "d"(sum));
  72. return sum;
  73. }
  74. static inline unsigned short int
  75. csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
  76. unsigned short proto, unsigned int sum)
  77. {
  78. return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  79. }
  80. /*
  81. * this routine is used for miscellaneous IP-like checksums, mainly
  82. * in icmp.c
  83. */
  84. extern unsigned short ip_compute_csum(const unsigned char * buff, int len);
  85. #define _HAVE_ARCH_IPV6_CSUM
  86. static __inline__ unsigned short int
  87. csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
  88. __u32 len, unsigned short proto, unsigned int sum)
  89. {
  90. register unsigned long tmp;
  91. __asm__("addl %2@,%0\n\t"
  92. "movel %2@(4),%1\n\t"
  93. "addxl %1,%0\n\t"
  94. "movel %2@(8),%1\n\t"
  95. "addxl %1,%0\n\t"
  96. "movel %2@(12),%1\n\t"
  97. "addxl %1,%0\n\t"
  98. "movel %3@,%1\n\t"
  99. "addxl %1,%0\n\t"
  100. "movel %3@(4),%1\n\t"
  101. "addxl %1,%0\n\t"
  102. "movel %3@(8),%1\n\t"
  103. "addxl %1,%0\n\t"
  104. "movel %3@(12),%1\n\t"
  105. "addxl %1,%0\n\t"
  106. "addxl %4,%0\n\t"
  107. "clrl %1\n\t"
  108. "addxl %1,%0"
  109. : "=&d" (sum), "=&d" (tmp)
  110. : "a" (saddr), "a" (daddr), "d" (len + proto),
  111. "0" (sum));
  112. return csum_fold(sum);
  113. }
  114. #endif /* _M68K_CHECKSUM_H */