|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)in_cksum.c 7.5 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "mbuf.h" ! 25: ! 26: /* ! 27: * Checksum routine for Internet Protocol family headers (CCI Version). ! 28: * ! 29: * This routine is very heavily used in the network ! 30: * code and should be modified for each CPU to be as fast as possible. ! 31: */ ! 32: ! 33: #define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; } ! 34: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} ! 35: ! 36: #define ADD(n) asm("adwc n (r10),r9") ! 37: #define MOP asm("adwc $0,r9") ! 38: #define BOTCH asm("addl2 r7,r9") ! 39: ! 40: in_cksum(m, len) ! 41: register struct mbuf *m; ! 42: register int len; ! 43: { ! 44: register u_short *w; /* On CCI, known to be r10 */ ! 45: register int sum = 0; /* On CCI, known to be r9 */ ! 46: register int mlen = 0; ! 47: #ifndef lint ! 48: register int ClearCarry = 0; /* On CCI, known to be r7; see BOTCH */ ! 49: #endif ! 50: int byte_swapped = 0; ! 51: ! 52: union { ! 53: char c[2]; ! 54: u_short s; ! 55: } s_util; ! 56: union { ! 57: u_short s[2]; ! 58: long l; ! 59: } l_util; ! 60: ! 61: for (;m && len; m = m->m_next) { ! 62: if (m->m_len == 0) ! 63: continue; ! 64: w = mtod(m, u_short *); ! 65: if (mlen == -1) { ! 66: /* ! 67: * The first byte of this mbuf is the continuation ! 68: * of a word spanning between this mbuf and the ! 69: * last mbuf. ! 70: * ! 71: * s_util.c[0] is already saved when scanning previous ! 72: * mbuf. sum was REDUCEd when we found mlen == -1. ! 73: */ ! 74: s_util.c[1] = *(char *)w; ! 75: sum += s_util.s; ! 76: w = (u_short *)((char *)w + 1); ! 77: mlen = m->m_len - 1; ! 78: len--; ! 79: } else ! 80: mlen = m->m_len; ! 81: if (len < mlen) ! 82: mlen = len; ! 83: len -= mlen; ! 84: /* ! 85: * Force to long boundary so we do longword aligned ! 86: * memory operations. ! 87: */ ! 88: if (3 & (int) w) { ! 89: REDUCE; ! 90: if ((1 & (int) w) && (mlen > 0)) { ! 91: sum <<= 8; ! 92: s_util.c[0] = *(char *)w; ! 93: w = (u_short *)((char *)w + 1); ! 94: mlen--; ! 95: byte_swapped = 1; ! 96: } ! 97: if ((2 & (int) w) && (mlen >= 2)) { ! 98: sum += *w++; ! 99: mlen -= 2; ! 100: } ! 101: } ! 102: /* ! 103: * Do as much of the checksum as possible 32 bits at at time. ! 104: * In fact, this loop is unrolled to make overhead from ! 105: * branches &c small. ! 106: */ ! 107: while ((mlen -= 32) >= 0) { ! 108: /* ! 109: * The loop construct clears carry for us ! 110: * on vaxen, however, on the CCI machine subtracting ! 111: * a small postive number from a larger one doesn't. ! 112: * ! 113: * Doing a bicpsw is very slow (slows down the routine ! 114: * by a factor of 2); explicitly adding an immediate ! 115: * 0 to a register is optimized out; so we fake out ! 116: * the optimizer and add a register whose contents ! 117: * is always zero. ! 118: */ ! 119: BOTCH; ! 120: ADD(0); ADD(4); ADD(8); ADD(12); ! 121: ADD(16); ADD(20); ADD(24); ADD(28); ! 122: MOP; w += 16; ! 123: } ! 124: mlen += 32; ! 125: while ((mlen -= 8) >= 0) { ! 126: BOTCH; ! 127: ADD(0); ADD(4); ! 128: MOP; ! 129: w += 4; ! 130: } ! 131: mlen += 8; ! 132: if (mlen == 0 && byte_swapped == 0) ! 133: continue; /* worth 1% maybe ?? */ ! 134: REDUCE; ! 135: while ((mlen -= 2) >= 0) { ! 136: sum += *w++; ! 137: } ! 138: if (byte_swapped) { ! 139: sum <<= 8; ! 140: byte_swapped = 0; ! 141: if (mlen == -1) { ! 142: s_util.c[1] = *(char *)w; ! 143: sum += s_util.s; ! 144: mlen = 0; ! 145: } else ! 146: mlen = -1; ! 147: } else if (mlen == -1) ! 148: /* ! 149: * This mbuf has odd number of bytes. ! 150: * There could be a word split betwen ! 151: * this mbuf and the next mbuf. ! 152: * Save the last byte (to prepend to next mbuf). ! 153: */ ! 154: s_util.c[0] = *(char *)w; ! 155: } ! 156: if (len) ! 157: printf("cksum: out of data\n"); ! 158: if (mlen == -1) { ! 159: /* The last mbuf has odd # of bytes. Follow the ! 160: standard (the odd byte is shifted left by 8 bits) */ ! 161: s_util.c[1] = 0; ! 162: sum += s_util.s; ! 163: } ! 164: REDUCE; ! 165: return (~sum & 0xffff); ! 166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.