Annotation of sys/arch/powerpc/powerpc/in_cksum.c, Revision 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