RTEMS CPU Kit with SuperCore  4.11.3
in_cksum_arm.h
Go to the documentation of this file.
1 /* $NetBSD: in_cksum_arm.c,v 1.3 2001/12/08 21:18:50 chris Exp $ */
2 
3 /*
4  * ARM version:
5  *
6  * Copyright (c) 1997 Mark Brinicome
7  * Copyright (c) 1997 Causality Limited
8  *
9  * Based on the sparc version.
10  */
11 
12 /*
13  * Sparc version:
14  *
15  * Copyright (c) 1995 Zubin Dittia.
16  * Copyright (c) 1995 Matthew R. Green.
17  * Copyright (c) 1994 Charles M. Hannum.
18  * Copyright (c) 1992, 1993
19  * The Regents of the University of California. All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  * 1. Redistributions of source code must retain the above copyright
25  * notice, this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must reproduce the above copyright
27  * notice, this list of conditions and the following disclaimer in the
28  * documentation and/or other materials provided with the distribution.
29  * 3. All advertising materials mentioning features or use of this software
30  * must display the following acknowledgement:
31  * This product includes software developed by the University of
32  * California, Berkeley and its contributors.
33  * 4. Neither the name of the University nor the names of its contributors
34  * may be used to endorse or promote products derived from this software
35  * without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  * @(#)in_cksum.c 8.1 (Berkeley) 6/11/93
50  */
51 
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/mbuf.h>
55 #include <netinet/in.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/ip_var.h>
59 
60 /*
61  * Checksum routine for Internet Protocol family headers.
62  *
63  * This routine is very heavily used in the network
64  * code and should be modified for each CPU to be as fast as possible.
65  *
66  * ARM version.
67  */
68 
69 #define ADD64 __asm __volatile(" \n\
70  ldmia %0!, {%2, %3, %4, %5} \n\
71  adds %1,%7,%2; adcs %1,%1,%3 \n\
72  adcs %1,%1,%4; adcs %1,%1,%5 \n\
73  ldmia %0!, {%2, %3, %4, %5} \n\
74  adcs %1,%1,%2; adcs %1,%1,%3 \n\
75  adcs %1,%1,%4; adcs %1,%1,%5 \n\
76  ldmia %0!, {%2, %3, %4, %5} \n\
77  adcs %1,%1,%2; adcs %1,%1,%3 \n\
78  adcs %1,%1,%4; adcs %1,%1,%5 \n\
79  ldmia %0!, {%2, %3, %4, %5} \n\
80  adcs %1,%1,%2; adcs %1,%1,%3 \n\
81  adcs %1,%1,%4; adcs %1,%1,%5 \n\
82  adcs %1,%1,#0\n" \
83  : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
84  : "0" (w), "r" (sum) \
85  : "cc")
86 
87 #define ADD32 __asm __volatile(" \n\
88  ldmia %0!, {%2, %3, %4, %5} \n\
89  adds %1,%7,%2; adcs %1,%1,%3 \n\
90  adcs %1,%1,%4; adcs %1,%1,%5 \n\
91  ldmia %0!, {%2, %3, %4, %5} \n\
92  adcs %1,%1,%2; adcs %1,%1,%3 \n\
93  adcs %1,%1,%4; adcs %1,%1,%5 \n\
94  adcs %1,%1,#0\n" \
95  : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
96  : "0" (w), "r" (sum) \
97  : "cc")
98 
99 #define ADD16 __asm __volatile(" \n\
100  ldmia %0!, {%2, %3, %4, %5} \n\
101  adds %1,%7,%2; adcs %1,%1,%3 \n\
102  adcs %1,%1,%4; adcs %1,%1,%5 \n\
103  adcs %1,%1,#0\n" \
104  : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
105  : "0" (w), "r" (sum) \
106  : "cc")
107 
108 #define ADD8 __asm __volatile(" \n\
109  ldmia %0!, {%2, %3} \n\
110  adds %1,%5,%2; adcs %1,%1,%3 \n\
111  adcs %1,%1,#0\n" \
112  : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2) \
113  : "0" (w), "r" (sum) \
114  : "cc" )
115 
116 #define ADD4 __asm __volatile(" \n\
117  ldr %2,[%0],#4 \n\
118  adds %1,%4,%2 \n\
119  adcs %1,%1,#0\n" \
120  : "=r" (w), "=r" (sum), "=&r" (tmp1) \
121  : "0" (w), "r" (sum) \
122  : "cc")
123 
124 /*#define REDUCE {sum = (sum & 0xffff) + (sum >> 16);}*/
125 #define REDUCE __asm __volatile(" \n\
126  mov %2, #0x00ff \n\
127  orr %2, %2, #0xff00 \n\
128  and %2, %0, %2 \n\
129  add %0, %2, %0, lsr #16\n" \
130  : "=r" (sum) \
131  : "0" (sum), "r" (tmp1))
132 
133 #define ADDCARRY {if (sum > 0xffff) sum -= 0xffff;}
134 #define ROL {sum = sum << 8;} /* depends on recent REDUCE */
135 #define ADDBYTE {ROL; sum += (*w << 8); byte_swapped ^= 1;}
136 #define ADDSHORT {sum += *(u_short *)w;}
137 #define ADVANCE(n) {w += n; mlen -= n;}
138 #define ADVANCEML(n) {mlen -= n;}
139 
140 static __inline__ int
141 in_cksum_internal(struct mbuf *m, int off, int len, u_int sum)
142 {
143  u_char *w;
144  int mlen = 0;
145  int byte_swapped = 0;
146 
147  /*
148  * Declare four temporary registers for use by the asm code. We
149  * allow the compiler to pick which specific machine registers to
150  * use, instead of hard-coding this in the asm code above.
151  */
152  register u_int tmp1=0, tmp2, tmp3, tmp4;
153 
154  for (; m && len; m = m->m_next) {
155  if (m->m_len == 0)
156  continue;
157  w = mtod(m, u_char *) + off;
158  mlen = m->m_len - off;
159  off = 0;
160  if (len < mlen)
161  mlen = len;
162  len -= mlen;
163 
164  /*
165  * Ensure that we're aligned on a word boundary here so
166  * that we can do 32 bit operations below.
167  */
168  if ((3 & (long)w) != 0) {
169  REDUCE;
170  if ((1 & (long)w) != 0 && mlen >= 1) {
171  ADDBYTE;
172  ADVANCE(1);
173  }
174  if ((2 & (long)w) != 0 && mlen >= 2) {
175  ADDSHORT;
176  ADVANCE(2);
177  }
178  }
179 
180  /*
181  * Do as many 32 bit operations as possible using the
182  * 64/32/16/8/4 macro's above, using as many as possible of
183  * these.
184  */
185 
186  while (mlen >= 64) {
187  ADD64;
188  ADVANCEML(64);
189  }
190  if (mlen >= 32) {
191  ADD32;
192  ADVANCEML(32);
193  }
194  if (mlen >= 16) {
195  ADD16;
196  ADVANCEML(16);
197  }
198  if (mlen >= 8) {
199  ADD8;
200  ADVANCEML(8);
201  }
202  if (mlen >= 4) {
203  ADD4;
204  ADVANCEML(4)
205  }
206  if (mlen == 0)
207  continue;
208 
209  REDUCE;
210  if (mlen >= 2) {
211  ADDSHORT;
212  ADVANCE(2);
213  }
214  if (mlen == 1) {
215  ADDBYTE;
216  }
217  }
218  if (byte_swapped) {
219  REDUCE;
220  ROL;
221  }
222  REDUCE;
223  ADDCARRY;
224 
225  return (0xffff ^ sum);
226 }
227 
228 int
229 in_cksum(
230  struct mbuf *m,
231  int len)
232 {
233  int cksum;
234  cksum =in_cksum_internal(m, 0, len, 0);
235  return cksum;
236 }
237 
238 int
239 in4_cksum(
240  struct mbuf *m,
241  u_int8_t nxt,
242  int off,
243  int len )
244 {
245  u_int sum = 0;
246 
247  if (nxt != 0) {
248  /* for ADD macros */
249  register u_int tmp1, tmp2, tmp3, tmp4;
250  u_char *w;
251  struct ipovly ipov;
252  /* pseudo header */
253  if (off < sizeof(struct ipovly))
254  panic("in4_cksum: offset too short");
255  if (m->m_len < sizeof(struct ip))
256  panic("in4_cksum: bad mbuf chain");
257 
258  bzero(&ipov, sizeof(ipov));
259  ipov.ih_len = htons(len);
260  ipov.ih_pr = nxt;
261  ipov.ih_src = mtod(m, struct ip *)->ip_src;
262  ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
263  w = (u_char *)&ipov;
264 
265  /* assumes sizeof(ipov) == 20 */
266  ADD16;
267  ADD4;
268  }
269  /* skip unnecessary part */
270  while (m && off > 0) {
271  if (m->m_len > off)
272  break;
273  off -= m->m_len;
274  m = m->m_next;
275  }
276  return (in_cksum_internal(m, off, len, sum));
277 }
Definition: ip.h:61
Definition: ip_var.h:43
Definition: mbuf.h:103