📄 plx_lib.c
字号:
UINT32 u32Data)
{
DWORD i;
UINT32 u32ReadBack, u32EnableAccess;
WORD wAddr, wData;
BYTE bEnableOffset;
if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_VPD_Write32"))
return WD_INVALID_PARAMETER;
if (dwOffset % 4)
{
ErrLog("PLX_EEPROM_VPD_Write32: Error - offset (0x%lX) is not a multiple of 4 "
"(device handle: 0x%p)\n", dwOffset, hDev);
return WD_INVALID_PARAMETER;
}
/* Clear EEDO Input Enable */
EEPROM_VPD_EnableAccess(hDev, &u32EnableAccess);
wAddr = (WORD)dwOffset;
EEPROM_VPD_RemoveWriteProtection(hDev, wAddr, &bEnableOffset);
EEPROM_VPD_Delay();
/* Write desired data to PVPDATA register */
WDC_PciWriteCfg32(hDev, PLX_VPD_DATA, u32Data);
/* Write a destination serial EEPROM address and flag of operation, value of 1 */
wAddr = (WORD)(wAddr | BIT15);
WDC_PciWriteCfg16(hDev, PLX_VPD_ADDR, wAddr);
/* Probe a flag of operation until it changes to a 0 to ensure the write completes */
for (i = 0; i < 10; i++)
{
EEPROM_VPD_Delay();
WDC_PciReadCfg16(hDev, PLX_VPD_ADDR, &wData);
if (wData & BIT15)
break;
}
EEPROM_VPD_RestoreWriteProtection((PWDC_DEVICE)hDev, bEnableOffset);
/* Restore EEDO Input Enable */
EEPROM_VPD_RestoreAccess(hDev, u32EnableAccess);
PLX_EEPROM_VPD_Read32(hDev, dwOffset, &u32ReadBack);
if (u32ReadBack != u32Data)
{
ErrLog("PLX_EEPROM_VPD_Write32: Error - Wrote 0x%08X, read back 0x%08X "
"(device handle 0x%p)\n", u32Data, u32ReadBack);
return WD_OPERATION_FAILED;
}
return WD_STATUS_SUCCESS;
}
/* Enable EEPROM access via VPD mechanism - disable EEDO Input (CNTRL[31]=0, default).
This bit is specific to PLX 9656 and PLX 9056 chips (it is reserved on other boards) */
static DWORD EEPROM_VPD_EnableAccess(WDC_DEVICE_HANDLE hDev, UINT32 *pu32DataOld)
{
DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
PLX_ReadReg32(hDev, dwCNTRL, pu32DataOld);
return PLX_WriteReg32(hDev, dwCNTRL, *pu32DataOld & ~BIT31);
}
/* Restore EEDO Input Enable */
static DWORD EEPROM_VPD_RestoreAccess(WDC_DEVICE_HANDLE hDev, UINT32 u32Data)
{
return PLX_WriteReg32(hDev, ((PPLX_DEV_CTX)((((PWDC_DEVICE)hDev)->pCtx)))->dwCNTRL,
u32Data);
}
static DWORD EEPROM_VPD_RemoveWriteProtection(WDC_DEVICE_HANDLE hDev, WORD wAddr,
PBYTE pbDataOld)
{
PPLX_DEV_CTX pDevCtx = (PPLX_DEV_CTX)WDC_GetDevContext(hDev);
PLX_ReadReg8(hDev, pDevCtx->dwPROT_AREA, pbDataOld);
wAddr /= 4;
wAddr &= 0x7F;
PLX_WriteReg8(hDev, pDevCtx->dwPROT_AREA, (BYTE)wAddr);
*pbDataOld *= 4; /* Expand from DWORD to BYTE count */
return WD_STATUS_SUCCESS;
}
static DWORD EEPROM_VPD_RestoreWriteProtection(WDC_DEVICE_HANDLE hDev, WORD wAddr)
{
PPLX_DEV_CTX pDevCtx = (PPLX_DEV_CTX)WDC_GetDevContext(hDev);
return PLX_WriteReg8(hDev, pDevCtx->dwPROT_AREA, (BYTE)wAddr);
}
DWORD PLX_EEPROM_RT_Read16(WDC_DEVICE_HANDLE hDev, DWORD dwOffset, PWORD pwData,
DWORD EEPROMmsb)
{
WORD i;
DWORD dwAddr = dwOffset >> 1;
BOOL bit = 0;
if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Read16"))
return WD_INVALID_PARAMETER;
*pwData = 0;
EEPROM_RT_ChipSelect(hDev, TRUE);
EEPROM_RT_WriteBit(hDev, 1);
EEPROM_RT_WriteBit(hDev, 1);
EEPROM_RT_WriteBit(hDev, 0);
/* CS06, CS46 EEPROM - send 6bit address
* CS56, CS66 EEPROM - send 8bit address */
for (i = (WORD)EEPROMmsb; i; i >>= 1)
EEPROM_RT_WriteBit(hDev, (dwAddr & i) == i);
for (i = BIT15; i; i >>= 1)
{
EEPROM_RT_ReadBit(hDev, &bit);
*pwData |= (bit ? i : 0);
}
EEPROM_RT_ChipSelect(hDev, FALSE);
return WD_STATUS_SUCCESS;
}
DWORD PLX_EEPROM_RT_Write16(WDC_DEVICE_HANDLE hDev, DWORD dwOffset, WORD wData,
DWORD EEPROMmsb)
{
WORD i;
DWORD dwAddr = dwOffset >> 1;
WORD wReadBack;
if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Write16"))
return WD_INVALID_PARAMETER;
EEPROM_RT_WriteEnableDisable(hDev, TRUE);
EEPROM_RT_ChipSelect(hDev, TRUE);
/* Send a PRWRITE instruction */
EEPROM_RT_WriteBit(hDev, 1);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, 1);
/* CS06, CS46 EEPROM - send 6bit address
* CS56, CS66 EEPROM - send 8bit address */
for (i = (WORD)EEPROMmsb; i; i >>= 1)
EEPROM_RT_WriteBit(hDev, (dwAddr & i) == i);
for (i = BIT15; i; i >>= 1)
EEPROM_RT_WriteBit(hDev, (wData & i) == i);
EEPROM_RT_ChipSelect(hDev, FALSE);
EEPROM_RT_WriteEnableDisable(hDev, TRUE);
PLX_EEPROM_RT_Read16(hDev, dwOffset, &wReadBack, EEPROMmsb);
if (wData != wReadBack)
{
ErrLog("PLX_EEPROM_RT_Write16: Error - Wrote 0x%04X, read back 0x%04X "
"(device handle 0x%p)\n", wData, wReadBack);
return WD_OPERATION_FAILED;
}
return WD_STATUS_SUCCESS;
}
DWORD PLX_EEPROM_RT_Read32(WDC_DEVICE_HANDLE hDev, DWORD dwOffset,
UINT32 *pu32Data, DWORD EEPROMmsb)
{
WORD wData1, wData2;
if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Read32"))
return WD_INVALID_PARAMETER;
if (dwOffset % 4)
{
ErrLog("PLX_EEPROM_RT_Read32: Error - offset (0x%lX) is not a multiple of 4 "
"(device handle: 0x%p)\n", dwOffset, hDev);
return WD_INVALID_PARAMETER;
}
PLX_EEPROM_RT_Read16(hDev, dwOffset, &wData1, EEPROMmsb);
PLX_EEPROM_RT_Read16(hDev, dwOffset + 2, &wData2, EEPROMmsb);
*pu32Data = (UINT32)((wData1 << 16) + wData2);
return WD_STATUS_SUCCESS;
}
DWORD PLX_EEPROM_RT_Write32(WDC_DEVICE_HANDLE hDev, DWORD dwOffset,
UINT32 u32Data, DWORD EEPROMmsb)
{
WORD wData1, wData2;
if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Write32"))
return WD_INVALID_PARAMETER;
if (dwOffset % 4)
{
ErrLog("PLX_EEPROM_RT_Write32: Error - offset (0x%lX) is not a multiple of 4 "
"(device handle: 0x%p)\n", dwOffset, hDev);
return WD_INVALID_PARAMETER;
}
wData1 = (WORD)(u32Data >> 16);
wData2 = (WORD)(u32Data & 0xFFFF);
PLX_EEPROM_RT_Write16(hDev, dwOffset, wData1, EEPROMmsb);
PLX_EEPROM_RT_Write16(hDev, dwOffset + 2, wData2, EEPROMmsb);
return WD_STATUS_SUCCESS;
}
static void EEPROM_RT_ChipSelect(WDC_DEVICE_HANDLE hDev, BOOL fSelect)
{
DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
UINT32 u32CNTRL;
PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
PLX_WriteReg32(hDev, dwCNTRL,
fSelect ? (u32CNTRL | BIT25) : (u32CNTRL & ~BIT25) );
EEPROM_RT_Delay();
}
static void EEPROM_RT_ReadBit(WDC_DEVICE_HANDLE hDev, BOOL *pBit)
{
DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
UINT32 u32CNTRL;
PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
/* clock */
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);
EEPROM_RT_Delay();
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL | BIT24);
EEPROM_RT_Delay();
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);
EEPROM_RT_Delay();
/* data */
PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
*pBit = (u32CNTRL & BIT27) == BIT27;
}
static void EEPROM_RT_WriteBit(WDC_DEVICE_HANDLE hDev, BOOL bit)
{
DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
UINT32 u32CNTRL;
PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
if (bit) /* data */
u32CNTRL |= BIT26;
else
u32CNTRL &= ~BIT26;
/* clock */
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);
EEPROM_RT_Delay();
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL | BIT24);
EEPROM_RT_Delay();
PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);
EEPROM_RT_Delay();
}
static void EEPROM_RT_WriteEnableDisable(WDC_DEVICE_HANDLE hDev, BOOL fEnable)
{
EEPROM_RT_ChipSelect(hDev, TRUE);
/* Send a WEN instruction */
EEPROM_RT_WriteBit(hDev, 1);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, fEnable ? 1 : 0);
EEPROM_RT_WriteBit(hDev, fEnable ? 1 : 0);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_WriteBit(hDev, 0);
EEPROM_RT_ChipSelect(hDev, FALSE);
}
/* -----------------------------------------------
Reset of PLX board
----------------------------------------------- */
/* Definition of abort bits in commad (CMD) configuration register */
#define PLX_M_CR_ABORT_BITS (\
BIT24 /* Detected Master Data Parity Error */ \
| BIT27 /* Signaled Target Abort */ \
| BIT28 /* Received Target Abort */ \
| BIT29 /* Received Master Abort */ \
| BIT30 /* Signaled System Error */ \
| BIT31 /* Detected Parity Error on PCI bus */ \
)
/* Software board reset for master devices (9054, 9056, 9080, 9656) */
void PLX_SoftResetMaster(WDC_DEVICE_HANDLE hDev)
{
BOOL fMUEnabled, fEEPROMPresent;
WORD wCMD = 0;
UINT32 u32QSR = 0;
UINT32 u32CNTRL = 0;
UINT32 u32INTLN = 0;
UINT32 u32MBOX0 = 0, u32MBOX1 = 0;
UINT32 u32HS_CNTL = 0;
UINT32 u32PMCSR = 0;
/* Clear any PCI errors */
WDC_PciReadCfg16(hDev, PCI_CR, &wCMD);
if (wCMD & PLX_M_CR_ABORT_BITS)
{
/* Write value back to clear aborts */
WDC_PciWriteCfg16(hDev, PCI_CR, wCMD);
}
/* Save state of I2O Decode Enable */
PLX_ReadReg32(hDev, PLX_M_QSR, &u32QSR);
fMUEnabled = u32QSR & BIT0 ? TRUE : FALSE;
/* Make sure S/W Reset & EEPROM reload bits are clear */
PLX_ReadReg32(hDev, PLX_M_CNTRL, &u32CNTRL);
u32CNTRL &= ~(BIT30 | BIT29);
/* Determine if an EEPROM is present */
fEEPROMPresent = PLX_EEPROMIsPresent(hDev);
/* Save some registers if EEPROM present */
if (fEEPROMPresent)
{
/* Run-time registers */
PLX_ReadReg32(hDev, PLX_M_MBOX0, &u32MBOX0);
PLX_ReadReg32(hDev, PLX_M_MBOX1, &u32MBOX1);
/* PCI configuration registers */
WDC_PciReadCfg32(hDev, PCI_ILR, &u32INTLN);
WDC_PciReadCfg32(hDev, PLX_HS_CAPID, &u32HS_CNTL);
WDC_PciReadCfg32(hDev, PLX_PMCSR, &u32PMCSR);
}
/* Issue Software Reset to hold PLX chip in reset */
PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL | BIT30);
/* Bring chip out of reset */
PLX_SOFT_RESET_DELAY();
PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL);
/* Issue EEPROM reload in case now programmed */
PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL | BIT29);
/* Clear EEPROM reload */
PLX_SOFT_RESET_DELAY();
PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL);
/* Restore I2O Decode Enable state */
if (fMUEnabled)
{
PLX_ReadReg32(hDev, PLX_M_QSR, &u32QSR);
PLX_WriteReg32(hDev, PLX_M_QSR, u32QSR | BIT0);
}
/* If EEPROM was present, restore registers */
if (fEEPROMPresent)
{
/* Run-time registers */
PLX_WriteReg32(hDev, PLX_M_MBOX0, u32MBOX0);
PLX_WriteReg32(hDev, PLX_M_MBOX1, u32MBOX1);
/* PCI configuration registers */
WDC_PciReadCfg32(hDev, PCI_ILR, &u32INTLN);
/* Mask out HS bits that can be cleared */
u32HS_CNTL &= ~(BIT23 | BIT22 | BIT17);
WDC_PciWriteCfg32(hDev, PLX_HS_CAPID, u32HS_CNTL);
/* Mask out PM bits that can be cleared */
u32PMCSR &= ~BIT15;
WDC_PciWriteCfg32(hDev, PLX_PMCSR, u32PMCSR);
}
}
/* -----------------------------------------------
Debugging and error handling
----------------------------------------------- */
static void ErrLog(const CHAR *sFormat, ...)
{
va_list argp;
va_start(argp, sFormat);
vsnprintf(gsPLX_LastErr, sizeof(gsPLX_LastErr) - 1, sFormat, argp);
#if defined(DEBUG)
WDC_Err("PLX lib: %s", gsPLX_LastErr);
#endif
va_end(argp);
}
static void TraceLog(const CHAR *sFormat, ...)
{
#if defined(DEBUG)
CHAR sMsg[256];
va_list argp;
va_start(argp, sFormat);
vsnprintf(sMsg, sizeof(sMsg) - 1, sFormat, argp);
WDC_Trace("PLX lib: %s", sMsg);
va_end(argp);
#endif
}
const char *PLX_GetLastErr(void)
{
return gsPLX_LastErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -