|
|
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.