;******************************************************************************
	page    58,132
	title   IWIO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   NAME:  IWIO.ASM $Revision: 1.14 $
;;  COPYRIGHT:
;;  "Copyright (c) 1994,1995 by e-Tek Labs"
;;
;;       "This software is furnished under a license and may be used,
;;       copied, or disclosed only in accordance with the terms of such
;;       license and with the inclusion of the above copyright notice.
;;       This software or any other copies thereof may not be provided or
;;       otherwise made available to any other person. No title to and
;;       ownership of the software is hereby transfered."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $Log: iwio.asm $
; Revision 1.14  1996/01/03 12:46:18  unknown
; Added code to clear the interrupt flag before calling into SBOS, this
; fixes DOOM and HERETIC in a windows 95 DOS box.
; Revision 1.13  1995/12/19 09:58:18  unknown
; Fixed bug caused by VMM not always scheduling event during VM_Not_Executeable
; in Windows 3.1
; Revision 1.12  1995/12/18 09:45:52  teckert
; Fixed 2 jump out of range errors in Win 3.1 build
; Revision 1.11  1995/12/14 14:13:41  unknown
; Added leading underscore to wDriver_segment, wDriver_offset and IW_Schedule
; _Driver_Callback to allow them to be accessed from C.
; Revision 1.10  1995/12/04 09:27:05  teckert
; Fixed a bug with the VM_Not_Executeable code, couldn't suspend the VM
; during this call.
; Revision 1.9  1995/11/28 10:55:18  teckert
; Changed allocation code to make callbacks to the ring 3 driver when a dos
; box allocates the hardware, also supports Sys VM access to the CODEC 
; anytime.
; Revision 1.8  1995/09/08 11:03:52  teckert
; Rolled in the windows 95 modifications
; Revision 1.7  1995/05/04 17:23:31  teckert
; Replaced SynthBase with SynthBase2X
; Revision 1.6  1995/04/28 16:06:51  teckert
; Bug fixes attempted (slighly re-arranged the SBOS read check function)
; Revision 1.5  1995/04/18 15:32:16  teckert
; Added priority access for windows mixer
; Revision 1.4  1995/04/12 13:23:44  teckert
; Added MPU401 to sbos support
; Revision 1.3  1995/04/06 18:41:59  teckert
; Added "Boss in a box" to driver
; Revision 1.2  1995/03/20 16:26:52  teckert
; Added file header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;******************************************************************************
;
;   Functional Description:
;      Provides I/O Trapping for auto-allocation and VM arbitration
;
;******************************************************************************
	.386p

;==============================================================================
;                             I N C L U D E S
;==============================================================================

.xlist
	include vmm.inc
	include debug.inc
	include vdmad.inc
	include vpicd.inc
.list
	include viwd.inc

VxD_LOCKED_CODE_SEG

;------------------------------------------------------------------------------
;                 E X T E R N A L    R E F E R E N C E S
;------------------------------------------------------------------------------

EXTRN IW_Acquire_InterWave:NEAR
EXTRN IW_Release_InterWave:NEAR
EXTRN IW_Transfer_Access:NEAR
VxD_LOCKED_CODE_ENDS

VxD_LOCKED_DATA_SEG
				     
SBOS_Scheduled_Event    dd      0        
	public wSBOS_segment
wSBOS_segment           dw      0
	public wSBOS_offset
wSBOS_offset            dw      0

Driver_Scheduled_Event  dd      0        
        public _wDriver_segment
_wDriver_segment         dw      0
        public _wDriver_offset
_wDriver_offset          dw      0
				     
;------------------------------------------------------------------------------
;                 E X T E R N A L    R E F E R E N C E S
;------------------------------------------------------------------------------

EXTRN _gIWI:NEAR         ; InterWave Info structure
EXTRN _gIW_ResTbl:NEAR   ; Resource Table
EXTRN INTERWAV_CB_Offset:NEAR



;------------------------------------------------------------------------------
;          G L O B A L   I N I T   D A T A   D E C L A R A T I O N S
;------------------------------------------------------------------------------

;
; Port maps for InterWave used for installing IO trap handlers
; These are in the locked segment because they are acessed during acquisition and release

;The following Adlib ports are always at the same location
Begin_VxD_IO_Table IW_AL_Port_Table

	VxD_IO  IW_PORT_UAACWR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UAADR, InterWave_Arb_Handler
		   
End_VxD_IO_Table IW_AL_Port_Table

;IW_AL_Port_Table_Entries equ (($-IW_AL_Port_Table_PAL)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

;The following group of ports will need to have P2XR added to them before
;the I/O handlers can be installed                   
Begin_VxD_IO_Table IW_2XR_Port_Table

	VxD_IO  IW_PORT_UMCR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_U2X6R, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UACWR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UADR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UACRR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UHRDP, InterWave_Arb_Handler
	VxD_IO  IW_PORT_UI2XCR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_U2XCR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_U2XER, InterWave_Arb_Handler
	VxD_IO  IW_PORT_URCR, InterWave_Arb_Handler

End_VxD_IO_Table IW_2XR_Port_Table

;IW_2XR_Port_Table_Entries equ (($-IW_2XR_Port_Table_PAL)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

;The following group of ports will need to have P3XR added to them before
;the I/O handlers can be installed                   
Begin_VxD_IO_Table IW_3XR_Port_Table

	VxD_IO  IW_PORT_SVSR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_IGIDXR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_I16DP, InterWave_Arb_Handler
	VxD_IO  IW_PORT_I8DP, InterWave_Arb_Handler

End_VxD_IO_Table IW_3XR_Port_Table

;IW_3XR_Port_Table_Entries equ (($-IW_3XR_Port_Table)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

;The following group of ports will need to have P3XR added to them before
;the I/O handlers can be installed                   
Begin_VxD_IO_Table IW_3XRPort_Port_Table

	VxD_IO  IW_PORT_GMCR, InterWave_Arb_Handler
	VxD_IO  IW_PORT_GMTDR, InterWave_Arb_Handler

End_VxD_IO_Table IW_3XRPort_Port_Table

;The following PNP ports are fixed in these locations
;Begin_VxD_IO_Table IW_PNP_Port_Table

	;VxD_IO IW_PORT_PCSNBR, PNP_IO_Handler
	;VxD_IO IW_PORT_PIDXR, PNP_IO_Handler
	;VxD_IO IW_PORT_PNPWRP, PNP_IO_Handler
;The PNP read port is configured by a write to an indexed regiser
; IW_PORT_PNPRDP        EQU     003h - 03FFh
								 
;End_VxD_IO_Table IW_PNP_Port_Table

;IW_PNP_Port_Table_Entries equ (($-IW_PNP_Port_Table_PAL)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

;The following group of ports will need to have PCODAR added to them before
;the I/O handlers can be installed                   
Begin_VxD_IO_Table IW_CODEC_Port_Table

	VxD_IO  IW_PORT_CIDXR, Codec_Index_Handler
	VxD_IO  IW_PORT_CDATAP, Codec_Data_Handler
	VxD_IO  IW_PORT_CSR1R, InterWave_Arb_Handler
	VxD_IO  IW_PORT_CPDR, InterWave_Arb_Handler

End_VxD_IO_Table IW_CODEC_Port_Table

;IW_CODEC_Port_Table_Entries equ (($-IW_CODEC_Port_Table_PAL)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

;The following group of ports will need to have PMPUR added to them before
;the I/O handlers can be installed                   
Begin_VxD_IO_Table IW_MPU401_Port_Table

	VxD_IO  IW_PORT_MPU0, InterWave_Arb_Handler
	VxD_IO  IW_PORT_MPU1, InterWave_Arb_Handler

End_VxD_IO_Table IW_MPU401_Port_Table

;IW_MPU401_Port_Table_Entries equ (($-IW_MPU401_Port_Table_PAL)-(SIZE VxD_IOT_Hdr)) / (SIZE VxD_IO_Struc)

VxD_LOCKED_DATA_ENDS


;==============================================================================
;                             I C O D E
;==============================================================================

VxD_ICODE_SEG

;------------------------------------------------------------------------------
;                 E X T E R N A L    R E F E R E N C E S
;------------------------------------------------------------------------------

VxD_ICODE_ENDS

;===========================================================================;
;                   N O N P A G E A B L E   C O D E
;===========================================================================;

VxD_LOCKED_CODE_SEG

BeginDoc
;---------------------------------------------------------------------------;
;
;   InterWave_Arb_Handler
;
;   DESCRIPTION:
;       Handle IO trapping of the InterWave ports.
;
;   ENTRY:
;       EBX = VM Handle.
;       ECX = Type of I/O
;       EDX = Port number
;       EBP = Pointer to client register structure
;
;   EXIT:
;       EAX = data input or output depending on type of I/O
;
;   USES:
;       FLAGS
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc InterWave_Arb_Handler, High_Freq

	public Default_Arbitration_Handling
Default_Arbitration_Handling:   
	push    eax                             ; save
	push    ecx                             ; save

	; first locate the resource structure that includes this port
	; iterate through the resource list and if the resource is a
	; port resource check if the port is within the specified range
	; ESI is used to track the resource acquire bit
	mov     edi,offset32 _gIW_ResTbl
	mov     ecx,IWAR_NUMRESOURCES
	mov     esi,1
IWAH_RESOURCE_LOOP:           
	mov     ax,[edi.iwri_wStatus]
	test    ax,IWRIS_DISABLED
	jnz     short NEXT_RESOURCE
	and     ax,IWRIS_TYPE
	cmp     ax,IWRIS_PORTS
	jne     short NEXT_RESOURCE
	mov     eax,[edi.iwri_dwResourceID]
	cmp     ax,dx
	jg      short NEXT_RESOURCE
	ror     eax,16
	cmp     ax,dx
	jl      short NEXT_RESOURCE
	jmp     short FOUND_RESOURCE          
NEXT_RESOURCE:  
	add     edi,(size IWRESOURCEINFO)
	rol     esi,1
	loop    IWAH_RESOURCE_LOOP
NO_RESOURCE:
	jmp     IW_IODef_Not_Owner
		
FOUND_RESOURCE:
	; EDI points to the resource structure and ESI is the resource
	; bit for that resource

	cmp     [edi.iwri_dwCurOwner], ebx  ; Q: does this VM own it?

	jne     short IW_IODef_New_Owner    ;   N: then try to assign owner
	
ifdef DEBUG
	test    [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	jnz     short IW_SBOS_Active
	Debug_Out "IW: #EAX OWNS IW AND TRAPPING IS ENABLED!?!"
IW_SBOS_Active:
endif

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   Trapping should have been disabled for the owning VM!  But, if
;   somehow we got hosed, allow access to the owner.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

        jmp     IW_IODef_Allow_Access

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   this is where the 'auto-acquire' comes in.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

	public IW_IODef_New_Owner
IW_IODef_New_Owner:

	cmp     DWORD PTR [edi.iwri_dwCurOwner], 0  ; Q: is there already an owner?
        jnz     IW_IODef_Not_Owner                        ; Y: yes, fail call!

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   We are going to auto-assign the IW to the VM that is trying to use the
;   board; it is currently unowned.
;       EAX = resource code
;       EBX = VM handle
;       ECX = type of I/O
;       EDX = port touched
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

	push    edx
	push    ebx
	push    ecx
	mov     eax,esi
	call    IW_Acquire_InterWave
	pop     ecx
	pop     ebx
	pop     edx
        jc      IW_IODef_Not_Owner   ; fail if cannot acquire!

	Debug_Out "IW_IO_Default_CODEC: autoacquired by VM #EBX"
                                                        
	test	eax,IWAR_CODECPLAY
	jz		IW_IODef_No_Codec
	
	; Enable trapping for the CODEC index and data ports
	push	edx
	mov     dx,WORD PTR [_gIWI.iwi_wCodecBase]
	VMMcall Enable_Local_Trapping
	inc		dx
	VMMcall Enable_Local_Trapping
	pop		edx
IW_IODef_No_Codec:

	; if this is not the system VM (and we have a windows driver callback) then we need to
	; halt this VM send a sleep message to the windows drivers, then switch access to the 
	; resources to the acquiring VM
	
	push	ebx
	push	edx
	mov		edx,ebx
	VMMCall	Get_Sys_VM_Handle
	cmp		ebx,edx
	pop		edx
	pop		ebx
	je		IW_IODef_Not_DOS_Box
	           
	push	edx	           
	push	eax
	mov		al,IW_KERNEL_SLEEP
        call    _IW_Schedule_Driver_Callback
	pop		eax
	VMMCall	Suspend_VM
	mov		edx,ebx
	VMMCall Get_Sys_VM_Handle
	call	IW_Transfer_Access
	pop		edx
	
IW_IODef_Not_DOS_Box:           

	public IW_IODef_Allow_Access
IW_IODef_Allow_Access:
	pop     ecx                         ; restore
	pop     eax                         ; restore

	Dispatch_Byte_IO Fall_Through, <short IW_IODef_Real_Out>
	in      al, dx                      ; input from physical port
	call    IW_Check_SBOS_Port_Read
	jmp     short IW_IODef_Exit

	public IW_IODef_Real_Out
IW_IODef_Real_Out:

	out     dx, al                      ; output to physical port
	call    IW_Check_SBOS_Port_Write
	Assumes_Fall_Through IW_IODef_Exit

	public IW_IODef_Exit
IW_IODef_Exit:

	ret

	public IW_IODef_Not_Owner
IW_IODef_Not_Owner:
	pop     ecx
	pop     eax

	Dispatch_Byte_IO Fall_Through, <short IW_FakeIO_Exit>
	xor     eax,eax
	sub     eax,1
				       ; ignore output
	Assumes_Fall_Through IW_FakeIO_Exit
IW_FakeIO_Exit:

	ret
	
EndProc InterWave_Arb_Handler


BeginDoc
;---------------------------------------------------------------------------;
;
;   Codec_Index_Handler
;
;   DESCRIPTION:
;       Handle IO trapping for the Codec index register.
;
;   ENTRY:
;       EBX = VM Handle.
;       ECX = Type of I/O
;       EDX = Port number
;       EBP = Pointer to client register structure
;
;   EXIT:
;       EAX = data input or output depending on type of I/O
;
;   USES:
;       FLAGS
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc Codec_Index_Handler, High_Freq

	; Is it the system VM?  Allow acess if it is
	mov		esi,ebx
	VMMCall	Get_Sys_VM_Handle	
	cmp		esi,ebx
	je		short IW_IOCIH_Allow
	mov		ebx,esi
	               
	; Is it the owning VM?  Allow acess if it is	               
	push	eax
	mov		eax,8		; the codec port range index in the ResTbl
	imul	edi,eax,size IWRESOURCEINFO
	pop		eax
	add		edi,offset32 _gIW_ResTbl
	
	cmp		esi,[edi.iwri_dwCurOwner]
	je		short IW_IOCIH_Allow
	
	cmp		DWORD PTR [edi.iwri_dwCurOwner],0
	jne		IW_IOCIH_Block
	
	; Allow the normal arbitration function to auto-acquire the hardware
	jmp	Default_Arbitration_Handling

IW_IOCIH_Block:
	Dispatch_Byte_IO Fall_Through, <short IW_IOCIH_Block_Out>
	xor     eax,eax
	sub     eax,1
IW_IOCIH_Block_Out:
	jmp     short IW_IOCIH_Exit

IW_IOCIH_Allow:
	; Get the control block into esi
	add	esi,DWORD PTR[INTERWAV_CB_Offset]

	Dispatch_Byte_IO Fall_Through, <short IW_IOCIH_Real_Out>
	
	mov     al, [esi.iwcb_bCodecIndex]	; return this VM's current index
	jmp     short IW_IOCIH_Exit

	public IW_IOCIH_Real_Out
IW_IOCIH_Real_Out:

	mov     [esi.iwcb_bCodecIndex], al	; save as this VM's current index
	Assumes_Fall_Through IW_IOCIH_Exit

	public IW_IOCIH_Exit
IW_IOCIH_Exit:

	ret

EndProc Codec_Index_Handler


BeginDoc
;---------------------------------------------------------------------------;
;
;   Codec_Data_Handler
;
;   DESCRIPTION:
;       Handle IO trapping for the Codec data register.
;
;   ENTRY:
;       EBX = VM Handle.
;       ECX = Type of I/O
;       EDX = Port number
;       EBP = Pointer to client register structure
;
;   EXIT:
;       EAX = data input or output depending on type of I/O
;
;   USES:
;       FLAGS
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc Codec_Data_Handler, High_Freq

	; Is it the System VM?  Allow acess if it is	               
	mov		esi,ebx
	VMMCall	Get_Sys_VM_Handle	
	cmp		esi,ebx
	je		short IW_IOCDH_Allow
	mov		ebx,esi
	
	; Is it the owning VM?  Allow acess if it is	               
	push	eax
	mov		eax,8		; the codec port range index in the ResTbl
	imul	edi,eax,size IWRESOURCEINFO
	pop		eax
	add		edi,offset32 _gIW_ResTbl
	
	cmp		esi,[edi.iwri_dwCurOwner]
	je		short IW_IOCDH_Allow
	
	cmp		DWORD PTR [edi.iwri_dwCurOwner],0
	jne		IW_IOCIH_Block
	
	; Allow the normal arbitration function to auto-acquire the hardware
	jmp	Default_Arbitration_Handling

IW_IOCDH_Allow:
	; Get the control block into esi
	add	esi,DWORD PTR[INTERWAV_CB_Offset]

	; Set the actual codec index to the VM's index          
	push	eax
	push	edx
	
	mov     al, [esi.iwcb_bCodecIndex]	; return this VM's current index
	mov		dx, [_gIWI.iwi_wCodecBase]	; index addr 
	out		dx, al                      ; write the index
	
	pop	edx
	pop	eax

	Dispatch_Byte_IO Fall_Through, <short IW_IOCDH_Real_Out>
	in	al,dx	
	jmp     short IW_IOCDH_Exit

	public IW_IOCDH_Real_Out
IW_IOCDH_Real_Out:
	out	dx,al
	jmp	short IW_IOCDH_Exit

	public IW_IOCDH_Exit
IW_IOCDH_Exit:

	ret
	
EndProc Codec_Data_Handler


BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_DisableList
;
;   DESCRIPTION:
;       Disable IO trapping of the InterWave ports for a list of ports for the
;       specified VM.
;
;   ENTRY:
;       EBX = VM Handle.
;       ESI = Address of I/O Table
;
;   EXIT:
;
;   USES:
;       ECX,ESI
;       FLAGS
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_DisableList

	movzx   ecx,WORD PTR[esi]
	add     esi,(size VxD_IOT_Hdr)
IWDL_Loop:
	movzx   edx,[esi.VxD_IO_Port]
	VMMcall Disable_Local_Trapping
	add     esi,(size VxD_IO_Struc)
	loop    IWDL_Loop
	ret

EndProc IW_DisableList

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_EnableList
;
;   DESCRIPTION:
;       Enable IO trapping of the InterWave ports for a list of ports for the
;       specified VM.
;
;   ENTRY:
;       EBX = VM Handle.
;       ESI = Address of I/O Table
;
;   EXIT:
;
;   USES:
;       ECX,ESI
;       FLAGS
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_EnableList

	movzx   ecx,WORD PTR[esi]
	add     esi,(size VxD_IOT_Hdr)
IWEL_Loop:
	movzx   edx,[esi.VxD_IO_Port]
	VMMcall Enable_Local_Trapping
	add     esi,(size VxD_IO_Struc)
	loop    IWEL_Loop
	ret

EndProc IW_EnableList

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Call_SBOS
;
;   DESCRIPTION:
;
;   ENTRY:
;       EBX - SBOS Virtual Machine
;       EBP - Client Reg Struct
;       DX  - Client's AX 
;
;   EXIT:
;
;   USES:
;
;---------------------------------------------------------------------------;
EndDoc
	  
BeginProc IW_Call_SBOS

	Push_Client_State                       ; gotta save this!
	VMMcall Begin_Nest_V86_Exec             ; prepare to call VM
		   
	and     DWORD PTR [SBOS_Scheduled_Event], 0
			       
	mov     [ebp.Client_AX],dx                             
	mov     cx, [wSBOS_segment]
	movzx   edx, [wSBOS_offset]

	VMMcall Simulate_Far_Call               ; set stuff up for call
        and     [ebp.Client_Flags],not IF_Mask
	or      [_gIWI.iwi_wFlags],IWI_FLAG_IN_SBOS
	VMMcall Resume_Exec
	and     [_gIWI.iwi_wFlags],not IWI_FLAG_IN_SBOS

	VMMcall End_Nest_Exec

	Pop_Client_State                        ; restore client stuff now

	ret
EndProc IW_Call_SBOS
    
BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Schedule_SBOS_Call
;
;   DESCRIPTION:
;
;   ENTRY:      
;       EBX - SBOS Virtual Machine
;       DX  - Client's AX 
;
;   EXIT:
;
;   USES:
;
;---------------------------------------------------------------------------;
EndDoc
	  
BeginProc IW_Schedule_SBOS_Call

	push    eax
	push    ecx
	push    edx
	push    esi
	push    edi

	mov     eax,High_Pri_Device_Boost
	mov     ecx,0
	mov     esi,offset32 IW_Call_SBOS
	mov     edi,80h         ; 128 millisecond time-out
	VMMcall Call_Priority_VM_Event
	mov     [SBOS_Scheduled_Event],esi
	
	pop     edi
	pop     esi
	pop     edx
	pop     ecx
	pop     eax
	ret
EndProc IW_Schedule_SBOS_Call
    
;---------------------------------------------------------------------------;
;
;   IW_Call_Driver
;
;   DESCRIPTION:
;
;   ENTRY:
;       EBX - System Virtual Machine
;       EBP - Client Reg Struct
;       DX  - DOS Box VM
;
;   EXIT:
;
;   USES:
;
;---------------------------------------------------------------------------;
EndDoc
	  
BeginProc IW_Call_Driver

    push    eax
	push	edx			   
	Push_Client_State                       ; gotta save this!
	VMMcall Begin_Nest_Exec                 ; prepare to call VM
		   
	and     DWORD PTR [Driver_Scheduled_Event], 0
			                                               
	movzx	dx,BYTE PTR[_gIWI.iwi_bPendingDriverOp]
	mov     [ebp.Client_AX],dx
        mov     ax,[_gIWI.iwi_wDriverDS]
        mov     [ebp.Client_DS],ax
	
        mov     cx, [_wDriver_segment]
        movzx   edx, [_wDriver_offset]

	VMMcall Simulate_Far_Call               ; set stuff up for call
	VMMcall Resume_Exec
	VMMcall End_Nest_Exec

	Pop_Client_State                        ; restore client stuff now
	pop		ebx
    pop     eax

	or		ebx,ebx
	jz		short Dont_Resume
	VMMCall	Resume_VM
Dont_Resume:

	movzx	dx,BYTE PTR[_gIWI.iwi_bPendingDriverOp]
        cmp             dl,IW_KERNEL_SLEEP
        je              Not_Waking_Sys_VM
	
	; iterate through the resource list looking for resources with
	; the Sys VM as the current owner
	
	VMMCall Get_Sys_VM_Handle
	xor		eax,eax	
	mov     edi,offset32 _gIW_ResTbl
	mov     ecx,IWAR_NUMRESOURCES
	mov     esi,1

IWCD_RESOURCE_LOOP:
	cmp     ebx,[edi.iwri_dwCurOwner]
	jne     short IWCD_NEXT_RESOURCE
                   
	or		eax,esi
	                   
IWCD_NEXT_RESOURCE:
	rol     esi,1
	add     edi,(size IWRESOURCEINFO)
	loop    IWCD_RESOURCE_LOOP

	or		eax,eax
	jz		Not_Waking_Sys_VM
	
	push    ecx
	push    edi
	push    esi
	call    IW_Release_InterWave
	pop     esi
	pop     edi
	pop     ecx   
	
Not_Waking_Sys_VM:

	ret
EndProc IW_Call_Driver

;---------------------------------------------------------------------------;
;
;   IW_Schedule_Driver_Callback
;
;   DESCRIPTION:
;
;   ENTRY:      
;       DX  - Client's AX 
;
;   EXIT:
;
;   USES:
;
;---------------------------------------------------------------------------;
EndDoc
	  
BeginProc _IW_Schedule_Driver_Callback

	push    eax                        
	push	ebx
	push    ecx
	push    edx
	push    esi
	push    edi
                   
	mov		[_gIWI.iwi_bPendingDriverOp],al
	mov		edx,ebx                            
	VMMCall	Get_Sys_VM_Handle
	mov     ecx,PEF_Always_Sched
	mov     eax,High_Pri_Device_Boost
	mov     esi,offset32 IW_Call_Driver
	mov     edi,80h         ; 128 millisecond time-out
	VMMcall Call_Priority_VM_Event
	mov     [Driver_Scheduled_Event],esi
	
	pop     edi
	pop     esi
	pop     edx
	pop     ecx
	pop		ebx
	pop     eax
	ret
EndProc _IW_Schedule_Driver_Callback
    
BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Check_SBOS_Port_Write
;
;   DESCRIPTION:
;
;   ENTRY:                        
;       AL  - BYTE DATA
;       DX  - Port Address
;       EBX - SBOS Virtual Machine
;
;   EXIT:
;
;   USES:
;       DX,BX,CX
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc IW_Check_SBOS_Port_Write
	; Make sure SBOS is running
	test    [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	jz      short IW_CSPW_Dont_Call_SBOS
	
	test    [_gIWI.iwi_wFlags],IWI_FLAG_IN_SBOS
	jnz     short IW_CSPW_Dont_Call_SBOS

	test    [_gIWI.iwi_wFlags],IWI_FLAG_MPU_ACTIVE
	jz      short IWCSPW_No_MPU
	
	sub     DX,[_gIWI.iwi_wMPUBase]
	cmp     dx,0
	jne     short IWCSPW_Not_MPU0
	mov     dx,04h
	jmp     short IW_CSPW_Call_SBOS
IWCSPW_Not_MPU0:        
	cmp     dx,1
	jne     short IWCSPW_Not_MPU1
	mov     dx,05h
	jmp     short IW_CSPW_Call_SBOS
IWCSPW_Not_MPU1:
	add     DX,[_gIWI.iwi_wMPUBase]  ; restore the port for the other cmp's
	
IWCSPW_No_MPU:
	; Check port
	cmp     dx,389h
	jne     short IWCSPW_Not_389
	mov     dx,01h
	jmp     short IW_CSPW_Call_SBOS
IWCSPW_Not_389:
	sub     DX,[_gIWI.iwi_wSynthBase2X]
	cmp     DX,06h
	jne     short IWCSPW_Not_2X6
	mov     dx,00h
	jmp     short IW_CSPW_Call_SBOS
IWCSPW_Not_2X6: 
	cmp     DX,09h
	jne     short IWCSPW_Not_2X9
	mov     dx,01h
	jmp     short IW_CSPW_Call_SBOS
IWCSPW_Not_2X9:
	cmp     DX,0Ch
	jne     short IW_CSPW_Dont_Call_SBOS
	mov     dx,02h
IW_CSPW_Call_SBOS:
	call    IW_Schedule_SBOS_Call
IW_CSPW_Dont_Call_SBOS:         
	ret
	
EndProc IW_Check_SBOS_Port_Write
	  
BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Check_SBOS_Port_Read
;
;   DESCRIPTION:
;
;   ENTRY:                        
;       AL  - BYTE DATA
;       DX  - Port Address
;       EBX - SBOS Virtual Machine
;
;   EXIT:
;
;   USES:
;       DX,BX
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc IW_Check_SBOS_Port_Read
	; Make sure SBOS is running
	test    [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	jz      short IW_CSPR_Dont_Call_SBOS
	
	test    [_gIWI.iwi_wFlags],IWI_FLAG_IN_SBOS
	jnz     short IW_CSPR_Dont_Call_SBOS

	test    [_gIWI.iwi_wFlags],IWI_FLAG_MPU_ACTIVE
	jz      short IWCSPR_No_MPU

	cmp     DX,[_gIWI.iwi_wMPUBase]
	jne     short IWCSPR_No_MPU
	mov     dx,06h
	jmp     short IW_CSPR_Call_SBOS
IWCSPR_No_MPU:  
	; Check port
	sub     DX,[_gIWI.iwi_wSynthBase2X]
	cmp     DX,0Eh
	jne     short IW_CSPR_Dont_Call_SBOS
	mov     DX,03h

IW_CSPR_Call_SBOS:
	call    IW_Schedule_SBOS_Call
IW_CSPR_Dont_Call_SBOS:         
	ret

	
EndProc IW_Check_SBOS_Port_Read
	  
	
BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Enable_SBOS_Trapping
;
;   DESCRIPTION:
;
;   ENTRY:                        
;       EBX - SBOS Virtual Machine
;
;   EXIT:
;
;   USES:
;       EDX
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc IW_Enable_SBOS_Trapping
	xor     edx,edx
	mov     dx,389h
	VMMcall Enable_Local_Trapping
	mov     dx,06h
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Enable_Local_Trapping
	mov     dx,09h
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Enable_Local_Trapping
	mov     dx,0Ch
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Enable_Local_Trapping
	mov     dx,0Eh
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Enable_Local_Trapping

	test    [_gIWI.iwi_wFlags],IWI_FLAG_MPU_ACTIVE
	jz      short IWEST_No_MPU
	mov     dx,WORD PTR [_gIWI.iwi_wMPUBase]
	VMMcall Enable_Local_Trapping
	inc     dx
	VMMcall Enable_Local_Trapping
	
IWEST_No_MPU:   
	ret
	
EndProc IW_Enable_SBOS_Trapping

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Disable_SBOS_Trapping
;
;   DESCRIPTION:
;
;   ENTRY:                        
;       EBX - SBOS Virtual Machine
;
;   EXIT:
;
;   USES:
;       EDX
;
;---------------------------------------------------------------------------;
EndDoc

BeginProc IW_Disable_SBOS_Trapping
	xor     edx,edx
	mov     dx,389h
	VMMcall Disable_Local_Trapping
	mov     dx,06h
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Disable_Local_Trapping
	mov     dx,09h
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Disable_Local_Trapping
	mov     dx,0Ch
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Disable_Local_Trapping
	mov     dx,0Eh
	add     dx,WORD PTR [_gIWI.iwi_wSynthBase2X]
	VMMcall Disable_Local_Trapping

	test    [_gIWI.iwi_wFlags],IWI_FLAG_MPU_ACTIVE
	jz      short IWDST_No_MPU
	mov     dx,WORD PTR [_gIWI.iwi_wMPUBase]
	VMMcall Disable_Local_Trapping
	inc     dx
	VMMcall Disable_Local_Trapping
	
IWDST_No_MPU:   
	ret
	
EndProc IW_Disable_SBOS_Trapping

VxD_LOCKED_CODE_ENDS

end
