📄 interrupt.c
字号:
//**********************************************************************
//
// Filename: interrupt.c
//
// Description: OEM Interrupt handler.
//
// 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.
//
// Use of this source code is subject to the terms of the Cirrus 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
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, 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>
static DWORD g_dwLastInterrupt=0;
#ifdef EDB9315A_CIR
#include <winbase.h>
// For DS6310 TV URC only
#define gnKeyIntCnt 26
const int gnMinInterval = 300; // 0.3ms
const int gnMaxInterval = 2600; // 2.6ms
LARGE_INTEGER gulIntTime[gnKeyIntCnt]; // Assume no more than 50 pulse for one key pressing.
int gnIntDif[gnKeyIntCnt]; // gpio input level
int gnWi; // write index
UINT gnKeyCode;
PUCHAR gstrKeyName;
static unsigned int gnKeyTable[10] = {
0x1410100, //0b1010000010000000100000000,
0x1000100, //0b1000000000000000100000000,
0x1400100, //0b1010000000000000100000000,
0x1100100, //0b1000100000000000100000000,
0x1500100, //0b1010100000000000100000000,
0x1040100, //0b1000001000000000100000000,
0x1440100, //0b1010001000000000100000000,
0x1140100, //0b1000101000000000100000000,
0x1540100, //0b1010101000000000100000000,
0x1010100 //0b1000000010000000100000000
};
static UCHAR gstrKeyNameTable[11][10] = {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"Unknown"
};
extern BOOL OEMQueryPerformanceCounter( LARGE_INTEGER *lpliPerformanceCount );
#endif
extern DWORD dwReschedTime;
#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;
//
// 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
//****************************************************************************
// 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;
DWORD dwFillCount=0;
//
// Check to see if the Transmit Fifo is emtpy.
//
ulSAIStatus = *SAI_GSR;
if(ulSAIStatus & GSR_TX0_FIFO_EMPTY )
dwFillCount=8;
else if(ulSAIStatus & GSR_TX0_FIFO_HALF_EMPTY )
dwFillCount=4;
if( dwFillCount )
{
//
// 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;
}
while ( dwFillCount -- )
{
*SAI_TX0_LEFT = *p++;
*SAI_TX0_RIGHT = *p++;
}
sPlayBack.pulPosition= p;
}
else
{
while ( dwFillCount -- )
{
*SAI_TX0_LEFT = 0;
*SAI_TX0_RIGHT = 0;
}
}
}
dwFillCount=0;
if(ulSAIStatus & GSR_RX0_FIFO_FULL )
dwFillCount=8;
else if(ulSAIStatus & GSR_RX0_FIFO_HALF_FULL )
dwFillCount=4;
if( dwFillCount )
{
//
// 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;
}
while ( dwFillCount -- )
{
*p++ = *SAI_RX0_LEFT;
*p++ = *SAI_RX0_RIGHT;
}
sRecord.pulPosition= p;
}
else
{
while ( dwFillCount -- )
{
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;
//
// 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.
//
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();
}
//
// 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;
//
// 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;
}
else if(ulVic1Irq & INT1_UNUSED1)
{
*VIC1_INTCLEAR = INT1_UNUSED1;
retval = SYSINTR_PIO_PLAYBACK;
}
else if(ulVic1Irq & INT1_UNUSED2)
{
*VIC1_INTCLEAR = INT1_UNUSED2;
retval = SYSINTR_PIO_RECORD;
}
//
// 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;
}
#if 0
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;
}
#endif // 0
else if (ulVic1Irq & INT1_DMAM2M0 )
{
*VIC1_INTCLEAR = INT1_DMAM2M0;
retval = SYSINTR_DMA_M2M0;
}
else if (ulVic1Irq & INT1_DMAM2M1 )
{
*VIC1_INTCLEAR = INT1_DMAM2M1;
retval = SYSINTR_DMA_M2M1;
}
//
// Check to see if it is a touch pad interrupt.
//
else if (ulVic1Irq & INT1_TOUCH)
{
*VIC1_INTCLEAR = INT1_TOUCH;
//RETAILMSG(1, (TEXT("TOUCH\r\n")));
// *VIC1_INTENABLE=INT1_TOUCH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -