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

📄 intr.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 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.
//
//------------------------------------------------------------------------------
//
//  File: intr.c
//
//  This file implement major part of interrupt module for BCM11xx SoC. 
//  The implementation uses virtual ethernet interrupt (IRQ_ETHER) which
//  address situation when tree interrupts to related to ethernet module.
//  NDIS doesn't support more that one interrupt so code must multiplex
//  IRQ_DMA_EMAC_RX, IRQ_DMA_EMAC_TX and IRQ_PHY to one virtual IRQ_ETHER.
//  The implementation also assumes no shared interrupt will be used on
//  device based on this SoC and there will not be secondary interrupt
//  handler on board.
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include <oal_intr_mips.h>
#include <bcm11.h>

//------------------------------------------------------------------------------
//
//  Define:  IRQ_ETHER_MASK
//
#define IRQ_ETHER_MASK  ((1<<IRQ_DMA_EMAC_RX)|(1<<IRQ_DMA_EMAC_TX)|(1<<IRQ_PHY))


//------------------------------------------------------------------------------
//
//  Function:  OALIntrInit
//
//  This function initialize Vr4131 interrupt hardware.
//

BOOL OALIntrInit()
{
    BOOL rc = FALSE;
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    
    OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALInterruptInit\r\n"));

    // Initialize interrupt mapping
    OALIntrMapInit();

    // Disable all interrupts
    OUTREG32(&pIntcRegs->MASK, 0);
    OUTREG32(&pIntcRegs->EXT_CTRL, 0);
    OUTREG32(&pIntcRegs->DSP_MASK, 0);
    OUTREG32(&pIntcRegs->MSPI_CTRL, 0);

    // Hook interrupts 0 to 4
    if (!HookInterrupt(0, OALIntr0Handler)) {
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIntrInit: HookInterrupt for MIPS interrupt 0 failed\r\n"
        ));
        goto cleanUp;
     }        
    if (!HookInterrupt(1, OALIntr1Handler)) {
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIntrInit: HookInterrupt for MIPS interrupt 1 failed\r\n"
        ));
        goto cleanUp;
    }        
    if (!HookInterrupt(2, OALIntr2Handler)) {
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIntrInit: HookInterrupt for MIPS interrupt 2 failed\r\n"
        ));
        goto cleanUp;
    }        
    if (!HookInterrupt(3, OALIntr3Handler)) {
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIntrInit: HookInterrupt for MIPS interrupt 3 failed\r\n"
        ));
        goto cleanUp;
    }
    if (!HookInterrupt(4, OALIntr4Handler)) {
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIntrInit: HookInterrupt for MIPS interrupt 3 failed\r\n"
        ));
        goto cleanUp;
    }
    
    // Let do board specific initialization
    rc = BSPIntrInit();

cleanUp:    
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALInterruptInit(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrRequestIrqs
//
//  This function returns IRQ for CPU/SoC devices based on their
//  physical address.
//
BOOL OALIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrqs)
{
    BOOL rc = FALSE;

    OALMSG(OAL_INTR&&OAL_FUNC, (
        L"+OALIntrRequestIrqs(0x%08x->%d/%d/0x%08x/%d, 0x%08x, 0x%08x)\r\n",
        pDevLoc, pDevLoc->IfcType, pDevLoc->BusNumber, pDevLoc->LogicalLoc,
        pDevLoc->Pin, pCount, pIrqs
    ));

    // This shouldn't happen
    if (*pCount < 1) goto cleanUp;

    if (pDevLoc->IfcType == Internal) {
        switch (pDevLoc->LogicalLoc) {
        case BCM11_ETH_REGS_PA:
            pIrqs[0] = IRQ_ETHER;
            *pCount = 1;
            rc = TRUE;
            break;
        }            
    }

#ifdef OAL_BSP_CALLBACKS
    if (!rc) rc = BSPIntrRequestIrqs(pDevLoc, pCount, pIrqs);
#endif    

cleanUp:
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrRequestIrqs(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrEnableIrqs
//
BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    BOOL rc = TRUE;
    UINT32 irq, i;
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    BCM11_TIMER_REGS *pTimerRegs = OALPAtoUA(BCM11_TIMER_REGS_PA);

    OALMSG(OAL_INTR&&OAL_VERBOSE, (
        L"+OALntrEnableIrqs(%d, 0x%08x)\r\n", count, pIrqs
    ));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to enable irq on subordinate interrupt controller
        irq = BSPIntrEnableIrq(pIrqs[i]);
#endif
        if (irq == OAL_INTR_IRQ_UNDEFINED) continue;

        if (irq == IRQ_ETHER) {
            // IRQ_ETHER is virual IRQ
            SETREG32(&pIntcRegs->MASK, IRQ_ETHER_MASK);
        } else if (irq < IRQ_EXT0) {
            SETREG32(&pIntcRegs->MASK, 1 << irq);
        } else if (irq < IRQ_TIMER0) {
            SETREG32(&pIntcRegs->EXT_CTRL, 1 << (irq - IRQ_EXT0 + 12));
        } else if (irq < IRQ_MSPI) {
            SETREG32(&pIntcRegs->MASK, 1 << IRQ_TIMER);
            SETREG32(&pTimerRegs->INTR, 1 << (irq - IRQ_TIMER0 + 8));
        } else if (irq == IRQ_MSPI) {
            SETREG32(&pIntcRegs->MSPI_CTRL, 1 << (IRQ_MSPI - IRQ_MSPI));
        } else {
            rc = FALSE;
        }
    }

    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrEnableIrqs(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDisableIrqs
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 irq, i;
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    BCM11_TIMER_REGS *pTimerRegs = OALPAtoUA(BCM11_TIMER_REGS_PA);

    OALMSG(OAL_INTR&&OAL_FUNC, (
        L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n", count, pIrqs
    ));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to disable irq on subordinate interrupt controller
        irq = BSPIntrDisableIrq(pIrqs[i]);
#endif
        // First care about virtual IRQ
        if (irq == IRQ_ETHER) {
            CLRREG32(&pIntcRegs->MASK, IRQ_ETHER_MASK);
        } else if (irq < IRQ_EXT0) {
            CLRREG32(&pIntcRegs->MASK, 1 << irq);
        } else if (irq < IRQ_TIMER0) {
            CLRREG32(&pIntcRegs->EXT_CTRL, 1 << (irq - IRQ_EXT0 + 12));
        } else if (irq < IRQ_MSPI) {
            CLRREG32(&pTimerRegs->INTR, 1 << (irq - IRQ_TIMER0 + 8));
        } else if (irq == IRQ_MSPI) {
            CLRREG32(&pIntcRegs->MSPI_CTRL, 1 << (IRQ_MSPI - IRQ_MSPI));
        }    
    }

    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrDisableIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDoneIrqs
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 irq, i;
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    BCM11_TIMER_REGS *pTimerRegs = OALPAtoUA(BCM11_TIMER_REGS_PA);

    OALMSG(OAL_INTR&&OAL_VERBOSE, (
        L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs
    ));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to finish irq on subordinate interrupt controller
        irq = BSPIntrDoneIrq(pIrqs[i]);
#endif
        // First care about virtual IRQ
        if (irq == IRQ_ETHER) {
            SETREG32(&pIntcRegs->MASK, IRQ_ETHER_MASK);
        } else if (irq < IRQ_EXT0) {
            SETREG32(&pIntcRegs->MASK, 1 << irq);
        } else if (irq < IRQ_TIMER0) {
            SETREG32(&pIntcRegs->EXT_CTRL, 1 << (irq - IRQ_EXT0 + 12));
        } else if (irq < IRQ_MSPI) {
            SETREG32(&pTimerRegs->INTR, 1 << (irq - IRQ_TIMER0 + 8));
        } else if (irq == IRQ_MSPI) {
            SETREG32(&pIntcRegs->MSPI_CTRL, 1 << (IRQ_MSPI - IRQ_MSPI));
        }    
    }

    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrDoneIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr0Handler
//
//  This is interrupt handler implementation for MIPS interrupt 0. On BCM11xx
//  it is shared between SoC devices.
//
UINT32 OALIntr0Handler()
{
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    BCM11_TIMER_REGS *pTimerRegs = OALPAtoUA(BCM11_TIMER_REGS_PA);
    UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 status, mask;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) g_oalILT.interrupts++;
#endif

    // Get pending interrupt
    if ((status = (
        INREG32(&pIntcRegs->STATUS) & INREG32(&pIntcRegs->MASK)
    )) != 0) {
        for (mask = 1, irq = 0; mask != 0; mask <<= 1, irq++) {
            if ((status & mask) != 0) break;
        }
        if (irq == IRQ_DMA_EMAC_RX || irq == IRQ_DMA_EMAC_TX || irq == IRQ_PHY) {
            irq = IRQ_ETHER;
            CLRREG32(&pIntcRegs->MASK, IRQ_ETHER_MASK);
        } else if (irq == IRQ_TIMER) {
            // This is timer interrupt, find which one...
            status = INREG32(&pTimerRegs->INTR);
            status &= (status >> 8) & 0xFF;
            for (
                mask = 1, irq = IRQ_TIMER0; irq <= IRQ_WDOG; mask <<= 1, irq++
            ) {
                if ((status & mask) != 0) break;
            }
            // Depending on result
            if (irq <= IRQ_WDOG) {
                // Disable timer interrupt
                OUTREG32(&pTimerRegs->INTR, status & (mask << 8));
            } else {
                // Disable all timer interrupts 
                CLRREG32(&pIntcRegs->MASK, 1 << IRQ_TIMER);
            }
        } else {
            // Disable it
            CLRREG32(&pIntcRegs->MASK, 1 << irq);
        }

    } else {

        // It should be MSPI interrupt
        status = INREG32(&pIntcRegs->MSPI_CTRL);
        status &= (status << 8) & 0xFF00;
        if ((status & (1 << 8)) != 0) {
            irq = IRQ_MSPI;
            // Disable interrupt
            CLRREG32(&pIntcRegs->MSPI_CTRL, 1 << 0);
        }
    }

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ
    irq = BSPIntrActiveIrq(irq);
#endif

    // If there is valid IRQ translate it to SYSINTR
    if (irq != OAL_INTR_IRQ_UNDEFINED) {
        sysIntr = OALIntrTranslateIrq(irq);
    }

    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr1Handler
//
//  This is interrupt handler implementation for MIPS interrupt 1. On BCM11xx
//  it is external interrupt 0.
//
UINT32 OALIntr1Handler()
{
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    UINT32 sysIntr = SYSINTR_NOP, irq;
    UINT32 status, mask;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) g_oalILT.interrupts++;
#endif

    // Get pending interrupt
    status = INREG32(&pIntcRegs->EXT_CTRL);
    mask = 1 << (IRQ_EXT0 - 32 + 12);

    // This should not happen, but to be nice
    if ((status & mask) == 0) goto cleanUp;
    
    // Disable it and clear edge
    status = (status & ~mask) | (1 << (IRQ_EXT0 - 32 + 8));
    OUTREG32(&pIntcRegs->EXT_CTRL, status);

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ
    irq = BSPIntrActiveIrq(IRQ_EXT0);
#endif

    // Find SYSINTR mappend to IRQ_EXT0
    sysIntr = OALIntrTranslateIrq(irq);

cleanUp:
    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr2Handler
//
//  This is interrupt handler implementation for MIPS interrupt 2. On BCM11xx
//  it is external interrupt 1.
//
UINT32 OALIntr2Handler()
{
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    UINT32 sysIntr = SYSINTR_NOP, irq;
    UINT32 status, mask;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) g_oalILT.interrupts++;
#endif

    // Get pending interrupt
    status = INREG32(&pIntcRegs->EXT_CTRL);
    mask = 1 << (IRQ_EXT1 - 32 + 12);

    // This should not happen, but to be nice
    if ((status & mask) == 0) goto cleanUp;

    // Disable it and clear edge
    status = (status & ~mask) | (1 << (IRQ_EXT1 - 32 + 8));
    OUTREG32(&pIntcRegs->EXT_CTRL, status);

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ
    irq = BSPIntrActiveIrq(IRQ_EXT1);
#endif

    // Find SYSINTR mappend to IRQ_EXT0
    sysIntr = OALIntrTranslateIrq(irq);

cleanUp:
    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr3Handler
//
//  This is interrupt handler implementation for MIPS interrupt 3. On BCM11xx
//  it is external interrupt 2.
//
UINT32 OALIntr3Handler()
{
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    UINT32 sysIntr = SYSINTR_NOP, irq;
    UINT32 status, mask;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) g_oalILT.interrupts++;
#endif

    // Get pending interrupt
    status = INREG32(&pIntcRegs->EXT_CTRL);
    mask = 1 << (IRQ_EXT2 - 32 + 12);

    // This should not happen, but to be nice
    if ((status & mask) == 0) goto cleanUp;

    // Disable it and clear edge
    status = (status & ~mask) | (1 << (IRQ_EXT2 - 32 + 8));
    OUTREG32(&pIntcRegs->EXT_CTRL, status);

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ
    irq = BSPIntrActiveIrq(IRQ_EXT2);
#endif

    // Find SYSINTR mappend to IRQ_EXT0
    sysIntr = OALIntrTranslateIrq(irq);

cleanUp:
    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr4Handler
//
//  This is interrupt handler implementation for MIPS interrupt 4. On BCM11xx
//  it is external interrupt 3.
//
UINT32 OALIntr4Handler()
{
    BCM11_INTC_REGS *pIntcRegs = OALPAtoUA(BCM11_INTC_REGS_PA);
    UINT32 sysIntr = SYSINTR_NOP, irq;
    UINT32 status, mask;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) g_oalILT.interrupts++;
#endif

    // Get pending interrupt
    status = INREG32(&pIntcRegs->EXT_CTRL);
    mask = 1 << (IRQ_EXT3 - 32 + 12);

    // This should not happen, but to be nice
    if ((status & mask) == 0) goto cleanUp;

    // Disable it and clear edge
    status = (status & ~mask) | (1 << (IRQ_EXT3 - 32 + 8));
    OUTREG32(&pIntcRegs->EXT_CTRL, status);

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ
    irq = BSPIntrActiveIrq(IRQ_EXT3);
#endif

    // Find SYSINTR mappend to IRQ_EXT0
    sysIntr = OALIntrTranslateIrq(irq);

cleanUp:
    return sysIntr;
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -