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