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