~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-s390/checksum.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.