;	[]===========================================================[]
;
;	NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R)
;	        INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE 	
;	        DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED	
;	        WRITTEN AUTHORIZATION FROM THE OWNER.
;
; 	[]===========================================================[]
;

;----------------------------------------------------------------------------
;Rev	Date	 Name	Description
;----------------------------------------------------------------------------
;R58	03/18/99 RIC	Add Int15_Func5F routine for Trident VGA BIOS of MVP4.
;R57	09/29/98 KVN	Release DMI and ESCD pool in flash ROM when not define
;			"ESCD_SUPPORT" and "FLASH_SUPPORT" in BIOS.CFG
;R56	09/03/98 DNL	Fixed Intel TESTVIEW utility report memory size error
;R55	07/17/98 RCH	Added OEM specific INT 15H functions support.
;R54	06/22/98 JKY	Added SMI811_VGA Support. 
;R53	03/10/98 RCH	Added SB-LINK BIOS interface for Creative PCI audio
;			support, please note that till now only Piix4 
;			platform support this feature.
;R52A	02/16/98 KVN	Fixed system hang in windows 95 command prompt mode
;			when run copy files from IDE to SCSI for large files
;R52	02/06/98 KVN	Fixed system reset in windows 95 command prompt mode
;			when run copy files to SCSI or any loop execution 
;			program thenelapse long times (over 10 hours maybe) 
;			that system will reset during executing
;R51	11/04/97 KGN	Add HPM Support for APM
;R50	10/13/97 JKY	Add S3 86C260 PCI VGA support
;R49	09/23/97 RAX	Add Cardbus ZV port support for systemsoft CardWizard.
;R48	09/09/97 RCH	Fixed EMM386 reporting "insufficient memory" on 5520
;			platform.
;R47	08/13/97 JSN	Only support 8042 control A20 for MICROSTAR. 
;R41A	08/07/97 DNL	Do not report ACPI memory except E820h function call
;R46	07/09/97 RCH	Fixed error stack return for function 8AH to 8FH
;R45	05/08/97 JKY	VGA S3CM65 Added int15.func5F Hook call
;R44A	05/07/97 JKY	Return success or not of all VGA Chip
;R44	04/03/97 RAX	Add "NeoMagic_2093AB" define for NeoMagic VGA should
;			return value to info BIOS success or not
;R43	04/01/97 KVN	Added func 0bfh for VSA VGA system
;R42	03/20/97 JKY	Added VGA BIOS hook for NeoMagic_2093AB
;R41	03/03/97 KVN	Added ACPI function support
;R40	11/23/96 DNL	Added codes to support more VGA BIOS hook 
;R39	10/11/96 RAX	Add Notebook Smart Battery support
;R38	09/17/96 RCH	Change memory size report method to get memory hole
;			size table for function E820H
;R35B	07/18/96 RAY	To solve the invalid descriptor problem of function
;			87h, a proper way which is stated by the AT spec. is
;			to fill the CMOS shutdown byte with 09h & let the 
;			CPU reset itself. The shutdown handler will take care
;			of the reset caused by this invalid descriptor!
;
;			Note: All R35 & R35A was cleared 
;
;R37	07/16/96 DNL	Added C&T LCD video BIOS hooks support
;R36	05/27/96 RCH	Move "EXC9HDLR" routine to file MISC.ASM to get more
;			space for F8000-FFFFF area
;R35A	04/30/96 RCH	Fixed error coding for R35
;R35	04/29/96 RCH	Fixed system hang or reset if invalid descriptor
;			input for function 87H, reported by NSTL, Following
;			instruction can duplicate the problem (must no
;			EMM386 installed).
;				mov	ah,87
;				mov	cx,100
;				mov	si,1000
;				int	15
;				int	3
;R34	04/09/96 KVN	Added P6 BIOS update feature
;R31A	03/06/96 RCH	Don't service VUMA handler too early , this will
;			impact performace of function 87H
;R33	01/20/96 RCH	Move the MP table to atbase.asm , because it can be 
;			located at any where in 0E0000-FFFFF. so don't occupy
;			run-time area
;R32	12/21/95 RCH	Added function E801H for supporting memory over 64Mb
;			for OS2.
;R31	11/15/95 TNY	Add VUMA support
;R30	11/01/95 RCH	"Process_Entry1" & "Process_Entry2" become publics
;			for P6 MP system
;R29A	10/23/95 RCH	The local APIC ID for first CPU is the biggest number
;			for P6 systems
;R29	08/28/95 RCH	Added CPU signature & features flag for P6 MP system
;R20F	08/21/95 DNL	Change display mode for Cirrus PCI VGA only
;R20E	08/17/95 RCH	Fixed error coding for R20
;R28	07/07/95 RCH	The INTEL/ORION chipset will hang at PCI/VGA initial
;			during warm boot or exit from setup.
;R21A	05/25/95 KVN	Move MP POST codes to ATBASE.ASM
;R26	05/24/95 KVN	Fixed shutdown system hang for [SCO UNIX V/386 release
;			3.2v4.2 OS] for MP
;R23A	04/13/95 RCH	Fixed memory bigger 64Mb support for WINDOWS NT
;R15A	03/02/95 KVN	Move power on post code to atorgs.asm
;R20D	01/13/95 DNL	Don't change display mode if VGA BIOS not found.
;R23	01/10/94 RCH	Open function E820H to support memory over 64Mb
;R20C	01/10/95 DNL	Fixed bug of system halt during warm boot under	WINDOWS V3.X
;R22	12/29/94 RCH	BIOS don't re-calculate checksum for MP table during
;			warm boot , so WINDOWS NT failed
;R20B	12/29/94 RCH	Fixed error coding for R20A
;R20A	12/23/94 RCH	Rewrite code for R20
;R21	12/19/94 RCH	Move MP codes from chipset.asm to here to be as
;			common codes
;R20	12/07/94 RCH	Set video display mode after warm boot, because
;			the CIRRUS PCI/VGA have no display while shutdown
;			under high resolution mode
;R19A	11/29/94 RCH	Fixed WINDOWS NT v3.5 for MP shutdown failure with
;			NCR/810
;R19	11/11/94 RCH	Fixed WINDOWS NT v3.5 for MP shutdown failure
;R18	10/21/94 RCH	Added function E820H to support memory beyond 64Mb
;			for WINDOWS NT v3.5
;R17	10/13/94 RCH	Enable interrupt before APM service , otherwise MTV
;			CD player failed
;R16A	09/22/94 RCH	System sometimes hang after warm boot or exit from
;			setup
;R16	09/22/94 RCH	System sometimes hang after warm boot or exit from
;			setup
;R15	09/10/94 RCH	Move power on post code from atbase.asm to here
;R14	07/25/94 RCH	Added INT 15 hook for special feature, for example:
;			function 4217H for KOREAN laguage PM support
;R12	08/02/94 RCH	Some customers do not want software speed control but
;			hardware need it
;R11	03/30/94 RAY	Move APM codes before STI instrution
;R10	10/06/93 RAY	APM_Service hook always exist!
;R09	09/20/93 RCH	Disable fast gate A20 if setup is disabled
;R08	05/13/93 RAY	Add APM support
;R07	06/23/92 BEN	NF: Added PM_KEYB_TRIGGER for Notebook power management
;			( Keyboard trigger )
;R06	05/26/92 RCH	Make MOUSE modbinable
;R05    05/11/92 RCH	Added CIRRUS/610/620 VGA LCD support
;R04	05/06/92 BEN	Added Hotkey_Ues_INT15 for hotkey function is called
;			in INT 15 sub function 4FH
;R03    02/24/92 RCH	Fixed XM.EXE installing failure bug, Because XM use
;			 shutdown No.9 to return to real mode
;R02    02/21/92 ALICE Added A20 service routine support for MS-DOS 5.0 
;			 HIMEM.SYS
;R01	12/17/91 RCH   Added turbo/normal speed change
;R00	05/17/91 JJ    Initial release for 4.2 - from old ver. 2.11

		PAGE	60,132
		TITLE	MULTISER.ASM   --   INT 15H HANDLER
.386P
;[]-----------------------------------[]
;
;   Award Software 386/486 BIOS
;   Multi-service (int 15h) rtns.
;   Initial Revision 17-Apr-1990
;
;[]-----------------------------------[]

.XLIST
		INCLUDE	BIOS.CFG
		INCLUDE COMMON.EQU

		INCLUDE	CMOS.EQU
		INCLUDE	8259.EQU
		INCLUDE	8254.EQU
		INCLUDE PORT61.EQU

comment %						;R15A
;R15 - start
		EXTRN	CPU_INIT:NEAR		
		EXTRN	CPU_CACHE:NEAR		
		extrn	Ct_Restore_Cyrix_Reg:Near
		extrn	Restore_Cyrix_Reg:near	
		extrn	Pup_Wait:near
		extrn	GetItem_Cmos:near
		extrn	A20_On:near 
		extrn	A20_On:near 
		extrn	Enable_Parity:near

ifdef	PM_SUPPORT
		extrn	Ct_Resume_Handle:near
		extrn	Ct_Sleep_Detect:near
		extrn	Ct_Check_SMI_Start:Near		
endif	;PM_SUPPORT

		INCLUDE 8042.EQU    
		INCLUDE MATHCOP.EQU 
;R15 - end
%							;R15A

		INCLUDE	ATORGS.EQU

		INCLUDE	AKBRD.EXT
		INCLUDE ATORGS.EXT
		INCLUDE ATBASE.EXT
		INCLUDE A20.EXT					    

		INCLUDE COMMON.MAC

		INCLUDE MOUSE.EXT
		extrn	ExtMem128Mb:near		;R32
		extrn	setspeed:near
		extrn	Do_F000_Shadow:Near
;R15A start
		extrn	ADDR_RNG_SIZE:ABS
		extrn	ADDR_RANGE_TBL:near
;R38		extrn	END_OF_RNG_TBL:near
;R15A end

ifdef VSA_VGA						;R43
		extrn	GX_INT15_Service:near		;R43
endif ;VSA_VGA						;R43
ifdef	VUMA						;R31
		extrn	VUMA_Service:near		;R31
endif	;VUMA						;R31

;R34 start
ifdef	P6_BIOS_ONLY
ifdef	FLASH_SUPPORT	;R57
		extrn	P6_BIOS_Update:near
endif	;FLASH_SUPPORT	;R57
endif	;P6_BIOS_ONLY
;R34 end

;R40 - start
	VGA_HOOK_CALL		=	0
ifdef		CHIP_655XX
	VGA_HOOK_CALL		=	5Fh
endif;		;CHIP_655XX
ifdef	TRIDENT_9385
	VGA_HOOK_CALL		=	5Fh
endif	;TRIDENT_9385
;R42 - start
ifdef	NeoMagic_2093AB
	VGA_HOOK_CALL		=	5Fh
endif	;NeoMagic_2093AB
;R42 - end
;R45 - START
ifdef	S3_86CM65
	VGA_HOOK_CALL		=	5Fh
endif	;S3_86CM65
;R45 - END
;R50 - start
ifdef	S3_86C260
	VGA_HOOK_CALL		=	5Fh
endif	;S3_86C260
;R50 - end
;R54 - start
ifdef	SMI811_VGA
	VGA_HOOK_CALL		=	7Fh
endif	;SMI811_VGA
;R54 - end
;R58 - start
ifdef	VT501
	VGA_HOOK_CALL		=	5Fh
endif;	VT501
;R58 - end
if	VGA_HOOK_CALL		NE	0
		extrn	Int15_Func5F:near
endif	;VGA_HOOK_CALL		NE	0
;R40 - end

.LIST
	
SPD_POL		EQU	01H			; bit 0 of SPD_DEF = 1 if low speed active high
SPD_SW_DISABLE	EQU	04H			; if set, then this is not a speed
						; switching machine.
PROTECTED	EQU	1


G_RAM		SEGMENT	USE16 AT 40H		
		INCLUDE	G_RAM.INC
G_RAM		ENDS

		extrn	POST_func_end:Near	;128k
		extrn	POST_VECT:Near		;128k

comment %						;R15A
;R15 - start
;[]---------------------------[]
;
;   Stack init
;
;[]---------------------------[]

BIOS_STK	SEGMENT	USE16 AT 0H
		ORG	400H
BIOSSTK_TOP	LABEL	WORD
		ORG	1000H				
POSTSTK_TOP	LABEL	WORD

BIOS_STK	ENDS
;R15 - end
%							;R15A

DGROUP		GROUP	FCODE
;R16 FCODE		SEGMENT	USE16 DWORD PUBLIC 'CODE'
FCODE		SEGMENT	USE16 PARA PUBLIC 'CODE'		;R16
		ASSUME	CS:FCODE,DS:FCODE,SS:FCODE,ES:FCODE

;[]========================================================================[]
;Name:   	Multi_service - Cassette_IO and 286 virtual mode extensions
;Entry:  	INT 15H
;Input:  	see individual functions
;Output: 	see individual functions
;Description:
;1. 	save environment
;2. 	perform function
;3. 	restore environment
;4. 	return to POI
;[]========================================================================[]
		PUBLIC	Multi_Service
		ALIGN	4
Multi_Service	PROC	far

		PUBLIC	Multi_Service_Near
Multi_Service_Near:

		sti				;R17
;R31A ;R31 - starts
;R31A ifdef	VUMA
;R31A 		cmp	ax,0F401h		;VUMA call?
;R31A 		jne	short VUMA_No		;no...
;R31A 		jmp	VUMA_Service
;R31A VUMA_No:
;R31A endif	;VUMA
;R31A ;R31 - ends

;R39 - start
ifdef SMBIOS_INTERFACE		
		cmp	ax,53b0h		;
		jne	@F			;
		extrn	SMB_Service:near	;
   		jmp	SMB_Service		;SMB bios service entry
@@:
endif; SMBIOS_INTERFACE
;R39 - end

ifndef	HPM_Support		;R51
;R11 - starts
		cmp	ah,53h			;APM call?
		jne	short ms_011		;no...
		extrn	APM_Service:near
		jmp	APM_Service
;R51 - Start
else	;HPM_Support
		CMP	AH,41H			; WAIT FOR EVENT (dos)
		JE	SHORT @F
		CMP	AH,54H			; SYSTEMSOFT APM
		JE	SHORT @F
		cmp	ah,53h			;APM call?
		jne	short ms_011		;no...
@@:						;hpm
		extrn	HPM_Service:near	;pmu.asm
		jmp	HPM_Service
endif	;HPM_Support
;R51 - End
ms_011:
;R11 - ends

;R17		sti

	;for performance purpose, the function 87h is tested at the earliest
	;possible
		cmp	ah,87h			;extended memory move
		jne	short ms_01
		jmp	Virtual_Move_Block	;function 87h
ms_01:

;R53 - start
ifdef SB_LINK_SUPPORT
		cmp	ah,0afh
		je	SB_LINK_FUNC
endif ;SB_LINK_SUPPORT
;R53 - end

;R55 - start
ifdef	OEM_INT15_SUPPORT		
		extrn	Oem_Int15_Handler:near	;invoke specific INT 15H.
		public	Oem_Int15_Exit
		jmp	Oem_Int15_Handler	;invoke specific INT 15H.
Oem_Int15_Exit:			      		;return from OEM INT 15H
endif;	OEM_INT15_SUPPORT		
;R55 - end

;R11 ;R08 start
;R11 ;R10 ifdef	ADVANCE_POWER_MANAGEMENT
;R11 
;R11 ;This APM function call should be checked as earlier as possible, since there
;R11 ;will be a lot of CPU idle calls
;R11 
;R11 		cmp	ah,53h			;APM call?
;R11 		jne	short ms_011		;no...
;R11 		extrn	APM_Service:near
;R11 		jmp	APM_Service
;R11 ms_011:
;R11 
;R11 ;R10 endif	;ADVANCE_POWER_MANAGEMENT
;R11 ;R08 end

;R06 ifdef	mouse					
		PUBLIC	INT15_NOT_MOUSE
		cmp	ah,0c1h 		
		jne	short not_func_c1		
		jmp	int15_ms		
not_func_c1:					
		cmp	ah,0c2h 		
		jne	short int15_not_mouse
		jmp	int15_ms		
int15_not_mouse:
;R06 endif	;mouse					

	;check valid function number and branch to the corresponding sub-
	;functions

ifdef	DOS_idle_detection
		cmp	ah,41h			;idle calls from DOS driver
		jne	short ms_01_0
		jmp	INT15_idle
ms_01_0:
endif	;DOS_idle_detection

;R31A - starts
ifdef	VUMA
		cmp	ax,0F401h		;VUMA call?
		jne	short VUMA_No		;no...
		jmp	VUMA_Service
VUMA_No:
endif	;VUMA
;R31A - end

;R43 start
ifdef VSA_VGA
		cmp	ah,0BFh
		jne	short Not_Cyrix_Ext
		jmp	GX_INT15_Service
Not_Cyrix_Ext:
endif ;VSA_VGA
;R43 end

;R01 - start
		cmp	ah,4fh
		je	Int15_Func4f
;R01 - end

;R14 - start
ifdef	INT15_4217_FUNC	
		cmp	ax,4217H
		jne	short Not_4217

		extrn	Ct_Set_Int15_4217:near
		call	Ct_Set_Int15_4217
		clc
		jmp	short Int15_Exit
		
Not_4217:
endif;	INT15_4217_FUNC	
;R14 - end

		cmp	ah,24h
		jne	short ms_01_1
		jmp	A20_Support
ms_01_1:

;R05 - start
ifdef		CIRRUS_610					
		cmp	ah,044h		;configuration byte	
		jne	short Not_Int15_Func44			
		jmp	Int15_Func44			
Not_Int15_Func44:
endif;		;CIRRUS_610					
;R05 - end

;R37 - start
;R40 ifdef		CHIP_655XX
;R40		extrn	Int15_Func5F:near
if	VGA_HOOK_CALL		NE	0	;R40
;R40		cmp	ah,05fh			;configuration byte	
		cmp	ah,VGA_HOOK_CALL	;R40
		jne	short Not_Int15_Func5f			
		Call	Int15_Func5F			
;R44A ifdef	NeoMagic_2093AB				;R44
		jmp	int15_exit		;R44
;R44A else	;NeoMagic_2093AB			;R44
;R44A		jmp	int15_Fail
;R44A endif	;NeoMagic_2093AB			;R44
Not_Int15_Func5F:
endif	;VGA_HOOK_CALL		NE	0	;R40
;R40 endif;		;CHIP_655XX
;R37 - end

;R49 start
ifdef	Cardbus_support
ifdef	Cardbus_ZV_Firmware_SUPPORT
		cmp	ah,99h
		jne	short NOT_ZV_CALL
		cmp	al,40h
		jne	short @F
		extrn	Chk_ZV_SUPPORT:near
		call	Chk_ZV_SUPPORT
		jmp	int15_iret
	@@:
		cmp	al,41h
		jne	short @F
		extrn	ZV_buffer_Ctrl:near
		call	ZV_buffer_Ctrl
		jmp	int15_iret
	@@:
NOT_ZV_CALL:
endif	;Cardbus_ZV_Firmware_SUPPORT
endif	;Cardbus_support
;R49 end

;R18 - start
QUERY_SYSTEM_ADDRESS_MAP	EQU	1	;R23
ifdef	QUERY_SYSTEM_ADDRESS_MAP
		cmp	eax,0E820H
		je	short Query_Address_Map
endif;	QUERY_SYSTEM_ADDRESS_MAP
;R18 - end

;R32 - start
		cmp	ax,0E801H		;function E801H ?
		je	Func_E801H		;yes
;R32 - end
;R34 start
ifdef	P6_BIOS_ONLY
ifdef	FLASH_SUPPORT	;R57
		cmp	ax,0d042h		;P6 BIOS update function
		jne	short Not_D042_func
		jmp	P6_BIOS_Update
Not_D042_func:
endif	;FLASH_SUPPORT	;R57
endif	;P6_BIOS_ONLY
;R34 end

		cmp	ah,80h			
;R46		jb	short int15_Invalid_Func
		jb	short int15_Fail			;R46

		cmp	ah,91h			;func 80h-91h
		ja	short ms_02

		push	bx			;save BX
		xor	bx,bx
		sub	ah,80h
		mov	bl,ah
		shl	bx,1
		jmp	word ptr cs:func_table_8_9[bx]
ms_02:
		cmp	ah,0c0h
;R46		jne	short int15_Invalid_Func
		jne	short int15_Fail			;R46
		jmp	Get_Sys_Config

	;Invlaid function - set ah = 86 and set carry

int15_Invalid_Func:
		pop	bx					;R46
int15_Fail:
		mov	ah,86h
       		stc

	; success - carry cleared

		ALIGN	4
int15_Exit:
		sti
		ret	2

		ALIGN	4
int15_iret:					; exit for functions 88h and 91h
		iret				; exit for "null" routines

Multi_Service	ENDP


	;entry table for function 80h-91h

		EVEN
func_table_8_9	dw	offset Device_Open	;function 80h
		dw	offset Device_Close	;function 81h
		dw	offset Process_Termination	;function 82h
		dw	offset Event_Wait	;function 83h
		dw	offset Joy_Stick_Read	;function 84h
		dw	offset Sysreq_Key	;function 85h
		dw	offset _Wait		;function 86h
		dw	offset Virtual_Move_Block	;function 87h
		dw	offset Extended_Memory_Size	;function 88h
		dw	offset Switch_to_Virtual_Mode	;function 89h
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Int15_Invalid_Func	;invalid function
		dw	offset Device_Busy	;function 90h
		dw	offset Interrupt_Complete	;function 91h

;R18 - start
ifdef	QUERY_SYSTEM_ADDRESS_MAP
;[]==============================================================[]
;Input :
;	eax   - function code 0E820H
;	ebx   - continuation code, zero for first call 
;	es:di -	buffer pointer , point to an buffer for BIOS to fill in.
;	ecx   - buffer size , minimum is 20 bytes
;	edx   - signature 'SMAP'
;Output:
;	CF    - non-carry indicates no error
;	eax   - signature return 'SMAP'
;	es:di - buffer pointer, same as input
;	ecx   - real buffer size return
;	ebx   - continuation code , zero return if last run occured
;[]==============================================================[]
;R23 E820_SIGNAURE	EQU	'PAMS'
E820_SIGNAURE	EQU	'SMAP'			;R23
Query_Address_Map	proc	near
;R23A		cmp	edx,'PAMS'	;check signature
		cmp	edx,E820_SIGNAURE	;check signature	;R23A
		jne	short int15_Fail;invalid function

		push	ds
		push	esi
		push	di

		mov	ax,bx	  			;get current run
		mov	cx,ADDR_RNG_SIZE
		mul	cl

		mov	si,offset Addr_Range_Tbl
		add	si,ax				;get current run addr.

		push	cs
		pop	ds
		cld
		rep	movsb				;move address range
							;descripton
		inc	ebx				;point to next run
;R38		cmp	si,offset End_Of_Rng_Tbl
		cmp	byte ptr [si],-1		;R38
		jne	short Not_End_Run
		xor	ebx,ebx				;mark last run
Not_End_Run:

		pop	di
		pop	esi
		pop	ds

		xor	ecx,ecx		;return buffer size to 20 bytes
		mov	cl,ADDR_RNG_SIZE
;R23A		mov	eax,'PAMS'	;return signature
		mov	eax,E820_SIGNAURE	;return signature	;R23A

		clc
		jmp	short Int15_Exit		
Query_Address_Map	endp
endif;	QUERY_SYSTEM_ADDRESS_MAP
;R18 - end

;R32 - start
Func_E801H	proc	near
;[]==============================================================[]
;Input :
;	ax    - function code 0E801H
;Output:
;	ax    - memory size in 1Kb for below 15Mb
;	bx    - memory size in 64Kb for above 15Mb
;	cx    - memory configured in 1Kb for below 15Mb
;	dx    - memory configured in 64Kb for above 15Mb
;[]==============================================================[]

		xor	bx,bx				;assume below 15Mb
		mov	dx,bx

		push	eax

		mov	eax,dword ptr cs:[ExtMem128Mb+8]
		shr	eax,10				;1kb unit

		cmp	eax,15*1024			;memory > 15M
		jbe	short E801_Exit			;no, just return

		push	edx

		mov	edx,15*1024			;maximum 15Mb
		sub	eax,edx
		xchg	eax,edx				;now ax=16Mb
		shr	edx,6				;64k unit
		mov	bx,dx				;bx= above 16Mb

		pop	edx
E801_Exit:		
		mov	cx,ax

		pop	eax 				;restore high word
		mov	ax,cx

		mov	dx,bx

		clc
		jmp	Int15_Exit		
Func_E801H	endp
;R32 - end

;R53 - start
ifdef SB_LINK_SUPPORT
		extrn	AGet_CfgSpace_word:near
		extrn	ASet_CfgSpace_word:near
		extrn	PciDmaChns:byte

SB_LINK_ID		EQU	0E8CH		;SB LINK Identifier
UNSPECIFIED_ERROR	EQU	080H		;unspecified error
INVALID_PARA		EQU	081H		;Invalid parameter
BUFF_TO_SMALL		EQU	082H		;buffer too small
FUNC_NOT_SUPPORT	EQU	086H		;function not support
SB_BUFF_SIZE		EQU	08H		;need 8-2 bytes buffer
;===== SB LINK command table =====
SB_LINK_CMD:
		dw	offset SB_LINK_FUN00	;Get information
		dw	offset SB_LINK_FUN01	;Save DMA Channel
		dw	offset SB_LINK_FUN02	;Set DMA Channel
		dw	offset SB_LINK_FUN03	;Restore DMA Channel
		dw	offset SB_LINK_FUN04	;Save Serialize IRQ Mode
		dw	offset SB_LINK_FUN05	;Set Serialize IRQ Mode
		dw	offset SB_LINK_FUN06	;Resotre Serialize IRQ Mode
		public	SB_LINK_CMD_MAX
SB_LINK_CMD_MAX	equ	($-offset SB_LINK_CMD)/2

;================================================================
;SB_LINK_FUNC
;
;	Call SB link correspond function
;================================================================
SB_LINK_FUNC:
		push	si			;store SI
		mov	ah, FUNC_NOT_SUPPORT	;assume invalid function
		cmp	al,SB_LINK_CMD_MAX	;check command overflow?
		jae	short SB_LINK_EXIT	;Yes,skip

		mov	ah, INVALID_PARA	;assume invalid parameter
		cmp	bx,SB_LINK_ID		;SB Link ID ?
		jne	short SB_LINK_EXIT

		movzx	si,al			;get function NO
		shl	si,1			;shift to word
		jmp	word ptr cs:[si]+offset SB_LINK_CMD	;jump to correspond function

SB_Link_Succeed:
		xor	ah,ah			;return no error
		clc
		jmp	short Sblink_Quit
SB_LINK_EXIT:
		stc
Sblink_Quit:

		pop	si			;restore SI
		retf	2			;return

;================================================================
;SB_LINK_FUN00	(Get Information)
;   Description :
;	This function allows the caller determine the current interface
;     version of SB-LINK, and which are the DMA channels available and be
;     configured as SB-LINK DMA channel to operate in PC/PCI mode.It also
;     retrun a signature of SB-LINK which the caller can use to confirm the
;     present of SB-LINK functions.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 0h (SBLINK_GET_INFO)
;	BX : 0E8CH
;   Exit:
;	AH : Return code
;	     00h = SB-LINK interface is present if DX set to 0E8Ch
;	AL : Serialize IRQ operating polarity
;	BL : Interface minor version in BCD value
;	BH : Interface major version in BCD value
;	CL : Pair of REQ/GNT that used as SB-LINK
;	CH : DMA channels available for SB-LINK
;	DX : 0E8Ch
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN00:
		mov	dx,bx		;return DX with value 0E8CH
		xor	al,al		;indicates serialize IRQ is
					;negative active polarity
		mov	bx,100h		;interface version
		mov	cl,REQ_GNT_PAIR	;Pair # of REQ/GNT is used in SB-LINK
					;1 = Pair A , 2 = Pair B , 3 = Pair C
;		mov	ch,0ebh		;DMA channels available for SB-LINK	cs:[DMA_]
		mov	ch,byte ptr cs:PciDmaChns
		jmp	SB_Link_Succeed

;================================================================
;SB_LINK_FUN01	(Save DMA Channel)
;   Description :
;	This function saves a DMA channel current information.This
;     information will be used to restore the PCI system controller
;     DMA channel settings prior to this call.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 1h (SBLINK_SAVE_DMA)
;	BX : 0E8CH
;	CL : DMA channel number to save
;	ES:DI : Segment:Offset of DataBuffer structure for real-mode
;	EDI : Offset of Data structure for 32-bit protected mode
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	     82h = Buffer too small
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN01:
		mov	ah, BUFF_TO_SMALL	;assume buffer too small
		cmp	word ptr es:[di],SB_BUFF_SIZE	;smaller than minimum size ?
		jae	short Buff_Enough

		mov	word ptr es:[di],SB_BUFF_SIZE	;set required buffer size
		jmp	short SB_LINK_EXIT	;buffer is too small
Buff_Enough:

		call	Ct_Save_DmaChannel

		jmp	SB_Link_Succeed

;================================================================
;SB_LINK_FUN02	(Set DMA Channel)
;   Description :
;	This function sets a DMA channel to perate in SB-LINK mode.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 2h (SBLINK_SET_DMA)
;	BX : 0E8CH
;	CL : DMA channel number to set
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN02:
		mov	ah, INVALID_PARA	;assume bad parameter
;		cmp	cl,2			;DMA 2 ?
;		je	short SB_LINK_EXIT
;		cmp	cl,4			;DMA 4 ?
;		je	short SB_LINK_EXIT
		cmp	cl,8			;valid DMA channel ?
		jae	short SB_LINK_EXIT

		push	ax
		mov	al,1 			;shift DMA channel into bit
		shl	al,cl			;map ( bit0 = DMA 0, ..etc)
		test	al,cs:PciDmaChns 	;DMA available ?
		pop	ax
		jz	short SB_LINK_EXIT	;no, return error

;		extrn	Ct_Set_PCI_Dma:near
		call	Ct_Set_PCI_Dma		;set PC/PCI DMA channel
		jmp	short SB_Link_Succeed


;================================================================
;SB_LINK_FUN03	(Restore DMA Channel)
;   Description :
;	This function restores the settings that has been changed by
;     the call of SBLINK_DMA.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 3h (SBLINK_RESTORE_DMA)
;	BX : 0E8CH
;	CL : DMA channel number to restore
;	ES:DI : Segment:Offset of DataBuffer structure for real-mode
;	EDI : Offset of Data structure for 32-bit protected mode
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	     82h = Buffer too small
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN03:
		call	Ct_Restore_DmaChannel

		jmp	short SB_Link_Succeed

;================================================================
;SB_LINK_FUN04	(Save Serialize IRQ Mode)
;   Description :
;	This function saves the current serialize IRQ operational mode.This
;     information will be used to restore the PCI system controller's
;     serialize IRQ settings prior to this call.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 4h (SBLINK_SAVE_SIRQ)
;	BX : 0E8CH
;	ES:DI : Segment:Offset of DataBuffer structure for real-mode
;	EDI : Offset of Data structure for 32-bit protected mode
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	     82h = Buffer too small
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN04:

		mov	ah, BUFF_TO_SMALL	;assume buffer too small
		cmp	word ptr es:[di],SB_BUFF_SIZE	;smaller than minimum size ?
		jae	short SirqBuff_Enough

		mov	word ptr es:[di],SB_BUFF_SIZE	;set required buffer size
		jmp	short SB_LINK_EXIT	;buffer is too small
SirqBuff_Enough:

		call	Ct_Save_SerIRQ
		jmp	SB_Link_Succeed

;================================================================
;SB_LINK_FUN05	(Set Serialize IRQ Mode)
;   Description :
;	This function enables and sets the serialize IRQ operational mode
;     to the SB-LINK mode.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 5h (SBLINK_SET_SIRQ)
;	BX : 0E8CH
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN05:
;		extrn	Ct_Set_SerialIRQ:near
		call	Ct_Set_SerialIRQ 	;enable serial IRQ mode
		jmp	SB_Link_Succeed

;================================================================
;SB_LINK_FUN06	(Restore Serialize IRQ Mode)
;   Description :
;	This function restores the settings that has been changed by
;     the call of SBLINK_SET_SIRQ.
;   Entry:
;	AH : 0AFH (SBLINK_FUNCTION_ID)
;	AL : 6h (SBLINK_RESTORE_SIRQ)
;	BX : 0E8CH
;	ES:DI : Segment:Offset of DataBuffer structure for real-mode
;	EDI : Offset of Data structure for 32-bit protected mode
;   Exit:
;	AH : Return code
;	     00h = success
;	     81h = Invalid parameter
;	     82h = Buffer too small
;	CF : set = error,cleared = success
;================================================================
SB_LINK_FUN06:
		call	Ct_Restore_SerIRQ
		jmp	SB_Link_Succeed

		extrn	ASet_CfgSpace_Byte:near


ifdef	PIIX_ID				;only for Intel PIIX4 platform

;Function : Save registers of PCI/DMA channel information
;Inptut   : ES:DI - buffer for saving
;Output   : none
Ct_Save_DmaChannel	proc	near
		pushad
		mov	cx,(PIIX_ID SHL 8) + 90H;PCI DMA config. reg.
		xor	bh,bh			;bus 0
		call	AGet_CfgSpace_word	;read PCI word
		mov	word ptr es:[di+2],ax	;save DMA registers
		popad
		ret
Ct_Save_DmaChannel	endp

;Function : Restore registers of PCI/DMA channel information
;Inptut   : ES:DI - buffer for restoring
;Output   : none
Ct_Restore_DmaChannel	proc	near

		pushad
		mov	ax,word ptr es:[di+2]	;restore DMA registers
		mov	cx,(PIIX_ID SHL 8) + 90H;PCI DMA config. reg.
		xor	bh,bh			;bus 0
		call	ASet_CfgSpace_word	;read PCI word
		popad

		ret
Ct_Restore_DmaChannel	endp


;Function : Program chipset to desired DMA channel for PC/PCI DMA mode
;Input    : CL - DMA channel number to set
;Output   : none
;Note     : The program need to enable REQ/GNT pair in this procedure
		public	Ct_Set_PCI_Dma
Ct_Set_PCI_Dma	proc	near

		pushad

	;Set PC/PCI DMA channel
		mov	bl,cl		       	;save DMA channel
		mov	cx,(PIIX_ID SHL 8) + 90H;PCI DMA config. reg.
		xor	bh,bh			;bus 0
		call	Aget_CfgSpace_word	;read PCI word

		mov	dx,01b			;set PC/PCI DMA mode
		mov	cl,bl			;DMA channel number
		shl	cl,1			;each DMA need 2 bits
		shl	dx,cl
		or	ax,dx
		mov	cx,(PIIX_ID SHL 8) + 90H;PCI DMA config. reg.
		call	ASet_CfgSpace_word	;write PCI word

	;program REQ/GNT pair
		mov	cx,(PIIX_ID SHL 8) +0B1H;REQ/GNT pin select
		call	AGet_CfgSpace_Byte	;read set PCI byte
		mov	dl,01h   		;register 0B1H
		mov	cl,REQ_GNT_PAIR-1	;get REQ/GNT pair
		shl	dl,cl
		or	al,dl
		mov	cx,(PIIX_ID SHL 8) +0B1H;REQ/GNT pin select
		call	ASet_CfgSpace_Byte	;read set PCI byte

		popad
		ret
Ct_Set_PCI_Dma	endp

;Function : Program chipset to serial IRQ mode for SB-LINK operation
;Input    : none
;Output   : none
		public	Ct_Set_SerialIRQ
Ct_Set_SerialIRQ	proc	near

		pushad

		xor	bh,bh			;bus 0
		mov	cx,(PIIX_ID SHL 8) +064H;serial IRQ control register
		mov	al,0d0h			;enable serial IRQ mode
		call	ASet_CfgSpace_Byte	;read set PCI byte

		mov	cx,(PIIX_ID SHL 8) +0B2H;
		call	AGet_CfgSpace_Byte	;read set PCI byte
		or	al,01h			;enable SERIRQ# pin
		mov	cx,(PIIX_ID SHL 8) +0B2H;
		call	ASet_CfgSpace_Byte	;read set PCI byte

		popad
		ret
Ct_Set_SerialIRQ	endp

;Function : Save registers of Serial IRQ information
;Inptut   : ES:DI - buffer for saving
;Output   : none
Ct_Save_SerIRQ	proc	near
		pushad
		mov	cx,(PIIX_ID SHL 8) + 64H;PCI Serial IRQ config. reg.
		xor	bh,bh			;bus 0
		extrn	AGet_CfgSpace_byte:near
		call	AGet_CfgSpace_byte	;read PCI word
		mov	byte ptr es:[di+2],al	;save SIRQ registers

		mov	cx,(PIIX_ID SHL 8) +0B2H;
		call	AGet_CfgSpace_Byte	;read set PCI byte
		mov	byte ptr es:[di+3],al	;save SIRQ registers

		popad
		ret
Ct_Save_SerIRQ	endp

;Function : Restore registers of Serial IRQ information
;Inptut   : ES:DI - buffer for saving
;Output   : none
Ct_Restore_SerIRQ	proc	near
		pushad
		mov	al,byte ptr es:[di+2]	;save SIRQ registers
		mov	cx,(PIIX_ID SHL 8) + 64H;PCI Serial IRQ config. reg.
		xor	bh,bh			;bus 0
		call	ASet_CfgSpace_Byte	;read set PCI byte

		mov	cx,(PIIX_ID SHL 8) +0B2H;
		mov	al,byte ptr es:[di+3]	;restore SIRQ registers
		call	ASet_CfgSpace_Byte	;write set PCI byte

		popad
	  	ret
Ct_Restore_SerIRQ	endp
endif;	PIIX_ID

endif ;SB_LINK_SUPPORT
;R53 - end

;R05 - start
ifdef		CIRRUS_610					
Int15_Func44:							
		cmp	al,08EH		;Is function 8EH	
		jne	short Is_8fh				
		mov	dl,99h		;return config. byte	
		jmp	Int15_Exit				
Is_8fh:								
		cmp	al,08FH		;Is function 8FH	
		jne	short Exit_44h				
		xor	ah,ah		;AH=0 for access	
		xor	dx,dx		;return user word	
Exit_44h:							
		jmp	Int15_Exit				
endif;	CIRRUS_610					
;R05 - end

;R01 - start
;*****************************************
;Name:		keyboard_function
;Entry: 	INT 15H
;Input: 	ah = 4FH
;		al = scan code
;		ds = g_ram
;******************************************
		extrn	Int15_4f_Hook:near
Int15_Func4f:

		call	Int15_4f_Hook
		jc	short @F   		;discard this key-stroke?
		jmp	Int15_Exit 		;yes
@@:

ifndef	NO_SOFTWARE_SPEED_CONTROL		;R12
		pusha
		push	ds

		push	ax
		mov	ax,40h
		mov	ds,ax
		pop	ax

		test	byte ptr ds:[017H],08H	; ALT
		je	short No_Sk		; NOT ALT1
		test	byte ptr ds:[017H],04H	; check for ctrl alt
		je	short No_Sk
		mov	ah,al
		xor	al,al
No_Rsk: 	
		cmp	ah,04ah			; '-'
		je	short Switch_Spd 	; set speed low
		cmp	ah,04eh			; '+'
		jne	short No_Sk		
Switch_Hi:
		mov	al,07fh 		; set speed high
Switch_Spd:
		or	al,080h 		; beep speaker.
		call	SetSpeed
Discard_Key_Exit:
		pop	ds
		popa
		clc	 			; flag for INT 9 qwik_exit
		jmp	Int15_Exit
No_Sk:
		pop	ds
		popa
endif;	NO_SOFTWARE_SPEED_CONTROL		;R12

		stc
		jmp	Int15_Exit
;R01 - end


;[]=======================================================================[]
;Name:   	A20_Support
;Entry:  	INT 15H
;Input:  	AH=24H
;		 AL=03H
;
;Output: 	BX=Status of A20 gate support
;
;		  =0000h - not supported on 8042 
;		  =0001h - supported on 8042
;
;		  =0000h - not supported with bit 1 of port 92h
;		  =0002h - supported with bit 1 of port 92h
;
;		  =0000h - no additional data available
;		  =8000h - additional data available
;			   (location of additional data is TBD)
;
;		AH=return code
;		  =00h - completed successfully
;		  =86h - function not support
;
;		CY=0 - successful
;		   1 - unsuccessful
;
;Description:
;1. 	save environment
;2. 	restore environment
;[]=======================================================================[]
		extrn	A20_Byte:byte
A20_Support	proc	
		cmp	al,03h
		jne	short a20_s_exit
		mov	bx,0001h		;assume keyboard Gate A20
		test	byte ptr cs:A20_Byte,01h;fast 92 port A20
		jz	short @F			
;R09 - start
		push	ds
		mov	ax,G_RAM
		mov	ds,ax
		ASSUME	DS:G_RAM
		test	byte ptr ds:FDD_VERIFY_CMD_FLAG,10h
		pop	ds
		jz	short @F		;no
;R09 - end

ifdef	FOR_MICROSTAR			;R47
		mov	bx,0001h
else;	FOR_MICROSTAR			;R47
		mov	bx,0003h
endif;	FOR_MICROSTAR			;R47

@@:
		mov	ah,0
		clc
		jmp	short a20_s_rtn
a20_s_exit:
		mov	ah,86h
		stc
a20_s_rtn:
		jmp	Int15_Exit
A20_Support	endp

;[]=======================================================================[]
;Name:   	Device_Open
;Entry:  	INT 15H
;Input:  	ah=80H
;                bx=device id
;                cx=process id
;Output: 	ah=0,cy=0
;Description:
;1. 	save environment
;2. 	restore environment
;3. 	return to POI
;[]=======================================================================[]
;[]=======================================================================[]
;Name:   	Device_Close
;Entry:  	INT 15H
;Input:  	ah=81H
;                bx=device id
;                cx=process id
;Output: 	ah=0,cy=0
;Description:
;1. 	save environment
;2. 	restore environment
;3. 	return to POI
;[]=======================================================================[]
;[]=======================================================================[]
;Name:   	Program_termination
;Entry:  	INT 15H
;Input:  	ah=82H
;                bx=device id
;Output: 	ah=0,cy=0
;Description:
;1. 	save environment
;2. 	restore environment
;3. 	return to POI
;[]=======================================================================[]

Device_Open	proc	far

Device_Close:
Process_Termination:

		pop	bx
		xor	ah,ah
		sti
		ret	2

Device_Open	endp

;[]=======================================================================[]
;Name:   	Event_Wait
;Entry:  	INT 15H
;Input:  	ah=83H
;		al=0 - set event wait
;		  es:bx - Pointer of semaphore byte that will have bit 7 set
;                         when the time interval expires.
;                 cx,dx - A 32-bit value in mircoseconds to wait upon
;
;		al=1 - clear event wait
;Output:	if al=0
;	 	  cf=1 if event timer already active.
;                 cf=0 if event posted.
;Description:
;1. 	save environment
;2. 	if no event wait already requested then
;          set 0:498H to bx, 0:49AH to es, 0:4A0H to 1, 0:49CH to dx,
;          0:49EH to cx, initialize and start PIE, cy=0
;        else cy = 0
;3. 	restore environment
;4. 	return to POI
;[]=======================================================================[]

Event_Wait	proc	far

		cli
		pop	bx			;retrieve BX
		push	ds			;save regs
		push	di
		mov	di,G_RAM			;change DS segment to 40H
		push	di
		pop	ds
		ASSUME	DS:G_RAM
		cmp	al,1			;Cancel command?
		jne	short E_W_1		;jump if not

	;cancel command

		mov	al,0bh NMI_ON		;get CMOS register B
		call	get_cmos
		mov	ah,al
		and	ah,10111111b		;remove periodic int
		mov	al,0bh NMI_ON		;set CMOS register B
		call	set_cmos
		xor	al,al			;clear al
		mov	byte ptr [WAIT_IN_USE],al	; and clear flag
		jmp	short E_W_3
E_W_1:						
		or	al,al			; see if set command
		jz	short E_W_2		; if not clear or set,
		dec	al			; then error.
		stc
		jmp	short E_W_END

	;set command
E_W_2:						
		test	byte ptr [WAIT_IN_USE],1	;is event wait in use?
		stc				; default in use
		jnz	short E_W_END		; exit with error if in use

		mov	[REQUESTER_FLG_OFFSET],bx	; save event flag place
		mov	[REQUESTER_SEG],es
		call	pie			; and set alarm
E_W_3:
		clc				; successful operation
E_W_END:
		pop	di
		pop	ds
		mov	ah,0			; SAVE FLAG
		sti
		ret	2

Event_Wait	endp

;[]======================================================================[]
;	PIE - enable periodic interrput (alarm interrupt)
;
; entry  - cx,dx - # microseconds to delay
;          ds = 40
;          flag location must be set prior to call 
; exit  -  ax destroyed
;[]======================================================================[]

		ALIGN	4
PIE		proc	near

		ASSUME	DS:G_RAM
		in	al,B8259+1		; mask off interrrupt
		newiodelay
		and	al,0FEh			; for alarm
		out	B8259+1,al
		newiodelay
		mov	byte ptr [WAIT_IN_USE],1	; set flags 
		mov	[LOW_NUM_MSECS],dx	; save time to delay
		mov	[HI_NUM_MSECS],cx
		MOV	AL,0BH NMI_ON		; enable alarm
		call	get_cmos
		mov	ah,al
		or	ah,40h			; set   bit 6
		and	ah,7Fh			; clear bit 7
		mov	al,0bh NMI_ON
		call	set_cmos
		ret

PIE		endp

;[]=======================================================================[]
;Name:   	Joy_Stick_Read
;Entry:  	INT 15H
;Input:         ah=84H
;               dx=0 reads current switch settings
;               dx=1 reads resistive inputs
;Output: 	if no joystick or dx > 1 
;		   cf=1
;               else
;                  if dx=0 al = switch settings in bits 7-4, bits 3-0 = 0
;                  if dx=1 ax=joystick A, X value, bx=joystick A, Y value,
;                          cx=joystick B, X value, dx=joystick B, Y value
;                  cf=0
;Description:
;1. 	save environment
;2.	read joystick according to the sub function selected
;3. 	restore environment
;4. 	return to POI
;[]=======================================================================[]

J_S_resist_in	STRUC		;temp storage for resistive reading
	B_Y	dw	0	;joystick B, Y value
	B_X	dw	0	;joystick B, X value
	A_Y	dw	0	;joystick A, Y value
	A_X	dw	0	;joystick A, X value
J_S_resist_in	ENDS


		ALIGN	4
Joy_Stick_Read	proc	far

		sti
		pop	bx			;retrieve bx
		cmp	dx,1			;valid command ?
		jbe	short J_S_R_0		;yes
		stc				;no, set CF
		jmp	short J_S_R_err_cmd  	; exit

J_S_R_0:
		mov	dx,201h
		je	short read_coord	;dx=1 read resistive input
		in	al,dx			;read switch D7-D4
		newiodelay
		and	ax,0F0h			;mask off D3-D0
		jmp	short J_S_R_exit

read_coord:
		push	si
		push	bp
		sub	sp,type J_S_resist_in	;reserve local storage
		mov	bp,sp			;use BP as frame pointer
		mov	bh,8			;start with B_Y value
		xor	si,si

		ALIGN	4
read_loop:
		cli				;interrupt off when reading
		call	read_timer_tic		;read starting time
		push	ax			;save it

		mov	cx,500h			;timeout count
		out	dx,al			;triger the one shot
		newiodelay

		ALIGN	4
wait_til_off:
		in	al,dx			;wait from 1 to 0
		newiodelay
		test	al,bh			
		jz	short coord_set

		loop	short wait_til_off

		pop	ax			;timeout
		xor	ax,ax			;return AX with 0
		jmp	short clr_inputs

coord_set:
		call	read_timer_tic
		mov	dx,ax
		pop	ax			;retrieve the starting value
		cmp	dx,ax			;roll over ?
		ja	short roll_over_adjust	;yes		
		sub	ax,dx			;ax = time elapsed
		jmp	short justify_coord
roll_over_adjust:
		not	dx			;get one's complement	
		add	ax,dx			;ax = time elapsed
justify_coord:
		and	ax,1FF0h		;
		shr	ax,4
clr_inputs:
		sti				;enable INT
		mov	[bp+si],ax		;save coordinate
		add	si,2

		mov	cx,500h
		mov	dx,201h

		ALIGN	4
clr_loop:
		in	al,dx			;clear resistive input
		newiodelay
		and	al,0Fh
		jz	short clr_done
		loop	short clr_loop
clr_done:
		shr	bh,1			;have we read all 4 ?
		jz	short all_read		;yes
		jmp	short read_loop		;no - read again

all_read:
		mov	ax,[bp].A_X		; A(x)
		mov	bx,[bp].A_Y		; A(y)
		mov	cx,[bp].B_X		; B(x)
		mov	dx,[bp].B_Y		; B(y)

		add	sp,type J_S_resist_in	;disgard local storage
		pop	bp
		pop	si
		
J_S_R_exit:
		clc
J_S_R_err_cmd:
		sti
		ret	2

Joy_Stick_Read	endp

;[]=======================================================================[]
;Name:		read_timer_tic
;
;Input:		none
;Output:	ax = timer tic
;[]=======================================================================[]

read_timer_tic	proc	near

		xor	ax,ax
		out	CTRL8254,al		;latch timer
		newiodelay
		in	al,DATA8254		;get LSB
		newiodelay
		mov	ah,al
		in	al,DATA8254		;get MSB
		newiodelay
		xchg	ah,al
		ret
	
read_timer_tic	endp



;[]=======================================================================[]
;Name:   	System_Request_Key
;Entry:  	INT 15H
;Input:  	ah=85H
;                al=Key status
;		    0: if key make (depression)
;                   1: if key break (release)
;Output:         cf=0
;Description:
;	This function is a dummy routine that always returns a success
;	status. A multitasking manager would be expected to capture 
;	INT 15 and process the request as necessary.
;[]=======================================================================[]

Sysreq_Key	proc	far

		pop	bx		;retrieve BX
		xor	ah,ah		;clear carry flag
		sti
		ret	2

Sysreq_Key	endp

;[]======================================================================[]
;Name:   	Wait
;Entry:  	INT 15H
;Input:  	ah=86H
;               cx:dx is a 32-bit value of microseconds to wait
;Output: 	cf=0 if function successful
;		cf=1 if a wait is already in progress
;Description:
;1. 	save environment
;2. 	wait for the specified number of mircorseconds to elapse.
;        set 0:498H to 4A0H, 0:49AH to 0, 0:4A0H to 1, 0:49CH to dx,
;        0:49EH to cx, initialize and start PIE, cy=0
;        wait for 0:4A0H to be set to 81H
;        set 0:4A0H to 0
;        cy = 0
;3. 	restore environment
;4. 	return to POI
;[]=======================================================================[]

		ALIGN	4
_WAIT		proc	far

		cli
		pop	bx			;retrieve BX
		push	ds
		pusha
		mov	bx,G_RAM
		push	bx
		pop	ds
		ASSUME	ds:G_RAM

		test	byte ptr [WAIT_IN_USE],1	; see if alarm active
		stc
		jne	short _W_END

		mov	[REQUESTER_FLG_OFFSET],offset WAIT_IN_USE
		mov	[REQUESTER_SEG],bx	; save event flag in place 
		call	PIE			; set interrupt to wait_in_use
		sti
		mov	bx,cx			; set bx to high count 
		xor	cx,cx			; set cx for ffffH looping 

		ALIGN	4
wait_loop_0:
		test	byte ptr [WAIT_IN_USE],80h	; flag set ?
		jnz	short wait_done
		newiodelay
		loop	short wait_loop_0	; safety check if rtc dies

		sub	bx,1
		jnc	short wait_loop_0

wait_loop_1:
		test	byte ptr [WAIT_IN_USE],80h	; flag set ?
		jnz	short wait_done
		newiodelay
		sub	dx,1
		jnc	short wait_loop_1

wait_done:
		mov	byte ptr [WAIT_IN_USE],0	; clear flag - V2.07 set to 0
		clc

_W_END:
		popa
		pop	ds
		mov	ah,0			; ah=0 for return value.
		sti
		ret	2

_WAIT		endp

;[]=======================================================================[]
;Name:   	Virtual_Move_Block
;Entry:  	INT 15H
;Input:  	ah=87H
;                     processor in virutal mode
;               es:si pointer to descriptor table
;                     descriptor table format used
;                     	8 bytes of dummy
;                    	GDT locations (8 bytes)
;                    	Source GDT (8 bytes)
;                    	Destination GDT (8 bytes)
;                    	BIOS CS (8 bytes)
;                    	SS (8 bytes)
;               cx = number of words to move (max of 8000H words)
;Output:        if successful
;                  ah=0, cf=0, zf=1
;               if unsuccessful
;                  cf=1,zf=0
;                  ah=1 ram parity (and parity error cleared when returned)
;                    =2 exception interrupt error
;                    =3 gate address for CS or SS failed
;               all regs except ax unchanged
;Description:
;1. 	save environment
;2. 	perform virtual memory move. Note that the source and destination
;        descriptors must have limits at least 2*(cx-1) bytes.
;3. 	restore environment
;4. 	return to POI
;[]=======================================================================[]

		ALIGN	4

		PUBLIC	Virtual_Move_Block
Virtual_Move	proc	far	
Virtual_Move_Block:
		cli
		cld

		pusha				; need to set stack for return
		push	es			; and save segs
		push	ds

;R35B;R35 - start
;R35B;MSBASE for GDT location and BIOS descriptor table should be 00H
;R35B		xor	al,al
;R35B		mov	bl,2			;error for bad descriptor
;R35B		cmp	byte ptr es:[si+MSBASE+8],al	;GDT location
;R35B		jne	J0_1
;R35B;R35A		cmp	byte ptr es:[si+MSBASE+20],al	;BIOS DT
;R35B		cmp	byte ptr es:[si+MSBASE+20H],al	;BIOS DT	;R35A
;R35B		jne	J0_1			;set error return
;R35B;R35 - end

		call	A20_On
		jc	v_m_b_aerr

;R35B - starts
	;fill shutdown byte in case the input selector is a invalid one
	;which will cause the CPU to reset
		mov	ax,G_RAM
		mov	ds,ax
		assume	ds:G_RAM
		mov	ds:[ROM_MODULE_SEG], ss
		mov	ds:[ROM_MODULE_OFFSET], sp
		mov	al, 0fh
		mov	ah, 09h
		call	Set_Cmos
		mov	al, 02h
		out	80h, al
;R35B - ends

;	From here until GOTO_REAL, BP = 0FFFFh, BX = 0000h
;	From here until protect mode, DS = caller's ES

		mov	bp,0ffffh
		xor	bx,bx

		mov	ax,es				; from shutdown
		mov	ds,ax

;	Caller's descriptor

		mov	word ptr [si+HILIMIT+8],bx	; clear reserved
		mov	byte ptr [si+ACCESS+8],bl	; set access	
		mov	word ptr [si+LIMIT+8],bp	; and set limit	

		mov	dl,ah				; 24-bit address calc
		shr	dl,4
		shl	ax,4
		add	ax,si
		adc	dl,0
		mov	[si+LOWBASE+8],ax		; set address	
		mov	[si+HIBASE+8],dl				


;	Stack descriptor

		mov	ax,ss				; now do stack descriptor
		mov	word ptr [si+HILIMIT+28h],bx	; clear 	
		mov	byte ptr [si+ACCESS+28h],93h	; set access	
		mov	word ptr [si+LIMIT+28h],bp	; and set limit	

		mov	dl,ah				; 24-bit address calc
		shr	dl,4
		shl	ax,4
		mov	[si+LOWBASE+28h],ax		; set address
		mov	[si+HIBASE+28h],dl				     

		lidt	fword ptr cs:[BIOS_IDT]
		lgdt	fword ptr ds:[si+8h]		; and load gdt reg

;	BIOS Descriptor

		mov	word ptr [si+HILIMIT+20h],bx	; clear 	
		mov	byte ptr [si+ACCESS+20h],09bh	; set access	
		mov	[si+LIMIT+20h],bp		; and set limit	
		mov	[si+LOWBASE+20h],bx		; set address	
		mov	byte ptr [si+HIBASE+20h],0FH			

;	Save stack segment

;R52		mov	bp,ss

		smsw	ax
		or	al,PROTECTED					
		lmsw	ax

		jmp	short v_m_b_101					

;	Set up segment descriptors

		ALIGN	4						
v_m_b_101:								
;R52		mov	ax,28h			; now set up stack and regs for move
;R52		mov	ss,ax
		xor	ah,ah			;R52
		mov	al,18h			; set up es (destination GDT)
		mov	es,ax
		mov	al,10h			; and ds (source GDT)
		mov	ds,ax

;	Move block

		xor	si,si			; clear
		xor	di,di
		shr	cx,1			; convert words -> dwords
		rep	movsd			; move dwords			
		jnc	short v_m_b_11		; no. of words was even		
		movsw				; move stray word		

		ALIGN	4							
v_m_b_11:

;	Status good: From here to end of routine, BL = Error status

v_m_b_12:

;	Check for parity error

		in	al,SYS1			; check for error
		mov	ah,al			; save ah
;R48		test	al,PARITY_CHECK		; check for parity or i/o error
		test	al,MEMORY_CHECK		; check for parity 	;R48
		jnz	short v_m_b_perr	; error
		xor	bl,bl			; no error flag (NEW CODE)

;	Return to real mode

goto_real:	
;R52		mov	ax,ss			; now set ds,es point to stack
		mov	ax,28h			;R52 now set ds,es point to stack
		mov	ds,ax
		mov	es,ax

		shr	eax,16			;R52A load high word of EAX to AX
		mov	cx,ax			;R52A store it to CX
		mov	eax,cr0			; mov_eax_cr0 to get machine word
		and	al,NOT PROTECTED					
		mov	cr0,eax			; write machine word to return to real

		jmp	short gr_1						

		ALIGN	4							
gr_1:										
		mov	ax,cx			;R52A restore high word of EAX
		shl	eax,16			;R52A set it
		lidt	fword ptr cs:[REAL_IDT_LOC]	; dummy load to clear

;R52		mov	ss,bp				; restore stack segment

		call	A20_Off

j0_1:
		mov	bp,sp							
		mov	byte ptr [bp+13h],bl	; ah = error code	

	;clear shutdown byte
		mov	ax, 000fh		;R35B
		call	Set_Cmos		;R35B
		mov	al, -1			;R35B
		out	80h, al			;R35B
							
		pop	ds			; recover regs	
		pop	es							
		popa								
										
		or	ah,ah							
		jnz	short j1							
										
		sti				; carry already cleared
		retf	2							
										
j1:										
		stc								
		sti								
		retf	2							

;	Report parity error in proteced mode

v_m_b_aerr:
		mov	bl,3			; set error return code
		jmp	short j0_1

v_m_b_perr:
		mov	cx,[si-2]		; do a dummy write to
		NEWIODELAY			; memory to clear off-board parity
						; latches
		NEWIODELAY			; only need to write to the source
		mov	[si-2],cx		; as no parity errors on writes.
		NEWIODELAY
		NEWIODELAY

		or	al,PARITY_CHECK_OFF
		out	SYS1,al			; by toggling parity enable
		NEWIODELAY
		NEWIODELAY
		mov	al,ah			; recover value and restore, in
		out	SYS1,al			; case one of bits was disabled.

		mov	bl,1			; set parity
		jmp	short goto_real
;R36;R03 - start
;R36;[]==================================================================[]
;R36;
;R36; EXC9HDLR:
;R36;
;R36;	Come here on type 9 shutdown. This was used when
;R36;	resetting the system on a 286. Applications also use
;R36;	this to come out of protected mode.
;R36;
;R36;ENTRY:	NONE
;R36; EXIT: NONE
;R36;
;R36;Author: Award
;R36;  Date: 11/27/90
;R36;
;R36;[]==================================================================[]
;R36
;R36		ALIGN	4
;R36		PUBLIC	EXC9HDLR			; *
;R36EXC9HDLR:
;R36		cli
;R36		lidt	fword ptr cs:[REAL_IDT_LOC]	; dummy load to clear
;R36
;R36		mov	ax,G_RAM
;R36		mov	ds,ax
;R36		assume	ds:G_RAM
;R36		mov	ss,ds:[ROM_MODULE_SEG]
;R36		mov	sp,ds:[ROM_MODULE_OFFSET]
;R36
;R36		call	A20_Off
;R36
;R36		mov	al,0fh NMI_ON		; enable NMI, as shut down
;R36		call	Get_CMOS
;R36
;R36		pop	ds			; recover regs
;R36		pop	es
;R36		popa
;R36
;R36		mov	ah,al			; save al
;R36		in	al,80h
;R36
;R36		or	al,al			; set zero flag
;R36		je	short exc_9
;R36
;R36		stc
;R36
;R36exc_9:		
;R36		xchg	ah,al			; swap regs and exit
;R36		sti
;R36		retf	2
;R36;R03 - end

Virtual_Move	endp

;[]=======================================================================[]
;Name:   	Extended_Memory_Size
;Entry:  	INT 15H
;Input:  	ah=88H
;Output: 	ax=number of consecutive 1k blocks starting at 1M
;Description:
;1. 	save environment
;2. 	get size from CMOS 30h and 31h.
;3. 	restore environment
;4. 	return to POI
;[]=======================================================================[]

		ALIGN	4
Extended_Memory_Size	proc	far

		pop	bx			;retrieve BX
		mov	al,30h NMI_ON		;read size
		call	get_cmos		; lo byte
		mov	ah,al			; 
		mov	al,31h NMI_ON
		call	get_cmos		; hi byte
		xchg	ah,al
;R41A ;R41 start
;R41A ifdef	ACPI_Support
;R41A 		sub	ax, ACPITableSize+ACPINVSSize	;subtract total size with ACPI size
;R41A endif;	ACPI_Support
;R41A ;R41 end
ifdef	ACPI_Support					;R56
		extrn	ACPI_RESERVED_MEM:word		;R56
		sub	ax,cs:[ACPI_RESERVED_MEM]	;R56
endif	;ACPI_Support					;R56
		iret

Extended_Memory_Size	endp

;[]=======================================================================[]
;Name:   	Switch_To_Virtual_Mode
;Entry:  	INT 15H
;Input:  	ah=89H
;               es:si=pointer to descriptor table (GDT built by user)
;                     descriptor table format used
;                    	8 bytes of dummy
;                    	GDT (8 bytes) GDT table 
;                    	IDT (8 bytes) caller defined IDT
;                    	DS (8 bytes) caller's data segment
;                    	ES (8 bytes) caller's extra segment
;                    	SS (8 bytes) caller's stack segment
;                    	CS (8 bytes) caller's code segment
;                    	Temp Bios CS (8 bytes)
;               bh=offset into IDT where first 8 8259 interrupts are
;                  to occur
;               bl=offset into IDT where second 8 8259 interrupts are
;                  to occur
;Output: 	if successful
;		   ah=0, segment registers set, ax and bp changed
;		   cf=0
;		if unsucessful
;		   ah=0ffh, cf=1
;Description:
;1. 	save environment
;2. 	initialize 8259's, gates and segment registers.
;3. 	restore environment
;4. 	return to POI
;[]======================================================================[]

		ALIGN	4
Switch_To_Virtual_Mode	proc	far

		pop	bx			;retrieve BX

		cli

		call	A20_On
		jnc	short s_t_vm_1		; no error...

		mov	ah,0ffh			; set error return code 
		stc				; and flag
		sti
		ret	2

;	Set up descriptor

S_T_VM_1:
		mov	ax,cs				;set ROM descriptor
		lea	di,[si+38h]
		mov	word ptr es:[di+HILIMIT],0	;clear 
		mov	byte ptr es:[di+ACCESS],9BH	;set access
		mov	word ptr es:[di+LIMIT],0FFFFh	;and set limit
		mov	dl,ah				;24-bit address calc
		shr	dl,4
		shl	ax,4
;R02		mov	[di+LOWBASE],ax			;set address
;R02		mov	[di+HIBASE],dl
		mov	es:[di+LOWBASE],ax	     	;set address
		mov	es:[di+HIBASE],dl

;	Load IDT and GDT

		lidt	fword ptr es:[si+10h]
		lgdt	fword ptr es:[si+8h] 

;	Initialize interrupt controllers

		mov	al,11h
		out	A8259,AL		; now init 8259's
		NEWIODELAY
		out	B8259,AL

		mov	al,bh
		out	A8259+1,al		; set master
		mov	al,bl
		out	B8259+1,al		; and set slave
		NEWIODELAY

		mov	al,4
		out	A8259+1,al		; expect slave
		mov	al,2
		out	B8259+1,al		; and no master
		NEWIODELAY

		mov	al,1
		out	A8259+1,al		; 8086 mode
		NEWIODELAY
		out	B8259+1,al

		mov	al,0ffh			; mask off all interrupts
		NEWIODELAY
		out	A8259+1,al
		NEWIODELAY
		out	B8259+1,al
		NEWIODELAY

		mov	eax,cr0			; mov_eax_cr0 to get machine word
		or	al,PROTECTED		; switch to protected
		mov	cr0,eax

		jmp	short $+2

		mov	ax,28h			; now set user
		mov	ss,ax
		mov	ax,18h
		mov	ds,ax
		mov	ax,20h			; segs
		mov	es,ax
	
		pop	cx			; now do a return from iret
		pop	ax			; ah must be 0
		pop	ax			; discard cs,flags
		mov	ax,30h			; cs selector
		push	ax
		push	cx
		ret

Switch_To_Virtual_Mode	endp


		public	REAL_IDT_LOC			;R36
REAL_IDT_LOC:	DW	3FFH
		DD	0

;[]=======================================================================[]
;Name:   	Device_Busy
;Entry:  	INT 15H
;Input:  	ah=90H
;               al=00-7FH sequentially usable devices (done by O.S.)
;                 =80-BFH reentrant devices
;                 =C0-FFH wait for "post". Basically timeout functions.
;Output: 	ah=0, cf=0.
;Description:
;	A multitasking manager would be expected to capture this function
;	so that it can dispatch other tasks while I/O is in progress.
;[]=======================================================================[]

Device_Busy	proc	far

		pop	bx			;retrieve BX
		xor	ah,ah
		sti
		ret	2

Device_Busy	endp


;[]=======================================================================[]
;Name:   	Interrupt_Complete
;Entry:  	INT 15H
;Input:  	ah=91H
;               al=00-7FH sequentially usable devices (done by O.S.)
;                 =80-BFH reentrant devices
;                 =C0-FFH wait for "post". Basically timeout functions.
;Output: 	ah = 0
;Description:
;	A multitasking manager would be expected to capture this function
;	so that it can be notified when I/O is completed and awaken the
;	requesting task.
;[]=======================================================================[]

Interrupt_Complete	proc	far

		pop	bx
		xor	ah,ah
		iret

Interrupt_Complete	endp

;[]=======================================================================[]
;Name:		Configuration Parameters 
;Entry		INT 15H
;Input:		ah=0C0H
;Output:	es:bx=address of parameter table where
;			word - length of table
;			byte - system model number
;			byte - system type
;			byte - bios revision
;			byte - info byte where
;				10000000 - dma channel 3 used by BIOS
;				01000000 - cascaded interrupt level 2
;				00100000 - real time clock available
;				00010000 - keyboard uses int 1aH
;			4 bytes - reserved
;Description:
;	Returns a pointer to a table containing various information about
;	the system configuration.
;[]=======================================================================[]

Get_Sys_Info	proc	far
Get_Sys_Config:
		mov	bx,cs			;set es to bios segment
		mov	es,bx
		mov	bx,offset cs:CONFIG_TABLE	;set bx to table (ATORGS.ASM)
		xor	ah,ah			;clear ah, ZF SET BY CMP
		sti
		ret	2

Get_Sys_Info	endp


;[]=======================================================================[]
;Name:   	INT15_41h
;Entry:  	INT 15H
;Input:  	ah=41H
;Output: 	cf=0
;Description:
;	An undocumented service which will be replaced by multitasking manager
;	called by DOS driver.
;[]=======================================================================[]

INT15_41h	proc	far
INT15_idle:
		clc
		sti
		ret	2

INT15_41h	endp


FCODE		ENDS
		END
