;----------------------------------------------------------------------------
;File name:	SKELPORT.S			Revision date:	1997.08.18
;Creator:	Ulf Ronald Andersson		Creation date:	1997.08.18
;(c)1997 by:	Ulf Ronald Andersson		All rights reserved
;Feedback to:	dlanor@oden.se			Released as FREEWARE
;----------------------------------------------------------------------------
;Required header declarations:
;
	.include	"uran\STRUCT.SH"	;PASM adapted structures
	.include	"uran\URAn_SYS.SH"	;Main system definitions
	.include	"uran\URAn_LA.SH"	;Line A variables etc
	.include	"uran\URAn_DOS.SH"	;GEMDOS, BIOS, XBIOS
	.include	"uran\URAn_JAR.SH"	;Cookie jar handling
	.include	"uran\URAn_XB.SH"	;XBRA protocol
;
	.include	"sting\PORT.SH"		;only used by modules
	.include	"sting\LAYER.SH"	;only used by servers
	.include	"sting\TRANSPRT.SH"	;used by servers/clients
	.include	"sting\TCP.SH"
	.include	"sting\UDP.SH"
	.include	"sting\NET_TCON.SH"	;handles network time conv.
	.include	"sting\DOMAIN.SH"	;handles domain name/ip conv.
;
;----------------------------------------------------------------------------
;
USE_TIMER	equ	0	;1 enables 'my_timer_func', 0 disables it.
USE_LOOPING	equ	1	;1 enables multipacket sending, 0 disables it
;
M_YEAR	equ	1997
M_MONTH	equ	8
M_DAY	equ	18
;
.MACRO	M_TITLE
	dc.b	'SkelPort'
.ENDM	M_TITLE
;
.MACRO	M_VERSION
	dc.b	'01.00'
.ENDM	M_VERSION
;
.MACRO	M_AUTHOR
	dc.b	'Ronald Andersson'
.ENDM	M_AUTHOR
;
;----------------------------------------------------------------------------
;Start of:	STX program
;----------------------------------------------------------------------------
;
	.text
;
;----------------------------------------------------------------------------
text_start:
;----------------------------------------------------------------------------
;
start:
basepage_p:			;after init this becomes a resident pointer
	bra	start_1
;
;----------------------------------------------------------------------------
;Start of:	Resident STX data
;----------------------------------------------------------------------------
;
my_port:
	dc.l	port_name_s	;prt_des_name
	dc.w	L_PAR_PTP	;prt_des_type
	dc.w	0		;prt_des_active		Activation flag
	dc.l	0		;prt_des_flags
	dc.l	0		;prt_des_ip_addr	IP_number
	dc.l	-1		;prt_des_sub_mask
	dc.w	1500		;prt_des_mtu
	dc.w	1500		;prt_des_max_mtu
	dc.l	0		;prt_des_stat_sd_data
	dc.l	0		;prt_des_send		->Tx queue
	dc.l	0		;prt_des_stat_rcv_data
	dc.l	0		;prt_des_receive	->Rx queue
	dc.w	0		;prt_des_stat_dropped
	dc.l	my_driver	;prt_des_driver		->driver struct
	dc.l	0		;prt_des_next		->next port
;
;
my_driver:
	dc.l	my_set_state	;drv_des_set_state
	dc.l	my_send		;drv_des_send
	dc.l	my_receive	;drv_des_receive
	dc.l	driver_name_s	;drv_des_name
	dc.l	version_s	;drv_des_version
	dc.w	((M_YEAR-1980)<<9)|(M_MONTH<<5)|M_DAY
	dc.l	author_s	;drv_des_author
	dc.l	0		;drv_des_next		->next driver
;
port_name_s:
driver_name_s:
	M_TITLE
	dc.b	NUL
	even
;
version_s:
	M_VERSION
	dc.b	NUL
	even
;
author_s:
	M_AUTHOR
	dc.b	NUL
	even
;
sting_drivers:	ds.l	1	;DRV_LIST	*sting_drivers;
tpl:		ds.l	1	;TPL		*tpl;
stx:		ds.l	1	;STX		*stx;
;
.IF	USE_LOOPING
work_time:	ds.l	1
.ENDIF	USE_LOOPING
;
;----------------------------------------------------------------------------
;End of:	Resident STX data
;----------------------------------------------------------------------------
;Start of:	Port driver functions
;----------------------------------------------------------------------------
;void	my_timer_func(void);
;
.IF	USE_TIMER
my_timer_func:
;
;Add port dependent timer function code here
;This will be called regularly even when port is not active
;
	rts
.ENDIF	USE_TIMER
;
;end of my_timer_func
;----------------------------------------------------------------------------
;void	my_send(PORT *port);
;
my_send:
	link	a6,#0
	movem.l	d3-d5/a2-a5,-(sp)
	lea	my_port(pc),a5			;a5 -> my_port
	cmpa.l	8(a6),a5			;argument correct ?
	bne	.exit				;exit if argument incorrect
	move.l	prt_des_send(a5),d3		;d3 = Tx queue, empty ?
	ble.s	.exit				;exit if queue empty
.IF	USE_LOOPING
	TIMER_now				;find work start time
	move.l	d0,work_time			;store start time for future
.ENDIF	USE_LOOPING
.send_loop:
	move.l	d3,a4				;a4 -> Tx dgram of my_port
	move.l	IPDG_next(a4),prt_des_send(a5)	;unlink it from the chain
	clr.l	IPDG_next(a4)			;and cut link from it
;
;Add port dependent packet encoding/transmission code here
;
.IF	USE_LOOPING
	move.l	prt_des_send(a5),d3		;d3 = Tx queue, empty ?
	ble.s	.exit				;exit when queue empty
	TIMER_elapsed	work_time(pc)		;how long have we worked ?
	cmp.l	#50,d0				;50 ms or more ?
	blo.s	.send_loop			;loop back until 50 ms reached
.ENDIF	USE_LOOPING
.exit:
	movem.l	(sp)+,d3-d5/a2-a5
	unlk	a6
	rts
;
;end of my_send
;----------------------------------------------------------------------------
;void	my_receive(PORT *port);
;
;NB: This will not be used for reception if the interrupt code can do it all,
;    which is most efficient.  But it will still be called by the Kernel, so
;    the minimum implementation is a single rts as shown below.
;
my_receive:
	rts
;
;end of my_receive
;----------------------------------------------------------------------------
;uint16	my_set_state(PORT *port, uint16 state);
;
my_set_state:
	link	a6,#0
	movem.l	d3-d5/a2-a5,-(sp)
	lea	my_port(pc),a5			;a5 -> my_port
	clr.l	d0				;prep error flag
	cmpa.l	8(a6),a5			;argument correct ?
	bne	.exit				;exit if argument incorrect
	move	12(a6),d0			;d0 = new state
	beq.s	.passivate
.activate:
;
;Add port dependent activation code here
;This must include all initialization the port needs
;
	move	#1,prt_des_active(a5)
	bra.s	.done
;
.passivate:
;
;Add port dependent passivation code here
;This must include release of any KRmalloc blocks etc
;
	clr	prt_des_active(a5)
.done:
	moveq	#1,d0
.exit:
	movem.l	(sp)+,d3-d5/a2-a5
	unlk	a6
	rts
;
;end of my_set_state
;----------------------------------------------------------------------------
;End of:	Port driver functions
;----------------------------------------------------------------------------
;Start of:	Resident subroutines
;----------------------------------------------------------------------------
;
;Add subroutines for port handling here
;
;----------------------------------------------------------------------------
;End of:	Resident subroutines
;----------------------------------------------------------------------------
;	Resident library function code will be expanded here
;
	make	JAR_links
	make	TCON_links
	make	DOMAIN_links
;
;----------------------------------------------------------------------------
resident_end:	;all beyond this point will be released in going resident
resident_size	equ	resident_end-text_start+$100
;----------------------------------------------------------------------------
;Start of:	STX Non-resident initialization code with tests
;----------------------------------------------------------------------------
;
start_1:
	move.l		a0,d0
	sne		d7
	bne.s		.have_basepage
	move.l		4(sp),d0
.have_basepage:
	move.l		d0,a5
	lea		mystack(pc),sp
	move.l		a5,basepage_p
	tst.b		d7
	bne		.ACC_launch
	gemdos		Mshrink,#0,(a5),#initial_size
	lea		bp_arglen(a5),a0
	lea		STinG_Load_s(pc),a1
	str_comp	a0,a1
	bne		.bad_launch
;
	gemdos		Super,0.w
	move.l		d0,d4
	eval_cookie	#"STiK"
	move.l		d0,d3				;d3 = d0 -> DRV_LIST structure
	gemdos		Super|_ind,d4
;
	move.l		d3,sting_drivers		;sting_drivers -> DRV_LIST structure
	ble		.STiK_not_found
	move.l		d3,a3				;a3 -> DRV_LIST structure
	lea		DRV_LIST_magic(a3),a0
	lea		STiKmagic_s(pc),a1
	moveq		#10-1,d0
.strcmp_loop:					;loop to test STiKmagic of DRV_LIST
	cmpm.b		(a0)+,(a1)+
	dbne		d0,.strcmp_loop
	bne		.STiK_not_valid
;
	move.l		DRV_LIST_get_dftab(a3),a0	;a0 -> get_dftab function
	pea		TRANSPORT_DRIVER_s		;-(sp) = "TRANSPORT_TCPIP"
	jsr		(a0)				;call get_dftab
	addq		#4,sp
	move.l		d0,tpl				;store pointer in 'tpl'
	ble		.driver_not_valid
;
	move.l		DRV_LIST_get_dftab(a3),a0	;a0 -> get_dftab function
	pea		MODULE_DRIVER_s			;-(sp) = "MODULE_LAYER"
	jsr		(a0)				;call get_dftab
	addq		#4,sp
	move.l		d0,stx				;store pointer in 'tpl'
	ble		.layer_not_valid
.install:
	link		a6,#-8
	query_chains	-8(a6),-4(a6),0.w
	movem.l		-8(a6),a3/a4			;a3->ports  a4->drivers
	unlk		a6
;
	move.l		a3,d0
	beq		.bad_port_list
.port_loop:
	move.l		d0,a3
	move.l		prt_des_next(a3),d0
	bne.s		.port_loop
;
	move.l		a4,d0
	beq		.bad_driver_list
.driver_loop:
	move.l		d0,a4
	move.l		drv_des_next(a4),d0
	bne.s		.driver_loop
;
.IF	USE_TIMER
	TIMER_call	my_timer_func(pc),#HNDLR_SET
	tst		d0
	beq.s		.timer_failure
.ENDIF	USE_TIMER
;
.final_install:
	move.l		#my_port,prt_des_next(a3)
	move.l		#my_driver,drv_des_next(a4)
;
	gemdos		Ptermres,#resident_size,#0
;
;-------------------------------------
;
.ACC_launch:
	lea		ACC_launch_s(pc),a0
	bsr.s		report_error
.loop:
	bra.s		.loop
;
;-------------------------------------
;
.bad_launch:
	lea		bad_launch_s(pc),a0
	bra.s		.error_exit
;
;-------------------------------------
;
.bad_port_list:
	lea		bad_port_list_s(pc),a0
	bra.s		.error_exit
;
;-------------------------------------
;
.bad_driver_list:
	lea		bad_driver_list_s(pc),a0
	bra.s		.error_exit
;
;-------------------------------------
;
.IF	USE_TIMER
.timer_failure:
	lea		timer_failure_s(pc),a0
	bra.s		.error_exit
.ENDIF	USE_TIMER
;
;-------------------------------------
;
.STiK_not_found:
	lea		STiK_not_found_s,a0
	bra.s		.error_exit
;
;-------------------------------------
;
.STiK_not_valid:
	lea		STiK_not_valid_s,a0
	bra.s		.error_exit
;
;-------------------------------------
;
.driver_not_valid:
	lea		driver_not_valid_s,a0
	bra.s		.error_exit
;
;-------------------------------------
.layer_not_valid:
	lea		layer_not_valid_s(pc),a0
.error_exit:
	bsr.s		report_error
	gemdos		Pterm,#E_ERROR
;
;-------------------------------------
;
report_error:
	move.l		a0,-(sp)
	lea		error_title_s(pc),a0
	bsr.s		Cconws_sub
	move.l		(sp)+,a0
	bsr		Cconws_sub
	lea		error_tail_s(pc),a0
Cconws_sub:
	gemdos		Cconws,(a0)
	rts
;
;----------------------------------------------------------------------------
;End of:	STX Non-resident initialization code with tests
;----------------------------------------------------------------------------
;	Non-resident library function code will be expanded here
;
	make	JAR_links
	make	TCON_links
	make	DOMAIN_links
;
;----------------------------------------------------------------------------
;
text_limit:
text_size	= text_limit-text_start
	.data
data_start:
;
;----------------------------------------------------------------------------
;
STinG_Load_s:
	dc.b	10,'STinG_Load',NUL
STiKmagic_s:
	dc.b	'STiKmagic',NUL
TRANSPORT_DRIVER_s:
	dc.b	'TRANSPORT_TCPIP',NUL
MODULE_DRIVER_s:
	dc.b	'MODULE_LAYER',NUL
;
ACC_launch_s:
	dc.b	'This non-ACC, was launched as an ACC,',CR,LF
	dc.b	'so now you must reset the computer !',CR,LF
	dc.b	'I am looping forever to avoid damage',CR,LF
	dc.b	'that could occur if I try to exit !',CR,LF
	dc.b	NUL
;
bad_launch_s:	
	dc.b	'This STX should only be launched by',CR,LF
	dc.b	'STinG, or another TCP/IP stack with',CR,LF
	dc.b	'a compatible module interface !',CR,LF
	dc.b	NUL
;
bad_port_list_s:
	dc.b	'The list chain of STinG ports was',CR,LF
	dc.b	'not found...!',CR,LF
	dc.b	NUL
;
bad_driver_list_s:
	dc.b	'The list chain of STinG drivers was',CR,LF
	dc.b	'not found...!',CR,LF
	dc.b	NUL
;
.IF	USE_TIMER
timer_failure_s:
	dc.b	'STinG TIMER_call function failed !',CR,LF
	dc.b	NUL
.ENDIF	USE_TIMER
;
STiK_not_found_s:
	dc.b	'There is no STiK cookie in the jar !',CR,LF
	dc.b	NUL
;
STiK_not_valid_s:
	dc.b	'The STiK cookie data is corrupt !',CR,LF
	dc.b	NUL
;
driver_not_valid_s:
	dc.b	'The main STinG driver is not valid !',CR,LF
	dc.b	NUL
;
layer_not_valid_s:
	dc.b	'The STinG module layer is not valid !',CR,LF
	dc.b	NUL
;
error_title_s:
	dc.b	BEL,CR,LF
	dc.b	'------------'
	M_TITLE
	dc.b	' '
	M_VERSION
	dc.b	'------------',CR,LF
	dc.b	NUL
;
error_tail_s:
	dc.b	BEL,CR,LF,NUL
;
;----------------------------------------------------------------------------
data_limit:
data_size	equ	data_limit-data_start
	.bss
bss_start:
;----------------------------------------------------------------------------
;
		ds.l	200		;subroutine stack >= 100 longs
mystack:	ds.l	1		;top of subroutine stack
;
;----------------------------------------------------------------------------
bss_limit:
bss_size	equ	bss_limit-bss_start
;----------------------------------------------------------------------------
initial_size	equ	text_size+data_size+bss_size+$100
;----------------------------------------------------------------------------
		.end
;----------------------------------------------------------------------------
;End of file:	SKELPORT.S
;----------------------------------------------------------------------------
