www.pudn.com > PlxSdk.rar > PlxChipFn.c


/*******************************************************************************
 * 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:
 *
 *      PlxChipFn.c
 *
 * Description:
 *
 *      Contains PLX chip-specific support functions
 *
 * Revision History:
 *
 *      02-01-07 : PLX SDK v5.00
 *
 ******************************************************************************/


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




/******************************************************************************
 *
 * Function   :  PlxChipInterruptsEnable
 *
 * Description:  Globally enables PLX chip interrupts
 *
 *****************************************************************************/
BOOLEAN
PlxChipInterruptsEnable(
    DEVICE_EXTENSION *pdx
    )
{
// DBG - Not implemented yet

    return FALSE;
}




/******************************************************************************
 *
 * Function   :  PlxChipInterruptsDisable
 *
 * Description:  Globally disables PLX chip interrupts
 *
 *****************************************************************************/
BOOLEAN
PlxChipInterruptsDisable(
    DEVICE_EXTENSION *pdx
    )
{
// DBG - Not implemented yet

    return FALSE;
}




/******************************************************************************
 *
 * Function   :  PlxMapUpstreamBar
 *
 * Description:  Maps the upstream BAR space for register accesses
 *
 ******************************************************************************/
BOOLEAN
PlxMapUpstreamBar(
    DEVICE_EXTENSION *pdx
    )
{
    U32 PciBar;
    U32 BarSize;


    if (pdx->bFromLinkSide == TRUE)
    {
        // Use PCI BAR 0 kernel address
        pdx->pRegVa = (U8*)(pdx->PciBar[0].pVa);

        if (pdx->pRegVa == NULL)
        {
            return FALSE;
        }

        DebugPrintf((
            "Using PCI BAR 0 (VA=%p) ==> PLX regs\n",
            pdx->pRegVa
            ));
    }
    else
    {
        // Get the BAR 0 value from the upstream port
        PlxPciRegisterRead(
            pdx->Key.bus - 1,   // Bus will be our bus minus 1
            0,                  // Always at slot 0
            0,
            0x10,               // BAR 0
            &PciBar
            );

        if (PciBar == 0)
        {
            return FALSE;
        }

        // Query BAR range
        PlxPciRegisterWrite(
            pdx->Key.bus - 1,
            0,
            0,
            0x10,               // BAR 0
            (U32)-1
            );

        // Read size
        PlxPciRegisterRead(
            pdx->Key.bus - 1,
            0,
            0,
            0x10,               // BAR 0
            &BarSize
            );

        // Restore BAR
        PlxPciRegisterWrite(
            pdx->Key.bus - 1,
            0,
            0,
            0x10,               // BAR 0
            PciBar
            );

        // Calculate BAR size
        BarSize = (~(BarSize & ~0xF)) + 1;

        // Clear any non-address bits
        PciBar &= ~(0xF);

        // Save BAR size
        pdx->UpstreamBarSize = BarSize;

        // Map the space
        pdx->pRegVa =
            ioremap(
                PciBar,
                BarSize
                );

        DebugPrintf((
            "Mapped upstream BAR 0 (%08lX) ==> PLX regs (VA=%p) (%dkb)\n",
            (PLX_UINT_PTR)PciBar, pdx->pRegVa, (BarSize >> 10)
            ));
    }

    return TRUE;
}




/*******************************************************************************
 *
 * Function   :  PlxErrataWorkAround_NtBarShadow
 *
 * Description:  Implements work-around for NT BAR shadow errata
 *
 ******************************************************************************/
VOID
PlxErrataWorkAround_NtBarShadow(
    DEVICE_EXTENSION *pdx
    )
{
    U8  i;
    U16 offset;
    U32 RegValue;


    /*****************************************************
     * This work-around handles the errata for NT Virtual
     * side BAR registers.  For BARs 2-5, the BAR space
     * is not accessible until the shadow registers are
     * updated manually.
     *
     * The procedure is to first read the BAR Setup registers
     * and write them back to themselves.  Then the PCI BAR
     * register is read and the same value is written back.
     * This updates the internal shadow registers of the PLX
     * chip and makes the BAR space accessible for NT data
     * transfers.
     *
     * Note: The BAR setup register must be written before
     *       the PCI BAR register.
     ****************************************************/

    // If link side, not errata so return
    if (pdx->bFromLinkSide)
        return;

    DebugPrintf(("Implementing NT Virtual-side BAR shadow errata work-around...\n"));

    // Read & write-back BAR setup and BAR registers for BARs 2-5
    for (i = 2; i <= 5; i++)
    {
        // Set offset for NT BAR setup register (D4h = Virtual-side BAR 2 Setup)
        offset = 0xD4 + ((i-2) * sizeof(U32));

        // Get Virtual-side BAR setup register
        PLX_PCI_REG_READ(
            pdx,
            offset,
            &RegValue
            );

        // Check if BAR is enabled
        if (RegValue & (1 << 31))
        {
            // Write BAR Setup back to itself
            PLX_PCI_REG_WRITE(
                pdx,
                offset,
                RegValue
                );

            // Read the corresponding PCI BAR
            PLX_PCI_REG_READ(
                pdx,
                0x10 + (i * sizeof(U32)),
                &RegValue
                );

            // Write PCI BAR back to itself
            PLX_PCI_REG_WRITE(
                pdx,
                0x10 + (i * sizeof(U32)),
                RegValue
                );
        }
    }
}