;	crithand.asm - Critical error handler
;
;************************************************************************/
;*	Copyright (C) 1986-1993 Phar Lap Software, Inc.			*/
;*	Unpublished - rights reserved under the Copyright Laws of the	*/
;*	United States.  Use, duplication, or disclosure by the 		*/
;*	Government is subject to restrictions as set forth in 		*/
;*	subparagraph (c)(1)(ii) of the Rights in Technical Data and 	*/
;*	Computer Software clause at 252.227-7013.			*/
;*	Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138	*/
;************************************************************************/

.twocase
include dosx.ah

_TEXT segment public byte use32 'CODE'
_TEXT ends

_DATA segment public dword 'DATA'
;
; valid segment registers
;
DSReg dw	?
ESReg dw	?
FSReg dw	?
GSReg dw	?

;
; addr of C routine to call
;
	align 4
	public	pProcessCritErr,_pProcessCritErr,pProcessCritErr_
_pProcessCritErr label dword
pProcessCritErr_ label dword
pProcessCritErr dd ?

;
; 8K stack for use by critical error handler
;
	align	4
	db	2000h dup (?)	
ProtTopOfStack label dword

_DATA ends

	assume	cs:_TEXT,ds:nothing
_TEXT segment
;
; void CritErrHand()
;
; Sets up a valid C stack, and calls a C routine to process the critical
; error.
;
	public	_CritErrHand,CritErrHand_,CritErrHand
CritErrHand label far
CritErrHand_ label far
_CritErrHand proc	far
;
; Stack frame
;
#EAX	equ	(dword ptr [ebp-4])	; Original EAX value

	sti				; enable interrupts
	push	ebp			; set up frame pointer
	mov	ebp,esp				;
	push	eax			; save all regs
	push	ebx				;
	push	ecx				;
	push	edx				;
	push	esi				;
	push	edi				;
	push	ds				;
	push	es				;
	push	fs				;
	push	gs				;

;
; Set seg regs to our protected mode values
; We'll use the fact that CS and DS are aliases when loading DS.
;
	mov	ds,cs:DSReg
	assume	ds:_DATA
	mov	es,ESReg
	mov	fs,FSReg
	mov	gs,GSReg

;
; Make sure Direction Flag is clear for C code
;
	cld

;
; Switch stacks, and call our C critical error handler.  We just use
; a hardcoded stack buffer here, which makes this handler non-reentrant.
; That's OK, because a critical error handler isn't allowed to call any
; DOS functions that could cause a second critical error.
;
; The C handler returns the desired action code in EAX
;
	mov	ecx,esp			; save current stack & interrupt stack
	mov	dx,ss				; frame
	mov	esi,ebp				;
	add	esi,4				;
	mov	ax,ds			; switch to new stack
	lea	ebx,ProtTopOfStack		;
	mov	ss,ax				;
	mov	esp,ebx				;
	push	edx			; save old stack pointer
	push	ecx				;
	push	edx			; call C critical error handler
	push	esi				;
	call	pProcessCritErr			;
	add	esp,8				;
	lss	esp,[esp]		; switch back to old stack
	mov	byte ptr #EAX,al	; return action code in AL

#exit:
;
; Restore regs and return
;
	pop	gs			; restore regs 
	pop	fs				;
	pop	es				;
	pop	ds				;
	pop	edi				;
	pop	esi				;
	pop	edx				;
	pop	ecx				;
	pop	ebx				;
	pop	eax				;
	mov	esp,ebp			; restore stack frame & exit
	pop	ebp				;
	iretd					;
_CritErrHand endp

;
; void GetSegRegs()
;
; Get segment registers, for use by critical error handler
;
	assume	cs:_TEXT,ds:_DATA
	public GetSegRegs,_GetSegRegs,GetSegRegs_
_GetSegRegs label near
GetSegRegs_ label near
GetSegRegs proc near
	mov	DSReg,ds
	mov	ESReg,es
	mov	FSReg,fs
	mov	GSReg,gs
	ret
GetSegRegs endp

_TEXT ends

end
