diff options
Diffstat (limited to 'include/asm-parisc/checksum.h')
-rw-r--r-- | include/asm-parisc/checksum.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h new file mode 100644 index 000000000..9088f9795 --- /dev/null +++ b/include/asm-parisc/checksum.h @@ -0,0 +1,174 @@ +#ifndef _PARISC_CHECKSUM_H +#define _PARISC_CHECKSUM_H + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +extern unsigned int csum_partial(const unsigned char *, int, unsigned int); + +/* + * the same as csum_partial, but copies from src while it + * checksums + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +extern unsigned int csum_partial_copy(const char *, char *, int, unsigned int); + +/* + * the same as csum_partial, but copies from user space + * + * this is obsolete and will go away. + */ +#define csum_partial_copy_fromuser csum_partial_copy + +/* + * this is a new version of the above that records errors it finds in *errp, + * but continues and zeros the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp); + +/* + * Note: when you get a NULL pointer exception here this means someone + * passed in an incorrect kernel address to one of these functions. + * + * If you use these functions directly please don't forget the + * verify_area(). + */ +extern __inline__ +unsigned int csum_partial_copy_nocheck (const char *src, char *dst, + int len, int sum) +{ + return csum_partial_copy (src, dst, len, sum); +} + +/* + * Optimized for IP headers, which always checksum on 4 octet boundaries. + * + * Written by Randolph Chung <tausq@debian.org> + */ +static inline unsigned short ip_fast_csum(unsigned char * iph, + unsigned int ihl) { + unsigned int sum; + + + __asm__ __volatile__ (" + ldws,ma 4(%1), %0 + addi -4, %2, %2 + comib,>= 0, %2, 2f + + ldws,ma 4(%1), %%r19 + add %0, %%r19, %0 + ldws,ma 4(%1), %%r19 + addc %0, %%r19, %0 + ldws,ma 4(%1), %%r19 + addc %0, %%r19, %0 +1: ldws,ma 4(%1), %%r19 + addib,<> -1, %2, 1b + addc %0, %%r19, %0 + addc %0, %%r0, %0 + + zdepi -1, 31, 16, %%r19 + and %0, %%r19, %%r20 + extru %0, 15, 16, %%r21 + add %%r20, %%r21, %0 + and %0, %%r19, %%r20 + extru %0, 15, 16, %%r21 + add %%r20, %%r21, %0 + subi -1, %0, %0 +2: + " + : "=r" (sum), "=r" (iph), "=r" (ihl) + : "1" (iph), "2" (ihl) + : "r19", "r20", "r21" ); + + return(sum); +} + +/* + * Fold a partial checksum + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + return ~sum; +} + +static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + __asm__(" + add %1, %0, %0 + addc %2, %0, %0 + addc %3, %0, %0 + addc %%r0, %0, %0 " + : "=r" (sum) + : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum)); + return sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline unsigned short ip_compute_csum(unsigned char * buf, int len) { + return csum_fold (csum_partial(buf, len, 0)); +} + +#define _HAVE_ARCH_IPV6_CSUM +static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, + struct in6_addr *daddr, + __u16 len, + unsigned short proto, + unsigned int sum) +{ + BUG(); + return csum_fold(sum); +} + +/* + * Copy and checksum to user + */ +#define HAVE_CSUM_COPY_USER +static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst, + int len, int sum, int *err_ptr) +{ + /* code stolen from include/asm-mips64 */ + sum = csum_partial(src, len, sum); + + if (copy_to_user(dst, src, len)) { + *err_ptr = -EFAULT; + return -1; + } + + return sum; +} + +#endif + |