⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interrupt.c

📁 ARM下加一个硬件驱动比较复杂
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -