www.pudn.com > vXworksBSPfors3c44b0.rar > sbcCksum.c


/* sbcCksum.c - internet checksum routines */ 
 
/* Copyright 1984-1996 Wind River Systems, Inc. */ 
#include "copyright_wrs.h" 
/* 
 * Copyright (c) 1988, 1992, 1993 
 *	The Regents of the University of California.  All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the distribution. 
 * 3. All advertising materials mentioning features or use of this software 
 *    must display the following acknowledgment: 
 *	This product includes software developed by the University of 
 *	California, Berkeley and its contributors. 
 * 4. Neither the name of the University nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software 
 *    without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 * 
 *	@(#)in_cksum.c	8.1 (Berkeley) 6/10/93 
 */ 
 
/* 
modification history 
-------------------- 
01b,27sep01,m_h  printf compile warning 
01a,05jun01,m_h  created from in_cksum.c 01a 
*/ 
 
/* 
DESCRIPTION 
This module provides the checksum function in_cksum as a workaround to 
avoid a hardware bug on the KS32C50100.  The ARMARCH4 version of this function 
is implemented using LDR rx, [ry] where the value of ry is not on a word boundary. 
According to documentation, this should be legal but, on the Samsung CPU, 
it generates a data abort. 
*/ 
 
#include "vxWorks.h" 
#include "net/systm.h" 
#include "net/mbuf.h" 
#include "logLib.h" 
#include "stdio.h" 
 
/* 
 * Checksum routine for Internet Protocol family headers (Portable Version). 
 * 
 * This routine is very heavily used in the network 
 * code and should be modified for each CPU to be as fast as possible. 
 */ 
 
#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x) 
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} 
 
int 
in_cksum(m, len) 
	register struct mbuf *m; 
	register int len; 
{ 
	register u_short *w; 
	register int sum = 0; 
	register int mlen = 0; 
	int byte_swapped = 0; 
 
	union { 
		char	c[2]; 
		u_short	s; 
	} s_util; 
	union { 
		u_short s[2]; 
		long	l; 
	} l_util; 
 
	for (;m && len; m = m->m_next) { 
		if (m->m_len == 0) 
			continue; 
		w = mtod(m, u_short *); 
		if (mlen == -1) { 
			/* 
			 * The first byte of this mbuf is the continuation 
			 * of a word spanning between this mbuf and the 
			 * last mbuf. 
			 * 
			 * s_util.c[0] is already saved when scanning previous  
			 * mbuf. 
			 */ 
			s_util.c[1] = *(char *)w; 
			sum += s_util.s; 
			w = (u_short *)((char *)w + 1); 
			mlen = m->m_len - 1; 
			len--; 
		} else 
			mlen = m->m_len; 
		if (len < mlen) 
			mlen = len; 
		len -= mlen; 
		/* 
		 * Force to even boundary. 
		 */ 
		if ((1 & (int) w) && (mlen > 0)) { 
			REDUCE; 
			sum <<= 8; 
			s_util.c[0] = *(u_char *)w; 
			w = (u_short *)((char *)w + 1); 
			mlen--; 
			byte_swapped = 1; 
		} 
		/* 
		 * Unroll the loop to make overhead from 
		 * branches &c small. 
		 */ 
		while ((mlen -= 32) >= 0) { 
			sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 
			sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 
			sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 
			sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 
			w += 16; 
		} 
		mlen += 32; 
		while ((mlen -= 8) >= 0) { 
			sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 
			w += 4; 
		} 
		mlen += 8; 
		if (mlen == 0 && byte_swapped == 0) 
			continue; 
		REDUCE; 
		while ((mlen -= 2) >= 0) { 
			sum += *w++; 
		} 
		if (byte_swapped) { 
			REDUCE; 
			sum <<= 8; 
			byte_swapped = 0; 
			if (mlen == -1) { 
				s_util.c[1] = *(char *)w; 
				sum += s_util.s; 
				mlen = 0; 
			} else 
				mlen = -1; 
		} else if (mlen == -1) 
			s_util.c[0] = *(char *)w; 
	} 
	if (len) 
		printf("cksum: out of data\n"); 
	if (mlen == -1) { 
		/* The last mbuf has odd # of bytes. Follow the 
		   standard (the odd byte may be shifted left by 8 bits 
		   or not as determined by endian-ness of the machine) */ 
		s_util.c[1] = 0; 
		sum += s_util.s; 
	} 
	REDUCE; 
	return (~sum & 0xffff); 
}