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