⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tmipc.c

📁 wince host 和 target PCI驱动程序
💻 C
字号:
/*---------------------------------------------------------------------------- 
COPYRIGHT (c) 1995 by Philips Semiconductors

THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED AND COPIED IN 
ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH A LICENSE AND WITH THE 
INCLUSION OF THE THIS COPY RIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES 
OF THIS SOFTWARE MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
PERSON. THE OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED. 

THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT ANY PRIOR NOTICE
AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY Philips Semiconductor. 

PHILIPS ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE
ON PLATFORMS OTHER THAN THE ONE ON WHICH THIS SOFTWARE IS FURNISHED.
----------------------------------------------------------------------------*/
/*
	HISTORY
	#define	TR	Tilakraj Roy
	960326	TR 	Created
	960328	TR	Added the DPC for ISR
	960531	TR	Started changes for moving IPC in VxD
	961025	TR	Removed allpacket transport functions from IPC.
	
*/

/*----------------------------------------------------------------------------
          SYSTEM INCLUDE FILES
----------------------------------------------------------------------------*/
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <vxdwraps.h>
#include <vpicd.h>

/*----------------------------------------------------------------------------
          DRIVER SPECIFIC INCLUDE FILES
----------------------------------------------------------------------------*/
#include "vxstd.h"
#include "vxwin.h"
#include "vxdbg.h"
#include "tmwincom.h"
#include "tmmmio.h"
#include "tmhd.h"
#include "tmshare.h"
#include "tmipc.h"

#pragma VxD_LOCKED_CODE_SEG
#pragma	VxD_LOCKED_DATA_SEG

VOID	ipcDebugDump ( PVOID pDevice );
STATUS	ipcCreate (  PVOID pContainer, BYTE bIRQ, PVOID	*ppIPC )
{
	PTMIPC_OBJECT	this;
	VID				IRQDescriptors;
	STATUS			Status;
	DWORD			IntCount;

	if ( *ppIPC )
	{
		this = *ppIPC;
		this->Flags = 0;
	}
	else
	{
		if ( ( this = vxdMalloc ( sizeof ( TMIPC_OBJECT ) ) ) == NULL )
		{
			Status = TM_STATUS ( TMIPC_ERR_OBJALLOCFAIL );
			goto	ipcCreate_fail1;
		}
		FlagSet ( this->Flags, TMIPC_FLAG_DYNAMICOBJ );
	}

	this->Size = sizeof ( TMIPC_OBJECT );
	this->pContainer = pContainer;
	this->pHAL = GetHALObject ( this->pContainer );
	this->bPCIIRQ = bIRQ;


	/* RETAIN BELOW ONLY IN IPC */
	// install the IRQ handler	
	IRQDescriptors.VID_IRQ_Number		= this->bPCIIRQ;
	IRQDescriptors.VID_Options	=  /*VPICD_OPT_REF_DATA; */
		VPICD_OPT_CAN_SHARE | VPICD_OPT_SHARE_PMODE_ONLY | VPICD_OPT_REF_DATA;
	IRQDescriptors.VID_Hw_Int_Proc		= (DWORD)vxdIRQHandlerA;
	IRQDescriptors.VID_Virt_Int_Proc	= 0;
	IRQDescriptors.VID_EOI_Proc	= 0;
	IRQDescriptors.VID_Mask_Change_Proc	= 0;
	IRQDescriptors.VID_IRET_Proc		= 0;
	IRQDescriptors.VID_IRET_Time_Out	= 500;
	IRQDescriptors.VID_Hw_Int_Ref		= (DWORD)this;

	
	if ( ! ( this->dwIRQHandle =
		winVPICD_Virtualize_IRQ((PWINVID)&IRQDescriptors )))
	{
		DP(0,"TM:ipcInit:winVPICD_Virtualize_IRQ:IRQ#[%x]FAIL\n",(BYTE)bIRQ );
		Status = (TM_STATUS(TMIPC_ERR_IRQINSTALLFAIL));
		goto	ipcCreate_fail2;

	}

	//this->bDSPIRQ = TMHD_IPC_DSPIRQNUMBER;

	if ( ( Status = shmemAllocate ( GetShMemObject(this->pContainer), 0 ,
		sizeof ( TMHD_IPC_SHARED ), &this->pSharedData,
		&this->SharedDataPhys ) ) != TMOK )
		goto	ipcCreate_fail3;

	boardParameterDWORDSet ( this->pContainer, TMHD_PARAM_IPC,
		this->SharedDataPhys );
	
	for (  IntCount = 0 ; IntCount < TMHD_IPC_MUXCOUNT ; IntCount++ )
	{
		this->Callback[IntCount].pCallback = NULL;
		this->Callback[IntCount].pContext = NULL;
	}

	dbgRegister ( ipcDebugDump, "IPC Manager");

	// prepare windows to accept interrupts from the DSP.
	winVPICD_Physically_Unmask ( this->dwIRQHandle );

	*ppIPC = this;

	/* this part goes in reset */
	this->pSharedData->T2HInterruptAck = 0;
	for (  IntCount = 0 ; IntCount < TMHD_IPC_MUXCOUNT ; IntCount++ )
	{
		this->pSharedData->H2T[IntCount].Req = 0; 
		this->pSharedData->H2T[IntCount].Ack = 0;
		this->pSharedData->T2H[IntCount].Req = 0; 
		this->pSharedData->T2H[IntCount].Ack = 0;
	}


	this->InterruptsOK = FALSE;

	//	generate a test interrupt to the board and make sure we get a response.
	halBIUHostIRQGen( this->pHAL );


		// once we whack the reset the chip is dead no mmio accessses will work.
	// wait for 350mS for TRI_RESET to be pulled highstabilize + 250uS for IIC to
	// dump the 10 bytes of EEPROM data.
	winStallProcessorExecution ( 1000 );

	if ( ! this->InterruptsOK )
	{
		if ( ((PINIT_OBJECT)(pDriverObject->pInitObj))->InteractiveMode )
		{
 			vxdErrorBox ( "TriMedia Manager : Win95 Kernel Mode Driver", 
				"WARNING : TriMedia to PC Interrupt may not be functioning : Click [OK] to Proceed" );
		}
		DP(0, "WARNING : TriMedia to PC Interrupt may not be functioning \n");
	}

	// reset the ACK count - as this has been incremented by the interrupt handler.
	this->pSharedData->T2HInterruptAck = 0;

	return TMOK;

	/* SEH code */
ipcCreate_fail3:
	winVPICD_Force_Default_Behavior ( this->dwIRQHandle );
ipcCreate_fail2:
	this->Size = 0;
	if ( FlagGet ( this->Flags, TMIPC_FLAG_DYNAMICOBJ ) )
	{	
		vxdFree ( this );
	}
ipcCreate_fail1:
	return Status;
}

STATUS	ipcReset (  PVOID pIPC )
{
	PTMIPC_OBJECT	this = (PTMIPC_OBJECT)pIPC;
	DWORD IntCount;

	this->pSharedData->T2HInterruptAck = 0;

	for (  IntCount = 0 ; IntCount < TMHD_IPC_MUXCOUNT ; IntCount++ )
	{
		this->pSharedData->H2T[IntCount].Req = 0; 
		this->pSharedData->H2T[IntCount].Ack = 0;
		this->pSharedData->T2H[IntCount].Req = 0; 
		this->pSharedData->T2H[IntCount].Ack = 0;
	}

	return TMOK;
}

VOID	ipcDestroy (PVOID pIPC)
{
	
	PTMIPC_OBJECT	this = (PTMIPC_OBJECT)pIPC;

	FlagClr ( this->Flags, TMIPC_FLAGINITIALIZED );
	winVPICD_Physically_Mask ( this->dwIRQHandle );
	winVPICD_Force_Default_Behavior ( this->dwIRQHandle );
	shmemFree ( GetShMemObject(this->pContainer), this->pSharedData );
	this->Size = 0;
	if ( FlagGet ( this->Flags, TMIPC_FLAG_DYNAMICOBJ ) )
	{	
		vxdFree ( this );
	}
}

/*
	vxdIRQHandlerC
	All data that this has to handle should be page locked, if this function
	makes any channel callbacks then all those data structures have to be
	page locked also.

	If the ISR cannot schedule cannot schedule multiple DPCs then we 
	have to have a queue of global events.
	? How worth while is it to process an ISR_READY or MBOX_READY message
		after a deffered amount of time ?
	or
	have the ISR dump all packets into a queue and let the DPC & Ring3 
	completion devioctls process the queue as and when possible. So all queues
	have to be page locked and the send callback has to access page locked 
	buffers also.


	if the ISR detects that there are packets in the page locked queue and no
	DPC or ring 3 thread is going to generate an active event that will process
	the queue then the ISR schedules a DPC.


	So the Ring3 applications processing latency will not be seen by the DSP.

	This is exactly how the NT model will be implemented.
*/

BOOL	vxdIRQHandlerC(DWORD dwVMHandle, DWORD dwIRQHandle, PVOID pvContext )
{
	// we should be getting the board handle from the IRQHandle
	PTMIPC_OBJECT	this = (PTMIPC_OBJECT)pvContext;
	DWORD	IdxInt;
/*	DP ( 0, ">" ); */
	if ( halBIUIsIRQOurs ( this->pHAL )  )
	{
		this->pSharedData->T2HInterruptAck++;

		this->InterruptsOK = TRUE;

		// the DSP is spinning for the interrupt pin to go low so do that first 
		// when things start working the way they should mode this at the end of 
		// the ISR
		
		halBIUHostIRQAck ( this->pHAL ); 

		for ( IdxInt = 0 ; IdxInt < TMHD_IPC_MUXCOUNT ; IdxInt ++ )
		{
			DWORD	IntCount;
			if ( ! this->Callback[IdxInt].pCallback )
				continue;

			for (  IntCount = 0; 
				this->pSharedData->T2H[IdxInt].Req != 
				this->pSharedData->T2H[IdxInt].Ack ;
				/* overflow - reset to 0 after 0xffffffff */
				this->pSharedData->T2H[IdxInt].Ack++, IntCount++ );

			if ( IntCount > 0)
			{
				DP ( 1, "TM:vxdIRQHandlerC:IntID[%x]:Count[%x]\n", IdxInt, IntCount );

				((TMIPC_ONINTERRUPT)this->Callback[IdxInt].pCallback) (
					IdxInt,	IntCount,
					this->Callback[IdxInt].pContext );
			}
		}

		winVPICD_Phys_EOI ( dwIRQHandle );
/*		DP ( 0, "<" ); */
		return TRUE;
	}
	else
	{
/*		DP ( 0, "<" ); */
		return FALSE;
	}
}

STATUS	ipcValidateHandle ( PVOID pIPC )
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC;

	if ( this->Size != sizeof(TMIPC_OBJECT) )
		goto ipcValidateHandle_fail;

	return TMOK;

ipcValidateHandle_fail:
	DP(0,"TM:ipcValidateHandle:pIPC[%x]:FAIL\n", pIPC);
	return TM_STATUS ( TMIPC_ERR_INVALIDHANDLE );

}


STATUS	ipcRegisterCallback  (
	PVOID pIPC,		/* ipc object */
	DWORD InterruptID,	/* interrupt command */
	TMIPC_ONINTERRUPT	OnInterrupt,	/* interrupt callback function */
	PVOID pContext )	/* callback context */
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC;
	if ( InterruptID > TMHD_IPC_MUXCOUNT )
		return TM_STATUS (TMIPC_ERR_INVALIDIINTID );
	if ( this->Callback[InterruptID].pCallback == NULL )
	{
		 this->Callback[InterruptID].pCallback = (PVOID)OnInterrupt;
		 this->Callback[InterruptID].pContext = pContext;
		 return TMOK;
	}
	else
	{
		return TM_STATUS (TMIPC_ERR_INTALLOCATED );
	}

}

STATUS	ipcUnregisterCallback  (
	PVOID pIPC,		/* ipc object */
	DWORD InterruptID )/* interrupt command */
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC;
	if ( InterruptID > TMHD_IPC_MUXCOUNT )
		return TM_STATUS (TMIPC_ERR_INVALIDIINTID );

	if ( this->Callback[InterruptID].pCallback != NULL )
	{
		 this->Callback[InterruptID].pCallback = NULL;
		 this->Callback[InterruptID].pContext = NULL;
		 return TMOK;
	}
	else
	{
		return TM_STATUS (TMIPC_ERR_INTNOTTALLOCATED );
	}

}




STATUS  ipcGenerateIRQ ( PVOID pIPC , DWORD dwIntID )
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC; 
	if ( dwIntID > TMHD_IPC_MUXCOUNT )
		return TM_STATUS (TMIPC_ERR_INVALIDIINTID );
	DP ( 1, "TM:ipcGenerateIRQ:IntID[%x]\n", dwIntID );
	this->pSharedData->H2T[dwIntID].Req++;
	halIRQDSPGen( this->pHAL );
	return TMOK;
}

STATUS  ipcDisableIRQ ( PVOID pIPC )
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC; 
	winVPICD_Physically_Mask ( this->dwIRQHandle );
	return TMOK;
}

STATUS  ipcEnableIRQ ( PVOID pIPC )
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC; 
	winVPICD_Physically_Unmask ( this->dwIRQHandle );
	return TMOK;
}

BOOL	ipcGetInterruptState ( PVOID pIPC ) 
{
	PTMIPC_OBJECT this = (PTMIPC_OBJECT)pIPC;
	return this->InterruptsOK;
}

VOID	ipcDebugDump ( PVOID pDevice )
{
	PTMIPC_OBJECT this = GetIPCObject ( pDevice );
	PTMHD_IPC_INTCOUNT pH2T;
	PTMHD_IPC_INTCOUNT pT2H;
	DWORD			Idx;

	CHAR	szTemp[81];

	/* dump the channel data structure */
	_Sprintf ( szTemp, 
		"ipcm:SIZE[%08x]:FLAG[%08x]:HIRQ[%08x]:TIRQ[%08x]:SHRD[%08x]\n",
		this->Size, this->Flags, this->bPCIIRQ, this->bDSPIRQ,
		this->pSharedData );
   	DP(0,szTemp);

	_Sprintf ( szTemp, 
		"irqc:H2TA[%08x]:T2HA[%08x]\n",
		this->pSharedData->H2TInterruptAck, this->pSharedData->T2HInterruptAck );
   	DP(0,szTemp);

	for ( Idx = 0 ; Idx < TMHD_IPC_MUXCOUNT ; Idx ++)
	{
		pH2T = &this->pSharedData->H2T[Idx];
		pT2H = &this->pSharedData->T2H[Idx];

		_Sprintf ( szTemp, 
			"shrd:IIDX[%08x]:H2TR[%08x]:H2TA[%08x]:T2HR[%08x]:T2HA[%08x]\n",
			Idx, pH2T->Req, pH2T->Ack, pT2H->Req, pT2H->Ack );
   		DP(0,szTemp);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -