📄 armint.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
Module Name:
Abstract:
ARM920(S3C2410) interrupt service routine
rev:
2002.4.3 : first S3C2410 version (SOC)
2002.2.5 : system tick modification (kwangyoon LEE, kwangyoon@samsung.com)
- one shot timer
2002.1.29 : bug fixups (kwangyoon LEE, kwangyoon@samsung.com)
- system tick interrupt
2002.1.28 : CE.NET port (kwangyoon LEE, kwangyoon@samsung.com)
2002.1.22 : Add USBD interrupt (kwangyoon LEE, kwangyoon@samsung.com)
Notes:
--*/
#include <windows.h>
#include <nkintr.h>
#include <oalintr.h>
#include "p2.h"
#include "p2debug.h"
#include "odoregs.h"
#include "drv_glob.h"
#include <S2410.h>
extern DWORD CurMSec;
extern DWORD DiffMSec;
#if (CE_MAJOR_VER == 0x0003)
extern DWORD ticksleft, dwSleepMin, dwPreempt;
extern DWORD DiffMSec;
#else
extern DWORD dwReschedTime;
#endif
extern DWORD AlarmTime;
extern volatile LARGE_INTEGER CurTicks;
extern DWORD dwReschedIncrement;
extern int (*PProfileInterrupt)(void);
extern DWORD dwIsrTime1, dwIsrTime2;
extern BOOL fIntrTime, fIntrTimeToggle;
extern WORD wNumInterrupts; // Reset by a read of the ISR times from the IST
extern DWORD dwIntrTimeCountdown;
extern DWORD dwIntrTimeCountdownRef;
extern DWORD dwSPC;
extern DWORD PerfCountSinceTick();
extern BOOL fInterruptFlag;
extern VOID CPUPowerReset();
DWORD OEMTranslateIrq(DWORD dwIrq)
{
return dwIrq;
}
DWORD OEMTranslateSysIntr(DWORD SysIntr)
{
return (SysIntr<SYSINTR_FIRMWARE?(DWORD)-1:SysIntr);
}
void OEMInterruptHandlerFIQ()
{
}
int flag = 1;
unsigned int tCnt = 0;
unsigned int ttt = 0;
int OEMInterruptHandler(unsigned int ra)
{
static BYTE nLED = 0;
volatile INTreg *s2410INT = (INTreg *)INT_BASE;
volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;
volatile PWMreg *s2410PWM = (PWMreg *)PWM_BASE;
unsigned int IntPendVal;
unsigned int SubIntPendVal; // for serial
// Update LEDs.
//
if (nLED++ > 0xf) nLED = 0;
OEMWriteDebugLED(0, ~nLED);
IntPendVal = s2410INT->rINTOFFSET; // Get pending IRQ mode interrupt in INTPND.
// Fake CPUEnterIdle needs to know about interrupt firing.
fInterruptFlag = TRUE;
if (fIntrTime) {
//
// We're doing interrupt timing. Get Time to ISR. We subtract TIMER_COUNTDOWN
// here because the compare register has not been updated.
//
dwIsrTime1 = PerfCountSinceTick() - dwReschedIncrement;
dwSPC = ra;
wNumInterrupts++;
}
//
// Check the timer interrupt.
//
if (IntPendVal == INTSRC_TIMER4)
{
DWORD ttmp;
s2410PWM->rTCNTB4 = dwReschedIncrement;
ttmp = s2410PWM->rTCON & (~(0xf << 20));
s2410PWM->rTCON = ttmp | (2 << 20); /* update TCVNTB4, stop */
s2410PWM->rTCON = ttmp | (1 << 20); /* one-shot mode, start */
// Update the tick counter.
//
CurTicks.QuadPart += dwReschedIncrement;
// Call the profile ISR if it's enabled.
//
if (PProfileInterrupt)
{
DWORD dwRetVal = SYSINTR_NOP;
dwRetVal = PProfileInterrupt();
if (dwRetVal == SYSINTR_RESCHED)
{
// Update the millisecond counter.
//
CurMSec += RESCHED_PERIOD;
#if (CE_MAJOR_VER == 0x0003)
DiffMSec += RESCHED_PERIOD;
#endif
}
// Clear the interrupt
//
s2410INT->rSRCPND = BIT_TIMER4;
s2410INT->rINTPND = BIT_TIMER4;
// Return whatever we got back from the profiling ISR.
//
return(dwRetVal);
}
// Update the millisecond counter.
//
#if (CE_MAJOR_VER == 0x0003)
DiffMSec += RESCHED_PERIOD;
#endif
CurMSec += RESCHED_PERIOD;
//
// Clear the interrupt
//
s2410INT->rSRCPND = BIT_TIMER4;
s2410INT->rINTPND = BIT_TIMER4;
if (fIntrTime)
{
//
// We're doing interrupt timing. Every other tick is a RESCHED.
//
dwIntrTimeCountdown--;
if (dwIntrTimeCountdown == 0)
{
dwIntrTimeCountdown = dwIntrTimeCountdownRef;
wNumInterrupts = 0;
dwIsrTime2 = PerfCountSinceTick();
return (SYSINTR_TIMING);
} else {
#if (CE_MAJOR_VER == 0x0003)
if (ticksleft || (dwSleepMin && (dwSleepMin <= DiffMSec)) || (dwPreempt && (dwPreempt <= DiffMSec)))
#else
if ((int) (CurMSec - dwReschedTime) >= 0)
#endif
return(SYSINTR_RESCHED);
}
} else {
#if (CE_MAJOR_VER == 0x0003)
if (ticksleft || (dwSleepMin && (DiffMSec >= dwSleepMin)) || (dwPreempt && (DiffMSec >= dwPreempt)))
#else
if ((int) (CurMSec - dwReschedTime) >= 0)
#endif
{
return(SYSINTR_RESCHED);
}
return(SYSINTR_NOP);
}
} else if (IntPendVal == INTSRC_EINT1) // Keyboard interrupt is connected to EINT1.
{
s2410INT->rINTMSK |= BIT_EINT1;
s2410INT->rSRCPND = BIT_EINT1;
s2410INT->rINTPND = BIT_EINT1;
return(SYSINTR_KEYBOARD);
} else if (IntPendVal == INTSRC_EINT2) // EINT2
{
s2410INT->rINTMSK |= BIT_EINT2;
s2410INT->rSRCPND = BIT_EINT2; /* Interrupt Clear */
s2410INT->rINTPND = BIT_EINT2;
CPUPowerReset();
return(SYSINTR_POWER);
}
else if (IntPendVal == INTSRC_EINT3) // PCMCIA interrupt is connected to EINT3. (nINT_P_DEV)
{
s2410INT->rINTMSK |= BIT_EINT3;
s2410INT->rSRCPND = BIT_EINT3;
s2410INT->rINTPND = BIT_EINT3;
return(SYSINTR_PCMCIA_STATE);
}
else if (IntPendVal == INTSRC_EINT8_23) // EINT8 ~ 23
{
DWORD dwSubMask = s2410IOP->rEINTPEND & (~s2410IOP->rEINTMASK);
if (dwSubMask & 0x200) // EINT9 : CS8900
{
s2410IOP->rEINTMASK |= 0x200; // Mask and clear interrupt at first-level controller.
s2410IOP->rEINTPEND = 0x200; //
// Note: we don't mask BIT_EINT8_23 because it's shared.
//
s2410INT->rSRCPND = BIT_EINT8_23; // Clear pending interrupt at second-level controller.
s2410INT->rINTPND = BIT_EINT8_23; //
return(SYSINTR_ETHER);
}
else if (s2410IOP->rEINTPEND & 0x100) // EINT8 : PD6710
{
s2410IOP->rEINTMASK |= 0x100; // Mask and clear interrupt at first-level controller.
s2410IOP->rEINTPEND = 0x100; //
// Note: we don't mask BIT_EINT8_23 because it's shared.
//
s2410INT->rSRCPND = BIT_EINT8_23; // Clear pending interrupt at second-level controller.
s2410INT->rINTPND = BIT_EINT8_23; //
return(SYSINTR_PCMCIA_LEVEL);
}
else
{
s2410INT->rSRCPND = BIT_EINT8_23; // Clear pending interrupt at second-level controller.
s2410INT->rINTPND = BIT_EINT8_23; //
}
}
else if (IntPendVal == INTSRC_ADC) { // INTSRC_ADC
s2410INT->rINTSUBMSK |= BIT_SUB_TC;
s2410INT->rINTMSK |= BIT_ADC;
s2410INT->rSRCPND = BIT_ADC; /* Interrupt Clear */
s2410INT->rINTPND = BIT_ADC;
return(SYSINTR_TOUCH);
}
else if (IntPendVal == INTSRC_TIMER3) { // INTSRC_TIMER3
s2410INT->rINTMSK |= BIT_TIMER3;
s2410INT->rSRCPND = BIT_TIMER3; /* Interrupt Clear */
s2410INT->rINTPND = BIT_TIMER3;
return(SYSINTR_TOUCH_CHANGED);
}
else if (IntPendVal == INTSRC_EINT0) { // POWER BUTTON
s2410INT->rINTMSK |= BIT_EINT0;
s2410INT->rSRCPND = BIT_EINT0; /* Interrupt Clear */
s2410INT->rINTPND = BIT_EINT0;
return(SYSINTR_POWER);
}
else if(IntPendVal == INTSRC_DMA1) // AUDIO DMA input.
{
s2410INT->rINTMSK |= BIT_DMA1;
s2410INT->rSRCPND = BIT_DMA1;
s2410INT->rINTPND = BIT_DMA1;
return(SYSINTR_AUDIO);
}
else if(IntPendVal == INTSRC_DMA2) // AUDIO DMA output.
{
s2410INT->rINTMSK |= BIT_DMA2;
s2410INT->rSRCPND = BIT_DMA2;
s2410INT->rINTPND = BIT_DMA2;
return(SYSINTR_AUDIO);
}
else if(IntPendVal == INTSRC_USBH) // USB.
{
s2410INT->rINTMSK |= BIT_USBH;
s2410INT->rSRCPND = BIT_USBH;
s2410INT->rINTPND = BIT_USBH;
return(SYSINTR_USB);
}
else if(IntPendVal == INTSRC_USBD)
{
s2410INT->rINTMSK |= BIT_USBD;
s2410INT->rSRCPND = BIT_USBD;
s2410INT->rINTPND = BIT_USBD;
return(SYSINTR_USBD);
}
else if(IntPendVal == INTSRC_UART0) // SERIAL (UART0) (physical COM1: P1 connector).
{
SubIntPendVal = s2410INT->rSUBSRCPND;
// Note that we only mask the sub source interrupt - the serial driver will clear the
// sub source pending register.
//
if(SubIntPendVal & INTSUB_ERR0)
{
s2410INT->rINTSUBMSK |= INTSUB_ERR0;
}
else if(SubIntPendVal & INTSUB_RXD0)
{
s2410INT->rINTSUBMSK |= INTSUB_RXD0;
}
else if(SubIntPendVal & INTSUB_TXD0)
{
s2410INT->rINTSUBMSK |= INTSUB_TXD0;
}
else
{
return(SYSINTR_NOP);
}
// NOTE: Don't clear INTSRC:UART0 here - serial driver does that.
//
s2410INT->rINTMSK |= BIT_UART0;
s2410INT->rINTPND = BIT_UART0;
return(SYSINTR_SERIAL);
}
else if(IntPendVal == INTSRC_UART2) // IrDA (UART2)
{
SubIntPendVal = s2410INT->rSUBSRCPND;
if(SubIntPendVal & INTSUB_ERR2)
{
s2410INT->rINTSUBMSK |= INTSUB_ERR2;
}
else if(SubIntPendVal & INTSUB_RXD2)
{
s2410INT->rINTSUBMSK |= INTSUB_RXD2;
}
else if(SubIntPendVal & INTSUB_TXD2)
{
s2410INT->rINTSUBMSK |= INTSUB_TXD2;
}
else
{
return(SYSINTR_NOP);
}
// NOTE: Don't clear INTSRC:UART2 here - serial driver does that.
//
s2410INT->rINTMSK |= BIT_UART2;
s2410INT->rINTPND = BIT_UART2;
return(SYSINTR_IR);
}
return(SYSINTR_NOP);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -