linux-old/include/asm-arm/checksum.h
<<
>>
Prefs
   1/*
   2 *  linux/include/asm-arm/checksum.h
   3 *
   4 * IP checksum routines
   5 *
   6 * Copyright (C) Original authors of ../asm-i386/checksum.h
   7 * Copyright (C) 1996-1999 Russell King
   8 */
   9#ifndef __ASM_ARM_CHECKSUM_H
  10#define __ASM_ARM_CHECKSUM_H
  11
  12/*
  13 * computes the checksum of a memory block at buff, length len,
  14 * and adds in "sum" (32-bit)
  15 *
  16 * returns a 32-bit number suitable for feeding into itself
  17 * or csum_tcpudp_magic
  18 *
  19 * this function must be called with even lengths, except
  20 * for the last fragment, which may be odd
  21 *
  22 * it's best to have buff aligned on a 32-bit boundary
  23 */
  24unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
  25
  26/*
  27 * the same as csum_partial, but copies from src while it
  28 * checksums, and handles user-space pointer exceptions correctly, when needed.
  29 *
  30 * here even more important to align src and dst on a 32-bit (or even
  31 * better 64-bit) boundary
  32 */
  33
  34unsigned int
  35csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
  36
  37unsigned int
  38csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
  39
  40/*
  41 * These are the old (and unsafe) way of doing checksums, a warning message will be
  42 * printed if they are used and an exception occurs.
  43 *
  44 * these functions should go away after some time.
  45 */
  46#define csum_partial_copy(src,dst,len,sum)      csum_partial_copy_nocheck(src,dst,len,sum)
  47
  48/*
  49 *      This is a version of ip_compute_csum() optimized for IP headers,
  50 *      which always checksum on 4 octet boundaries.
  51 */
  52static inline unsigned short
  53ip_fast_csum(unsigned char * iph, unsigned int ihl)
  54{
  55        unsigned int sum, tmp1;
  56
  57        __asm__ __volatile__(
  58        "ldr    %0, [%1], #4            @ ip_fast_csum          \n\
  59        ldr     %3, [%1], #4                                    \n\
  60        sub     %2, %2, #5                                      \n\
  61        adds    %0, %0, %3                                      \n\
  62        ldr     %3, [%1], #4                                    \n\
  63        adcs    %0, %0, %3                                      \n\
  64        ldr     %3, [%1], #4                                    \n\
  651:      adcs    %0, %0, %3                                      \n\
  66        ldr     %3, [%1], #4                                    \n\
  67        tst     %2, #15                 @ do this carefully     \n\
  68        subne   %2, %2, #1              @ without destroying    \n\
  69        bne     1b                      @ the carry flag        \n\
  70        adcs    %0, %0, %3                                      \n\
  71        adc     %0, %0, #0                                      \n\
  72        adds    %0, %0, %0, lsl #16                             \n\
  73        addcs   %0, %0, #0x10000                                \n\
  74        mvn     %0, %0                                          \n\
  75        mov     %0, %0, lsr #16"
  76        : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
  77        : "1" (iph), "2" (ihl)
  78        : "cc");
  79        return sum;
  80}
  81
  82/*
  83 *      Fold a partial checksum without adding pseudo headers
  84 */
  85static inline unsigned int
  86csum_fold(unsigned int sum)
  87{
  88        __asm__(
  89        "adds   %0, %1, %1, lsl #16     @ csum_fold             \n\
  90        addcs   %0, %0, #0x10000"
  91        : "=r" (sum)
  92        : "r" (sum)
  93        : "cc");
  94        return (~sum) >> 16;
  95}
  96
  97static inline unsigned int
  98csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
  99                   unsigned int proto, unsigned int sum)
 100{
 101        __asm__(
 102        "adds   %0, %1, %2              @ csum_tcpudp_nofold    \n\
 103        adcs    %0, %0, %3                                      \n\
 104        adcs    %0, %0, %4                                      \n\
 105        adcs    %0, %0, %5                                      \n\
 106        adc     %0, %0, #0"
 107        : "=&r"(sum)
 108        : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len) << 16), "Ir" (proto << 8)
 109        : "cc");
 110        return sum;
 111}       
 112/*
 113 * computes the checksum of the TCP/UDP pseudo-header
 114 * returns a 16-bit checksum, already complemented
 115 */
 116static inline unsigned short int
 117csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
 118                  unsigned int proto, unsigned int sum)
 119{
 120        __asm__(
 121        "adds   %0, %1, %2              @ csum_tcpudp_magic     \n\
 122        adcs    %0, %0, %3                                      \n\
 123        adcs    %0, %0, %4                                      \n\
 124        adcs    %0, %0, %5                                      \n\
 125        adc     %0, %0, #0                                      \n\
 126        adds    %0, %0, %0, lsl #16                             \n\
 127        addcs   %0, %0, #0x10000                                \n\
 128        mvn     %0, %0"
 129        : "=&r"(sum)
 130        : "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (proto << 8)
 131        : "cc");
 132        return sum >> 16;
 133}
 134
 135
 136/*
 137 * this routine is used for miscellaneous IP-like checksums, mainly
 138 * in icmp.c
 139 */
 140static inline unsigned short
 141ip_compute_csum(unsigned char * buff, int len)
 142{
 143        return csum_fold(csum_partial(buff, len, 0));
 144}
 145
 146#define _HAVE_ARCH_IPV6_CSUM
 147extern unsigned long
 148__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
 149                __u32 proto, unsigned int sum);
 150
 151static inline unsigned short int
 152csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
 153                unsigned short proto, unsigned int sum)
 154{
 155        return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len),
 156                                           htonl(proto), sum));
 157}
 158#endif
 159
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.