📄 interrupt.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.
//
/* -*-C-*-
*
*
* intx20.c - ARMX20 (X = 7, 9, 10) platform interrupt service routine
*
* Copyright (c) ARM Limited 1998, 1999
* All Rights Reserved.
*/
#include <windows.h>
#include <nkintr.h>
#include <oalintr.h>
#include <bldver.h> // Needed for CE_MAJOR_VER.
#include <drv_glob.h>
#include <hwdefs.h>
#include <clocks.h>
#if (CE_MAJOR_VER == 0x0003)
extern DWORD ticksleft, dwSleepMin, dwPreempt;
extern DWORD DiffMSec;
#else
extern DWORD dwReschedTime;
#endif
volatile BOOL fInterruptFlag;
volatile DWORD gdwInterruptMask1, gdwInterruptMask2;
volatile DWORD gdwInterruptWakeMask1, gdwInterruptWakeMask2;
volatile BOOL fPS2Int;
volatile BYTE gfSysIntrWakeupMask[SYSINTR_MAXIMUM];
volatile BOOL gfResumeFlag;
volatile DWORD gdwLastWakeupSource;
extern volatile BOOLEAN fResumeFlag;
extern DWORD CurMSec;
extern volatile LARGE_INTEGER CurTicks;
extern DWORD dwReschedIncrement;
extern int (*PProfileInterrupt)(void);
extern DWORD dwIsrTime1, dwIsrTime2;
extern BOOL fIntrTime;
extern WORD wNumInterrupts; // Reset by a read of the ISR times from the IST
extern DWORD dwIntrTimeCountdown;
extern DWORD dwIntrTimeCountdownRef;
//
// Function prototypes.
//
DWORD PerfCountSinceTick(void);
int TimerInterrupt(void);
DWORD OEMTranslateIrq(DWORD Irq);
BOOL CPUClearSysTimerIRQ(void);
// ULONG ulVic1Last, ulVic2Last;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void OEMInterruptHandlerFIQ()
{
// Fake CPUEnterIdle needs to know about interrupt firing.
fInterruptFlag = TRUE;
}
//****************************************************************************
// OEMInterruptHandler
//****************************************************************************
// This checks the timer first, then the other interrupts. This could
// be rewritten using the priority registers in the ARM vectored interrupt
// controller, but I don't think that is currently necessary .
//
//
int OEMInterruptHandler(unsigned int ra)
{
register ULONG ulVic1Irq, ulVic2Irq;
// volatile ULONG ulDummyRead;
DWORD retval;
//
// Read the interrupt status registers.
//
ulVic1Irq = *VIC1_IRQSTATUS;
ulVic2Irq = *VIC2_IRQSTATUS;
//
// Set the default value to nop
//
retval = SYSINTR_NOP;
//
// Fake CPUEnterIdle needs to know about interrupt firing.
//
fInterruptFlag = TRUE;
if(ulVic1Irq & INT1_TIMER1)
{
//
// Temporary hack for the PS2 keyboard driver.
//
if((gdwInterruptMask2 & INT2_SPI) && (*SPI_SR & SPISR_RNE) && !fPS2Int)
{
fPS2Int = 1;
*VIC2_INTCLEAR = INT2_SPI;
retval = SYSINTR_SPI;
}
else
{
retval = TimerInterrupt();
CPUClearSysTimerIRQ();
}
}
else
{
//
// If we're timing interrupts, keep track of when this one came in
//
if (fIntrTime)
{
//
// Subtract off dwReschedIncrment since interrupt hasn't been cleared
//
dwIsrTime1 = PerfCountSinceTick();
wNumInterrupts++;
}
//
// This was not a timer interrupt, must be a device interrupt.
// Change the priority of the interrupt by changing the order that
// the interrupt is processed.
//
//
// Ethernet interrupt.
//
if(ulVic2Irq & INT2_ETHERNET)
{
*VIC2_INTCLEAR = INT2_ETHERNET;
retval = SYSINTR_ETHER;
}
//
// USB interrupt
//
else if(ulVic2Irq & INT2_USB)
{
*VIC2_INTCLEAR = INT2_USB;
retval = SYSINTR_USB;
}
//
// Check the serial port interrupts.
//
else if(ulVic2Irq & INT2_UART1)
{
*VIC2_INTCLEAR = INT2_UART1;
retval = SYSINTR_UART1;
}
else if(ulVic2Irq & INT2_UART2)
{
*VIC2_INTCLEAR = INT2_UART2;
retval = SYSINTR_UART2;
}
else if(ulVic2Irq & INT2_UART3)
{
*VIC2_INTCLEAR = INT2_UART3;
retval = SYSINTR_UART3;
}
//
// Check to see if it is a keyboard interrupt
//
else if(ulVic1Irq & INT1_KEYPAD)
{
*VIC1_INTCLEAR = INT1_KEYPAD;
retval = SYSINTR_KEYBOARD;
}
//
// Check to see if the SPI port has generated an interrupt.
// This is used for the PS/2 keyboard driver.
//
else if(ulVic2Irq & INT2_SPI)
{
fPS2Int = 1;
*VIC2_INTCLEAR = INT2_SPI;
retval = SYSINTR_SPI;
}
//
// Real time clock interrupt. Occurs very infrequently so
// put at the bottom of the interrupt priority list.
//
else if (ulVic2Irq & INT2_RTC)
{
*VIC2_INTCLEAR = INT2_RTC;
retval = SYSINTR_RTC_ALARM;
}
//
// Check the DMA channels.
//
else if (ulVic1Irq & INT1_DMAM2P0 )
{
*VIC1_INTCLEAR = INT1_DMAM2P0;
retval = SYSINTR_DMA0;
}
else if (ulVic1Irq & INT1_DMAM2P1 )
{
*VIC1_INTCLEAR = INT1_DMAM2P1;
retval = SYSINTR_DMA1;
}
else if (ulVic1Irq & INT1_DMAM2P2 )
{
*VIC1_INTCLEAR = INT1_DMAM2P2;
retval = SYSINTR_DMA2;
}
else if (ulVic1Irq & INT1_DMAM2P3 )
{
*VIC1_INTCLEAR = INT1_DMAM2P3;
retval = SYSINTR_DMA3;
}
else if (ulVic1Irq & INT1_DMAM2P4 )
{
*VIC1_INTCLEAR = INT1_DMAM2P4;
retval = SYSINTR_DMA4;
}
else if (ulVic1Irq & INT1_DMAM2P5 )
{
*VIC1_INTCLEAR = INT1_DMAM2P5;
retval = SYSINTR_DMA1;
}
else if (ulVic1Irq & INT1_DMAM2P5 )
{
*VIC1_INTCLEAR = INT1_DMAM2P5;
retval = SYSINTR_DMA5;
}
else if (ulVic1Irq & INT1_DMAM2P6 )
{
*VIC1_INTCLEAR = INT1_DMAM2P6;
retval = SYSINTR_DMA6;
}
else if (ulVic1Irq & INT1_DMAM2P7 )
{
*VIC1_INTCLEAR = INT1_DMAM2P7;
retval = SYSINTR_DMA7;
}
else if (ulVic1Irq & INT1_DMAM2P8 )
{
*VIC1_INTCLEAR = INT1_DMAM2P8;
retval = SYSINTR_DMA8;
}
else if (ulVic1Irq & INT1_DMAM2P9 )
{
*VIC1_INTCLEAR = INT1_DMAM2P9;
retval = SYSINTR_DMA9;
}
//
// Check to see if it is a touch pad interrupt.
//
else if (ulVic1Irq & INT1_TOUCH)
{
*VIC1_INTCLEAR = INT1_TOUCH;
retval = SYSINTR_TOUCH;
}
//
// See if it is timer 2 also used for the touch interface.
//
else if (ulVic1Irq & INT1_TIMER2)
{
*VIC1_INTCLEAR = INT1_TIMER2;
retval = SYSINTR_TIMER2;
}
//
// Check to see if it the IRDA interrupt.
//
else if (ulVic2Irq & INT2_IRDA )
{
*VIC2_INTCLEAR = INT2_IRDA;
retval = SYSINTR_IR;
}
//
// Check to see if it is the IDE interrupt.
//
else if (ulVic2Irq & INT2_EXT3)
{
*VIC2_INTCLEAR = INT2_EXT3;
retval = SYSINTR_IDE;
}
else if(ulVic2Irq & INT2_PCMCIA_IRQ)
{
*VIC2_INTCLEAR = INT2_PCMCIA_IRQ;
// OEMEthISR();
retval = SYSINTR_PCMCIA_LEVEL;
}
else if((ulVic1Irq & (INT1_PCMCIA_CD1 | INT1_PCMCIA_CD2 | INT1_PCMCIA_BVD1)) ||
(ulVic2Irq & INT2_PCMCIA_BVD2))
{
*VIC1_INTCLEAR = (INT1_PCMCIA_CD1 | INT1_PCMCIA_CD2 | INT1_PCMCIA_BVD1);
*VIC2_INTCLEAR = INT2_PCMCIA_BVD2;
retval = SYSINTR_PCMCIA_STATE;
}
else
{
// OEMWriteDebugByte('U') ;
// NKDbgPrintfW(L"U = 0x%x, 0x%x,0x%x, 0x%x, 0x%x, 0x%x\r\n", ulVic1Irq, ulVic2Irq, ulVic1Last,ulVic2Last,fPS2Int, ulDummyRead);
}
}
// ulVic1Last = ulVic1Irq;
// ulVic2Last = ulVic2Irq;
//
// If we get any device interrupts, signal the resume flag. The flag
// will release the CPU from OEMPowerOff if the user had previously
// chosen to suspend the platform. In OEMPowerOff, only the interrupts
// allowed to wake us up will be enabled so we needn't worry about
// that here.
//
if(retval < SYSINTR_MAXIMUM && !gfResumeFlag)
{
if( gfSysIntrWakeupMask[retval] )
{
gfResumeFlag = TRUE;
gdwLastWakeupSource = retval;
}
}
return retval;
}
//****************************************************************************
// TimerInterrupt
//****************************************************************************
// Lets put all of the timer interrupt handling in one place.
// This code was taken from the arm integrator platform.
// The code is confusing, so I cleaned it up a little bit by making one
// ending point.
//
int TimerInterrupt(void)
{
DWORD retval = SYSINTR_NOP;
// static int iCount = 0;
//
// update the tick count
//
CurTicks.QuadPart += dwReschedIncrement;
//
// Print out a 1 every second. I want to make sure that we are getting ticks.
//
//if(iCount++ == 1000)
//{
// OEMWriteDebugByte('T') ;
// iCount = 0;
//}
//
// Call the profile ISR if it's enabled.
//
if (PProfileInterrupt)
{
retval = PProfileInterrupt();
if(retval == SYSINTR_RESCHED)
{
//
// Update the millisecond counter
//
CurMSec += RESCHED_PERIOD;
#if (CE_MAJOR_VER == 0x0003)
DiffMSec += RESCHED_PERIOD;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -