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

📄 plxchipapi.c

📁 PCI接口产品中桥芯片PLX6000、PLX8000、PLX9000和PLXsrv驱动模块源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
 * Copyright (c) 2007 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:
 *
 *      PlxChipApi.c
 *
 * Description:
 *
 *      Implements chip-specific API functions
 *
 * Revision History:
 *
 *      06-01-07 : PLX SDK v5.10
 *
 ******************************************************************************/


#include "Eep_9000.h"
#include "PciSupport.h"
#include "PlxChipApi.h"
#include "SupportFunc.h"




/******************************************************************************
 *
 * Function   :  PlxChip_BoardReset
 *
 * Description:  Resets a device using software reset feature of PLX chip
 *
 ******************************************************************************/
RETURN_CODE
PlxChip_BoardReset(
    DEVICE_EXTENSION *pdx
    )
{
    U8  MU_Enabled;
    U32 RegValue;
    U32 RegInterrupt;


    // Clear any PCI errors
    PLX_PCI_REG_READ(
        pdx,
        CFG_COMMAND,
        &RegValue
        );

    if (RegValue & (0xf8 << 24))
    {
        // Write value back to clear aborts
        PLX_PCI_REG_WRITE(
            pdx,
            CFG_COMMAND,
            RegValue
            );
    }

    // Save state of I2O Decode Enable
    RegValue =
        PLX_9000_REG_READ(
            pdx,
            PCI9080_FIFO_CTRL_STAT
            );

    MU_Enabled = (U8)(RegValue & (1 << 0));

    // Determine if an EEPROM is present
    RegValue =
        PLX_9000_REG_READ(
            pdx,
            PCI9080_EEPROM_CTRL_STAT
            );

    // Make sure S/W Reset & EEPROM reload bits are clear
    RegValue &= ~((1 << 30) | (1 << 29));

    // Save interrupt line
    PLX_PCI_REG_READ(
        pdx,
        CFG_INT_LINE,
        &RegInterrupt
        );

    // Issue Software Reset to hold PLX chip in reset
    PLX_9000_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue | (1 << 30)
        );

    // Delay for a bit
    Plx_sleep(100);

    // Bring chip out of reset
    PLX_9000_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue
        );

    // Issue EEPROM reload in case now programmed
    PLX_9000_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue | (1 << 29)
        );

    // Delay for a bit
    Plx_sleep(10);

    // Clear EEPROM reload
    PLX_9000_REG_WRITE(
        pdx,
        PCI9080_EEPROM_CTRL_STAT,
        RegValue
        );

    // Restore I2O Decode Enable state
    if (MU_Enabled)
    {
        // Save state of I2O Decode Enable
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9080_FIFO_CTRL_STAT
                );

        PLX_9000_REG_WRITE(
            pdx,
            PCI9080_FIFO_CTRL_STAT,
            RegValue | (1 << 0)
            );
    }

    // Restore interrupt line
    PLX_PCI_REG_WRITE(
        pdx,
        CFG_INT_LINE,
        RegInterrupt
        );

    return ApiSuccess;
}




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


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

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

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

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

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

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

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

        // Make sure DMA done interrupt is enabled & routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9080_DMA0_MODE
                );

        PLX_9000_REG_WRITE(
            pdx,
            PCI9080_DMA0_MODE,
            RegValue | (1 << 17) | (1 << 10)
            );
    }

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

        // Make sure DMA done interrupt is enabled & routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9080_DMA1_MODE
                );

        PLX_9000_REG_WRITE(
            pdx,
            PCI9080_DMA1_MODE,
            RegValue | (1 << 17) | (1 << 10)
            );
    }

    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_9000_REG_READ(
            pdx,
            PCI9080_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;

    if (pPlxIntr->MuOutboundPost)
    {
        PLX_9000_REG_WRITE(
            pdx,
            PCI9080_OUTPOST_INT_MASK,
            0
            );
    }

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

    if (pPlxIntr->MuOutboundOverflow)
    {
        RegData.BitsToSet |=  (1 << 1);
        QueueCsr          &= ~(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_9000_REG_WRITE(
            pdx,
            PCI9080_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    return ApiSuccess;
}




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


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

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

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

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

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

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

    if (pPlxIntr->DmaChannel_0)
    {
        // Check if DMA interrupt is routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9080_DMA0_MODE
                );

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

            // Disable DMA interrupt enable
            PLX_9000_REG_WRITE(
                pdx,
                PCI9080_DMA0_MODE,
                RegValue & ~(1 << 10)
                );
        }
    }

    if (pPlxIntr->DmaChannel_1)
    {
        // Check if DMA interrupt is routed to PCI
        RegValue =
            PLX_9000_REG_READ(
                pdx,
                PCI9080_DMA1_MODE
                );

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

            // Disable DMA interrupt enable
            PLX_9000_REG_WRITE(
                pdx,
                PCI9080_DMA1_MODE,
                RegValue & ~(1 << 10)
                );
        }
    }

    // Inbound Post Queue Interrupt Control/Status Register
    QueueCsr_Original =
        PLX_9000_REG_READ(
            pdx,
            PCI9080_FIFO_CTRL_STAT
            );

    QueueCsr = QueueCsr_Original;

    if (pPlxIntr->MuOutboundPost)
    {
        PLX_9000_REG_WRITE(
            pdx,
            PCI9080_OUTPOST_INT_MASK,
            (1 << 3)
            );
    }

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

    if (pPlxIntr->MuOutboundOverflow)
        QueueCsr |= (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_9000_REG_WRITE(
            pdx,
            PCI9080_FIFO_CTRL_STAT,
            QueueCsr
            );
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxChip_EepromReadByOffset
 *
 * Description:  Read a 32-bit value from the EEPROM at a specified offset
 *
 ******************************************************************************/
RETURN_CODE
PlxChip_EepromReadByOffset(
    DEVICE_EXTENSION *pdx,
    U16               offset,
    U32              *pValue
    )
{
    // Verify the offset
    if ((offset & 0x3) || (offset > 0x200))
    {
        DebugPrintf(("ERROR - Invalid EEPROM offset\n"));
        return ApiInvalidOffset;
    }

    // Read EEPROM
    Plx9000_EepromReadByOffset(
        pdx,
        Eeprom93CS46,
        offset,
        pValue
        );

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxChip_EepromWriteByOffset
 *
 * Description:  Write a 32-bit value to the EEPROM at a specified offset
 *
 ******************************************************************************/
RETURN_CODE
PlxChip_EepromWriteByOffset(
    DEVICE_EXTENSION *pdx,
    U16               offset,
    U32               value
    )
{
    // Verify the offset
    if ((offset & 0x3) || (offset > 0x200))
    {
        DebugPrintf(("ERROR - Invalid EEPROM offset\n"));
        return ApiInvalidOffset;
    }

    // 9080 does not protect the EEPROM from write access, do nothing

    // Write to EEPROM
    Plx9000_EepromWriteByOffset(
        pdx,
        Eeprom93CS46,
        offset,
        value
        );

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxChip_DmaControl
 *
 * Description:  Control the DMA engine
 *
 ******************************************************************************/
RETURN_CODE
PlxChip_DmaControl(
    DEVICE_EXTENSION *pdx,
    U8                channel,
    PLX_DMA_COMMAND   command
    )
{
    U8  i;
    U8  shift;
    U32 RegValue;


    // Verify valid DMA channel
    switch (channel)
    {
        case 0:
        case 1:
            i     = channel;
            shift = (channel * 8);
            break;

        default:
            DebugPrintf(("ERROR - Invalid DMA channel\n"));
            return ApiDmaChannelInvalid;
    }

    switch (command)
    {
        case DmaPause:
            // Pause the DMA Channel
            RegValue =
                PLX_9000_REG_READ(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT
                    );

            PLX_9000_REG_WRITE(
                pdx,
                PCI9080_DMA_COMMAND_STAT,
                RegValue & ~((1 << 0) << shift)
                );

            // Check if the transfer has completed
            RegValue =
                PLX_9000_REG_READ(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT
                    );

            if (RegValue & ((1 << 4) << shift))
                return ApiDmaDone;
            break;

        case DmaResume:
            // Verify that the DMA Channel is paused
            RegValue =
                PLX_9000_REG_READ(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT
                    );

            if ((RegValue & (((1 << 4) | (1 << 0)) << shift)) == 0)
            {
                PLX_9000_REG_WRITE(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT,
                    RegValue | ((1 << 0) << shift)
                    );
            }
            else
            {
                return ApiDmaInProgress;
            }
            break;

        case DmaAbort:
            // Pause the DMA Channel
            RegValue =
                PLX_9000_REG_READ(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT
                    );

            PLX_9000_REG_WRITE(
                pdx,
                PCI9080_DMA_COMMAND_STAT,
                RegValue & ~((1 << 0) << shift)
                );

            // Check if the transfer has completed
            RegValue =
                PLX_9000_REG_READ(
                    pdx,
                    PCI9080_DMA_COMMAND_STAT
                    );

            if (RegValue & ((1 << 4) << shift))
                return ApiDmaDone;

            // Abort the transfer (should cause an interrupt)
            PLX_9000_REG_WRITE(
                pdx,
                PCI9080_DMA_COMMAND_STAT,
                RegValue | ((1 << 2) << shift)
                );
            break;

        default:
            return ApiDmaCommandInvalid;
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxChip_DmaStatus
 *
 * Description:  Get status of a DMA channel
 *
 ******************************************************************************/
RETURN_CODE
PlxChip_DmaStatus(
    DEVICE_EXTENSION *pdx,
    U8                channel

⌨️ 快捷键说明

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