Annotation of sys/arch/powerpc/powerpc/in_cksum.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: in_cksum.c,v 1.7 2005/05/02 02:39:45 brad Exp $ */
2: /* $NetBSD: in_cksum.c,v 1.7 2003/07/15 02:54:48 lukem Exp $ */
3:
4: /*
5: * Copyright 2001 Wasabi Systems, Inc.
6: * All rights reserved.
7: *
8: * Written by Simon Burge and Eduardo Horvath for Wasabi Systems, Inc.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed for the NetBSD Project by
21: * Wasabi Systems, Inc.
22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23: * or promote products derived from this software without specific prior
24: * written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #if 0
40: #include <sys/cdefs.h>
41: __KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.7 2003/07/15 02:54:48 lukem Exp $");
42: #endif
43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/mbuf.h>
47: #include <sys/socketvar.h>
48: #include <netinet/in.h>
49: #include <netinet/in_systm.h>
50: #include <netinet/ip.h>
51: #include <netinet/ip_var.h>
52:
53: /*
54: * Checksum routine for Internet Protocol family headers.
55: *
56: * This routine is very heavily used in the network
57: * code and should be modified for each CPU to be as fast as possible.
58: *
59: * PowerPC version.
60: */
61:
62: #define REDUCE1 sum = (sum & 0xffff) + (sum >> 16)
63: /* Two REDUCE1s is faster than REDUCE1; if (sum > 65535) sum -= 65536; */
64: #define REDUCE { REDUCE1; REDUCE1; }
65:
66: static __inline__ int
67: in_cksum_internal(struct mbuf *m, int off, int len, u_int sum)
68: {
69: uint8_t *w;
70: int mlen = 0;
71: int byte_swapped = 0;
72: int n;
73:
74: union {
75: uint8_t c[2];
76: uint16_t s;
77: } s_util;
78:
79: for (;m && len; m = m->m_next) {
80: if (m->m_len == 0)
81: continue;
82: w = mtod(m, uint8_t *) + off;
83:
84: /*
85: * 'off' can only be non-zero on the first pass of this
86: * loop when mlen != -1, so we don't need to worry about
87: * 'off' in the if clause below.
88: */
89: if (mlen == -1) {
90: /*
91: * The first byte of this mbuf is the continuation
92: * of a word spanning between this mbuf and the
93: * last mbuf.
94: *
95: * s_util.c[0] is already saved when scanning previous
96: * mbuf.
97: */
98: s_util.c[1] = *w++;
99: sum += s_util.s;
100: mlen = m->m_len - 1;
101: len--;
102: } else {
103: mlen = m->m_len - off;
104: off = 0;
105: }
106: if (len < mlen)
107: mlen = len;
108: len -= mlen;
109:
110: /*
111: * Force to a word boundary.
112: */
113: if ((3 & (long) w) && (mlen > 0)) {
114: if ((1 & (long) w)) {
115: REDUCE;
116: sum <<= 8;
117: s_util.c[0] = *w++;
118: mlen--;
119: byte_swapped = 1;
120: }
121: if ((2 & (long) w) && (mlen > 1)) {
122: /*
123: * Since the `sum' may contain full 32 bit
124: * value, we can't simply add any value.
125: */
126: __asm __volatile(
127: "lhz 7,0(%1);" /* load current data
128: half word */
129: "addc %0,%0,7;" /* add to sum */
130: "addze %0,%0;" /* add carry bit */
131: : "+r"(sum)
132: : "b"(w)
133: : "7"); /* clobber r7 */
134: w += 2;
135: mlen -= 2;
136: }
137: }
138:
139: if (mlen >= 64) {
140: n = mlen >> 6;
141: __asm __volatile(
142: "addic 0,0,0;" /* clear carry */
143: "mtctr %1;" /* load loop count */
144: "1:"
145: "lwz 7,4(%2);" /* load current data
146: word */
147: "lwz 8,8(%2);"
148: "lwz 9,12(%2);"
149: "lwz 10,16(%2);"
150: "adde %0,%0,7;" /* add to sum */
151: "adde %0,%0,8;"
152: "adde %0,%0,9;"
153: "adde %0,%0,10;"
154: "lwz 7,20(%2);"
155: "lwz 8,24(%2);"
156: "lwz 9,28(%2);"
157: "lwz 10,32(%2);"
158: "adde %0,%0,7;"
159: "adde %0,%0,8;"
160: "adde %0,%0,9;"
161: "adde %0,%0,10;"
162: "lwz 7,36(%2);"
163: "lwz 8,40(%2);"
164: "lwz 9,44(%2);"
165: "lwz 10,48(%2);"
166: "adde %0,%0,7;"
167: "adde %0,%0,8;"
168: "adde %0,%0,9;"
169: "adde %0,%0,10;"
170: "lwz 7,52(%2);"
171: "lwz 8,56(%2);"
172: "lwz 9,60(%2);"
173: "lwzu 10,64(%2);"
174: "adde %0,%0,7;"
175: "adde %0,%0,8;"
176: "adde %0,%0,9;"
177: "adde %0,%0,10;"
178: "bdnz 1b;" /* loop */
179: "addze %0,%0;" /* add carry bit */
180: : "+r"(sum)
181: : "r"(n), "b"(w - 4)
182: : "7", "8", "9", "10"); /* clobber r7, r8, r9,
183: r10 */
184: w += n * 64;
185: mlen -= n * 64;
186: }
187:
188: if (mlen >= 8) {
189: n = mlen >> 3;
190: __asm __volatile(
191: "addic 0,0,0;" /* clear carry */
192: "mtctr %1;" /* load loop count */
193: "1:"
194: "lwz 7,4(%2);" /* load current data
195: word */
196: "lwzu 8,8(%2);"
197: "adde %0,%0,7;" /* add to sum */
198: "adde %0,%0,8;"
199: "bdnz 1b;" /* loop */
200: "addze %0,%0;" /* add carry bit */
201: : "+r"(sum)
202: : "r"(n), "b"(w - 4)
203: : "7", "8"); /* clobber r7, r8 */
204: w += n * 8;
205: mlen -= n * 8;
206: }
207:
208: if (mlen == 0 && byte_swapped == 0)
209: continue;
210: REDUCE;
211:
212: while ((mlen -= 2) >= 0) {
213: sum += *(uint16_t *)w;
214: w += 2;
215: }
216:
217: if (byte_swapped) {
218: REDUCE;
219: sum <<= 8;
220: byte_swapped = 0;
221: if (mlen == -1) {
222: s_util.c[1] = *w;
223: sum += s_util.s;
224: mlen = 0;
225: } else
226: mlen = -1;
227: } else if (mlen == -1)
228: s_util.c[0] = *w;
229: }
230: if (len)
231: printf("cksum: out of data\n");
232: if (mlen == -1) {
233: /* The last mbuf has odd # of bytes. Follow the
234: standard (the odd byte may be shifted left by 8 bits
235: or not as determined by endian-ness of the machine) */
236: s_util.c[1] = 0;
237: sum += s_util.s;
238: }
239: REDUCE;
240: return (~sum & 0xffff);
241: }
242:
243: int
244: in_cksum(struct mbuf *m, int len)
245: {
246:
247: return (in_cksum_internal(m, 0, len, 0));
248: }
249:
250: int
251: in4_cksum(struct mbuf *m, uint8_t nxt, int off, int len)
252: {
253: uint16_t *w;
254: u_int sum = 0;
255: union {
256: struct ipovly ipov;
257: u_int16_t w[10];
258: } u;
259:
260: if (nxt != 0) {
261: /* pseudo header */
262: memset(&u.ipov, 0, sizeof(u.ipov));
263: u.ipov.ih_len = htons(len);
264: u.ipov.ih_pr = nxt;
265: u.ipov.ih_src = mtod(m, struct ip *)->ip_src;
266: u.ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
267: w = u.w;
268: /* assumes sizeof(ipov) == 20 */
269: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
270: sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
271: }
272:
273: /* skip unnecessary part */
274: while (m && off > 0) {
275: if (m->m_len > off)
276: break;
277: off -= m->m_len;
278: m = m->m_next;
279: }
280:
281: return (in_cksum_internal(m, off, len, sum));
282: }
CVSweb