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