;*****************************************************
;*
;*	SUPERVISOR INTERFACE ROUTINES
;*
;*****************************************************

;=========
user_entry:
;=========
;	User Entry Point - enter here from a INT 224
;
;		REGISTER USAGE
;	ENTRY			EXIT
;	-----			----
;  CL - Function Code	  AX - Copy of BX
;  DX - Param     	  BX - Return
;  DS - Seg Addr  	  CX - Error Code	
;			  ES - Segment Return
;
;		DS,SI,DI,BP preserved through call
;
;		SETUP FOR MPM ENVIRONMENT
;		-------------------------
;	contents of users stack
;		Flags
;		CS
;		IP		<- u_stack_ss,_sp
;	DS =  Sysdat Segment
;	ES -> user_data_area (UDA)
;	DX -> function parameter
;	u_wrkseg == user's DS
;	u_retseg == user's ES
					;interrupts are off

					;set up MPM,CCPM environment
	cld ! mov ax,ds			;AX = user's DS
	mov ds,sysdat
	mov bx,rlr
	mov ds,p_uda[bx]		;DS = UDA segment
	mov ds:u_retseg,es		;save user's ES

					;U_INSYS is count of times
					;through this entry point
	cmp ds:u_insys,0 ! jne noswt	;change stacks to UDA stack
					;if U_INSYS = 0
					;otherwise leave stack alone

					;U_WRKSEG where is user's entry DS
					;is saved
	  mov ds:u_wrkseg,ax		;wipe out earlier u_wrkseg
	  mov ds:u_stack_ss,ss
	  mov ds:u_stack_sp,sp
	  mov ax,ds
	  mov ss,ax ! mov sp,ulen	;stack starts at end of UDA
	  jmps uecont
noswt:
	push ds:u_wrkseg		;save current u_wrkseg on UDA stack
	mov ds:u_wrkseg,ax

uecont:
	sti
	inc ds:u_insys
	mov ax,ds ! mov es,ax		;register moves are faster than
	mov ds,sysdat			;push and pop, DS=SYSDAT,ES=UDA 
	push si ! push di ! push bp

	mov u_func,cl			;record function number in UDA
	xor ch,ch			;call function and do
	call netchk			;netwrk chk, returns BX, ES, CX

coret:
	pop bp ! pop di ! pop si
	mov ax,es			;setup user's environment and return
	mov ds,ax			;DS = UDA segment
	mov es,ds:u_retseg		;restore ES from entry unless
					;function returns a segment value
	mov ax,ds:u_wrkseg		;AX = user's entry DS
	dec ds:u_insys ! jnz nstk	;switch back to user's stack
					;if U_INSYS = 0 
	  cli
	  mov ss,ds:u_stack_ss
	  mov sp,ds:u_stack_sp
	  jmps ueout
nstk:
	pop ds:u_wrkseg			;restore previous U_WRKSEG if not 
					;going back to user's stack
ueout:	mov ds,ax			;DS = user's entry DS
	mov ax,bx			;parameter return BX = AX
	inc ax
	jz u_err1			;CX=error code if AX,BX=0FFFFH
	  xor cx,cx			;CX always 0 if no error
u_err1:
	dec ax
	iret				;back to user ...
					;restore interrupts as they
 					;were on entry

sysfunc:	; call system function
;-------	-----------------------
;	entry:	if CH <> 0 then CH is module number
;		     (usually 1:SUP, 2:RTM, 3:MEM, 4:CIO, 5:BDOS)
;		     network check is bypassed
;		if CH = 0 then network check is done
;		CL = function #
;		DX = arg
;		BX = arg
;	exit:	BX = return value
;		ES = segment return value
;		CX = error code if BX = 0FFFFH

	test ch,ch ! jz netchk			;network or local
	    mov ax,cx ! jmps localfunc		;in local module


illfunc:				;illegal function number

	jmp i_ent

netchk:
;	enter here for network check
;	check for function numbers represented in function table,
;	ENTTAB_TABLE.  Table space is saved by making the functions
;	contiguous as we check the range.
;	The table has entries for functions 0-69, 98-112, 128-164.
;	Numbers 70-97, 112-127, 165-255 are not in the table.
;	Illegal functions in this table return the error codes
;	not implemented (1) or illegal function number (2).
;	Function not in the table return the illegal function number

;	code.
;	To add a new user function modify the files SYSDAT.DAT and
;	MODFUNC.DEF as well as the ranges immediately
;	below.  All of the modules SUP,RTM,MEM,CIO,BDOS,SYSDAT must
;	then be reassembled.

	cmp cl,69 ! jbe okfunc
	    sub cl,28 ! cmp cl,70 ! jb illfunc	;98-112 are now 70-84
	        cmp cl,84 ! jbe okfunc		;128-164 are now 100-136
		    sub cl,15			;128-164 are now 85-121
			cmp cl,121 ! ja illfunc

okfunc:						;CL is now 0 - num entries
						;- 1 in entry table
	mov si,cx ! shl si,1			;times 2 for entry table
	add si,offset sysent			;AH high nibble flags
	mov ax,enttab_entry[si]			;AH low nibble module
						;AL function number
						;within module
	test ah,ef_network ! jz localfunc	;not a network function
	    and ah,not ef_network		;turn off network bit
	    mov al,module_map
	    test al,netmod_bit ! je localfunc	;network module is not there
		push ax
		callf dword ptr .netmod		;call network CL = func
		cmp al,true			;if AL=0FFH do func locally
		pop ax				;in addition over network
		jne localfunc
		    mov ax,bx ! ret


localfunc:					;not over the network
	cmp ah,sup ! je insup			;AH=module, AL=function	
	    mov cl,ah
	    mov ch,module_map ! shr ch,cl	;does module exist ?
	    jnc badmod
		xor ch,ch ! dec cx		;make module 0 relative
		shl cx,1 ! shl cx,1 ! shl cx,1	;* 8
		mov si,cx ! mov cl,al		;func # in CL
		callf dword ptr module_table[si]
		ret
badmod:
	jmp n_imp
insup:
	xor ah,ah
	shl ax,1 ! mov si,ax 			; mov cx,ax
	jmp cs:supfunc[si]


;=====
entry:		; Supervisor module entry point
;=====		-------------------------------
;
;		Arrive here usually on a CALLF using address
;		at SYSDAT:4.  Note: flag set is handled specially.
;
;	entry:	if CH <> 0 then CH is module number
;		     (usually 1:SUP, 2:RTM, 3:MEM, 4:CIO, 5:BDOS)
;		     network check is bypassed
;		if CH = 0 then network check is done;		
;		CL = function #. If CH = 0 then CL is treated
;		     as a function number used with an INT 224:
;		     it is a USER function.
;		     If CH is not 0 then CL is the function number
;		     within the module specified by CH.
;		     The file MODFUNC.DEF contains the equates
;		     used for accessing functions from within the O.S.
;		     These functions are INTERNAL functions.
;		     Note the INTERNAL functions are a superset of
;		     the USER functions.  The equates for USER
;		     functions in MODFUNC.DEF have a 0 for the high byte
;		     forcing network checking from this entry point.
;		     An example: if f_conin (from MODFUNC.DEF) is
;		     equal to 0001H.  A Console output call to this
;		     entry point thus result in CH = 0, CL = 1.
;		DX = arg
;		BX = arg
;
;	exit:	BX = return value
;		ES = segment return value
;		CX = error code if BX = 0FFFFH



	cmp cx,f_flagset ! jne notfs	;flag set is exception:
	    mov cx,f_inflagset		;do not go over network,
	    call sysfunc		;make path shorter,
	    mov ax,bx			;parameter return BX = AX
	    inc ax			;AX=0FFFFH if error
	    jz u_err2			;CX= error code if AX,BX=0FFFFH
	      xor cx,cx			;CX=0 if no error
u_err2:
	    dec ax			;set AX back to 0 or 0FFFFH
	    retf			;DS must equal system
notfs:					;data segment

	mov u_unused,cx			;save 16 bit function number
	call osif ! retf

osif:					;point SUP uses to get
					;to other modules
	push u_wrkseg			;save current u_wrkseg
	mov ax,ds
	mov u_wrkseg,ax
	mov ax,sysdat
	mov ds,ax
	call sysfunc
	mov ax,u_wrkseg
	mov ds,ax
	pop u_wrkseg
	mov ax,bx			;BX,CX are return codes
	inc ax				;AX=0FFFFH if error
	jz u_err3			;CX= error code if AX,BX=0FFFFH
	  xor cx,cx			;CX=0 if no error
u_err3:
 	dec ax				;set AX back to 0 or 0FFFFH
	ret


;=========
user_retf:
;=========
;	If a user process does a RETF to terminate,
;	the process ends here.  The Load function sets up
;	the default stack to point here.

	mov bx,rlr
	and p_flag[bx],not pf_keep+pf_tempkeep+pf_ctlc+pf_sys
	mov cx,f_terminate
	xor dx,dx
	int osint		;make sure the terminate
				;succeed by reseting the
				;the keep,tempkeep,ctlc,sys flags

;======
xiosif:
;======
	callf dword ptr .xiosmod ! ret

;*****************************************************
;*
;*	Supervisor function table
;*
;*****************************************************

	org	((offset $)+1) AND 0fffeh	;Word Boundary

supfunc	dw	n_imp		; 0-not implemented
	dw	i_ent		; 1-illegal function number
	dw	bver_ent	; 2-(12)get BDOS version
	dw	cbios_ent	; 3-(50)call bios
	dw	load_ent	; 4-(59)user load function
	dw	cli_ent		; 5-(150)CLI
	dw	rpl_ent		; 6-(151)Call RPL
	dw	parse_ent	; 7-(152)parse filename
	dw	sdat_ent	; 8-(154)get sysdat addr
	dw	tod_ent		; 9-(155)get tod addr
	dw	load		; 10-load function
	dw	over_ent	; 11-O.S. version number
	dw	chain_ent	; 12-(47)Program Chain
	dw	ser_ent		; 13-(107)return serial
	dw	cload_ent	; 14-chain load function

