📄 apifunctions.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:
*
* 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 + -