;----------------------------------------------------------------------------
;File name:	TCP_SUBS.S			Revision date:	1999.10.16
;Revised by:	Ulf Ronald Andersson		Revision start:	1999.01.14
;Created by:	Peter Rottengatter		Creation date:	1997.02.19
;----------------------------------------------------------------------------
;Project:	TCP high level protocol module for STinG
;Module:	Assembler functions
;----------------------------------------------------------------------------
	.export	illegal		;RA: AMON breakpoint function
	.export illegal_n	;RA: AMON D0 flagged breakpoint function
;-------------------------------------
	.export	_appl_yield	;Function for AES task switch
;-------------------------------------
	.export	req_flag	;Function for requesting semaphore
	.export	rel_flag	;Function for releasing semaphore
;-------------------------------------
	.export	get_pending	;Function for getting pending data
	.export	check_sum	;Function for checksumming data
;-------------------------------------
	.export	pe_poll_work	;protect_exec called by poll_receive
	.import	timer_work	;reached through poll_work in super mode
;-------------------------------------
	.export	sm_get_imask	;supermode subroutine to get interrupt mask
	.export	sm_set_imask	;supermode subroutine to set interrupt mask
	.export	sm_dis_imask	;supermode subroutine to disable interrupts
	.export	sm_pol_imask	;supermode subroutine to poll interrupts
;-------------------------------------
	.export	pe_get_imask	;protect_exec routine to get interrupt mask
	.export	pe_set_imask	;protect_exec routine to set interrupt mask
	.export	pe_dis_imask	;protect_exec routine to disable interrupts
	.export	pe_pol_imask	;protect_exec routine to poll interrupts
;----------------------------------------------------------------------------
;uint16	sm_get_imask(void);
;-------------------------------------
sm_get_imask:
	move	sr,d0		;d0 = current sr
	rts			;return
;----------------------------------------------------------------------------
;void	sm_set_imask(uint16 imask);
;-------------------------------------
sm_set_imask:
	move	d0,sr		;new sr = d0
	rts			;return
;----------------------------------------------------------------------------
;uint16	sm_dis_imask(void);
;-------------------------------------
sm_dis_imask:
	move	sr,d0		;d0 = old sr
	or	#$0700,sr	;disable interrupts in new sr
	rts			;return
;----------------------------------------------------------------------------
;void	sm_pol_imask(uint16 imask);
;-------------------------------------
sm_pol_imask:
	move	sr,d1		;save old sr in d1
	move	d0,sr		;poll interrupts with d0 as temp sr
	move	d1,sr		;restore old sr from d1
	rts			;return
;----------------------------------------------------------------------------
;uint16	pe_get_imask(void);
;-------------------------------------
pe_get_imask:
	move	8(sp),d0	;d0 = current_pre_protection_sr
	rts			;return, which reactivates precall SR
;----------------------------------------------------------------------------
;void	pe_set_imask(void *imask);
;-------------------------------------
pe_set_imask:
	move	6(sp),8(sp)	;new_post_protection_SR = (uint16) imask
	rts			;return which activates modified SR
;----------------------------------------------------------------------------
;uint16	pe_dis_imask(void);
;-------------------------------------
pe_dis_imask:
	move	8(sp),d0	;d0 = old_pre_protection_SR
	or	#$0700,8(sp)	;disable interrupts in new_post_protection_SR
	rts			;return, which activates modified SR
;----------------------------------------------------------------------------
;void	pe_pol_imask(void *imask);
;-------------------------------------
pe_pol_imask:
	move	6(sp),sr	;current_SR = (uint16) imask /* to poll */
	rts			;return, which restores precall SR
;----------------------------------------------------------------------------
;int32	cdecl	pe_poll_work(void *conn);
;-------------------------------------
pe_poll_work:	;int32	cdecl poll_doit (CONNEC *connec,uint16 old_status);
	move	8(sp),d0	;d0 = pre_protection sr
	or	#$2000,d0	;set super bit
	move	d0,sr		;int_mask = pre_protection int_mask
	move.l	4(sp),a0	;a0 = CONNEC *connec  for timer_work
	jmp	timer_work
;----------------------------------------------------------------------------
;void	illegal(void);			/* AMON breakpoint function	*/
;void	illegal_n(uint32 flag);		/* AMON d0-flagged breakpoint	*/
;-------------------------------------
illegal:
illegal_n:
	illegal
	rts
;-------------------------------------
;end of functions illegal_n & illegal
;----------------------------------------------------------------------------
_appl_yield:
	move.w  #$c9, d0	;Opcode for _appl_yield
	trap    #2		;Call GEM dispatcher
	rts
;----------------------------------------------------------------------------
req_flag:
	moveq	#1, d0		;Preset TRUE in case of lock
	tas	(a0)		;Test semaphore, and set bit 7
	bne.s	denied		;Was set ? Return TRUE
	or.b	#$ff, (a0)	;Now the lock is ours
	clr.l	d0		;And return FALSE
denied:	rts
;-------
rel_flag:
	clr.b   (a0)		;Clear semaphore
	rts
;----------------------------------------------------------------------------
get_pending:
	move.w  sr, -(sp)	;Save CPU status
	or.w    #$0700, sr	;Disable interupts
	move.l  (a0), -(sp)	;Get value
	clr.l   (a0)		;And reset it
	move.l  (sp)+, a0	;Return value
	move.w  (sp)+, sr	;Restore CPU status
	rts
;----------------------------------------------------------------------------
check_sum:
	and.b   #$ef, ccr	;Clear extended carry
	addx.l  d1, d0		;Add dest_ip to src_ip
	move.l  #$060000, d1	;Prepare TCP pseudo header word
	move.w  d2, d1		;Length for pseudo header word
	addx.l  d1, d0		;Add it to accumulator
	clr.l   d1		;For adding carries
	addx.l  d1, d0		;Add carry to the accumulator
;NB: another carry addition may be needed here
	move.b  d2, remain	;Save last two bits of length
	and.l   #$ffff, d2	;Extend to longword
	move.l  d2, d1		;Save length
	lsr.l   #6, d1		;Length by 64 is loop count
	and.l   #$3c, d2	;Find fraction of a chunk (loop)
	neg.l   d2		;Negate to offset beyond loop body
	and.b   #$ef, ccr	;Clear extended carry
	lea     lp_end, a1	;End of loop body
	jmp     (a1, d2)	;Jump into loop
;-------
loop:
	move.l  (a0)+, d2	;Fetch  1st longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  2nd longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  3rd longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  4th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  5th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  6th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  7th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  8th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch  9th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 10th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 11th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 12th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 13th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 14th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 15th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
	move.l  (a0)+, d2	;Fetch 16th longword (4 bytes)
	addx.l  d2, d0		;Add it to accumulator
lp_end:
	dbra    d1, loop	;Loop it
;
	move.l  d0, d1		;Save high word
	swap    d1		;Transfer it to low word
	addx.w  d1, d0		;Add both words
	btst    #1, remain	;Do we have 2 or 3 remaining bytes ?
	beq     no_word		;No ...
	move.w  (a0)+, d2	;Else fetch another word
	addx.w  d2, d0		;And add it to the accumulator
no_word:    btst    #0, remain	;Do we have another remaining byte ?
	beq     no_byte		;No ...
	move.w  (a0)+, d2	;Else fetch another word
	clr.b   d2		;But only use upper byte
	addx.w  d2, d0		;And add it to the accumulator
no_byte:    clr.w   d2		;For adding carries
	addx.w  d2, d0		;Add carry to the accumulator
	addx.w  d2, d0		;Again if another overflow
	and.l   #$ffff, d0	;And truncate to word length
	eor.w   #$ffff, d0	;Invert the result
	rts
;-------
remain:     ds.w    1		;Storage for last two length bits
;----------------------------------------------------------------------------
	.end
;----------------------------------------------------------------------------
;End of file:	TCP_SUBS.S
;----------------------------------------------------------------------------
