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

📄 plxinterrupt.c

📁 PCI9054RDK-LITE开发板的原程序
💻 C
字号:
/*******************************************************************************
 * Copyright (c) 2006 PLX Technology, Inc.
 *
 * PLX Technology Inc. licenses this software under specific terms and
 * conditions.  Use of any of the software or derviatives thereof in any
 * product without a PLX Technology chip is strictly prohibited.
 *
 * PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY,
 * EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  PLX makes no guarantee
 * or representations regarding the use of, or the results of the use of,
 * the software and documentation in terms of correctness, accuracy,
 * reliability, currentness, or otherwise; and you rely on the software,
 * documentation and results solely at your own risk.
 *
 * IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
 * OF ANY KIND.  IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM
 * PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER.
 *
 ******************************************************************************/

/******************************************************************************
 *
 * File Name:
 *
 *      PlxInterrupt.c
 *
 * Description:
 *
 *      This file handles interrupts for the PLX device
 *
 * Notes:
 *
 *      This driver handles interrupt sharing with other PCI device drivers.
 *      The PLX chip is checked to see if it is the true source of an interrupt.
 *      If an interrupt is truly active, the interrupt source is cleared and
 *      any waiting user-mode applications are notified.
 *
 * Revision History:
 *
 *      02-01-06 : PCI SDK v4.40
 *
 ******************************************************************************/


#include "DriverDefs.h"
#include "PlxInterrupt.h"
#include "SupportFunc.h"




/******************************************************************************
 *
 * Function   :  OnInterrupt
 *
 * Description:  The Interrupt Service Routine for the PLX device
 *
 ******************************************************************************/
BOOLEAN
OnInterrupt(
    PKINTERRUPT pInterrupt,
    PVOID       ServiceContext
    )
{
    U32               RegPciInt;
    U32               InterruptSource;
    DEVICE_EXTENSION *pdx;


    // Get the device extension
    pdx = (DEVICE_EXTENSION *)ServiceContext;

    // Read interrupt status register
    RegPciInt =
        PLX_REG_READ(
            pdx,
            PCI9050_INT_CTRL_STAT
            );

    // Check for master PCI interrupt enable
    if ((RegPciInt & (1 << 6)) == 0)
        return FALSE;

    // Verify that an interrupt is truly active

    // Clear the interrupt type flag
    InterruptSource = INTR_TYPE_NONE;

    // Check if Local Interrupt 1 is active and not masked
    if ((RegPciInt & (1 << 2)) && (RegPciInt & (1 << 0)))
    {
        InterruptSource |= INTR_TYPE_LOCAL_1;
    }

    // Check if Local Interrupt 2 is active and not masked
    if ((RegPciInt & (1 << 5)) && (RegPciInt & (1 << 3)))
    {
        InterruptSource |= INTR_TYPE_LOCAL_2;
    }

    // Software Interrupt
    if (RegPciInt & (1 << 7))
    {
        InterruptSource |= INTR_TYPE_SOFTWARE;
    }

    // Return if no interrupts are active
    if (InterruptSource == INTR_TYPE_NONE)
        return FALSE;

    // At this point, the device interrupt is verified

    // Mask the PCI Interrupt
    PLX_REG_WRITE(
        pdx,
        PCI9050_INT_CTRL_STAT,
        RegPciInt & ~(1 << 6)
        );

    //
    // Schedule deferred procedure (DPC) to complete interrupt processing
    //

    KeInsertQueueDpc(
        &(pdx->DpcForIsr),
        (VOID *)(PLX_UINT_PTR)InterruptSource,
        NULL
        );

    return TRUE;
}




/******************************************************************************
 *
 * Function   :  DpcForIsr
 *
 * Description:  This routine will be triggered by the ISR to service an interrupt.
 *
 * Note       :  The 9052 supports Edge-triggerable interrupts as well as level
 *               triggered interrupts.  The 9050 only supports level triggered
 *               interrupts.  The interrupt masking code below handles both cases.
 *               If the chip is a 9050, the same code is used but should work
 *               ok since edge triggerable interrupts will always be disabled.
 *
 ******************************************************************************/
VOID
DpcForIsr(
    PKDPC pDpc,
    PVOID pContext,
    PVOID pArg1,
    PVOID pArg2
    )
{
    U32               RegValue;
    U32               IntSource;
    PLX_REG_DATA      RegData;
    DEVICE_EXTENSION *pdx;


    // Get the device extension
    pdx = (DEVICE_EXTENSION *)pContext;

    // Get interrupt source
    IntSource = PtrToUlong(pArg1);

    KeAcquireSpinLockAtDpcLevel(
        &(pdx->Lock_HwAccess)
        );

    // Local Interrupt 1
    if (IntSource & INTR_TYPE_LOCAL_1)
    {
        // Setup to synchronize access to Interrupt Control/Status Register
        RegData.pdx         = pdx;
        RegData.offset      = PCI9050_INT_CTRL_STAT;
        RegData.BitsToSet   = 0;
        RegData.BitsToClear = 0;

        // Check if this is an edge-triggered interrupt
        RegValue =
            PLX_REG_READ(
                pdx,
                PCI9050_INT_CTRL_STAT
                );

        if ((RegValue & (1 << 1)) && (RegValue & (1 << 8)))
        {
            // Clear edge-triggered interrupt
            RegData.BitsToSet = (1 << 10);

            KeSynchronizeExecution(
                pdx->pInterruptObject,
                PlxSynchronizedRegisterModify,
                (VOID *)&RegData
                );
        }
        else
        {
            // Mask Local Interrupt 1
            RegData.BitsToClear = (1 << 0);

            KeSynchronizeExecution(
                pdx->pInterruptObject,
                PlxSynchronizedRegisterModify,
                (VOID *)&RegData
                );
        }
    }

    // Local Interrupt 2
    if (IntSource & INTR_TYPE_LOCAL_2)
    {
        // Setup to synchronize access to Interrupt Control/Status Register
        RegData.pdx         = pdx;
        RegData.offset      = PCI9050_INT_CTRL_STAT;
        RegData.BitsToSet   = 0;
        RegData.BitsToClear = 0;

        // Check if this is an edge-triggered interrupt
        RegValue =
            PLX_REG_READ(
                pdx,
                PCI9050_INT_CTRL_STAT
                );

        if ((RegValue & (1 << 4)) && (RegValue & (1 << 9)))
        {
            // Clear edge-triggered interrupt
            RegData.BitsToSet = (1 << 11);

            KeSynchronizeExecution(
                pdx->pInterruptObject,
                PlxSynchronizedRegisterModify,
                (VOID *)&RegData
                );
        }
        else
        {
            // Mask Local Interrupt 2
            RegData.BitsToClear = (1 << 3);

            KeSynchronizeExecution(
                pdx->pInterruptObject,
                PlxSynchronizedRegisterModify,
                (VOID *)&RegData
                );
        }
    }

    // Software Interrupt
    if (IntSource & INTR_TYPE_SOFTWARE)
    {
        // Setup to synchronize access to Interrupt Control/Status Register
        RegData.pdx       = pdx;
        RegData.offset    = PCI9050_INT_CTRL_STAT;
        RegData.BitsToSet = 0;

        // Clear the software interrupt
        RegData.BitsToClear = (1 << 7);

        KeSynchronizeExecution(
            pdx->pInterruptObject,
            PlxSynchronizedRegisterModify,
            (VOID *)&RegData
            );
    }

    // Save the interrupt sources
    pdx->InterruptSource = IntSource;

    KeReleaseSpinLockFromDpcLevel(
        &(pdx->Lock_HwAccess)
        );

    // Signal any objects waiting for notification
    PlxSignalNotifications(
        pdx,
        IntSource
        );

    // Re-enable the PCI interrupt
    KeSynchronizeExecution(
        pdx->pInterruptObject,
        PlxChipPciInterruptEnable,
        pdx
        );
}

⌨️ 快捷键说明

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