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

📄 map.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
字号:
//
// Copyright (c) Special Computing.  All rights reserved. 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//------------------------------------------------------------------------------
//
//  File: map.c
//
//  This file implements functionality related to mapping between IRQ and
//  SYSINTR. There is custom implementation for OMAP3 because hardware
//  supports 96 different IRQs compared to maximal 64 IRQs allowed in generic
//  implementation. The implementation also supports multiple IRQ per one
//  SYSINTR mapping.
//
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <omap2420.h>


//------------------------------------------------------------------------------
//
//  Globals: g_oalSysIntr2Irq/g_oalIrq2SysIntr
//
static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM][OMAP3_IRQ_PER_SYSINTR];
static UINT32 g_oalIrq2SysIntr[OMAP3_IRQ_MAXIMUM];

//------------------------------------------------------------------------------
//
//  Globals: g_oalSysIntr2Irq/g_oalIrq2SysIntr
//
static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM][OMAP3_IRQ_PER_SYSINTR];
static UINT32 g_oalIrq2SysIntr[OMAP3_IRQ_MAXIMUM];

//------------------------------------------------------------------------------
//
//  Function:  OALIntrMapInit
//
//  This function must be called from OALInterruptInit to initialize mapping
//  between IRQ and SYSINTR. It simply initialize mapping arrays.
//
VOID
OALIntrMapInit(
    )
{
    UINT32 i, j;

    OALMSG(OAL_FUNC&&OAL_INTR, (L"+OEMInterruptMapInit\r\n"));

    // Initialize interrupt maps
    for (i = 0; i < SYSINTR_MAXIMUM; i++)
        {
        for (j = 0; j < OMAP3_IRQ_PER_SYSINTR; j++)
            {
            g_oalSysIntr2Irq[i][j] = OAL_INTR_IRQ_UNDEFINED;
            }
        }
    for (i = 0; i < OMAP3_IRQ_MAXIMUM; i++)
        {
        g_oalIrq2SysIntr[i] = SYSINTR_UNDEFINED;
        }

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

//------------------------------------------------------------------------------
//
//  Function:   OALIntrStaticTranslate
//
//  This function sets static translation between IRQ and SYSINTR.
//
VOID
OALIntrStaticTranslate(
    UINT32 sysIntr, 
    UINT32 irq
    )
{
    UINT32 i;

    OALMSG(OAL_FUNC&&OAL_INTR, (
        L"+OALIntrStaticTranslate(%d, %d)\r\n", sysIntr, irq
        ));
    if ((irq >= OMAP3_IRQ_MAXIMUM) || (sysIntr >= SYSINTR_MAXIMUM))
        goto cleanUp;

    for (i = 0; i < OMAP3_IRQ_PER_SYSINTR; i++)
        {
        if (g_oalSysIntr2Irq[sysIntr][i] != OAL_INTR_IRQ_UNDEFINED) continue;
        g_oalSysIntr2Irq[sysIntr][i] = irq;
        g_oalIrq2SysIntr[irq] = sysIntr;
        break;
        }

cleanUp:
    OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrStaticTranslate\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  OALIntrTranslateSysIntr
//
//  This function maps a SYSINTR to its corresponding IRQ. It is typically used
//  in OEMInterruptXXX to obtain IRQs for given SYSINTR.
//
BOOL
OALIntrTranslateSysIntr(
    UINT32 sysIntr, 
    UINT32 *pCount, 
    const UINT32 **ppIrqs
    )
{
    BOOL rc;

    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALTranslateSysIntr(%d)\r\n", sysIntr));

    // Valid SYSINTR?
    if (sysIntr >= SYSINTR_MAXIMUM)
        {
        rc = FALSE;
        goto cleanUp;
        }
    *pCount = OMAP3_IRQ_PER_SYSINTR;
    *ppIrqs = g_oalSysIntr2Irq[sysIntr];
    rc = TRUE;

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

//------------------------------------------------------------------------------
//
//  Function:  OALIntrTranslateIrq
//
//  This function maps a IRQ to its corresponding SYSINTR.
//
UINT32
OALIntrTranslateIrq(
    UINT32 irq
    )
{
    UINT32 sysIntr = SYSINTR_UNDEFINED;

    OALMSG(OAL_FUNC&&OAL_VERBOSE, (L"+OALIntrTranslateIrq(%d)\r\n", irq));

    if (irq < OMAP3_IRQ_MAXIMUM) sysIntr = g_oalIrq2SysIntr[irq];

    OALMSG(OAL_FUNC&&OAL_VERBOSE, (
        L"-OALIntrTranslateIrq(sysIntr = %d)\r\n", sysIntr
        ));
    return sysIntr;
}

//------------------------------------------------------------------------------
//
//  Function:  OALIntrRequestSysIntr
//
//  This function allocate new SYSINTR for given IRQ and it there isn't
//  static mapping for this IRQ it will create it.
//
UINT32
OALIntrRequestSysIntr(
    UINT32 count, 
    const UINT32 *pIrqs, 
    UINT32 flags
    )
{
    UINT32 sysIntr, i, j;


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

    // Valid IRQ?
    if (count > OMAP3_IRQ_PER_SYSINTR)
        {
        OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
            L"Only %d IRQs for SYSINTR is supported\r\n",
            OMAP3_IRQ_PER_SYSINTR
            ));
        sysIntr = SYSINTR_UNDEFINED;
        goto cleanUp;
        }

    // If static mapping is requested check if we can obtain one
    if ((flags & OAL_INTR_STATIC) != 0)
        {
        for (i = 0; i < count; i++)
            {
            if (pIrqs[i] >= OMAP3_IRQ_MAXIMUM)
                {
                OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
                    L"IRQ %d out of range\r\n", pIrqs[i]
                    ));
                sysIntr = SYSINTR_UNDEFINED;
                goto cleanUp;
                }

            if (g_oalIrq2SysIntr[pIrqs[i]] != SYSINTR_UNDEFINED)
                {
                OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
                    L"Static mapping for IRQ %d already assigned\r\n", pIrqs[i]
                    ));
                sysIntr = SYSINTR_UNDEFINED;
                goto cleanUp;
                }
            }
        }

    // If translate flag is set all IRQs must be mapped to same SYSINTR
    if (pIrqs[0] >= OMAP3_IRQ_MAXIMUM)
        {
        OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
            L"IRQ %d out of range\r\n", pIrqs[0]
            ));
        sysIntr = SYSINTR_UNDEFINED;
        goto cleanUp;
        }

    if (((flags & OAL_INTR_TRANSLATE) != 0) &&
        (g_oalIrq2SysIntr[pIrqs[0]] != SYSINTR_UNDEFINED))
        {
        sysIntr = g_oalIrq2SysIntr[pIrqs[0]];
        // Check remaining IRQs
        for (i = 1; i < count; i++)
            {
            if (pIrqs[i] >= OMAP3_IRQ_MAXIMUM)
                {
                OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
                    L"IRQ %d out of range\r\n", pIrqs[i]
                    ));
                sysIntr = SYSINTR_UNDEFINED;
                goto cleanUp;
                }
            // If it is mapped to same SYSINTR, we are fine
            if (g_oalIrq2SysIntr[pIrqs[i]] == sysIntr) continue;
            // It isn't mapped or mapped to some other SYSINTR, error...
            sysIntr = SYSINTR_UNDEFINED;
            }
        goto cleanUp;
        }

    // Find next available SYSINTR value...
    for (sysIntr = SYSINTR_FIRMWARE; sysIntr < SYSINTR_MAXIMUM; sysIntr++)
        {
        if (g_oalSysIntr2Irq[sysIntr][0] == OAL_INTR_IRQ_UNDEFINED) break;
        }

    // Any available SYSINTRs left?
    if (sysIntr >= SYSINTR_MAXIMUM)
        {
        OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
            L"No available SYSINTR found\r\n"
            ));
        sysIntr = SYSINTR_UNDEFINED;
        goto cleanUp;
        }

    // Make SYSINTR -> IRQs association
    for (i = 0; i < count; i++)
        {
        if (pIrqs[i] >= OMAP3_IRQ_MAXIMUM)
            {
            OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "
                L"IRQ %d out of range\r\n", pIrqs[i]
                ));
            for (j = 0; j < i; j++)
                {
                g_oalSysIntr2Irq[sysIntr][j] = OAL_INTR_IRQ_UNDEFINED;
                }
            sysIntr = SYSINTR_UNDEFINED;
            goto cleanUp;
            }
        g_oalSysIntr2Irq[sysIntr][i] = pIrqs[i];
        }
    while (i < OMAP3_IRQ_PER_SYSINTR)
        {
        g_oalSysIntr2Irq[sysIntr][i++] = OAL_INTR_IRQ_UNDEFINED;
        }

    // Make IRQ -> SYSINTR association, only if not multiply-mapped
    if ((flags & OAL_INTR_DYNAMIC) != 0) goto cleanUp;
    for (i = 0; i < count; i++)
        {
        if ((g_oalIrq2SysIntr[pIrqs[i]] == SYSINTR_UNDEFINED) ||
            ((flags & OAL_INTR_FORCE_STATIC) != 0))
            {
            g_oalIrq2SysIntr[pIrqs[i]] = sysIntr;
            }
        }

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

//------------------------------------------------------------------------------
//
//  Function:  OALIntrReleaseSysIntr
//
//  This function release given SYSINTR and remove static mapping if exists.
//
BOOL 
OALIntrReleaseSysIntr(
    UINT32 sysIntr
    )
{
    BOOL rc = TRUE;

    UINT32 i, irq;

    OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALIntrReleaseSysIntr(%d)\r\n", sysIntr));

    if ((sysIntr < SYSINTR_FIRMWARE) || (sysIntr >= SYSINTR_MAXIMUM))
        {
        OALMSG(OAL_ERROR, (L"ERROR: OALIntrReleaseSysIntr: "
            L"Invalid sysIntr value %d\r\n", sysIntr
            ));
        rc = FALSE;
        goto cleanUp;
        }

    // Release all mapping for given SYSINTR
    for (i = 0; i < OMAP3_IRQ_PER_SYSINTR; i++)
        {
        if (g_oalSysIntr2Irq[sysIntr][i] == OAL_INTR_IRQ_UNDEFINED) continue;
        // Remove the SYSINTR -> IRQ mapping
        irq = g_oalSysIntr2Irq[sysIntr][i];
        g_oalSysIntr2Irq[sysIntr][i] = OAL_INTR_IRQ_UNDEFINED;
        // If there is IRQ -> SYSINTR for this IRQ release it also
        if (irq >= OMAP3_IRQ_MAXIMUM)
            {
            rc = FALSE;
            continue;
            }
        if (g_oalIrq2SysIntr[irq] == sysIntr)
            {
            g_oalIrq2SysIntr[irq] = SYSINTR_UNDEFINED;
            }
        }

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

//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptEnable
//
//  This function enables the IRQ given its corresponding SysIntr value.
//  Function returns true if SysIntr is valid, else false.
//
BOOL
OEMInterruptEnable(
    DWORD sysIntr, 
    VOID* pData, 
    DWORD dataSize
    )
{
    BOOL rc = FALSE;

    OALMSG(OAL_INTR&&OAL_VERBOSE, 
        (L"+OEMInterruptEnable(%d, 0x%x, %d)\r\n", sysIntr, pData, dataSize
        ));

    // SYSINTR_VMINI & SYSINTR_TIMING are special cases
    if ((sysIntr == SYSINTR_VMINI) || (sysIntr == SYSINTR_TIMING))
        {
        rc = TRUE;
        goto cleanUp;
        }

    // Enable interrupts
    rc = OALIntrEnableIrqs(OMAP3_IRQ_PER_SYSINTR, g_oalSysIntr2Irq[sysIntr]);

cleanUp:    
    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptEnable(rc = 1)\r\n"));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptDisable
//
//  This function disables the IRQ given its corresponding SysIntr value.
//
VOID
OEMInterruptDisable(
    DWORD sysIntr
    )
{
    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptDisable(%d)\r\n", sysIntr));

    // Disable interrupts
    OALIntrDisableIrqs(OMAP3_IRQ_PER_SYSINTR, g_oalSysIntr2Irq[sysIntr]);

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

//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptMask
//
//  This function masks the IRQ given its corresponding SysIntr value.
//
//
VOID
OEMInterruptMask(
    DWORD sysIntr, 
    BOOL mask
    )
{
    OALMSG(OAL_INTR&&OAL_VERBOSE, (
        L"+OEMInterruptMask(%d, %d)\r\n", sysIntr, mask
        ));

    // Based on mask enable or disable
    if (mask)
        {
        OALIntrDisableIrqs(OMAP3_IRQ_PER_SYSINTR, g_oalSysIntr2Irq[sysIntr]);
        }
    else 
        {
        OALIntrEnableIrqs(OMAP3_IRQ_PER_SYSINTR, g_oalSysIntr2Irq[sysIntr]);
        }

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

//------------------------------------------------------------------------------
//
//  Function: OEMInterruptDone
//
//  OEMInterruptDone is called by the kernel when a device driver
//  calls InterruptDone(). The system is not preemtible when this
//  function is called.
//
VOID
OEMInterruptDone(
    DWORD sysIntr
    )
{
    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptDone(%d)\r\n", sysIntr));

    // Re-enable interrupts
    OALIntrDoneIrqs(OMAP3_IRQ_PER_SYSINTR, g_oalSysIntr2Irq[sysIntr]); 
    
    OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptDone\r\n"));
}

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

⌨️ 快捷键说明

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