📄 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>
#include <audiopio.h>
#if (CE_MAJOR_VER == 0x0003)
extern DWORD ticksleft, dwSleepMin, dwPreempt;
extern DWORD DiffMSec;
#else
extern DWORD dwReschedTime;
#endif
#define DEBUG_ALARM 0
volatile BOOL gfRTCAlarm=FALSE;
volatile LARGE_INTEGER gliRTCAlarmTicks;
volatile BOOL fInterruptFlag;
volatile DWORD gdwInterruptMask1=INT1_TIMER1, gdwInterruptMask2=0;
volatile DWORD gdwInterruptWakeMask1, gdwInterruptWakeMask2;
volatile BOOL fPS2Int;
volatile BYTE gfSysIntrWakeupMask[SYSINTR_MAXIMUM];
volatile BOOL gfResumeFlag=TRUE;
volatile DWORD gdwLastWakeupSource;
volatile DWORD dwTimeValueWhenSuspend;
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;
LONG EnableInterruptCount[100];
//
// Function prototypes.
//
DWORD PerfCountSinceTick(void);
int TimerInterrupt(void);
DWORD OEMTranslateIrq(DWORD Irq);
BOOL CPUClearSysTimerIRQ(void);
// ULONG ulVic1Last, ulVic2Last;
struct AudioPIO sPlayBack;
struct AudioPIO sRecord;
BOOL gbAC97;
ULONG gulTransmitBuffer[MAX_TRANSMIT_BUFFER_SIZE>>2];
ULONG gulRecieveBuffer[MAX_TRANSMIT_BUFFER_SIZE>>2];
#define AC97CH AC97I_CH1_BASE
//---------------------------------------------------------------------------
//added by cyx 2005 06 21
int GetIrqNum(unsigned long mask1,unsigned long mask2)
{
int irqno=0,base=0;
unsigned long mask;
if(mask1){ mask =mask1;base=0;}
if(mask2){ mask =mask2;base=32;}
while(mask){
mask=mask>>1;
irqno++;
}
return irqno+base;
}
//---------------------------------------------------------------------------
//****************************************************************************
// OEMInterruptHandlerFIQ
//****************************************************************************
// Used for PIO Audio instead of using a DMA channel.
//
// On the EP93XX Rev D1 and E0 the following may cause audio glitches.
//
// 1. Boot in 16 Bit mode
// 2. Use USB
// 3. Use DMA
//
// To work around this problem we use the FIQ handler to perform PIO audio.
//
void OEMInterruptHandlerFIQ()
{
volatile register ULONG ulTemp;
register ULONG *p;
// Fake CPUEnterIdle needs to know about interrupt firing.
fInterruptFlag = TRUE;
if(gbAC97)
{
//register ULONG ulAC97Status;
register ULONG ulAC97ISR;
register ULONG *pAC97DR = (ULONG *)AC97CH+(AC97I_DR>>2);
// ulAC97Status = AC97CH[AC97I_SR>>2];
ulAC97ISR = AC97CH[AC97I_ISR>>2];
if(ulAC97ISR & ISR_TIS)
{
//
// Check to see if the transmit buffer is enabled.
//
if(sPlayBack.bEnabled )
{
p = sPlayBack.pulPosition;
if(p == sPlayBack.pulBufferHalf)
{
*VIC1_SOFTINT = INT1_UNUSED1;
}
else if(p >= sPlayBack.pulBufferEnd )
{
p = sPlayBack.pulPosition = sPlayBack.pulBuffer;
*VIC1_SOFTINT = INT1_UNUSED1;
}
*pAC97DR = *p++;
*pAC97DR = *p++;
*pAC97DR = *p++;
*pAC97DR = *p++;
sPlayBack.pulPosition = p;
}
else
{
*pAC97DR = 0;
*pAC97DR = 0;
*pAC97DR = 0;
*pAC97DR = 0;
}
}
//if(ulAC97Status & SR_RXFF)
if(ulAC97ISR & ISR_RIS)
{
//
// Check to see if the recieve buffer is enabled.
//
if(sRecord.bEnabled )
{
p = sRecord.pulPosition;
if(p == sRecord.pulBufferHalf)
{
*VIC1_SOFTINT = INT1_UNUSED2;
}
else if(p >= sRecord.pulBufferEnd )
{
p = sRecord.pulPosition = sRecord.pulBuffer;
*VIC1_SOFTINT = INT1_UNUSED2;
}
*p++ = *pAC97DR;
*p++ = *pAC97DR;
*p++ = *pAC97DR;
*p++ = *pAC97DR;
sRecord.pulPosition= p;
}
else
{
ulTemp = *pAC97DR;
ulTemp = *pAC97DR;
ulTemp = *pAC97DR;
ulTemp = *pAC97DR;
}
}
}
else
{
register ULONG ulSAIStatus;
//
// Check to see if the Transmit Fifo is emtpy.
//
ulSAIStatus = *SAI_GSR;
if(ulSAIStatus & GSR_TX0_FIFO_EMPTY )
{
//
// Check to see if the transmit buffer is enabled.
//
if(sPlayBack.bEnabled )
{
p = sPlayBack.pulPosition;
if(p == sPlayBack.pulBufferHalf)
{
*VIC1_SOFTINT = INT1_UNUSED1;
}
else if(p >= sPlayBack.pulBufferEnd )
{
p = sPlayBack.pulPosition = sPlayBack.pulBuffer;
*VIC1_SOFTINT = INT1_UNUSED1;
}
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
sPlayBack.pulPosition= p;
}
else
{
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
}
}
if(ulSAIStatus & GSR_RX0_FIFO_FULL )
{
//
// Check to see if the recieve buffer is enabled.
//
if(sRecord.bEnabled )
{
p = sRecord.pulPosition;
if(p == sRecord.pulBufferHalf)
{
*VIC1_SOFTINT = INT1_UNUSED2;
}
else if(p >= sRecord.pulBufferEnd )
{
p = sRecord.pulPosition = sRecord.pulBuffer;
*VIC1_SOFTINT = INT1_UNUSED2;
}
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
sRecord.pulPosition= p;
}
else
{
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
ulTemp = *SAI_RX0_LEFT;
ulTemp = *SAI_RX0_RIGHT;
}
}
}
}
//****************************************************************************
// 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;
DWORD retval;
LARGE_INTEGER tmpCurTicks;
DWORD dwSysIntr_UART;
//
// 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 if(sPlayBack.bIntOccurred)
//{
// sPlayBack.bIntOccurred = FALSE;
// retval = SYSINTR_PIO_PLAYBACK;
//}
else
{
retval = TimerInterrupt();
CPUClearSysTimerIRQ();
}
//
// Check if RTC Alarm arrived when TimerInterrupt returns NOP.
//
if( (gfRTCAlarm) && (retval == SYSINTR_NOP) )
{
// Tell the world that we were here....
#if (1 == DEBUG_ALARM)
OEMWriteDebugByte('e');
#endif // ( DEBUG_ALARM )
tmpCurTicks.QuadPart = CurTicks.QuadPart ;
if (gliRTCAlarmTicks.QuadPart <= tmpCurTicks.QuadPart)
{
#if (1 == DEBUG_ALARM)
// Tell the world that the interrupt was hit...
OEMWriteDebugByte('t');
OEMWriteDebugByte('\r');
OEMWriteDebugByte('\n');
#endif // ( DEBUG_ALARM )
gfRTCAlarm = FALSE;
retval = SYSINTR_RTC_ALARM;
}
}
}
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++;
}
//
// 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.
//
//gfResumeFlag = TRUE;
/*if(ulVic2Irq & INT2_EXT1)
{
retval = NKCallIntChain(33);
if(retval == SYSINTR_OEMUART1) //SYSINTR_CHAIN && dwSysIntr_UART != SYSINTR_NOP)
{
*VIC2_INTCLEAR = INT2_EXT1;
//dwSysIntr_UART = SYSINTR_OEMUART1;
}
}*/
//
// 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_GPIO)
{
retval = NKCallIntChain(59);
if( (retval == SYSINTR_CAN1) ||(retval == SYSINTR_CAN2)) //SYSINTR_CHAIN && dwSysIntr_UART != SYSINTR_NOP)
{
*VIC2_INTCLEAR = INT2_GPIO;
}
}
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;
}
//--------------------------------------------------
//
//OEM UART added by cyx 2005 06 08
//
#ifdef SBS_SAM3210
else if(ulVic2Irq & INT2_EXT1)
{
retval = NKCallIntChain(33);
if( (retval == SYSINTR_OEMUART1) ||(retval == SYSINTR_OEMUART2)||
(retval == SYSINTR_OEMUART3) ||(retval == SYSINTR_OEMUART4)) //SYSINTR_CHAIN && dwSysIntr_UART != SYSINTR_NOP)
{
*VIC2_INTCLEAR = INT2_EXT1;
}
}
#endif
//--------------------------------------------------
//--------------------------------------------------
//
//OEM UART added by cyx 2005 06 08
//
#ifdef SBS_SBS04A03
else if(ulVic2Irq & INT2_EXT0)
{
retval = NKCallIntChain(32);
if( (retval == SYSINTR_OEMUART1) ) //SYSINTR_CHAIN && dwSysIntr_UART != SYSINTR_NOP)
{
*VIC2_INTCLEAR = INT2_EXT0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -