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

📄 apifunctions.c

📁 本压缩包为作者截取的PCI9054的WDM官方驱动源码。欢迎下载。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************
 * 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:
 *
 *      ApiFunctions.c
 *
 * Description:
 *
 *      This file contains the implementation of the PCI API functions
 *      specific to a PLX Chip.
 *
 * Revision History:
 *
 *      03-01-06 : PCI SDK v4.40
 *
 ******************************************************************************/


#include "ApiFunctions.h"
#include "Eeprom_9000.h"
#include "PciSupport.h"
#include "PlxInterrupt.h"
#include "SupportFunc.h"




/******************************************************************************
 *
 * Function   :  PlxRegisterRead
 *
 * Description:  Reads a PLX chip local register
 *
 ******************************************************************************/
RETURN_CODE
PlxRegisterRead(
    DEVICE_EXTENSION *pdx,
    U16               offset,
    U32              *pValue
    )
{
    // Make sure register offset is valid
    if ((offset & 0x3) || (offset >= MAX_PLX_REG_OFFSET))
    {
        DebugPrintf(("ERROR - invalid register offset (0x%x)\n", offset));

        *pValue = (U32)-1;

        return ApiInvalidRegister;
    }

    *pValue =
        PLX_REG_READ(
            pdx,
            offset
            );

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxRegisterWrite
 *
 * Description:  Writes a value to a PLX local register
 *
 ******************************************************************************/
RETURN_CODE
PlxRegisterWrite(
    DEVICE_EXTENSION *pdx,
    U16               offset,
    U32               value
    )
{
    // Make sure register offset is valid
    if ((offset & 0x3) || (offset >= MAX_PLX_REG_OFFSET))
    {
        DebugPrintf(("ERROR - invalid register offset (0x%x)\n", offset));
        return ApiInvalidRegister;
    }

    PLX_REG_WRITE(
        pdx,
        offset,
        value
        );

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciIntrEnable
 *
 * Description:  Enables specific interupts of the PLX Chip
 *
 ******************************************************************************/
RETURN_CODE
PlxPciIntrEnable(
    DEVICE_EXTENSION *pdx,
    PLX_INTR         *pPlxIntr
    )
{
    U32          QueueCsr;
    U32          QueueCsr_Original;
    U32          RegisterValue;
    PLX_REG_DATA RegData;


    // Setup to synchronize access to Interrupt Control/Status Register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9054_INT_CTRL_STAT;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = 0;


    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_REG_READ(
            pdx,
            PCI9054_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;


    if (pPlxIntr->OutboundPost)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9054_OUTPOST_INT_MASK,
            0
            );
    }

    if (pPlxIntr->InboundPost)
        QueueCsr &= ~(1 << 4);

    if (pPlxIntr->OutboundOverflow)
    {
        RegData.BitsToSet |=  (1 << 1);
        QueueCsr          &= ~(1 << 6);
    }

    if (pPlxIntr->PciDmaChannel0)
    {
        RegData.BitsToSet |= (1 << 18);

        // Make sure DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA0_MODE
                );

        PLX_REG_WRITE(
            pdx,
            PCI9054_DMA0_MODE,
            RegisterValue | (1 << 17)
            );
    }

    if (pPlxIntr->PciDmaChannel1)
    {
        RegData.BitsToSet |= (1 << 19);

        // Make sure DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA1_MODE
                );

        PLX_REG_WRITE(
            pdx,
            PCI9054_DMA1_MODE,
            RegisterValue | (1 << 17)
            );
    }

    if (pPlxIntr->IopDmaChannel0)
    {
        RegData.BitsToSet |= (1 << 18);

        // Make sure DMA interrupt is routed to IOP
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA0_MODE
                );

        PLX_REG_WRITE(
            pdx,
            PCI9054_DMA0_MODE,
            RegisterValue & ~(1 << 17)
            );
    }

    if (pPlxIntr->IopDmaChannel1)
    {
        RegData.BitsToSet |= (1 << 19);

        // Make sure DMA interrupt is routed to IOP
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA1_MODE
                );

        PLX_REG_WRITE(
            pdx,
            PCI9054_DMA1_MODE,
            RegisterValue & ~(1 << 17)
            );
    }

    if (pPlxIntr->Mailbox0 || pPlxIntr->Mailbox1 ||
        pPlxIntr->Mailbox2 || pPlxIntr->Mailbox3)
    {
        RegData.BitsToSet |= (1 << 3);
    }

    if (pPlxIntr->IopDoorbell)
        RegData.BitsToSet |= (1 << 17);

    if (pPlxIntr->PciDoorbell)
        RegData.BitsToSet |= (1 << 9);

    if (pPlxIntr->IopToPciInt)
        RegData.BitsToSet |= (1 << 11);

    if (pPlxIntr->PciMainInt)
        RegData.BitsToSet |= (1 << 8);

    if (pPlxIntr->IopMainInt)
        RegData.BitsToSet |= (1 << 16);

    if (pPlxIntr->PciAbort)
        RegData.BitsToSet |= (1 << 10);

    if (pPlxIntr->AbortLSERR)
        RegData.BitsToSet |= (1 << 0);

    if (pPlxIntr->ParityLSERR)
        RegData.BitsToSet |= (1 << 1);

    if (pPlxIntr->RetryAbort)
        RegData.BitsToSet |= (1 << 12);

    if (pPlxIntr->PowerManagement)
        RegData.BitsToSet |= (1 << 4);

    if (pPlxIntr->LocalParityLSERR)
    {
        RegData.BitsToSet |= (1 << 0);
        RegData.BitsToSet |= (1 << 6);
    }

    // Write register values if they have changed

    if (RegData.BitsToSet != 0)
    {
        // Synchronize write of Interrupt Control/Status Register
        KeSynchronizeExecution(
            pdx->pInterruptObject,
            PlxSynchronizedRegisterModify,
            &RegData
            );
    }

    if (QueueCsr != QueueCsr_Original)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9054_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    // Power Management Interrupt
    if (pPlxIntr->PciPME)
    {
        // Verify that the capability is enabled
        if (PlxIsNewCapabilityEnabled(
                pdx,
                CAPABILITY_POWER_MANAGEMENT
                ) == TRUE)
        {
            PLX_PCI_REG_READ(
                pdx,
                PCI9054_PM_CSR,
                &RegisterValue
                );

            // Set PME Enable bit
            RegisterValue |= (1 << 8);

            PLX_PCI_REG_WRITE(
                pdx,
                PCI9054_PM_CSR,
                RegisterValue
                );
        }
    }

    // Hot Swap Interrupt
    if (pPlxIntr->Enum)
    {
        // Verify that the capability is enabled
        if (PlxIsNewCapabilityEnabled(
                pdx,
                CAPABILITY_HOT_SWAP
                ) == TRUE)
        {
            PLX_PCI_REG_READ(
                pdx,
                PCI9054_HS_CAP_ID,
                &RegisterValue
                );

            // Turn off INS & EXT bits so we don't clear them
            RegisterValue &= ~((1 << 23) | (1 << 22));

            // Disable Enum Interrupt mask
            RegisterValue &= ~(1 << 17);

            PLX_PCI_REG_WRITE(
                pdx,
                PCI9054_HS_CAP_ID,
                RegisterValue
                );
        }
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciIntrDisable
 *
 * Description:  Disables specific interrupts of the PLX Chip
 *
 ******************************************************************************/
RETURN_CODE
PlxPciIntrDisable(
    DEVICE_EXTENSION *pdx,
    PLX_INTR         *pPlxIntr
    )
{
    U32          QueueCsr;
    U32          QueueCsr_Original;
    U32          RegisterValue;
    PLX_REG_DATA RegData;


    // Setup to synchronize access to Interrupt Control/Status Register
    RegData.pdx         = pdx;
    RegData.offset      = PCI9054_INT_CTRL_STAT;
    RegData.BitsToSet   = 0;
    RegData.BitsToClear = 0;

    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_REG_READ(
            pdx,
            PCI9054_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;


    if (pPlxIntr->OutboundPost)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9054_OUTPOST_INT_MASK,
            (1 << 3)
            );
    }

    if (pPlxIntr->InboundPost)
        QueueCsr |= (1 << 4);

    if (pPlxIntr->OutboundOverflow)
        QueueCsr |= (1 << 6);

    if (pPlxIntr->PciDmaChannel0)
    {
        // Check if DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA0_MODE
                );

        if (RegisterValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 18);

            // Make sure DMA interrupt is routed to IOP
            PLX_REG_WRITE(
                pdx,
                PCI9054_DMA0_MODE,
                RegisterValue & ~(1 << 17)
                );
        }
    }

    if (pPlxIntr->PciDmaChannel1)
    {
        // Check if DMA interrupt is routed to PCI
        RegisterValue =
            PLX_REG_READ(
                pdx,
                PCI9054_DMA1_MODE
                );

        if (RegisterValue & (1 << 17))
        {
            RegData.BitsToClear |= (1 << 19);

            // Make sure DMA interrupt is routed to IOP
            PLX_REG_WRITE(
                pdx,
                PCI9054_DMA1_MODE,
                RegisterValue & ~(1 << 17)
                );
        }
    }

    if (pPlxIntr->IopDmaChannel0)
        RegData.BitsToClear |= (1 << 18);

    if (pPlxIntr->IopDmaChannel1)
        RegData.BitsToClear |= (1 << 19);

    if (pPlxIntr->Mailbox0 || pPlxIntr->Mailbox1 ||
        pPlxIntr->Mailbox2 || pPlxIntr->Mailbox3)
    {
        RegData.BitsToClear |= (1 << 3);
    }

    if (pPlxIntr->PciDoorbell)
        RegData.BitsToClear |= (1 << 9);

    if (pPlxIntr->IopDoorbell)
        RegData.BitsToClear |= (1 << 17);

    if (pPlxIntr->PciMainInt)
        RegData.BitsToClear |= (1 << 8);

    if (pPlxIntr->IopToPciInt)
        RegData.BitsToClear |= (1 << 11);

    if (pPlxIntr->IopMainInt)
        RegData.BitsToClear |= (1 << 16);

    if (pPlxIntr->PciAbort)
        RegData.BitsToClear |= (1 << 10);

    if (pPlxIntr->AbortLSERR)
        RegData.BitsToClear |= (1 << 0);

    if (pPlxIntr->ParityLSERR)
        RegData.BitsToClear |= (1 << 1);

    if (pPlxIntr->RetryAbort)
        RegData.BitsToClear |= (1 << 12);

    if (pPlxIntr->PowerManagement)
        RegData.BitsToClear |= (1 << 4);

    if (pPlxIntr->LocalParityLSERR)
        RegData.BitsToClear |= (1 << 6);


    // Write register values if they have changed

    if (RegData.BitsToClear != 0)
    {
        // Synchronize write of Interrupt Control/Status Register
        KeSynchronizeExecution(
            pdx->pInterruptObject,
            PlxSynchronizedRegisterModify,
            &RegData
            );
    }

    if (QueueCsr != QueueCsr_Original)
    {
        PLX_REG_WRITE(
            pdx,
            PCI9054_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    // Power Management Interrupt
    if (pPlxIntr->PciPME)
    {
        // Verify that the capability is enabled
        if (PlxIsNewCapabilityEnabled(
                pdx,
                CAPABILITY_POWER_MANAGEMENT
                ) == TRUE)
        {
            PLX_PCI_REG_READ(
                pdx,
                PCI9054_PM_CSR,
                &RegisterValue
                );

            // Disable PME interrupt
            RegisterValue &= ~(1 << 8);

⌨️ 快捷键说明

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