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
);
}
}
}