	page    60, 132
;******************************************************************************
	title   IWAPI.ASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   NAME:  IWAPI.ASM $Revision: 1.16 $
;;  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: iwapi.asm $
; Revision 1.16  1995/12/14 14:12:42  unknown
; Added leading underscore to wDriver_segment, wDriver_offset and IW_Schedule
; _Driver_Callback to allow them to be accessed from C.
; Revision 1.15  1995/12/04 09:27:52  teckert
; Fixed a bug with the VM_Not_Executeable code, couldn't suspend the VM
; during this call.
; Revision 1.14  1995/11/28 10:55:16  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.13  1995/11/15 09:22:24  sdsmith
; Fixed a few warnings about short jumps
; Revision 1.12  1995/11/10 15:00:24  sdsmith
; Changes for Win95 compatability
; Revision 1.11  1995/11/08 14:43:13  sdsmith
; Revision 1.10  1995/10/12 19:28:29  teckert
; Added support for Direct Sound acquisition
; Revision 1.9  1995/10/07 15:18:19  teckert
; Fixed DMA 2 resource reporting that caused "Full Duplex" bug
; Revision 1.8  1995/09/21 16:04:48  teckert
; Added Read_DMA_Count API function
; Revision 1.7  1995/09/08 11:03:55  teckert
; Rolled in the windows 95 modifications
; Revision 1.6  1995/05/04 17:28:21  teckert
; Revision 1.5  1995/04/18 15:31:50  teckert
; Added priority access for windows mixer
; Revision 1.4  1995/04/12 13:23:31  teckert
; Added MPU401 to sbos support
; Revision 1.3  1995/04/06 18:41:24  teckert
; Added "Boss in a box" to driver
; Revision 1.2  1995/03/20 16:26:39  teckert
; Added file header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;******************************************************************************
;
;   Functional Description:
;      Provides V86/PM API for DOS apps or Windows driver.
;
;******************************************************************************

	.386p

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

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

VxD_ICODE_SEG
EXTRN   VIWD_Sys_Crit_Init:NEAR
EXTRN   VIWD_Device_Init:NEAR
VxD_ICODE_ENDS

VxD_CODE_SEG
EXTRN   VIWD_System_Exit:NEAR
EXTRN   VIWD_API_Success:NEAR
EXTRN   VIWD_API_Failed:NEAR

IFDEF _WIN95
EXTRN	_VIWD_CD_Device_Init:NEAR
EXTRN	_VIWD_Game_Device_Init:NEAR
ENDIF

VxD_CODE_ENDS

VxD_LOCKED_CODE_SEG
EXTRN   IW_DisableList:NEAR
EXTRN   IW_EnableList:NEAR
EXTRN   IW_Enable_SBOS_Trapping:NEAR
EXTRN   IW_Disable_SBOS_Trapping:NEAR
EXTRN   _IW_Schedule_Driver_Callback:NEAR
VxD_LOCKED_CODE_ENDS

;==============================================================================
;                      P A G E A B L E   D A T A
;==============================================================================

VxD_DATA_SEG

;------------------------------------------------------------------------------
;                 Acquisition Promotion Table
;------------------------------------------------------------------------------

; the following are the acquisition groups
IWAR_VOICES     equ     (IWAR_SOMEVOICES OR IWAR_ALLVOICES)
IWAR_MEMORY     equ     (IWAR_SOMEMEMORY OR IWAR_ALLMEMORY)
IWAR_CODEC      equ     (IWAR_CODECPLAY OR IWAR_CODECREC OR IWAR_CODECMIX)
IWAR_PORT       equ     (IWAR_PORTIN OR IWAR_PORTOUT)
IWAR_VSB        equ     (IWAR_VSNDBLST OR IWAR_VADLIB)


; This is the all-or-nothing version of the VxD so that each resource always pulls in
; every other resource.  Therefore, all the codes in the promotion table are 0xFFFF
; Except: the CODEC mixer can be allocated separately
IW_PROMOTION_TABLE  LABEL DWORD
	     dd IWAR_ALL				; IWAR_IRQ1
	     dd IWAR_ALL				; IWAR_IRQ2
	     dd IWAR_ALL				; IWAR_DMA1
	     dd IWAR_ALL       			; IWAR_DMA2
	     dd IWAR_ALL				; IWAR_SOMEVOICES
	     dd IWAR_ALL				; IWAR_ALLVOICES
	     dd IWAR_ALL				; IWAR_SOMEMEMORY
	     dd IWAR_ALL				; IWAR_ALLMEMORY
	     dd IWAR_ALL				; IWAR_CODECPLAY
	     dd IWAR_ALL				; IWAR_CODECREC
	     dd IWAR_ALL           		; IWAR_CODECMIX
	     dd IWAR_ALL       			; IWAR_PORTIN
	     dd IWAR_ALL       			; IWAR_PORTOUT
	     dd IWAR_ALL       			; IWAR_VADLIB
	     dd IWAR_ALL       			; IWAR_VSNDBLST
	     dd IWAR_ALL    			; IWAR_VMPU401   
	     dd 00010000h
	     dd 00020000h
IW_MAX_FLAG    equ ($-IW_PROMOTION_TABLE)/4

VxD_DATA_ENDS

VxD_LOCKED_DATA_SEG

;------------------------------------------------------------------------------
;                 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 wSBOS_segment:NEAR
EXTRN wSBOS_offset:NEAR
EXTRN _wDriver_segment:NEAR
EXTRN _wDriver_offset:NEAR
EXTRN INTERWAV_CB_Offset:NEAR

VxD_LOCKED_DATA_ENDS


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

VxD_CODE_SEG

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


BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_Get_Version, PMAPI, RMAPI
;
;   DESCRIPTION:
;       Version call for API entry point
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_Get_Version (0)
;
;   EXIT:
;       Client_EFLAGS = carry clear
;       Client_AX = Version
;
;   USES:
;       FLAGS, EAX, ECX, EDX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_Get_Version

	Assert_Client_Ptr ebp

        mov     [ebp.Client_AX], VIWD_VERSION
	clc
	ret

EndProc IW_API_Get_Version

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_PromoteAcquisitionRequest
;
;   DESCRIPTION:
;       Promotes an acquisition request to include resourses that are
;       necessarily included with the requested resourses.
;
;   ENTRY:
;       EAX = resource code
;
;   EXIT:
;       EAX = promoted resource code
;
;   USES:
;       EAX, EBX, ECX, EDX, EDI, FLAGS
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_PromoteAcquisitionRequest

	mov     edi,offset32 IW_PROMOTION_TABLE
	mov     ecx,IW_MAX_FLAG
	mov     ebx,1
	xor     edx,edx
IWPAR_LOOP:
	test    eax,ebx         ; is this flag set?
	jz      short IWPAR_NEXT; No, go to the next resource
	or      edx,[edi]       ; Yes, add its resources
	cmp     edx,IWAR_ALL    ; is edx maxed out?
	je      short IWPAR_DONE; Yes, exit loop
IWPAR_NEXT:
	add     edi,4
	rol     ebx,1
	loop    IWPAR_LOOP
IWPAR_DONE:
	mov     eax,edx         ; replace resource code with promoted code
	ret
	
EndProc IW_PromoteAcquisitionRequest

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_Acquire_InterWave, PMAPI, RMAPI
;
;   DESCRIPTION:
;       Acquires InterWave Resource(s)
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_Acquire_InterWave (1)
;       Client_AX = resource code, loword
;       Client_DI = resource code, hiword
;
;   EXIT:
;       Client_EFLAGS = success, carry clear; failure, carry set
;       Client_AX = promoted resource code, loword
;       Client_DI = promoted resource code, hiword
;       Client_DX = resources that need to be reinitialized, loword
;                   i.e. had a previous owner not equal to new owner
;       Client_SI = resources that need to be reinitialized, hiword
;
;   USES:
;       FLAGS, EAX, ECX, EDX, EDI, ESI
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_Acquire_InterWave

	movzx   eax,WORD PTR[ebp.Client_DI]
	rol     eax,16
	mov     ax,WORD PTR[ebp.Client_AX]
	
	call IW_Acquire_InterWave
	     
	jnc     short IWA_CLEAR_CARRY
	or      [ebp.Client_Flags], CF_Mask
	jmp     short IWA_CONTINUE
IWA_CLEAR_CARRY:
	and     [ebp.Client_Flags], not CF_Mask

IWA_CONTINUE:   
	mov     WORD PTR[ebp.Client_AX],ax
	ror     eax,16
	mov     WORD PTR[ebp.Client_DI],ax

; if DX is not equal to zero and we have reconfigured then set the reconfig bit
	cmp	edx,edx
        jz      short IWA_DX_EQ_0
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV_RECONFIG
        jz      short IWA_DX_EQ_0
	or	eax,IWAR_RECONFIG
	and	[_gIWI.iwi_bDeviceInit],not IWINFO_DEV_RECONFIG
IWA_DX_EQ_0:
	mov     WORD PTR[ebp.Client_DX],dx
	ror     edx,16
	mov     WORD PTR[ebp.Client_SI],dx
	
	ret

EndProc IW_API_Acquire_InterWave

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Acquire_InterWave
;
;   DESCRIPTION:
;       Acquires InterWave Resource(s), internal entry point
;
;   ENTRY:
;       EAX = Requested Resources
;       EBX = Current VM Handle
;
;   EXIT:
;       carry clear if successful, set otherwise
;       EAX = promoted resource code
;       EDX = re-initialize resource code
;
;   USES:
;       FLAGS, EAX, EBX, ECX, EDX, EDI, ESI
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_Acquire_InterWave

	Assert_Client_Ptr ebp
	
	; if pnp device zero is not initialized fail
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV0_INIT
	jnz	short IWAR_DEVICE_INIT_OK
	jmp	IWA_FailedAcquisition
	
IWAR_DEVICE_INIT_OK:
	
	; first promote the request
	push    ebx
	call IW_PromoteAcquisitionRequest
	pop     ebx
	
	; store the promoted request for the client
	
	; setup a register so we can track which resources are newly acquired
	xor     edx,edx
	mov     ecx,IWAR_NUMRESOURCES
	mov     edi,offset32 _gIW_ResTbl
	mov     esi,1
	; go through all the resources marking the new ones with our new owner
	; if one comes up that has a previous owner reset all the ones changed
	; so far and return the failure code    
IWAR_CHECK_RESOURCES:
	test    eax,esi
	jz      short IWAR_CHECK_NEXT_RESOURCE
	cmp     DWORD PTR[edi.iwri_dwCurOwner],0
	jne     short IWAR_HAS_OWNER
	mov     DWORD PTR[edi.iwri_dwCurOwner],ebx
IFNDEF NO_DIRECTSOUND
	test	eax,IWAR_DIRECT                 ; Is requestor a DS driver?
	jz	short IWAR_REQNOTDIRECT			
	or	WORD PTR[edi.iwri_wStatus],IWRIS_DIRECT
IWAR_REQNOTDIRECT:	
ENDIF
	or      edx,esi
	jmp     short IWAR_CHECK_NEXT_RESOURCE
IWAR_HAS_OWNER:
	cmp     DWORD PTR[edi.iwri_dwCurOwner],ebx
	jne     short IWAR_FAILED_CHECK         ; wrong owner
	
IFNDEF NO_DIRECTSOUND
	test	eax,IWAR_DIRECT                 ; Is requestor a DS driver?
	jz	short IWAR_NOTDIRECT			
	test	WORD PTR[edi.iwri_wStatus],IWRIS_DIRECT	; Is owner a DS driver?
	jz      short IWAR_FAILED_CHECK         ; requestor is a DS driver, owner is not
	jmp	short IWAR_CHECK_NEXT_RESOURCE  ; requestor is a DS driver, so is owner
IWAR_NOTDIRECT:	
	test	WORD PTR[edi.iwri_wStatus],IWRIS_DIRECT	; Is owner a DS driver?
	jnz     short IWAR_FAILED_CHECK         ; requestor is not a DS driver, owner is
						; requestor is not a DS driver, neither is owner
ENDIF
	jmp     short IWAR_CHECK_NEXT_RESOURCE

IWAR_CHECK_NEXT_RESOURCE:
	rol     esi,1
	add     edi,(size IWRESOURCEINFO)
	loop    IWAR_CHECK_RESOURCES
	jmp     short IWAR_SETUP_RESOURCES
	
IWAR_FAILED_CHECK:
	mov     ecx,IWAR_NUMRESOURCES
	mov     edi,offset32 _gIW_ResTbl
	mov     esi,1
IWAR_RESET_RESOURCES:
	test    edx,esi
	jz      short IWAR_RESET_NEXT_RESOURCE
	mov     DWORD PTR[edi.iwri_dwCurOwner],0
	sub     edx,esi                 ; clear that edx flag
        jz      IWA_FailedAcquisition   ; if edx==0 we're done
IWAR_RESET_NEXT_RESOURCE:
	rol     esi,1
	add     edi,(size IWRESOURCEINFO)
	loop    IWAR_RESET_RESOURCES
	
    jmp     IWA_FailedAcquisition
	
IWAR_SETUP_RESOURCES:
    push    eax             ; save this register for return information
	mov     ecx,IWAR_NUMRESOURCES
	mov     edi,offset32 _gIW_ResTbl
	mov     esi,1
IWAR_SETUP_LOOP:
	test    edx,esi
	push    ecx
	push	ebx
	jz      short IWAR_SETUP_NEXT_RESOURCE
	; if the last owner of the resource was the same, clear the re-init flag
	cmp		ebx,[edi.iwri_dwPrevOwner]
	jnz		short IWAR_SETUP_REINIT
	not		esi
	and		edx,esi
	not		esi
IWAR_SETUP_REINIT:
	mov		[edi.iwri_dwPrevOwner],ebx
	VMMCall	Get_Sys_VM_Handle			; we always originally allow acess to the system VM
										; ( so we can call the sleep function ).
	
	mov     ax,[edi.iwri_wStatus]
	and     ax,IWRIS_TYPE

	cmp     ax,IWRIS_IRQ
	je      short IWAR_SETUP_IRQ
	
	cmp     ax,IWRIS_DMA
	je      short IWAR_SETUP_DMA
	
	cmp     ax,IWRIS_PORTS
	je      short IWAR_SETUP_PORT

IWAR_SETUP_NEXT_RESOURCE:
	pop		ebx
	pop     ecx
	rol     esi,1
	add     edi,(size IWRESOURCEINFO)
	loop    IWAR_SETUP_LOOP
	pop     eax
IWAR_SETUP_COMPLETE:
    jmp     short IWA_Success

IWAR_SETUP_IRQ:
	; If it is an IRQ resource match the physical mask state of the
	; IRQ to the virtual mask state for this VM
	
	;Check the virtual state for the interrupt mask for each InterWave IRQ
	;for this virtual machine and make the physical state match it.
	mov     eax,[edi.iwri_dwResourceHandle] ;handle returned from VPICD_Virtualize_IRQ
	VxDcall VPICD_Get_Complete_Status
	test    ecx,VPICD_Stat_Virt_Mask
	jz      short IWA_Virtually_Unmasked
	
	;IRQ is virtually masked
	VxDcall VPICD_Physically_Mask
	jmp     short IWA_No_IRQ_Mask_Change
	
IWA_Virtually_Unmasked:
	;IRQ is virtually unmasked
	VxDcall VPICD_Physically_Unmask

IWA_No_IRQ_Mask_Change:                                                  
	jmp     IWAR_SETUP_NEXT_RESOURCE

IWAR_SETUP_PORT:
	; If it is a port resource disable trapping for this VM
	push    esi
	push    edx
	mov     esi,[edi.iwri_dwResourceHandle]
	call IW_DisableList
	pop     edx
	pop     esi
	jmp     IWAR_SETUP_NEXT_RESOURCE

IWAR_SETUP_DMA:
	; The DMA section is not currently used, fall through.
	; If its a DMA resource and this VM is the system VM and the translation
	; is not currently disabled for the DMA channel(s) then disable translation
;       VMMcall Test_Sys_VM_Handle
;       jne     short IWA_NEXT_RESOURCE
;       test    [edi.iwri_wStatus],IWRIS_FLAG_DMA_DTRAN
;       jnz     short IWA_Success
;       mov     eax,[_gIWI.iwi_dwDMA1Handle]
;       VxDcall VDMAD_Disable_Translation
;       or      [_gIWI.iwi_wFlags],IWI_FLAG_DMA_DTRAN
;       test    [_gIWI.iwi_wFlags],IWI_FLAG_ONE_DMA
;       jnz     short IWA_Success
;       mov     eax,[_gIWI.iwi_dwDMA2Handle]
;       VxDcall VDMAD_Disable_Translation
	jmp     IWAR_SETUP_NEXT_RESOURCE
	
IWA_FailedAcquisition:
	stc
	ret

IWA_Success:
	clc
	ret

EndProc IW_Acquire_InterWave

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_Release_InterWave, PMAPI, RMAPI
;
;   DESCRIPTION:
;       Releases InterWave Resource(s)
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_Release_InterWave (2)
;       Client_AX = resource code
;
;   EXIT:
;       Client_EFLAGS = carry clear
;       Client_AX = Version
;
;   USES:
;       FLAGS, EAX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_Release_InterWave

	movzx   eax,WORD PTR[ebp.Client_DI]
	rol     eax,16
	mov     ax,WORD PTR[ebp.Client_AX]
	
	call IW_Release_InterWave
	
	ret

EndProc IW_API_Release_InterWave

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_Release_InterWave
;
;   DESCRIPTION:
;       Releases InterWave Resource(s), internal entry point
;
;   ENTRY:
;       EAX = resource code
;       EBX = Current VM Handle
;
;   EXIT:
;       carry clear
;
;   USES:
;       FLAGS, EAX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_Release_InterWave

	Assert_Client_Ptr ebp

	mov		edx,ebx
	VMMCall Get_Sys_VM_Handle

	mov     ecx,IWAR_NUMRESOURCES
	mov     edi,offset32 _gIW_ResTbl
	mov     esi,1
	
IWR_RELEASE_RESOURCE:
	test    eax,esi
	push	eax
	jz      short IWR_NEXT_RESOURCE
	cmp     edx,[edi.iwri_dwCurOwner]
	jnz     short IWR_NEXT_RESOURCE
	sub     eax,esi
	mov     [edi.iwri_dwCurOwner],0
IFNDEF NO_DIRECTSOUND
	and	WORD PTR[edi.iwri_wStatus],NOT IWRIS_DIRECT
ENDIF	
	mov     [edi.iwri_dwPrevOwner],edx
	
	mov     ax,[edi.iwri_wStatus]
	and     ax,IWRIS_TYPE

	cmp     ax,IWRIS_IRQ
    je      short IWR_RELEASE_IRQ
	
	cmp     ax,IWRIS_DMA
    je      short IWR_RELEASE_DMA
	
	cmp     ax,IWRIS_PORTS
	je      short IWR_RELEASE_PORT
	
IWR_NEXT_RESOURCE:
	pop		eax
	add     edi,(size IWRESOURCEINFO)
	rol     esi,1
	loop    IWR_RELEASE_RESOURCE
    jmp     short IWR_Success
			
IWR_RELEASE_PORT:
	push    esi
	push    ecx
	push    edx
	mov     esi,[edi.iwri_dwResourceHandle]
	call IW_EnableList
	pop     edx
	pop     ecx
	pop     esi
	jmp     IWR_NEXT_RESOURCE                
		 
IWR_RELEASE_IRQ:
	;If its an IRQ resource physically mask the IRQ, issue an EOI to clear any pending
	;interrupts and clear any pending virtual interrupt requests
	mov     eax,[edi.iwri_dwResourceHandle]     ;handle returned from VPICD_Virtualize_IRQ
	VxDcall VPICD_Physically_Mask
	VxDcall VPICD_Phys_EOI
	VxDcall VPICD_Clear_Int_Request
	jmp     IWR_NEXT_RESOURCE                

IWR_RELEASE_DMA:        
	;If its a DMA resource and it has translation disabled, re-enable it    
;       test    [_gIWI.iwi_wFlags],IWI_FLAG_DMA_DTRAN
;       jz              short IWR_Success
;       mov             eax,[_gIWI.iwi_dwDMA1Handle]
;       VxDcall VDMAD_Enable_Translation
;       and             [_gIWI.iwi_wFlags],NOT (IWI_FLAG_DMA_DTRAN)
	jmp     IWR_NEXT_RESOURCE
	
IWR_Fail:
	stc
	ret
	
IWR_Success:
	clc
	ret

EndProc IW_Release_InterWave

;---------------------------------------------------------------------------;
;
;   IW_Transfer_Access
;
;   DESCRIPTION:
;       Transfers access to the indicated ports and IRQ's from the From VM
;		to the To VM.  Used to allow system VM access to the hardware after
;		it has been acquired for a DOS Box.
;
;   ENTRY:
;       EAX = Requested Resources
;       EBX = From VM Handle
;		EDX = To VM Handle
;
;   EXIT:
;       carry clear if successful, set otherwise
;
;   USES:
;       FLAGS, EAX, EBX, ECX, EDX, EDI, ESI
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_Transfer_Access

	; first promote the request
	push    ebx
	push	edx
	call IW_PromoteAcquisitionRequest
	pop		edx
	pop     ebx
	
	mov     ecx,IWAR_NUMRESOURCES
	mov     edi,offset32 _gIW_ResTbl
	mov     esi,1
IWTA_XFER_LOOP:
	test    eax,esi
	push    ecx
	push	eax
	jz      short IWTA_XFER_NEXT_RESOURCE

	mov     ax,[edi.iwri_wStatus]
	and     ax,IWRIS_TYPE

	cmp     ax,IWRIS_IRQ
	je      short IWTA_XFER_IRQ
	
	cmp     ax,IWRIS_DMA
	je      short IWTA_XFER_DMA
	
	cmp     ax,IWRIS_PORTS
	je      short IWTA_XFER_PORT

IWTA_XFER_NEXT_RESOURCE:
	pop		eax
	pop     ecx
	rol     esi,1
	add     edi,(size IWRESOURCEINFO)
	loop    IWTA_XFER_LOOP
IWTA_XFER_COMPLETE:
    jmp     short IWTA_Success

IWTA_XFER_IRQ:
	;If its an IRQ resource physically mask the IRQ, issue an EOI to clear any pending
	;interrupts and clear any pending virtual interrupt requests
	mov     eax,[edi.iwri_dwResourceHandle]     ;handle returned from VPICD_Virtualize_IRQ
	VxDcall VPICD_Physically_Mask
	VxDcall VPICD_Phys_EOI
	VxDcall VPICD_Clear_Int_Request

	; If it is an IRQ resource match the physical mask state of the
	; IRQ to the virtual mask state for this VM
	
	;Check the virtual state for the interrupt mask for each InterWave IRQ
	;for this virtual machine and make the physical state match it.
	xchg	ebx,edx
	mov     eax,[edi.iwri_dwResourceHandle] ;handle returned from VPICD_Virtualize_IRQ
	VxDcall VPICD_Get_Complete_Status
	test    ecx,VPICD_Stat_Virt_Mask
	jz      IWTA_Virtually_Unmasked
	
	;IRQ is virtually masked
	VxDcall VPICD_Physically_Mask
	jmp     IWTA_No_IRQ_Mask_Change
	
IWTA_Virtually_Unmasked:
	;IRQ is virtually unmasked
	VxDcall VPICD_Physically_Unmask

IWTA_No_IRQ_Mask_Change:                                                  
	xchg	ebx,edx
	jmp     IWTA_XFER_NEXT_RESOURCE

IWTA_XFER_PORT:
	; If it is a port resource disable trapping for this VM
	push    esi
	push    ecx
	push    edx
	mov     esi,[edi.iwri_dwResourceHandle]
	call IW_EnableList
	pop     edx
	pop     ecx
	pop     esi

	xchg	ebx,edx
	
	push    esi
	push    edx
	mov     esi,[edi.iwri_dwResourceHandle]
	call IW_DisableList
	pop     edx
	pop     esi
    
	xchg	ebx,edx

	jmp     IWTA_XFER_NEXT_RESOURCE

IWTA_XFER_DMA:
	; The DMA section is not currently used, fall through.
	jmp     IWTA_XFER_NEXT_RESOURCE
	
IWTA_Failed_Transter:
	stc
	ret

IWTA_Success:
	clc
	ret

EndProc IW_Transfer_Access

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_Register_SBOS_Support, PMAPI, RMAPI
;
;   DESCRIPTION:
;       Registers the callback for the SBOS driver function
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_Register_SBOS_Support (3)
;
;   EXIT:
;       Client_EFLAGS = carry clear
;       Client_AX = Version
;
;   USES:
;       FLAGS, EAX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_Register_SBOS_Support
						     
	;First check to see if sbos has already been registered for this VM
	test    [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	jnz     short IW_ARSBS_Installed_OK
	
	;The VxD may need to access functions in the driver to implement SBOS,
	;this API will be used to register with the VxD the address of the 
	;function in the driver that the VxD can call
	mov     ax,[ebp.Client_ES]
	mov     WORD PTR[wSBOS_segment],ax
	mov     ax,[ebp.Client_DI]      
	mov     WORD PTR[wSBOS_offset],ax
		
	mov     eax,IWAR_IWSBOS
	call    IW_Acquire_InterWave
	jnc     short IW_ARSBS_Acquire_OK
	ret
	
IW_ARSBS_Acquire_OK:
	or		edx,edx
	jz		IW_ARSBS_No_Callback
	           
	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_ARSBS_No_Callback:
	
	mov     [_gIWI.iwi_dwSBOSOwner],ebx
	or      [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	test    [ebp.Client_SI],1
	jz      short IW_ARSBS_No_MPU
	or      [_gIWI.iwi_wFlags],IWI_FLAG_MPU_ACTIVE   
IW_ARSBS_No_MPU:
	call    IW_Enable_SBOS_Trapping
IW_ARSBS_Installed_OK:
	mov     [ebp.Client_DX],0       ; Signal SBOS Loader to Load
	clc
	ret

EndProc IW_API_Register_SBOS_Support

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_SBOS_Functions, PMAPI, RMAPI
;
;   DESCRIPTION:
;       API for use by driver-level SBOS functions
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_SBOS_Functions (4)
;
;   EXIT:
;       Client_EFLAGS = carry clear
;       Client_AX = 
;
;   USES:
;       FLAGS, EAX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_SBOS_Functions

		;This function gives the driver level SBOS code access to the VxD.
	clc
	ret

EndProc IW_API_SBOS_Functions

BeginDoc
;---------------------------------------------------------------------------;
;
;   IW_API_Register_Driver_Callback, PMAPI, RMAPI
;
;   DESCRIPTION:
;       Releases InterWave Resource(s)
;
;   ENTRY:
;       EBX = Current VM Handle
;       EBP = Pointer to Client Register Structure.
;
;       Client_DX = InterWave_API_Register_Driver_Callback (5)
;
;   EXIT:
;       Client_EFLAGS = carry clear
;       Client_AX = Version
;
;   USES:
;       FLAGS, EAX
;
;---------------------------------------------------------------------------;
EndDoc
BeginProc IW_API_Register_Driver_Callback

	;The VxD may need to access functions in the driver to implement SBOS,
	;this API will be used to register with the VxD the address of the 
	;function in the driver that the VxD can call
	mov     ax,[ebp.Client_ES]
        mov     WORD PTR[_wDriver_segment],ax
	mov     ax,[ebp.Client_DI]      
        mov     WORD PTR[_wDriver_offset],ax

        ;Now save the current DS so we can restore it before a callback to the
        ;driver
        mov     ax,[ebp.Client_DS]
        mov     WORD PTR[_gIWI.iwi_wDriverDS],ax
		
	clc
	ret

EndProc IW_API_Register_Driver_Callback

VxD_CODE_ENDS

VxD_LOCKED_CODE_SEG

latch db 0,1,0,2,0,3,4,5

;---------------------------------------------------------------------------;
;
;   VIWD_VM_Not_Executeable
;
;   DESCRIPTION:
;       This procedure checks whether the VM being destroyed owns any resources.
;       If it does, then iwri_dwCurOwner field is cleared.
;
;   ENTRY:
;       EBX = handle of VM being destroyed
;       EDX = Flags: VNE_Crashed, VNE_Nuked, VNE_CreateFail,
;                    VNE_CrInitFail, VNE_InitFail
;
;   EXIT:
;       Carry clear
;
;   USES:
;       FLAGS, EBX, ECX, EDI, ESI
;
;---------------------------------------------------------------------------;

BeginProc VIWD_VM_Not_Executeable
		 
	test    [_gIWI.iwi_wFlags],IWI_FLAG_SBOS_ACTIVE
	jz      IWNE_Not_SBOS_VM
	cmp     [_gIWI.iwi_dwSBOSOwner],ebx
	jne     IWNE_Not_SBOS_VM
	mov     [_gIWI.iwi_dwSBOSOwner],0
	and     [_gIWI.iwi_wFlags],not (IWI_FLAG_SBOS_ACTIVE OR IWI_FLAG_MPU_ACTIVE)

	; restore the DMA channels to thier previouse settings
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	push	esi
	
	movzx	eax,BYTE PTR [_gIWI.iwi_bDMA2]
	add	eax,offset32 latch
	movzx	edi,BYTE PTR[eax]

	movzx	eax,BYTE PTR [_gIWI.iwi_bDMA1]
	cmp	al,[_gIWI.iwi_bDMA2]
        jne     short IWNE_Two_DMAs
	mov	edi,8	
IWNE_Two_DMAs:
	rol	edi,3
	add	eax,offset32 latch
        movzx   esi,BYTE PTR[eax]
        add     edi,esi			; edi now contains dma control register value
        
        mov	dx,[_gIWI.iwi_wSynthBase3X]
        add	dx,3		; reg_index
        mov	al,059h		; IW_ICMPTI
        out	dx,al
        add	dx,2		; reg_data_high
        in	al,dx
        mov	bl,al		; bl = IW_ICMPTI value
        or	al,010h		; open the back door
        out	dx,al
        
        mov	dx,[_gIWI.iwi_wSynthBase2X]
        add	dx,0Fh		; reg_2xFcontrol
        xor	ax,ax
        out	dx,al
        
        mov	dx,[_gIWI.iwi_wSynthBase2X] ; reg_mixer
        in	al,dx		; read mixer mask
        mov	bh,al		; bh = mixer mask
        out	dx,al
        add	dx,0Bh		; reg_2xBindexed
        mov	eax,edi
        or	al,80h
        out	dx,al
        
        mov	dx,[_gIWI.iwi_wSynthBase2X] ; reg_mixer
        mov	al,bh		; bh = mixer mask
        out	dx,al
        add	dx,0Bh		; reg_2xBindexed
        mov	eax,edi
        out	dx,al
	
        mov	dx,[_gIWI.iwi_wSynthBase3X]
        add	dx,3		; reg_index
        mov	al,059h		; IW_ICMPTI

	add	dx,2		; reg_data_high
	mov	al,bl		; bl = IW_ICMPTI value
	out	dx,al		; close the back door
	
	pop	esi
	pop	edi
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	
	call    IW_Disable_SBOS_Trapping
IWNE_Not_SBOS_VM:     
                           
	; iterate through the resource list looking for resources with
	; EBX as the current owner
	
	xor		eax,eax	
	mov     edi,offset32 _gIW_ResTbl
	mov     ecx,IWAR_NUMRESOURCES
	mov     esi,1

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

	or		eax,eax
	jz		IWNE_Success
	
	mov		edx,ebx

	push	eax           
	push	edx
	xor		edx,edx
	mov		al,IW_KERNEL_WAKE
        call    _IW_Schedule_Driver_Callback
	pop		edx
	pop		eax
	
	push    ecx
	push    edi
	push    esi
	call    IW_Release_InterWave
	pop     esi
	pop     edi
	pop     ecx   

IWNE_Success:	
	clc
	ret

EndProc VIWD_VM_Not_Executeable


VxD_LOCKED_CODE_ENDS
VxD_CODE_SEG

BeginDoc
;** IW_API_Get_Buffer
;*
;*  DESCRIPTION:
;*
;*  ENTRY:
;*      EBX             :       VM Handle.
;*      EBP             :       Client register structure.
;*      Client AX       ;       Number of 4K pages
;*
;*  EXIT:
;*      Client:
;*              Carry clear     :  if successfull
;*              Carry set       : failure
;*
;*  NOTES:
;*
EndDoc

BeginProc IW_API_Get_Buffer

	mov     eax,[_gIWI.iwi_dwDMALinear]
	mov     ecx,[_gIWI.iwi_dwDMABufferSize]
	jecxz   short IWGB_No_Buffer
	dec     ecx
	VMMcall Map_Lin_To_VM_Addr
IWGB_No_Buffer:
	mov [ebp.Client_CX],cx
	mov eax,[_gIWI.iwi_dwDMAPhysical]
	mov [ebp.Client_AX],ax
	ror eax,16
	mov [ebp.Client_BX],ax
	jmp VIWD_API_Success
	    
EndProc IW_API_Get_Buffer


BeginDoc
;** IW_API_Get_Resource_Config
;*
;*  DESCRIPTION:
;*
;*  ENTRY:
;*      EBX             :       VM Handle.
;*      EBP             :       Client register structure.
;*      Client AX       ;       Resource Code
;*
;*  EXIT:
;*      Client AX       ;       Resource Value
;*      Client:
;*              Carry clear     :  if successfull
;*              Carry set       : failure
;*
;*  NOTES:
;*
EndDoc

BeginProc IW_API_Get_Resource_Config
        push	eax
        
        mov	ax,[ebp.Client_AX]
        
        ; Device 0, the Audio Device
        cmp	ax,IWGRC_CODEC_BASE
        jg      IWGRC_Check_Device_1
	
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV0_INIT
	jz	IWGRC_Failed
	        
        mov	dx,[_gIWI.iwi_wSynthBase2X]
	cmp	ax,IWGRC_SYNTH_BASE_2X
	je	IWGRC_Got_Resource

        mov	dx,[_gIWI.iwi_wSynthBase3X]
	cmp	ax,IWGRC_SYNTH_BASE_3X   
	je	IWGRC_Got_Resource
	
        movzx	dx,BYTE PTR [_gIWI.iwi_bIRQ1]
	cmp	ax,IWGRC_IRQ_1
	je	IWGRC_Got_Resource

        movzx	dx,BYTE PTR [_gIWI.iwi_bIRQ2]
	cmp	ax,IWGRC_IRQ_2
	je	IWGRC_Got_Resource

        movzx	dx,BYTE PTR [_gIWI.iwi_bDMA1]
	cmp	ax,IWGRC_DMA_1
	je	IWGRC_Got_Resource

        movzx   dx,BYTE PTR [_gIWI.iwi_bDMA2]
	cmp	ax,IWGRC_DMA_2
	je	IWGRC_Got_Resource

        mov	dx,[_gIWI.iwi_wCodecBase]
	jmp	IWGRC_Got_Resource
        
        ; Device 1, the CDROM interface
IWGRC_Check_Device_1:
        cmp	ax,IWGRC_CD_DMA
        jg	short IWGRC_Check_Device_2
	
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV1_INIT
        jnz     short IWGRC_Device_1_Ready
	        
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEVICE_ID_INIT
	jz	IWGRC_Failed
	
;	call	Read_CDROM_Configuration
IFDEF _WIN95
	call	_VIWD_CD_Device_Init
ENDIF
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV1_INIT
	jz	IWGRC_Failed
	
IWGRC_Device_1_Ready:                   
	mov	dx,[_gIWI.iwi_wCDBase]
	cmp	ax,IWGRC_CD_BASE      
	je	IWGRC_Got_Resource
	
	mov	dx,[_gIWI.iwi_wATAPIBase]
	cmp	ax,IWGRC_ATAPI_BASE
	je	IWGRC_Got_Resource
	
	movzx	dx,BYTE PTR[_gIWI.iwi_bCDIRQ]
	cmp	ax,IWGRC_CD_IRQ
	je	IWGRC_Got_Resource
	
	movzx	dx,BYTE PTR[_gIWI.iwi_bCDDMA]
	jmp	short IWGRC_Got_Resource
	
        
        ; Device 2, the Game interface
IWGRC_Check_Device_2:
	cmp	ax,IWGRC_GAME_BASE
	jne	short IWGRC_Check_Device_3
                       
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV2_INIT
        jnz     short IWGRC_Device_2_Ready
	        
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEVICE_ID_INIT
IFDEF _WIN95
	jz	IWGRC_Failed
ELSE
        jz      short IWGRC_Failed
ENDIF
	
;	call	Read_Joystick_Configuration
IFDEF _WIN95
	call	_VIWD_Game_Device_Init
ENDIF
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV2_INIT
        jz      short IWGRC_Failed
	
IWGRC_Device_2_Ready:
	mov	dx,[_gIWI.iwi_wGameBase]
        jmp     short IWGRC_Got_Resource

        ; Device 3, Adlib Emulation Ports and SB IRQ
IWGRC_Check_Device_3:        
	cmp	ax,IWGRC_SB_IRQ
        jg      short IWGRC_Check_Device_4
	
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV3_INIT
        jz      short IWGRC_Failed
	        
	mov	dx,[_gIWI.iwi_wAdlibBase]
	cmp	ax,IWGRC_ADLIB_BASE 
        je      short IWGRC_Got_Resource
	
	movzx	dx,BYTE PTR[_gIWI.iwi_bSBIRQ]
        jmp     short IWGRC_Got_Resource
	
	; Device 4, MPU401 emulation port and IRQ
IWGRC_Check_Device_4:	
	test	[_gIWI.iwi_bDeviceInit],IWINFO_DEV4_INIT
        jz      short IWGRC_Failed
	        
	mov	dx,[_gIWI.iwi_wMPUBase]
	cmp	ax,IWGRC_MPU_BASE
        je      short IWGRC_Got_Resource

	movzx	dx,BYTE PTR[_gIWI.iwi_bMPUIRQ]
	cmp	ax,IWGRC_MPU_IRQ
        je      short IWGRC_Got_Resource

IWGRC_Failed:
	pop	eax
	jmp	VIWD_API_Failed
	                  
IWGRC_Got_Resource:                  
        mov	[ebp.Client_AX],dx
        pop	eax
	jmp	VIWD_API_Success
        	    
EndProc IW_API_Get_Resource_Config


BeginDoc
;** IW_API_Read_Port_Byte
;*
;*  DESCRIPTION:
;*
;*  ENTRY:
;*      EBX             :       VM Handle.
;*      EBP             :       Client register structure.
;*      Client BX       ;       Port 
;*
;*  EXIT:
;*      Client AL       ;       Port Value Read
;*      Client:
;*              Carry clear     :  if successfull
;*              Carry set       : failure
;*
;*  NOTES:
;*
EndDoc

BeginProc IW_API_Read_Port_Byte
	push	edx
	push	eax
	mov	dx,[ebp.Client_BX]
	xor	ax,ax
	in	al,dx
	mov	[ebp.Client_AX],ax
	pop	eax
	pop	edx
	jmp VIWD_API_Success
EndProc IW_API_Read_Port_Byte


BeginDoc
;** IW_API_Write_Port_Byte
;*
;*  DESCRIPTION:
;*
;*  ENTRY:
;*      EBX             :       VM Handle.
;*      EBP             :       Client register structure.
;*      Client BX       ;       Port
;*	Client Al	;	Value
;*
;*  EXIT:
;*      Client:
;*              Carry clear     :  if successfull
;*              Carry set       : failure
;*
;*  NOTES:
;*
EndDoc

BeginProc IW_API_Write_Port_Byte
	push	edx
	push	eax
	mov	dx,[ebp.Client_BX]
	mov	ax,[ebp.Client_AX]
	out	dx,al
	pop	eax
	pop	edx          
	jmp VIWD_API_Success
EndProc IW_API_Write_Port_Byte

BeginDoc
;** IW_API_Read_DMA_Count
;*
;*  DESCRIPTION: reads the DMA count
;*
;*  ENTRY:
;*      EBX             :       VM Handle.
;*      EBP             :       Client register structure.
;*      Client BX       ;       DMA Count Port
;*	Client AX	;	Clear FF Port
;*
;*  EXIT:
;*      Client:                              
;*		CX		: dma count 
;*              Carry clear     : if successfull
;*              Carry set       : failure
;*
;*  NOTES:
;*
EndDoc

BeginProc IW_API_Read_DMA_Count
	push	edx
	push	ecx
	push	eax
	push	esi
first:
	pushfd
	cli
	mov	dx,[ebp.Client_AX]	; get clear ff port
	xor	ax,ax
	out	dx,al			; clear ff
	mov	dx,[ebp.Client_BX]	; get count port
	in	al,dx                   ; read the count twice...
	xchg	al,ah
	in	al,dx
        xchg    al,ah
	mov	si,ax			; storing the first read in cx
	popfd				; we're done reading so restore the flags
second:
	pushfd
	cli
	mov	dx,[ebp.Client_AX]	; get clear ff port
	xor	ax,ax
	out	dx,al			; clear ff
	mov	dx,[ebp.Client_BX]	; get count port
	in	al,dx                   ; read the count twice...
	xchg	al,ah
	in	al,dx
        xchg    al,ah
	mov	bx,ax			; storing the first read in cx
	popfd				; we're done reading so restore the flags
	mov     ax,si
	cmp	bh,ah				; did the MSB increment?
	jne     short go_around
        jmp     short done
go_around:
	mov	si,bx
	jmp	short second
done:
	mov	[ebp.Client_CX],bx
	pop	esi
	pop	eax
	pop	ecx
	pop	edx          
	jmp VIWD_API_Success
EndProc IW_API_Read_DMA_Count

VxD_CODE_ENDS
	end
