115291Swollman/*-
215291Swollman * Copyright (c) 1990 The Regents of the University of California.
315291Swollman * All rights reserved.
415291Swollman *
515291Swollman * Redistribution and use in source and binary forms, with or without
615291Swollman * modification, are permitted provided that the following conditions
715291Swollman * are met:
815291Swollman * 1. Redistributions of source code must retain the above copyright
915291Swollman *    notice, this list of conditions and the following disclaimer.
1015291Swollman * 2. Redistributions in binary form must reproduce the above copyright
1115291Swollman *    notice, this list of conditions and the following disclaimer in the
1215291Swollman *    documentation and/or other materials provided with the distribution.
13286336Semaste * 3. Neither the name of the University nor the names of its contributors
1415291Swollman *    may be used to endorse or promote products derived from this software
1515291Swollman *    without specific prior written permission.
1615291Swollman *
1715291Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1815291Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1915291Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2015291Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2115291Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2215291Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2315291Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2415291Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2515291Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2615291Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2715291Swollman * SUCH DAMAGE.
2815291Swollman *
2915291Swollman *	from tahoe:	in_cksum.c	1.2	86/01/05
3015291Swollman *	from:		@(#)in_cksum.c	1.3 (Berkeley) 1/19/91
3115291Swollman *	from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp
3250477Speter * $FreeBSD$
3315291Swollman */
3415291Swollman
3515291Swollman#ifndef _MACHINE_IN_CKSUM_H_
3615291Swollman#define	_MACHINE_IN_CKSUM_H_	1
3715291Swollman
38143063Sjoerg#ifndef _SYS_CDEFS_H_
39143063Sjoerg#error this file needs sys/cdefs.h as a prerequisite
40143063Sjoerg#endif
41143063Sjoerg
4269133Salfred/*
4369133Salfred * MP safe (alfred)
4469133Salfred */
4569133Salfred
4615291Swollman#include <sys/cdefs.h>
4715291Swollman
4860104Sjlemon#define in_cksum(m, len)	in_cksum_skip(m, len, 0)
4960104Sjlemon
5015291Swollman/*
5115291Swollman * It it useful to have an Internet checksum routine which is inlineable
5215291Swollman * and optimized specifically for the task of computing IP header checksums
5315291Swollman * in the normal case (where there are no options and the header length is
5415291Swollman * therefore always exactly five 32-bit words.
5515291Swollman */
56143063Sjoerg#if defined(__GNUCLIKE_ASM) && !defined(__INTEL_COMPILER)
57235941Sbz#if defined(IPVERSION) && (IPVERSION == 4)
5815291Swollmanstatic __inline u_int
5915291Swollmanin_cksum_hdr(const struct ip *ip)
6015291Swollman{
61194111Sed	u_int sum = 0;
6215291Swollman
63194111Sed	__asm(
64134300Sobrien		"addl %1, %0\n"
65134300Sobrien		"adcl %2, %0\n"
66134300Sobrien		"adcl %3, %0\n"
67134300Sobrien		"adcl %4, %0\n"
68134300Sobrien		"adcl %5, %0\n"
69134300Sobrien		"adcl $0, %0"
70134300Sobrien		: "+r" (sum)
71134300Sobrien		: "g" (((const u_int32_t *)ip)[0]),
72134300Sobrien		  "g" (((const u_int32_t *)ip)[1]),
73134300Sobrien		  "g" (((const u_int32_t *)ip)[2]),
74134300Sobrien		  "g" (((const u_int32_t *)ip)[3]),
75134300Sobrien		  "g" (((const u_int32_t *)ip)[4])
76194111Sed		: "cc"
77134300Sobrien	);
7815291Swollman	sum = (sum & 0xffff) + (sum >> 16);
7915291Swollman	if (sum > 0xffff)
8015291Swollman		sum -= 0xffff;
8115291Swollman
8215291Swollman	return ~sum & 0xffff;
8315291Swollman}
8415884Swollman
8515884Swollmanstatic __inline void
8615884Swollmanin_cksum_update(struct ip *ip)
8715884Swollman{
8815884Swollman	int __tmpsum;
8915884Swollman	__tmpsum = (int)ntohs(ip->ip_sum) + 256;
9015884Swollman	ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16));
9115884Swollman}
92235941Sbz#endif
9315884Swollman
9458698Sjlemonstatic __inline u_short
9558698Sjlemonin_addword(u_short sum, u_short b)
9658698Sjlemon{
97194111Sed	__asm(
98172835Sbz		"addw %1, %0\n"
99172835Sbz		"adcw $0, %0"
100172835Sbz		: "+r" (sum)
101194111Sed		: "g" (b)
102194111Sed		: "cc"
103172835Sbz	);
10458698Sjlemon	return (sum);
10558698Sjlemon}
10658698Sjlemon
10758698Sjlemonstatic __inline u_short
10858698Sjlemonin_pseudo(u_int sum, u_int b, u_int c)
10958698Sjlemon{
110194111Sed	__asm(
111172835Sbz		"addl %1, %0\n"
112172835Sbz		"adcl %2, %0\n"
113172835Sbz		"adcl $0, %0"
114172835Sbz		: "+r" (sum)
115172835Sbz		: "g" (b),
116172835Sbz		  "g" (c)
117194111Sed		: "cc"
118172835Sbz	);
11958698Sjlemon	sum = (sum & 0xffff) + (sum >> 16);
12058698Sjlemon	if (sum > 0xffff)
12158698Sjlemon		sum -= 0xffff;
12258698Sjlemon	return (sum);
12358698Sjlemon}
12458698Sjlemon
12515291Swollman#else
126235941Sbz#if defined(IPVERSION) && (IPVERSION == 4)
12715884Swollman#define	in_cksum_update(ip) \
12815884Swollman	do { \
12915884Swollman		int __tmpsum; \
13015884Swollman		__tmpsum = (int)ntohs(ip->ip_sum) + 256; \
13115884Swollman		ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \
13215884Swollman	} while(0)
13315884Swollman
13415291Swollman#endif
135235941Sbz#endif
13615291Swollman
13755205Speter#ifdef _KERNEL
138143063Sjoerg#if !defined(__GNUCLIKE_ASM) || defined(__INTEL_COMPILER)
139235941Sbz#if defined(IPVERSION) && (IPVERSION == 4)
140126891Strhodesu_int in_cksum_hdr(const struct ip *ip);
141235941Sbz#endif
142126891Strhodesu_short in_addword(u_short sum, u_short b);
143126891Strhodesu_short in_pseudo(u_int sum, u_int b, u_int c);
144126891Strhodes#endif
145126891Strhodesu_short in_cksum_skip(struct mbuf *m, int len, int skip);
14655205Speter#endif /* _KERNEL */
14728270Swollman
14815291Swollman#endif /* _MACHINE_IN_CKSUM_H_ */
149