1 /*	pup_cksum.c	4.1	83/05/30	*/
2 
3 #include "../h/types.h"
4 #include "../h/mbuf.h"
5 
6 /*
7  * Checksum routine for PUP-I Protocol family (VAX Version).
8  */
9 pup_cksum(m, len)
10 	register struct mbuf *m;
11 	register int len;
12 {
13 	register u_short *w;
14 	register int sum = 0;			/* known to be r8 */
15 	register int mlen = 0;
16 
17 	for (;;) {
18 		/*
19 		 * Each trip around loop adds in
20 		 * words from one mbuf segment.
21 		 */
22 		w = mtod(m, u_short *);
23 		if (mlen == -1) {
24 			/*
25 			 * There is a byte left from the last segment;
26 			 * add it into the checksum.
27 			 */
28 			sum += *(u_char *)w << 8;
29 			asm("rotl $1,r8,r8");
30 			w = (u_short *)((char *)w + 1);
31 			mlen = m->m_len - 1;
32 			len--;
33 		} else
34 			mlen = m->m_len;
35 		m = m->m_next;
36 		if (len < mlen)
37 			mlen = len;
38 		len -= mlen;
39 		while ((mlen -= 2) >= 0) {
40 			asm("addw2 (r9)+,r8; rotl $1,r8,r8;");
41 		}
42 		if (mlen == -1)
43 			sum += *(u_char *)w;
44 		if (len == 0)
45 			break;
46 		/*
47 		 * Locate the next block with some data.
48 		 * If there is a word split across a boundary we
49 		 * will wrap to the top with mlen == -1 and
50 		 * then add it in shifted appropriately.
51 		 */
52 		for (;;) {
53 			if (m == 0) {
54 				printf("pup_cksum: out of data\n");
55 				goto done;
56 			}
57 			if (m->m_len)
58 				break;
59 			m = m->m_next;
60 		}
61 	}
62 done:
63 	return (sum);
64 }
65