; Micro-X -- an X server for DOS
; Copyright (C) 1994 StarNet Communications Corp.

; 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 (at your option) 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

; StarNet Communications Corp.
; 550 Lakeside Dr. #3
; Sunnyvale CA 94086 US
; http://www.starnet.com
; x-dos@starnet.com

	title INIT - Initialization routines

	.286p

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

_TEXT	SEGMENT  para PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT PARA PUBLIC 'DATA'
_DATA	ENDS
_BSS	SEGMENT PARA PUBLIC 'BSS'
_BSS	ENDS
STACK	SEGMENT WORD STACK 'STACK'
STACK	ENDS

DGROUP	GROUP	_DATA,_BSS,STACK

_DATA	SEGMENT
net_busy	db	0
	align	2
oldint08off	dw	0
oldint08seg	dw	0

oldint28off	dw	0
oldint28seg	dw	0

busyptr		dd	0
_DATA	ENDS
_BSS	SEGMENT
savesp	dw	?
savess	dw	?
_BSS	ENDS
STACK	SEGMENT
	PUBLIC	mystack
; Why is this '0' instead of '?'.  Because this is an overlay and the
; minload element from the .exe header is ignored for overlays.  Thus
; all memory we use has to be initialized to be included in the .exe
; file itself.
mystack	dw	200h dup (0)
estack	equ	$ - 2
STACK	ENDS

	ASSUME cs:_TEXT, ds:nothing, es:nothing, ss:nothing

_TEXT	SEGMENT
	EXTRN	_rpc_entry:NEAR, _netsleep:NEAR

	; real procedure entry point
	; called from MicroX with:
	; AX	= function
	; BX	= arg
	; CX	= size of buffer
	; DS:0 = transaction buffer
	; return AX = return value
	;	 BX = neterrno
	;	 CX = errno or bytes returned
	;
	; push this stuff on the stack and call the C routine.
	ASSUME	ds:nothing
p_rpc		PROC	FAR
	push	si
	push	es
	mov	si,ax		; save function
	mov	ax,ds
	mov	es,ax		; save buffer
	mov	ax,DGROUP
	mov	ds,ax
	ASSUME	ds:DGROUP

	; We must set the busy flag before we move to the new
	; stack because the interrupt routine will use the same
	; stack.
	mov	net_busy,1

	; setup my stack
	mov	savess,ss
	mov	savesp,sp

	mov	ss,ax
	ASSUME	ss:DGROUP
	lea	sp,DGROUP:estack

	push	es
	push	word ptr 0	; buffer
	push	cx		; len
	push	bx		; arg
	push	si		; func
	call	_rpc_entry
	add	sp,2		; don't pop ax
	pop	bx
	pop	cx		; data modified on stack by C routine
	add	sp,4		; buffer

	; restore our stack
	mov	ss,savess
	ASSUME	ss:nothing
	mov	sp,savesp

	; now we can let the interrupt routine in
	mov	net_busy,0

	pop	es
	pop	si
	iret
p_rpc		ENDP

	ASSUME	ds:DGROUP
	PUBLIC	_intr_init
_intr_init	PROC	NEAR
	mov	ah,34h		; get DOS busy flag
	int	21h
	mov	word ptr busyptr,bx
	mov	word ptr busyptr+2,es

	mov	ax,03508h
	int	21h
	mov	oldint08off,bx
	mov	oldint08seg,es
	mov	cx,ds		; save ds
	mov	ax,cs
	mov	ds,ax
	ASSUME	ds:_TEXT
	mov	dx,offset _TEXT:clock_int
	mov	ax,02508h
	int	21h

	mov	ds,cx		; restore ds
	ASSUME	ds:DGROUP

	mov	ax,03528h
	int	21h
	mov	oldint28off,bx
	mov	oldint28seg,es
	mov	ax,cs
	mov	ds,ax
	ASSUME	ds:_TEXT
	mov	dx,offset _TEXT:kbd_loop
	mov	ax,02528h
	int	21h

	mov	ds,cx		; restore ds
	ASSUME	ds:DGROUP
	ret
_intr_init	ENDP

	PUBLIC	_intr_exit
_intr_exit	PROC NEAR
	mov	cx,ds		; save ds
	lds	dx,dword ptr oldint08off
	ASSUME	ds:nothing
	or	dx,dx
	jz	shut_1
	mov	ax,02508h
	int	21h
shut_1:
	mov	ds,cx
	assume	ds:DGROUP
	lds	dx,dword ptr oldint28off
	ASSUME	ds:nothing
	or	dx,dx
	jz	shut_2
	mov	ax,02528h
	int	21h
shut_2:
	mov	ds,cx
	assume	ds:DGROUP
	ret
_intr_exit	ENDP

kbd_loop	PROC FAR
	ASSUME	ds:nothing
	push	ds
	push	ax
	mov	ax,DGROUP
	mov	ds,ax
	ASSUME	ds:DGROUP
	pushf
	call	dword ptr [oldint28off]
	jmp	short int_common

clock_int:
	push	ds
	push	ax
	mov	ax,DGROUP
	mov	ds,ax
	ASSUME	ds:DGROUP
	pushf
	call	dword ptr [oldint08off]

	push	si
	push	ds
	lds	si,busyptr
	ASSUME	ds:nothing
	mov	al,[si]
	pop	ds
	ASSUME	ds:DGROUP
	pop	si

	or	al,al
	jnz	int_exit

int_common:

	test	net_busy,0ffh
	jnz	int_exit

	mov	net_busy,1

	; switch stacks
	mov	savess,ss
	mov	savesp,sp

	mov	ax,ds
	mov	ss,ax
	ASSUME	ss:DGROUP
	lea	sp,DGROUP:estack

	sti

	push	es
	push	bx
	push	cx
	push	dx

	call	_netsleep

	pop	dx
	pop	cx
	pop	bx
	pop	es

	cli
	mov	ss,savess
	ASSUME	ss:nothing
	mov	sp,savesp

	mov	net_busy,0

int_exit:
	pop	ax
	pop	ds
	ASSUME	ds:nothing
	iret
kbd_loop	ENDP

_TEXT	ENDS
	END	p_rpc
