📄 mpc8240epic.c
字号:
int intLevel /* interrupt level to enable */
)
{
LOCAL_INT_DATA enable;
/*int mask;*/
/* Validate vector. */
if (intLevel < 0)
return (ERROR);
#if(0)
/* add by xdg 00.10.13*/
if(intLevel>=WBPIC_INTERRUPT_BASE && intLevel<WBPIC_INTERRUPT_BASE+0x10)
{
mask = sysPciIbcIntEnable (intLevel-WBPIC_INTERRUPT_BASE);
if (mask == ERROR)
{
return (ERROR);
}
return( OK );
}
#endif
enable.regAddr = getEpicVecAddr(intLevel);
if (enable.regAddr > 0)
{
/* read the vector register */
enable.regVal = sysPciInLong((UINT32)(enable.regAddr));
/* enable the interrupt */
enable.regVal &= (~INT_MASK_BIT);
/* write the contents of the vector register back */
sysPciOutLong((UINT32)(enable.regAddr), enable.regVal);
}
return (OK);
}
/******************************************************************************
*
* sysEpicIntDisable - disable an Epic interrupt level
*
* This routine disables a specified Epic interrupt level.
*
* RETURNS: OK or ERROR if interrupt level not supported
*/
LOCAL int sysEpicIntDisable
(
int intLevel /* interrupt level to disable */
)
{
LOCAL_INT_DATA disable;
/*int mask;*/
/* Validate vector. */
if (intLevel < 0)
return (ERROR);
#if(0) /*because no winbond*/
/* add by xdg 00.10.13*/
if(intLevel>=WBPIC_INTERRUPT_BASE && intLevel<WBPIC_INTERRUPT_BASE+0x10)
{
mask = sysPciIbcIntDisable (intLevel-WBPIC_INTERRUPT_BASE);
if (mask == ERROR)
{
return (ERROR);
}
return( OK );
}
#endif
/* get the vector reg. offset value */
disable.regAddr = getEpicVecAddr(intLevel);
if (disable.regAddr > 0)
{
/* read the vector register */
disable.regVal = sysPciInLong((UINT32)(disable.regAddr));
/* disable the interrupt */
disable.regVal |= INT_MASK_BIT;
/* write the contents of the vector register back */
sysPciOutLong((UINT32)(disable.regAddr), disable.regVal);
}
return (OK);
}
/*******************************************************************************
*
* sysEpicIntHandlerExec - execute the handlers for a given vector
*
* This routine executes all the handlers chained to a given vector.
* If a vector has no handlers attached to it, a logMsg is generated.
*
* NOMANUAL
*
* RETURNS: N/A
* This functiong added by xdg, 00.10.13
*/
void sysEpicIntHandlerExec
(
UCHAR intVec
)
{
INT_HANDLER_DESC * pCurrHandler;
/* call each respective interrupt handler */
if ((pCurrHandler = sysIntTbl [intVec]) == NULL)
{
logMsg ("uninitalized PIC interrupt vector %x\r\n",
intVec, 0,0,0,0,0);
}
else
{
/* call Each respective chained interrupt handler */
while (pCurrHandler != NULL)
{
(*pCurrHandler->vec) (pCurrHandler->arg);
pCurrHandler = pCurrHandler->next;
}
}
}
/*add by zhu*/
#ifndef PPC_EIEIO_SYNC
#define PPC_EIEIO_SYNC __asm__ volatile (" eieio; sync")
#endif
void sysEUMBBARWrite
(
ULONG regNum,
ULONG regVal
)
{
*(ULONG *) (EPIC_EOI_REG + regNum) = LONGSWAP(regVal);
PPC_EIEIO_SYNC;
return ;
}
/******************************************************************************
*
* sysEpicIntHandler - handle an interrupt received at the Epic
*
* This routine will process interrupts received from PCI or ISA devices as
* these interrupts arrive via the EPIC. This routine supports EPIC interrupt
* nesting.
*
* RETURNS: N/A
*/
void sysEpicIntHandler
(
void
)
{
UINT32 vecNum;
UINT32 vecRegAddr;
int dontCare;
int intPriority;
int oldLevel;
/* get the vector from the EPIC IACK reg. */
vecNum = sysPciInLong((UINT32)EPIC_IACK_REG);
vecNum &= VECTOR_MASK;
/* add by xdg */
/* Check for spurious interrupt. */
if (vecNum == 0xFF)
{
/*logMsg ("EPIC Spurious Interrupt!\n", 0,0,0,0,0,0);*/
return;
}
#if(1)
vecRegAddr = getEpicVecAddr(vecNum);
intPriority = getEpicPrio(vecRegAddr);
if ((oldLevel = epicCurTaskPrioSet (intPriority)) == EPIC_INV_PRIO_ERROR)
{
return;
}
#endif
/*
* Allow maskable interrupts to the CPU. EPIC will hold off
* lower and equal interrupts until EPIC_EOI is performed.
*/
CPU_INT_UNLOCK(_PPC_MSR_EE);
#ifdef INCLUDE_INSTRUMENTATION /*should not be defined */
if (evtLogTIsOn)
(* _func_evtLogT1_noTS) (EVENT_INT_ENT((int)vecNum),
evtTimeStamp);
#endif
sysEpicIntHandlerExec( (UCHAR)vecNum );
/* Disable external interrupts. */
CPU_INT_LOCK(&dontCare);
/*
* ERRATA FIX:
* sysDecDelay() is needed for Mpc8240(MPC8240) Revision 1.0/1.1
* Errata #2, EPIC Serial Mode Interrupt Twice from Single Source.
* See Mpc8240 Errata Sheet - Version 1.0.3
*/
/*del by zhu , 6.11*/
/* sysDecDelay(1);*/
/* Issue an end-of-interrupt to the EPIC */
sysPciOutLong((UINT32)EPIC_EOI_REG, 0);
PPC_EIEIO_SYNC;
/* add by xdg */
#if(1)
epicCurTaskPrioSet (oldLevel);
#endif
return;
}
/******************************************************************************
*
* getEpicVecAddr - get the vector address of an EPIC register
*
* This routine returns the appropriate EPIC register address based on the
* specified EPIC interrupt level.
*
* RETURNS: EPIC register address or zero if not a supported level.
*/
LOCAL int getEpicVecAddr
(
int intLevel /* interrupt level to translate */
)
{
int offset = 0;
/* check for a timer interrupt level */
if ((intLevel >= TIMER_INTERRUPT_BASE) &&
(intLevel < EXTERNAL_INTERRUPT_BASE))
{
offset = intLevel - TIMER_INTERRUPT_BASE;
offset = (int)EPIC_TIMER0_VEC_PRI_REG + (offset * REG_OFFSET * 4);
}
/* check for Internal interrupt level */
if ((intLevel >= INTERNAL_INTERRUPT_BASE) &&
(intLevel < SERIAL_INTERRUPT_BASE))
{
offset = intLevel - INTERNAL_INTERRUPT_BASE;
offset = (int)EPIC_I2C_INTR_VEC_SRC + (offset * REG_OFFSET * 2);
}
/* check for external interrupt level */
if ((intLevel >= EXTERNAL_INTERRUPT_BASE) &&
(intLevel < INTERNAL_INTERRUPT_BASE))
{
offset = intLevel - EXTERNAL_INTERRUPT_BASE;
offset = (int)EPIC_EXT_SRC0_VEC_PRI_REG + (offset * REG_OFFSET * 2);
}
/* check for a serial interrupt level */
if (intLevel >= SERIAL_INTERRUPT_BASE)
{
offset = intLevel - SERIAL_INTERRUPT_BASE;
offset = (int)EPIC_SER_SRC0_VEC_PRI_REG + (offset * REG_OFFSET * 2);
}
/*check for Message Unit interrupt level, 8.21, by zhu*/
if (intLevel == MSGUNIT_INT_LVL)
{
offset = (int)EPIC_MSG_UNIT_INTR_VEC_SRC;
}
if ((intLevel >= DUART_INTERRUPT_BASE) &&
(intLevel < DUART_INTERRUPT_BASE+2))
{
offset = intLevel - DUART_INTERRUPT_BASE;
offset = (int)EPIC_DUART_CHAN1_INTR_VEC_SRC + (offset * REG_OFFSET * 2);
}
return (offset);
}
/***************************************************
* getEpicPrio(UINT32 vecRegAddr)
*
* added by xdg, 01.1.9
*/
LOCAL int getEpicPrio(UINT32 vecRegAddr)
{
UINT32 temp;
temp = sysPciInLong(vecRegAddr);
return((temp&EPIC_SRC_PRI_MASK)>>16);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -