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

📄 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 Au1 SoC.
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include <oal_intr_mips.h>
#include <oal_info_mips.h>
#include <au1.h>


//------------------------------------------------------------------------------
//
//  Globals:  g_pIC0Regs/g_pIC1Regs
//
//  The global variables are storing virual address for IC0 and IC1 units
//  for use in interrupt handling to avoid possible time consumig call to
//  OALPAtoVA function.
//
static AU1_IC_REGS *g_pIC0Regs;
static AU1_IC_REGS *g_pIC1Regs;

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

BOOL OALIntrInit()
{
    BOOL rc = FALSE;
    OAL_MIPS_PROCESSOR_ID id;
    
    OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALInterruptInit\r\n"));

    // Initialize interrupt mapping
    OALIntrMapInit();

    // Get and save uncached virtual addresses for IC0 and IC1
    g_pIC0Regs = OALPAtoUA(AU1_IC0_REGS_PA);
    g_pIC1Regs = OALPAtoUA(AU1_IC1_REGS_PA);

    // First IC0
    OUTREG32(&g_pIC0Regs->CFG0CLR,    0xFFFFFFFF);   // All disabled
    OUTREG32(&g_pIC0Regs->CFG1CLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC0Regs->CFG2CLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC0Regs->SRCSET,     0xFFFFFFFF);   // All hardware
    OUTREG32(&g_pIC0Regs->ASSIGNSET,  0xFFFFFFFF);   // All request 0
    OUTREG32(&g_pIC0Regs->WAKECLR,    0xFFFFFFFF);   // No wakeup
    OUTREG32(&g_pIC0Regs->MASKCLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC0Regs->RISINGCLR,  0xFFFFFFFF);
    OUTREG32(&g_pIC0Regs->FALLINGCLR, 0xFFFFFFFF);
    
    // Then IC1
    OUTREG32(&g_pIC1Regs->CFG0CLR,    0xFFFFFFFF);   // All disabled
    OUTREG32(&g_pIC1Regs->CFG1CLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC1Regs->CFG2CLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC1Regs->SRCSET,     0xFFFFFFFF);   // All hardware
    OUTREG32(&g_pIC1Regs->ASSIGNSET,  0xFFFFFFFF);   // All request 0
    OUTREG32(&g_pIC1Regs->WAKECLR,    0xFFFFFFFF);   // No wakeup
    OUTREG32(&g_pIC1Regs->MASKCLR,    0xFFFFFFFF);
    OUTREG32(&g_pIC1Regs->RISINGCLR,  0xFFFFFFFF);
    OUTREG32(&g_pIC1Regs->FALLINGCLR, 0xFFFFFFFF);

    // Get chip identification
    id.value = OALMIPSGetProcessorId();

    // If we know chip set configuration bit 
    if (id.companyId == OAL_MIPS_COMP_ID_AMD) {
        switch (id.option) {
        case AU1_SOC_ID_AU1000:
            OUTREG32(&g_pIC0Regs->CFG0SET, AU1000_IC_CFG0);
            OUTREG32(&g_pIC0Regs->CFG1SET, AU1000_IC_CFG1);
            OUTREG32(&g_pIC0Regs->CFG2SET, AU1000_IC_CFG2);
            break;
        case AU1_SOC_ID_AU1100:
            OUTREG32(&g_pIC0Regs->CFG0SET, AU1100_IC_CFG0);
            OUTREG32(&g_pIC0Regs->CFG1SET, AU1100_IC_CFG1);
            OUTREG32(&g_pIC0Regs->CFG2SET, AU1100_IC_CFG2);
            break;
        case AU1_SOC_ID_AU1500:
            OUTREG32(&g_pIC0Regs->CFG0SET, AU1500_IC_CFG0);
            OUTREG32(&g_pIC0Regs->CFG1SET, AU1500_IC_CFG1);
            OUTREG32(&g_pIC0Regs->CFG2SET, AU1500_IC_CFG2);
            break;
        }

    }    
    // Hook interrupts 0 to 2
    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;
    }
    
#ifdef OAL_BSP_CALLBACKS
    // Give BSP change to initialize subordinate controller
    rc = BSPIntrInit();
#else
    rc = TRUE;
#endif

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


//------------------------------------------------------------------------------
//
//  Function:  OALIntrRequestIrq
//
//  This function returns IRQ for CPU/SoC devices based on their
//  physical address.
//
BOOL OALIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrq)
{
    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, pIrq
    ));

    // This shouldn't happen
    if (*pCount < 1) goto cleanUp;
    
    if (pDevLoc->IfcType == Internal) {
        switch (pDevLoc->LogicalLoc) {
        case AU1_MACA0_REGS_PA:
        case AU1_MACB0_REGS_PA:
            pIrq[0] = IRQ_MAC0;
            *pCount = 1;
            rc = TRUE;
            break;
        case AU1_MACA1_REGS_PA:
        case AU1_MACB1_REGS_PA:
            pIrq[0] = IRQ_MAC1;
            *pCount = 1;
            rc = TRUE;
            break;
        case AU1_USBD_REGS_PA:
            pIrq[0] = IRQ_USBD;
            *pCount = 1;
            rc = TRUE;
            break;
        }
    } 

#ifdef OAL_BSP_CALLBACKS
    if (!rc) rc = BSPIntrRequestIrqs(pDevLoc, pCount, pIrq);
#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;

    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 < 32) {
            OUTREG32(&g_pIC0Regs->WAKESET, 1 << irq);
            OUTREG32(&g_pIC0Regs->MASKSET, 1 << irq);
        } else if (irq < 64) {
            OUTREG32(&g_pIC1Regs->WAKESET, 1 << (irq - 32));
            OUTREG32(&g_pIC1Regs->MASKSET, 1 << (irq - 32));
        } 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;

    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
        if (irq < 32) {
            OUTREG32(&g_pIC0Regs->MASKCLR, 1 << irq);
        } else if (irq < 64) {
            OUTREG32(&g_pIC1Regs->MASKCLR, 1 << (irq - 32));
        }        
    }

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


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDoneIrqs
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 irq, i;

    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
        if (irq < 32) {
            OUTREG32(&g_pIC0Regs->MASKSET, 1 << irq);
        } else if (irq < 64) {
            OUTREG32(&g_pIC1Regs->MASKSET, 1 << (irq - 32));
        }        
    }

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


//------------------------------------------------------------------------------
//
//  Function:  OALIntr0Handler
//
//  This is interrupt handler implementation for MIPS interrupt 0 on Au1.
//
UINT32 OALIntr0Handler()
{
    UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 status, mask = 0;

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

    // Get pending interrupt
    if ((status = INREG32(&g_pIC0Regs->REQ0INT)) != 0) {
        for (mask = 1, irq = 0; mask != 0; mask <<= 1, irq++) {
            if ((status & mask) != 0) break;
        }
        // Disable it and clear edges
        OUTREG32(&g_pIC0Regs->MASKCLR, mask);
        OUTREG32(&g_pIC0Regs->RISINGCLR, mask);
        OUTREG32(&g_pIC0Regs->FALLINGCLR, mask);
    }

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to translate IRQ -- if there is subordinate
    // interrupt controller in BSP it give chance to decode its status
    // and change IRQ
    irq = BSPIntrActiveIrq(irq);
#endif

    // If there isn't valid IRQ leave
    if (irq == OAL_INTR_IRQ_UNDEFINED) goto cleanUp;
    
    // First find if IRQ is claimed by chain
    sysIntr = NKCallIntChain((UCHAR)irq);
    if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
        // IRQ wasn't claimed or SYSINTR isn't valid, use static mapping
        sysIntr = OALIntrTranslateIrq(irq);
    }

    // unmask interrupts in case it's NOP or invalid
    if (SYSINTR_NOP == sysIntr) {
#ifdef OAL_BSP_CALLBACKS
        // Give BSP chance to translate IRQ -- if there is subordinate
        // interrupt controller in BSP it give chance to decode its status
        // and change IRQ
        BSPIntrEnableIrq (irq);
#endif
        if (mask) {
            OUTREG32(&g_pIC0Regs->MASKSET, mask);
        }
    }
    
cleanUp:    
    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr1Handler
//
//  This is interrupt handler implementation for MIPS interrupt 1 on Au1.
//

UINT32 OALIntr1Handler()
{
    UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 status, mask = 0;

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

    // Get pending interrupt
    if ((status = INREG32(&g_pIC0Regs->REQ1INT)) != 0) {
        for (mask = 1, irq = 0; mask != 0; mask <<= 1, irq++) {
            if ((status & mask) != 0) break;
        }
        // Disable it and clear edges
        OUTREG32(&g_pIC0Regs->MASKCLR, mask);
        OUTREG32(&g_pIC0Regs->RISINGCLR, mask);
        OUTREG32(&g_pIC0Regs->FALLINGCLR, mask);
    }

    // First find if IRQ is claimed by chain
    sysIntr = NKCallIntChain((UCHAR)irq);
    if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
        // IRQ wasn't claimed or SYSINTR isn't valid, use static mapping
        sysIntr = OALIntrTranslateIrq(irq);
    }

    if (mask && (SYSINTR_NOP == sysIntr)) {
        OUTREG32(&g_pIC0Regs->MASKSET, mask);
    }

    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr2Handler
//
//  This is interrupt handler implementation for MIPS interrupt 2 on Au1.
//

UINT32 OALIntr2Handler()
{
    UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 status, mask = 0;

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

    // Get pending interrupt
    if ((status = INREG32(&g_pIC1Regs->REQ0INT)) != 0) {
        for (mask = 1, irq = 32; mask != 0; mask <<= 1, irq++) {
            if ((status & mask) != 0) break;
        }
        // Disable it and clear edges
        OUTREG32(&g_pIC1Regs->MASKCLR, mask);
        OUTREG32(&g_pIC1Regs->RISINGCLR, mask);
        OUTREG32(&g_pIC1Regs->FALLINGCLR, mask);
    }

    // First find if IRQ is claimed by chain
    sysIntr = NKCallIntChain((UCHAR)irq);
    if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
        // IRQ wasn't claimed or SYSINTR isn't valid, use static mapping
        sysIntr = OALIntrTranslateIrq(irq);
    }

    if (mask && (SYSINTR_NOP == sysIntr)) {
        OUTREG32(&g_pIC1Regs->MASKSET, mask);
    }

    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntr3Handler
//
//  This is interrupt handler implementation for MIPS interrupt 3 on Au1.
//

UINT32 OALIntr3Handler()
{
    UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 status, mask = 0;

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

    // Get pending interrupt
    if ((status = INREG32(&g_pIC1Regs->REQ1INT)) != 0) {
        for (mask = 1, irq = 32; mask != 0; mask <<= 1, irq++) {
            if ((status & mask) != 0) break;
        }
        // Disable it and clear edges
        OUTREG32(&g_pIC1Regs->MASKCLR, mask);
        OUTREG32(&g_pIC1Regs->RISINGCLR, mask);
        OUTREG32(&g_pIC1Regs->FALLINGCLR, mask);
    }

    // First find if IRQ is claimed by chain
    sysIntr = NKCallIntChain((UCHAR)irq);
    if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
        // IRQ wasn't claimed or SYSINTR isn't valid, use static mapping
        sysIntr = OALIntrTranslateIrq(irq);
    }

    if (mask && (SYSINTR_NOP == sysIntr)) {
        OUTREG32(&g_pIC1Regs->MASKSET, mask);
    }

    return sysIntr;
}

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

⌨️ 快捷键说明

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