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

📄 interrupt.c

📁 Cirrus EP9315 wince bsp
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -