📄 cfw.c
字号:
// calls <f InterruptDone>. The system is not preemtible when this
// function is called.
// @xref <l Overview.Kernel Interrupt Support> <f InterruptDone>
//
//------------------------------------------------------------------------------
void
OEMInterruptDone(DWORD idInt) // @parm Interrupt ID. See <t Interrupt ID's>
// for the list of possible values.
{
volatile INTreg *s2440INT = (INTreg *)INT_BASE;
volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;
INTERRUPTS_OFF();
switch (idInt)
{
case SYSINTR_DMA0:
s2440INT->rINTMSK &= ~BIT_DMA0; // SDIO DMA interrupt
//RETAILMSG(1,(TEXT("::: SYSINTR_DMA0 OEMInterruptDone\r\n")));
break;
case SYSINTR_SDMMC:
s2440INT->rINTMSK &= ~BIT_MMC;
//RETAILMSG(1,(TEXT("::: SYSINTR_SDMMC OEMInterruptDone\r\n")));
break;
case SYSINTR_SDMMC_SDIO_INTERRUPT:
s2440INT->rINTMSK &= ~BIT_MMC;
//RETAILMSG(1,(TEXT("::: SYSINTR_SDMMC_SDIO_INTERRUPT OEMInterruptDone\r\n")));
break;
case SYSINTR_SDMMC_CARD_DETECT:
#if SDIO_FOR_100BD // for b'd revision 1.00
s2440IOP->rEINTPEND = (1<<18);
s2440IOP->rEINTMASK &= ~(1 << 18);
//RETAILMSG(1,(TEXT("::: SYSINTR_SDMMC_CARD_DETECT OEMInterruptDone\r\n")));
#else // for b'd revision 0.17
s2440IOP->rEINTPEND = (1<<16);
s2440IOP->rEINTMASK &= ~(1 << 16);
#endif
s2440INT->rINTMSK &= ~BIT_EINT8_23;
break;
case SYSINTR_TOUCH:
/*
* Nothing has to be done here as interrupts are masked and unmasked by the touch
* handler in the HAL.
*/
s2440INT->rINTMSK &= ~BIT_TIMER1;
break;
case SYSINTR_TOUCH_CHANGED:
/*
* Nothing has to be done here as interrupts are masked and unmasked by the touch
* handler in the HAL.
*/
s2440INT->rINTMSK &= ~BIT_ADC;
s2440INT->rINTSUBMSK &= ~INTSUB_TC;
//RETAILMSG(0,(TEXT("OEMInterruptDone:TOUCH CHANGED\n\r\n")));
break;
case SYSINTR_KEYBOARD:
s2440INT->rINTMSK &= ~BIT_EINT1;
break;
case SYSINTR_SERIAL:
s2440INT->rINTMSK &= ~BIT_UART0;
s2440INT->rINTSUBMSK &= ~INTSUB_RXD0;
break;
case SYSINTR_SERIAL2:
s2440INT->rINTMSK &= ~BIT_UART1;
s2440INT->rINTSUBMSK &= ~INTSUB_RXD1;
break;
case SYSINTR_SERIAL3:
s2440INT->rINTMSK &= ~BIT_UART2;
s2440INT->rINTSUBMSK &= ~INTSUB_RXD2;
break;
case SYSINTR_AUDIO:
// DMA1 is for audio input.
// DMA2 is for audio output.
s2440INT->rSRCPND = (BIT_DMA1 | BIT_DMA2);
if (s2440INT->rINTPND & BIT_DMA1) s2440INT->rINTPND = BIT_DMA1;
if (s2440INT->rINTPND & BIT_DMA2) s2440INT->rINTPND = BIT_DMA2;
s2440INT->rINTMSK &= ~BIT_DMA1;
s2440INT->rINTMSK &= ~BIT_DMA2;
break;
case SYSINTR_ADC:
break;
case SYSINTR_PCMCIA_LEVEL:
s2440INT->rSRCPND = BIT_EINT8_23;
if (s2440INT->rINTPND & BIT_EINT8_23) s2440INT->rINTPND = BIT_EINT8_23;
s2440INT->rINTMSK &= ~BIT_EINT8_23;
s2440IOP->rEINTMASK &= ~(1<<8);
//RETAILMSG(1,(TEXT("::: SYSINTR_PCMCIA_LEVEL OEMInterruptDone\r\n")));
break;
case SYSINTR_PCMCIA_EDGE:
//RETAILMSG(1,(TEXT("::: SYSINTR_PCMCIA_EDGE OEMInterruptDone\r\n")));
break;
case SYSINTR_PCMCIA_STATE:
s2440INT->rINTMSK &= ~BIT_EINT3;
//RETAILMSG(1,(TEXT("::: SYSINTR_PCMCIA_STATE OEMInterruptDone\r\n")));
break;
case SYSINTR_ETHER:
s2440INT->rINTMSK &= ~BIT_EINT8_23;
s2440IOP->rEINTMASK &= ~0x200;
//RETAILMSG(1, (TEXT("::: SYSINTR_USBD OEMInterruptDone\r\n")));
break;
case SYSINTR_DM9000: // Ethernet on EINT14.
s2440INT->rINTMSK &= ~BIT_EINT8_23;
s2440IOP->rEINTMASK &= ~0x4000;
//RETAILMSG(1, (TEXT("::: SYSINTR_DM9000 OEMInterruptDone\r\n")));
break;
case SYSINTR_USB:
s2440INT->rINTMSK &= ~BIT_USBH;
break;
case SYSINTR_USBD:
s2440INT->rINTMSK &= ~BIT_USBD;
//RETAILMSG(1,(TEXT("::: SYSINTR_USBD OEMInterruptDone\r\n")));
break;
case SYSINTR_POWER:
s2440INT->rSRCPND = BIT_EINT0;
// S3C2440X Developer Notice (page 4) warns against writing a 1 to a 0 bit in the INTPND register.
if (s2440INT->rINTPND & BIT_EINT0) s2440INT->rINTPND = BIT_EINT0;
s2440INT->rINTMSK &= ~BIT_EINT0;
s2440INT->rSRCPND = BIT_EINT2;
// S3C2440X Developer Notice (page 4) warns against writing a 1 to a 0 bit in the INTPND register.
if (s2440INT->rINTPND & BIT_EINT2) s2440INT->rINTPND = BIT_EINT2;
s2440INT->rINTMSK &= ~BIT_EINT2;
break;
case SYSINTR_CAM:
s2440INT->rSUBSRCPND = INTSUB_CAM_P;
s2440INT->rSUBSRCPND = INTSUB_CAM_C;
s2440INT->rSRCPND = BIT_CAM;
if (s2440INT->rINTPND & BIT_CAM)
{
s2440INT->rINTPND = BIT_CAM;
}
s2440INT->rINTSUBMSK &= ~(INTSUB_CAM_P | INTSUB_CAM_C);
s2440INT->rINTMSK &= ~BIT_CAM;
break;
case SYSINTR_IIC:
s2440INT->rINTMSK &= ~BIT_IIC;
break;
}
INTERRUPTS_ON();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
OEMGetExtensionDRAM(
LPDWORD lpMemStart,
LPDWORD lpMemLen
)
{
return FALSE; // no extension DRAM
}
//------------------------------------------------------------------------------
//
// OEMQueryPerformanceCounter
//
// The OEMQueryPerformanceCounter function retrieves the current value of
// the high-resolution performance counter, if one exists.
//
// BOOL QueryPerformanceCounter(
//
// LARGE_INTEGER *lpliPerformanceCount // address of current counter value
// );
//
// Parameters
//
// lpliPerformanceCount
//
// Points to a variable that the function sets, in counts, to the current
// performance-counter value. If the installed hardware does not support
// a high-resolution performance counter, this parameter can be to zero.
//
// Return Value
//
// If the installed hardware supports a high-resolution performance
// counter, the return value is TRUE.
// If the installed hardware does not support a high-resolution
// performance counter, the return value is FALSE.
//
// If this function is implemented by the OEM, the pointer pQueryPerformanceCounter
// should be initialized as follows:
//
// BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
//
//------------------------------------------------------------------------------
BOOL
OEMQueryPerformanceCounter(
LARGE_INTEGER *lpliPerformanceCount
)
{
extern DWORD PerfCountSinceTick();
ULARGE_INTEGER liBase;
DWORD dwCurCount;
// Make sure CurTicks is the same before and after read of counter to account for
// possible rollover
do {
liBase = CurTicks;
dwCurCount = PerfCountSinceTick();
} while (liBase.LowPart != CurTicks.LowPart) ;
lpliPerformanceCount->QuadPart = liBase.QuadPart + dwCurCount;
return TRUE;
}
//------------------------------------------------------------------------------
//
// OEMQueryPerformanceFrequency
//
// The OEMQueryPerformanceFrequency function retrieves the frequency of
// the high-resolution performance counter, if one exists.
//
// BOOL OEMQueryPerformanceFrequency(
//
// LARGE_INTEGER *lpliPerformanceFreq // address of current frequency
// );
//
// Parameters
//
// lpliPerformanceFreq
//
// Points to a variable that the function sets, in counts per second, to
// the current performance-counter frequency. If the installed hardware
// does not support a high-resolution performance counter, this parameter
// can be to zero.
//
// Return Value
//
// If the installed hardware supports a high-resolution performance
// counter, the return value is TRUE.
// If the installed hardware does not support a high-resolution
// performance counter, the return value is FALSE.
//
// If this function is implemented by the OEM, the pointer pQueryPerformanceFrequency
// should be initialized as follows:
//
// BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpPerformanceFrequency)=OEMQueryPerformanceFrequency;
//
//------------------------------------------------------------------------------
BOOL
OEMQueryPerformanceFrequency(
LARGE_INTEGER *lpliPerformanceFreq
)
{
extern DWORD PerfCountFreq();
lpliPerformanceFreq->HighPart = 0;
lpliPerformanceFreq->LowPart = PerfCountFreq();
return TRUE;
}
// set pointers to OEM functions
BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpliPerformanceFreq)=OEMQueryPerformanceFrequency;
//
// CPU-specific functions for OEMIdle
//
extern void CPUEnterIdle(DWORD dwIdleParam);
extern DWORD CPUGetSysTimerCountMax(DWORD dwIdleMSecRequested);
extern void CPUSetSysTimerCount(DWORD dwIdleMSec);
extern BOOL CPUClearSysTimerIRQ(void);
//
// dougfir or later
//
extern DWORD
CPUGetSysTimerCountElapsed(
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
DWORD *pPartialCurMSec,
volatile ULARGE_INTEGER *pCurTicks
);
//------------------------------------------------------------------------------
//
// This routine is called by the kernel when there are no threads ready to
// run. The CPU should be put into a reduced power mode and halted. It is
// important to be able to resume execution quickly upon receiving an interrupt.
// Note: It is assumed that interrupts are off when OEMIdle is called. Interrrupts
// are turned off when OEMIdle returns.
//
//------------------------------------------------------------------------------
static DWORD dwPartialCurMSec = 0; // Keep CPU-specific sub-millisecond leftover.
void
OEMIdle( DWORD dwIdleParam )
{
DWORD dwIdleMSec;
DWORD dwPrevMSec = *pCurMSec;
// Use for 64-bit math
ULARGE_INTEGER currIdle = { curridlelow, curridlehigh };
if ((int) (dwIdleMSec = dwReschedTime - dwPrevMSec) <= 0)
{
return; // already time to wakeup
}
// just idle till tick if profiling or running iltiming
if (bProfileTimerRunning || fIntrTime) // fIntrTime : Interrupt Latency timeing.
{
// idle till end of 'tick'
CPUEnterIdle(dwIdleParam);
// Update global idle time and return
currIdle.QuadPart += RESCHED_PERIOD;
curridlelow = currIdle.LowPart;
curridlehigh = currIdle.HighPart;
return;
}
//
// Since OEMIdle( ) is being called in the middle of a normal reschedule
// period, CurMSec, dwPartialCurMSec, and CurTicks need to be updated accordingly.
// Once we reach this point, we must re-program the timer (if we ever did)
// because dwPartialCurMSec will be modified in the next function call.
//
CPUGetSysTimerCountElapsed(RESCHED_PERIOD, pCurMSec, &dwPartialCurMSec, pCurTicks);
if ((int) (dwIdleMSec -= *pCurMSec - dwPrevMSec) > 0)
{
dwPrevMSec = *pCurMSec;
//
// The system timer may not be capable of arbitrary timeouts. Get the
// CPU-specific highest possible timeout available.
//
dwIdleMSec = CPUGetSysTimerCountMax(dwIdleMSec);
//
// Set the timer to wake up much later than usual, if needed.
//
CPUSetSysTimerCount(dwIdleMSec);
CPUClearSysTimerIRQ( );
//
// Enable wakeup on any interrupt, then go to sleep.
//
// DEBUGMSG(1, (TEXT("OEMIDle \r\n")));
CPUEnterIdle(dwIdleParam);
INTERRUPTS_OFF( );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -