📄 tmipc.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 + -