	title INIT - Initialization routines

	.286p

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

_DATA	SEGMENT PARA PUBLIC 'DATA'
n_buf	db	6 dup (0)
nums	db	'0123456789abcdef'
_DATA	ENDS
_BSS	SEGMENT PARA PUBLIC 'BSS'
savesp	dw	?
savess	dw	?
	EXTRN	_errno:WORD
_BSS	ENDS
STACK	SEGMENT PARA STACK 'STACK'
	ALIGN	16
	PUBLIC	mystack
mystack	db	200h dup (?)
estack	label	word
STACK	ENDS
_TEXT	SEGMENT  para PUBLIC 'CODE'
_TEXT	ENDS

DGROUP	GROUP	_DATA,_BSS,STACK

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

_TEXT	SEGMENT
	EXTRN	_rpc_entry:NEAR

init_rpc	PROC	FAR
	mov	dx,offset p_rpc
	mov	ax,cs
	mov	ds,ax
	ASSUME	ds:_TEXT
	ret
init_rpc	ENDP

	; real procedure entry point
	; called by kernel with:
	; CX	= # bytes in transaction buffer
	; AX	= max # of bytes to return
	; DS:DX = transaction buffer
	; return AX = # bytes returned
	;
	; push this stuff on the stack and call the C routine.
	ASSUME	ds:nothing
p_rpc		PROC	FAR
	mov	bx,ds	; rmember old ds
	mov	ax,DGROUP
	mov	ds,ax
	ASSUME	ds:DGROUP
	; setup my stack
	mov	savess,ss
	mov	savesp,sp

	mov	ss,ax
	lea	sp,estack

	push	cx
	push	bx	; was ds
	push	dx
	call	_rpc_entry
	pop	dx
	pop	bx	; old ds
	pop	cx

	; restore our stack
	mov	ss,savess
	mov	sp,savesp
	mov	ds,bx
	ASSUME	ds:nothing
	ret
p_rpc		ENDP

	ASSUME	ds:DGROUP

	PUBLIC	@dfputs
; void _fastcall dfputs(cp)
; char near *cp;
@dfputs	PROC NEAR
	push	si
	mov	si,bx
	mov	ah,2
put_loop:
	lodsb
	or	al,al
	jz	put_exit
	mov	dl,al
	int	21h
	jmp	short put_loop
put_exit:
	pop	si
	ret
@dfputs	ENDP

	PUBLIC	@printn
@printn PROC NEAR
	xor	bl,bl
	mov	n_buf+4,bl
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+3,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+2,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf+1,bl
	shr	ax,4
	mov	bx,ax
	and	bx,0fh
	mov	bl,nums[bx]
	mov	n_buf,bl
	mov	bx,offset n_buf
	jmp	short @dfputs
@printn	ENDP

	PUBLIC	@printd
@printd PROC NEAR
	mov	bx,offset n_buf+5
	xor	cl,cl
	mov	[bx],cl
	mov	cx,10		; divide by 10
pd_1:
	xor	dx,dx		; divide number by 10
	div	cx
	add	dx,'0'		; remainder is in dx
	dec	bx
	mov	[bx],dl
	or	ax,ax
	jnz	pd_1		; more to divide
	jmp	short @dfputs
@printd	ENDP

	public	__dosyscall
__dosyscall	PROC NEAR
	int	061h		; this instruction will be modified
	ret
__dosyscall	ENDP

	public	_patch_vec
_patch_vec PROC NEAR
	push	bp
	mov	bp,sp
	mov	ax,[bp+X]	; vector
	mov	byte ptr cs:__dosyscall+1,al
	pop	bp
	ret
_patch_vec ENDP

	public	@int86
@int86	PROC NEAR
	push	bp
	mov	bp,sp
	push	ax
	mov	al,[bp+X]	; vector
	mov	byte ptr cs:intnum+1,al
	pop	ax
	pop	bp
intnum:
	int	061h
	ret	2
@int86	ENDP

	PUBLIC	_open
_open	PROC NEAR
	push	bp
	mov	bp,sp
	mov	dx,[bp+X]
	mov	al,[bp+X+2]
	mov	ah,03dh
	int	21h
	jnc	open_ok
	mov	_errno,ax
	mov	ax,-1
open_ok:
	pop	bp
	ret
_open	ENDP

	PUBLIC	_ioctl
; int ioctl(fd, func, buffer, len)
; char *buffer;
_ioctl	PROC NEAR
	push	bp
	mov	bp,sp
	mov	ah,044h
	mov	bx,[bp+X]
	mov	al,[bp+X+2]
	mov	dx,[bp+X+4]
	mov	cx,[bp+X+6]
	int	21h
	jnc	ioctl_ok
	mov	_errno,ax
	mov	ax,-1
	pop	bp
	ret
ioctl_ok:
	; we have to do special handling for some functions
	mov	cl,[bp+X+2]	; func
	or	cl,cl
	jnz	ioctl_1		; if function 0
	mov	ax,dx		; device info
	jmp	short ioctl_out
ioctl_1:
	sub	cl,6		;
	jl	ioctl_out	; if function 1-5
	xor	ah,ah		; function 6 or 7 returns al only
				; function 8 returns only 1 or 0
ioctl_out:
	pop	bp
	ret
_ioctl	ENDP

	PUBLIC	_read
_read	PROC NEAR
	push	bp
	mov	bp,sp
	mov	ah,03fh
	mov	bx,[bp+X]
	mov	dx,[bp+X+2]
	mov	cx,[bp+X+4]
	int	21h
	jnc	read_ok
	mov	_errno,ax
	mov	ax,-1
read_ok:
	pop	bp
	ret
_read	ENDP

	PUBLIC	_write
_write	PROC NEAR
	push	bp
	mov	bp,sp
	mov	ah,040h
	mov	bx,[bp+X]
	mov	dx,[bp+X+2]
	mov	cx,[bp+X+4]
	int	21h
	jnc	write_ok
	mov	_errno,ax
	mov	ax,-1
write_ok:
	pop	bp
	ret
_write	ENDP

	PUBLIC	_close
_close	PROC NEAR
	push	bp
	mov	bp,sp
	mov	ah,03eh
	mov	bx,[bp+X]
	int	21h
	jnc	close_ok
	mov	_errno,ax
	mov	ax,-1
close_ok:
	pop	bp
	ret
_close	ENDP

	PUBLIC	@htonl, @ntohl
; u_long near _fastcall ntohl(x)
; u_long x;
;
; u_long near _fastcall 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

_TEXT	ENDS
	END	init_rpc
