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