|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985, 1986 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: * @(#)ns_cksum.c 7.5 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "mbuf.h" ! 25: ! 26: ! 27: /* ! 28: * Checksum routine for Network Systems Protocol Packets (VAX Version). ! 29: * ! 30: * This routine is very heavily used in the network ! 31: * code and should be modified for each CPU to be as fast as possible. ! 32: */ ! 33: ! 34: u_short ! 35: ns_cksum(m, len) ! 36: register struct mbuf *m; ! 37: register int len; ! 38: { ! 39: register u_short *w; /* on vax, known to be r9 */ ! 40: register int sum = 0; /* on vax, known to be r8 */ ! 41: register int low = 0; /* on vax, known to be r7 */ ! 42: register int mlen = low; /* want 0, shuts lint up about low */ ! 43: ! 44: for (;;) { ! 45: /* ! 46: * Each trip around loop adds in ! 47: * word from one mbuf segment. ! 48: */ ! 49: w = mtod(m, u_short *); ! 50: if (mlen == -1) { ! 51: /* ! 52: * There is a byte left from the last segment; ! 53: * add it into the checksum. Don't have to worry ! 54: * about a carry-out here because we make sure ! 55: * that high part of (32 bit) sum is small below. ! 56: */ ! 57: sum += *(u_char *)w << 8; ! 58: sum += sum; ! 59: w = (u_short *)((char *)w + 1); ! 60: mlen = m->m_len - 1; ! 61: len--; ! 62: } else ! 63: mlen = m->m_len; ! 64: m = m->m_next; ! 65: if (len < mlen) ! 66: mlen = len; ! 67: len -= mlen; ! 68: /* ! 69: * Force to long boundary so we do longword aligned ! 70: * memory operations. It is too hard to do byte ! 71: * adjustment, do only word adjustment. ! 72: */ ! 73: if (((int)w&0x2) && mlen >= 2) { ! 74: sum += *w++; ! 75: sum += sum; ! 76: mlen -= 2; ! 77: } ! 78: /* ! 79: * ! 80: * We can do a 16 bit ones complement sum using ! 81: * 32 bit arithmetic registers for adding, ! 82: * with carries from the low added ! 83: * into the high (by normal carry-chaining) ! 84: * so long as we fold back before 16 carries have occured. ! 85: * ! 86: */ ! 87: while ((mlen -= 32) >= 0) { ! 88: /*asm("bicpsw $1"); clears carry */ ! 89: #undef ADD ! 90: #define ADD asm("movw (r9)+,r7")asm("addl2 r7,r8")asm("addl2 r8,r8") ! 91: #define FOLD { asm("ashl $-16,r8,r0")asm(" addw2 r0,r8"); \ ! 92: asm("adwc $0,r8")asm(" movzwl r8,r8"); } ! 93: FOLD; ! 94: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; ! 95: FOLD; ! 96: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; ! 97: } ! 98: mlen += 32; ! 99: while ((mlen -= 8) >= 0) { ! 100: /*asm("bicpsw $1"); clears carry */ ! 101: FOLD; ! 102: ADD; ADD; ADD; ADD; ! 103: } ! 104: mlen += 8; ! 105: /* ! 106: * Now eliminate the possibility of carry-out's by ! 107: * folding back to a 16 bit number (adding high and ! 108: * low parts together.) Then mop up trailing words ! 109: * and maybe an odd byte. ! 110: */ ! 111: FOLD; ! 112: while ((mlen -= 2) >= 0) { ! 113: ADD; ! 114: } ! 115: if (mlen == -1) { ! 116: sum += *(u_char *)w; ! 117: } ! 118: if (len == 0) ! 119: break; ! 120: /* ! 121: * Locate the next block with some data. ! 122: * If there is a word split across a boundary we ! 123: * will wrap to the top with mlen == -1 and ! 124: * then add it in shifted appropriately. ! 125: */ ! 126: for (;;) { ! 127: if (m == 0) { ! 128: printf("idpcksum: out of data\n"); ! 129: goto done; ! 130: } ! 131: if (m->m_len) ! 132: break; ! 133: m = m->m_next; ! 134: } ! 135: } ! 136: done: ! 137: /* ! 138: * Add together high and low parts of sum ! 139: * and carry to get cksum. ! 140: * Have to be careful to not drop the last ! 141: * carry here. ! 142: */ ! 143: FOLD; ! 144: ! 145: if(sum==0xffff) sum = 0; ! 146: return (sum); ! 147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.