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: }
Defined functions
Defined macros
ADD
defined in line
75; used 22 times
FOLD
defined in line
76; used 5 times