1 /*
2 * include/asm-mips/checksum.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995 by Ralf Baechle
9 */
10 #ifndef __ASM_MIPS_CHECKSUM_H
11 #define __ASM_MIPS_CHECKSUM_H
12
13 /*
14 * computes the checksum of a memory block at buff, length len,
15 * and adds in "sum" (32-bit)
16 *
17 * returns a 32-bit number suitable for feeding into itself
18 * or csum_tcpudp_magic
19 *
20 * this function must be called with even lengths, except
21 * for the last fragment, which may be odd
22 *
23 * it's best to have buff aligned on a 32-bit boundary
24 */
25 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
26
27 /*
28 * the same as csum_partial, but copies from src while it
29 * checksums
30 *
31 * here even more important to align src and dst on a 32-bit (or even
32 * better 64-bit) boundary
33 */
34 unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
35
36 /*
37 * the same as csum_partial, but copies from user space (but on the alpha
38 * we have just one address space, so this is identical to the above)
39 */
40 #define csum_partial_copy_fromuser csum_partial_copy
41
42 /*
43 * This is a version of ip_compute_csum() optimized for IP headers,
44 * which always checksum on 4 octet boundaries.
45 *
46 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
47 * Arnt Gulbrandsen.
48 */
49 static inline unsigned short ip_fast_csum(unsigned char * iph,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
50 unsigned int ihl)
51 {
52 unsigned short int sum;
53 unsigned long dummy1, dummy2;
54
55 /*
56 * This is optimized for 32-bit MIPS processors.
57 * I tried it in plain C but the generated code looks to bad to
58 * use with old first generation MIPS CPUs.
59 * Using 64-bit code could even further improve these routines.
60 */
61 __asm__("
62 .set noreorder
63 .set noat
64 lw %0,(%3)
65 subu %1,4
66 blez %1,2f
67 sll %1,%4,2 # delay slot
68 lw %2,4(%3)
69 addu %1,%3 # delay slot
70 addu %0,%2
71 sltu $1,%0,%2
72 lw %2,8(%3)
73 addu %0,$1
74 addu %0,%2
75 sltu $1,%0,%2
76 lw %2,12(%3)
77 addu %0,$1
78 addu %0,%2
79 sltu $1,%0,%2
80 addu %0,$1
81 1: lw %2,16(%3)
82 addu %1,4
83 addu %0,%2
84 sltu $1,%0,%2
85 bne %1,%3,1b
86 addu %0,$1 # delay slot
87 srl $1,%0,16
88 addu %0,$1
89 sltu $1,%0,$1
90 addu %0,$1
91 nor %0,$0,%0
92 andi %0,0xffff
93 2: .set at
94 .set reorder"
95 : "=r" (sum), "=r" (dummy1), "=r" (dummy2)
96 : "r" (iph), "r"(ihl)
97 : "$1");
98
99 return sum;
100 }
101
102 /*
103 * computes the checksum of the TCP/UDP pseudo-header
104 * returns a 16-bit checksum, already complemented
105 */
106 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
107 unsigned long daddr,
108 unsigned short len,
109 unsigned short proto,
110 unsigned int sum)
111 {
112 __asm__("
113 .set noat
114 addu %0,%2
115 sltu $1,%0,%2
116 addu %0,$1
117 addu %0,%3
118 sltu $1,%0,%3
119 addu %0,$1
120 addu %0,%4
121 sltu $1,%0,%4
122 addu %0,$1
123 srl $1,%0,16
124 addu %0,$1
125 sltu $1,%0,$1
126 addu %0,$1
127 nor %0,$0,%0
128 andi %0,0xffff
129 .set at"
130 : "=r" (sum)
131 : "0" (daddr), "r"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
132 : "$1");
133
134 return (unsigned short)sum;
135 }
136
137 /*
138 * Fold a partial checksum without adding pseudo headers
139 */
140 static inline unsigned short int csum_fold(unsigned int sum)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
141 {
142 __asm__("
143 .set noat
144 srl $1,%0,16
145 addu %0,$1
146 sltu $1,%0,$1
147 nor %0,$0,%0
148 andi %0,0xffff
149 .set at"
150 : "=r"(sum)
151 : "0" (sum)
152 : "$1");
153
154 return sum;
155 }
156
157 /*
158 * this routine is used for miscellaneous IP-like checksums, mainly
159 * in icmp.c
160 */
161 static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
162 unsigned short int sum;
163
164 __asm__("
165 .set noat
166 srl $1,%0,16
167 addu %0,$1
168 sltu $1,%0,$1
169 nor %0,$0,%0
170 andi %0,0xffff
171 .set at"
172 : "=r"(sum)
173 : "r" (csum_partial(buff, len, 0))
174 : "$1");
175
176 return sum;
177 }
178
179 #endif /* __ASM_MIPS_CHECKSUM_H */