/*
 **************************************************************************
 *
 * Boot-ROM-Code to load an operating system across a TCP/IP network.
 *
 * Module:  utility.S86
 * Purpose: Various functions for the network library, which are
 *          better written in assembler
 * Entries: _ipchksum, _udpchksum
 *
 **************************************************************************
 *
 * Copyright (C) 1995-2007 Gero Kuhlmann <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: utility.S86,v 1.6 2007/01/06 18:30:47 gkminix Exp $
 *
 */


/*
 **************************************************************************
 *
 * Include assembler macros:
 *
 */
#include <common.i86>
#include <romconfig.i86>

.file __FILE__
.line __LINE__



/*
 **************************************************************************
 *
 * Start code segment.
 *
 */
	.text

	.global	_ipchksum
	.global	_udpchksum




/*
 **************************************************************************
 *
 * Compute IP header checksum.
 * Input:  1. arg  -  pointer to buffer (AX)
 *         2. arg  -  length of header
 * Output: checksum
 * Registers changed: AX, CX, DX
 */
_ipchksum:

	enter	0,0			# setup standard stack frame

#define bufsiz	_ARG(0)

	push	si
	mov	si,ax			# get buffer pointer
	mov	cx,[bp + bufsiz]		# get buffer size
	shr	cx,1

	cld
	clc
	xor	dx,dx			# add checksum in DX
1:	lodsw
	adc	dx,ax			# add checksum
	loop	1b
	adc	dx,0			# add carry
	not	dx
	mov	ax,dx			# prepare return value
	pop	si
	leave
	ret

#undef bufsiz



/*
 **************************************************************************
 *
 * Compute UDP header checksum.
 * Input:  1. arg  -  near pointer to pseudo header (AX)
 *         2. arg  -  length of pseudo header (has to be even)
 *         3. arg  -  near pointer to UDP header
 *         4. arg  -  length of UDP header (has to be even)
 *         5. arg  -  far pointer to data buffer
 *         6. arg  -  length of data buffer
 * Output: checksum
 * Registers changed: AX, CX, DX
 */
_udpchksum:

	enter	0,0			# setup standard stack frame

#define plen	_ARG(0)
#define ubuf	_ARG(1)
#define ulen	_ARG(2)
#define dbuf	_ARG(3)
#define dlen	_ARG(4)

	cld
	push	si
	mov	si,ax			# get pseudo header address
	mov	cx,[bp + plen]		# get pseudo header length
	shr	cx,1
	xor	dx,dx			# add checksum in DX
1:	lodsw
	adc	dx,ax			# add checksum
	loop	1b
	adc	dx,0			# add carry

	mov	si,[bp + ubuf]		# get UDP header address
	mov	cx,[bp + ulen]		# get UDP header length
	shr	cx,1
	clc
2:	lodsw
	adc	dx,ax			# add checksum
	loop	2b
	adc	dx,0			# add carry

	push	ds
	lds	si,[bp + dbuf]		# get data address
	mov	cx,[bp + dlen]		# get data length
	shr	cx,1
	clc
3:	lodsw
	adc	dx,ax			# add checksum
	loop	3b
	adc	dx,0			# add carry

	test	word ptr [bp + dlen],0x0001
	jz	4f			# check if odd number of bytes in data
	lodsb
	xor	ah,ah			# add last byte in
	add	dx,ax
	adc	dx,0			# add carry
4:	pop	ds

	not	dx
	mov	ax,dx			# prepare return value
	pop	si
	leave
	ret

#undef plen
#undef ubuf
#undef ulen
#undef dbuf
#undef dlen




/*
 **************************************************************************
 *
 */

	.end

