	TITLE	SUPPORT
	NAME	SUPPORT

	include	dos.mac

X	equ	4		; for near calls
;X	equ	6		; for far calls

LIBTCP_TEXT	SEGMENT
	PUBLIC  @n_clicks
; u_long _near _fastcall n_clicks(void)
;
;	get the number of timer clicks from BIOS
;
@n_clicks  proc	near
	mov	ah,0
	int	1ah
	mov	ax,dx		; MSC uses AX-lo, DX-hi
	mov	dx,cx		; return values from interrupt 1A
	ret
@n_clicks endp

	PUBLIC	@iphcheck, @ipcheck
; u_int near iphcheck(ptr)
; struct iph far *ptr;		; passed as a u_long because of MSC crock
;
; u_int near ipcheck(ptr, len)
; struct iph near *ptr;
; u_int len;
;
;	Internet header checksum
;	header checksum is calculated for a higher level program to verify
;

ipcheck	proc	near
@ipcheck:
	push	ds
	push	si
	ASSUME	ds: LIBTCP_DATA_GROUP
	mov	si,bx
	mov	cx,ax
	jmp short ipentry

@iphcheck:
	push	ds
        push	si
	ASSUME	ds:nothing
	mov	ds,dx
	mov	si,ax
	mov	cx,20		; 20 bytes in ipheader
ipentry:
	mov	dl,cl		; save low bit
	and	dl,1
	shr	cx,1		; len = len / 2
	sub	bx,bx		; also clears carry
chksum:
	lodsw			; get next word
	adc	bx,ax		; keep adding
	loop	chksum		; til' done

	mov	cl,dl
	jcxz	ipnotodd
	lodsb			; get that last byte
	mov	ah,ch		; clear the high portion
	adc	bx,ax		; add the last one in
				; don't modify CF until the adc instruction
ipnotodd:

	adc	bx,0		; adds the carry bit in
	cmp	bx,-1
	jz	L1
	not	bx		; take one more 1-complement
L1:
	mov	ax,bx
        pop	si
	pop	ds
	ASSUME	ds: nothing
	ret
ipcheck	endp

	PUBLIC	_tcpcheck
; u_int near tcpcheck(psptr, tcpptr, tcplen)
; struct pseudotcp far *psptr;
; struct tcph far *tcpptr;
; u_int tcplen;
;
;  TCP checksum
;
_tcpcheck	proc	near
	push	bp
	mov	bp,sp
	push	ds
        push	si
	ASSUME	ds:nothing

	lds	si,[bp+X+4]	; pointer
	mov	cx,[bp+X+8]	; count of bytes to test
	mov	dl,cl		; keep a copy of LSB
	and	dl,1		; keep LSB only
	shr	cx,1		; divide by two, round down

	sub	bx,bx           ; clear to begin
rchksum:
	lodsw
	adc	bx,ax		; add to running sum
	loop	rchksum
				; don't modify CF until the adc instruction
	mov	cl,dl
	jcxz	notodd
	lodsb			; get that last byte
	mov	ah,ch		; clear the high portion
	adc	bx,ax		; add the last one in
				; don't modify CF until the adc instruction
notodd:
	lds	si,[bp+X]	; pointer to data
	mov	cx,6		; length of p-hdr in words
pchksum:
	lodsw			; get next word
	adc	bx,ax		; keep adding
	loop	pchksum		; til' done
	adc	bx,0		; adds the carry bit in

	cmp	bx,-1
	jz	L2
	not	bx		; take one more 1-complement
L2:
	mov	ax,bx
        pop	si
	pop	ds
	pop	bp
	ret
_tcpcheck	endp

	PUBLIC	@htonl, @ntohl
; u_long near ntohl(x)
; u_long x;
;
; u_long near htonl(x)
; u_long x;
;
;	swap the bytes of a long integer from PC
;	order (reverse) to in-order.  This will work both ways.
;	returns the new long value
;
longswap	proc	near
@ntohl:
@htonl:
	xchg	ax,dx		; swap high and low ints
	xchg	dh,dl		; swap the bytes also
	xchg	ah,al		; swap the others
	ret
longswap	endp
LIBTCP_TEXT	ends
	end
