Commit | Line | Data |
---|---|---|
da7c5cc6 KM |
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) %G% | |
7 | */ | |
135f78ff | 8 | |
1884f3f6 JB |
9 | #include "types.h" |
10 | #include "mbuf.h" | |
135f78ff SL |
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 | } |