source: rtems/cpukit/libnetworking/netinet/in_cksum.c @ 39e6e65a

4.104.114.84.95
Last change on this file since 39e6e65a was 39e6e65a, checked in by Joel Sherrill <joel.sherrill@…>, on 08/19/98 at 21:32:28

Base files

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 1988, 1992, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *      @(#)in_cksum.c  8.1 (Berkeley) 6/10/93
34 * $Id$
35 */
36
37#include <sys/param.h>
38#include <sys/mbuf.h>
39
40#if (defined(__GNUC__) && (defined(__mc68000__) || defined(__m68k__)))
41
42#define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; }
43
44/*
45 * Motorola 68k version of Internet Protocol Checksum routine
46 * W. Eric Norum
47 * Saskatchewan Accelerator Laboratory
48 * August, 1998
49 */
50int
51in_cksum(m, len)
52        struct mbuf *m;
53        int len;
54{
55        unsigned short *w;
56        unsigned long sum = 0;
57        int mlen = 0;
58        int byte_swapped = 0;
59        union {
60                char    c[2];
61                u_short s;
62        } s_util;
63
64        for ( ; m && len ; m = m->m_next) {
65                if (m->m_len == 0)
66                        continue;
67                w = mtod(m, u_short *);
68                if (mlen == -1) {
69                        /*
70                         * The first byte of this mbuf is the continuation
71                         * of a word spanning between this mbuf and the
72                         * last mbuf.
73                         *
74                         * s_util.c[0] is already saved when scanning previous
75                         * mbuf.
76                         */
77                        s_util.c[1] = *(char *)w;
78                        sum += s_util.s;
79                        w = (u_short *)((char *)w + 1);
80                        mlen = m->m_len - 1;
81                        len--;
82                } else
83                        mlen = m->m_len;
84                if (len < mlen)
85                        mlen = len;
86                len -= mlen;
87
88                /*
89                 * Force to longword boundary.
90                 */
91                if (3 & (int)w) {
92                        REDUCE;
93                        if ((1 & (int) w) && (mlen > 0)) {
94                                sum <<= 8;
95                                s_util.c[0] = *(u_char *)w;
96                                w = (u_short *)((char *)w + 1);
97                                mlen--;
98                                byte_swapped = 1;
99                        }
100                        if ((2 & (int) w) && (mlen >= 2)) {
101                                sum += *w++;
102                                mlen -= 2;
103                        }
104                }
105
106                /*
107                 * Sum all the longwords in the buffer.
108                 * See RFC 1071 -- Computing the Internet Checksum.
109                 * It should work for all 68k family members.
110                 */
111                {
112                unsigned long tcnt = mlen, t1;
113                __asm__ volatile (
114                "movel   %2,%3\n\t"
115                "lsrl    #6,%2       | count/64 = # loop traversals\n\t"
116                "andl    #0x3c,%3    | Then find fractions of a chunk\n\t"
117                "negl    %3\n\t      | Each long uses 4 instruction bytes\n\t"
118                "andi    #0xf,%%cc   | Clear X (extended carry flag)\n\t"
119                "jmp     %%pc@(lcsum2_lbl-.-2:b,%3)  | Jump into loop\n"
120                "lcsum1_lbl:     | Begin inner loop...\n\t"
121                "movel   %1@+,%3     |  0: Fetch 32-bit word\n\t"
122                "addxl   %3,%0       |    Add word + previous carry\n\t"
123                "movel   %1@+,%3     |  1: Fetch 32-bit word\n\t"
124                "addxl   %3,%0       |    Add word + previous carry\n\t"
125                "movel   %1@+,%3     |  2: Fetch 32-bit word\n\t"
126                "addxl   %3,%0       |    Add word + previous carry\n\t"
127                "movel   %1@+,%3     |  3: Fetch 32-bit word\n\t"
128                "addxl   %3,%0       |    Add word + previous carry\n\t"
129                "movel   %1@+,%3     |  4: Fetch 32-bit word\n\t"
130                "addxl   %3,%0       |    Add word + previous carry\n\t"
131                "movel   %1@+,%3     |  5: Fetch 32-bit word\n\t"
132                "addxl   %3,%0       |    Add word + previous carry\n\t"
133                "movel   %1@+,%3     |  6: Fetch 32-bit word\n\t"
134                "addxl   %3,%0       |    Add word + previous carry\n\t"
135                "movel   %1@+,%3     |  7: Fetch 32-bit word\n\t"
136                "addxl   %3,%0       |    Add word + previous carry\n\t"
137                "movel   %1@+,%3     |  8: Fetch 32-bit word\n\t"
138                "addxl   %3,%0       |    Add word + previous carry\n\t"
139                "movel   %1@+,%3     |  9: Fetch 32-bit word\n\t"
140                "addxl   %3,%0       |    Add word + previous carry\n\t"
141                "movel   %1@+,%3     |  A: Fetch 32-bit word\n\t"
142                "addxl   %3,%0       |    Add word + previous carry\n\t"
143                "movel   %1@+,%3     |  B: Fetch 32-bit word\n\t"
144                "addxl   %3,%0       |    Add word + previous carry\n\t"
145                "movel   %1@+,%3     |  C: Fetch 32-bit word\n\t"
146                "addxl   %3,%0       |    Add word + previous carry\n\t"
147                "movel   %1@+,%3     |  D: Fetch 32-bit word\n\t"
148                "addxl   %3,%0       |    Add word + previous carry\n\t"
149                "movel   %1@+,%3     |  E: Fetch 32-bit word\n\t"
150                "addxl   %3,%0       |    Add word + previous carry\n\t"
151                "movel   %1@+,%3     |  F: Fetch 32-bit word\n\t"
152                "addxl   %3,%0       |    Add word + previous carry\n"
153                "lcsum2_lbl:\n\tdbf    %2,lcsum1_lbl   | (NB- dbra doesn't affect X)\n\t"
154                "movel    %0,%3         | Fold 32 bit sum to 16 bits\n\t"
155                "swap    %3             | (NB- swap doesn't affect X)\n\t"
156                "addxw   %3,%0          |\n\t"
157                "moveq   #0,%3          | Add in last carry\n\t"
158                "addxw   %3,%0          |\n\t"
159                "andl    #0xffff,%0     | Mask to 16-bit sum\n" :
160                        "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1) :
161                        "0" (sum), "1" (w), "2" (tcnt) :
162                        "cc", "memory");
163                }
164                mlen &= 3;
165
166                /*
167                 * Soak up the last 1, 2 or 3 bytes
168                 */
169                while ((mlen -= 2) >= 0)
170                        sum += *w++;
171                if (byte_swapped) {
172                        REDUCE;
173                        sum <<= 8;
174                        byte_swapped = 0;
175                        if (mlen == -1) {
176                                s_util.c[1] = *(char *)w;
177                                sum += s_util.s;
178                                mlen = 0;
179                        } else
180                                mlen = -1;
181                } else if (mlen == -1)
182                        s_util.c[0] = *(char *)w;
183        }
184        if (len)
185                sum = 0xDEAD;
186        if (mlen == -1) {
187                /* The last mbuf has odd # of bytes. Follow the
188                   standard (the odd byte may be shifted left by 8 bits
189                   or not as determined by endian-ness of the machine) */
190                s_util.c[1] = 0;
191                sum += s_util.s;
192        }
193        REDUCE;
194        return (~sum & 0xffff);
195}
196
197
198#else
199/*
200 * Checksum routine for Internet Protocol family headers (Portable Version).
201 *
202 * This routine is very heavily used in the network
203 * code and should be modified for each CPU to be as fast as possible.
204 */
205
206
207int
208in_cksum(m, len)
209        register struct mbuf *m;
210        register int len;
211{
212        register u_short *w;
213        register int sum = 0;
214        register int mlen = 0;
215        int byte_swapped = 0;
216
217        union {
218                char    c[2];
219                u_short s;
220        } s_util;
221        union {
222                u_short s[2];
223                long    l;
224        } l_util;
225
226        for (;m && len; m = m->m_next) {
227                if (m->m_len == 0)
228                        continue;
229                w = mtod(m, u_short *);
230                if (mlen == -1) {
231                        /*
232                         * The first byte of this mbuf is the continuation
233                         * of a word spanning between this mbuf and the
234                         * last mbuf.
235                         *
236                         * s_util.c[0] is already saved when scanning previous
237                         * mbuf.
238                         */
239                        s_util.c[1] = *(char *)w;
240                        sum += s_util.s;
241                        w = (u_short *)((char *)w + 1);
242                        mlen = m->m_len - 1;
243                        len--;
244                } else
245                        mlen = m->m_len;
246                if (len < mlen)
247                        mlen = len;
248                len -= mlen;
249                /*
250                 * Force to even boundary.
251                 */
252                if ((1 & (int) w) && (mlen > 0)) {
253                        REDUCE;
254                        sum <<= 8;
255                        s_util.c[0] = *(u_char *)w;
256                        w = (u_short *)((char *)w + 1);
257                        mlen--;
258                        byte_swapped = 1;
259                }
260                /*
261                 * Unroll the loop to make overhead from
262                 * branches &c small.
263                 */
264                while ((mlen -= 32) >= 0) {
265                        sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
266                        sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
267                        sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
268                        sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
269                        w += 16;
270                }
271                mlen += 32;
272                while ((mlen -= 8) >= 0) {
273                        sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
274                        w += 4;
275                }
276                mlen += 8;
277                if (mlen == 0 && byte_swapped == 0)
278                        continue;
279                REDUCE;
280                while ((mlen -= 2) >= 0) {
281                        sum += *w++;
282                }
283                if (byte_swapped) {
284                        REDUCE;
285                        sum <<= 8;
286                        byte_swapped = 0;
287                        if (mlen == -1) {
288                                s_util.c[1] = *(char *)w;
289                                sum += s_util.s;
290                                mlen = 0;
291                        } else
292                                mlen = -1;
293                } else if (mlen == -1)
294                        s_util.c[0] = *(char *)w;
295        }
296        if (len)
297                printf("cksum: out of data\n");
298        if (mlen == -1) {
299                /* The last mbuf has odd # of bytes. Follow the
300                   standard (the odd byte may be shifted left by 8 bits
301                   or not as determined by endian-ness of the machine) */
302                s_util.c[1] = 0;
303                sum += s_util.s;
304        }
305        REDUCE;
306        return (~sum & 0xffff);
307}
308#endif
Note: See TracBrowser for help on using the repository browser.