📄 plx9054.c
字号:
return ERROR;
}
if( (spaceIndex < P9054_ADDR_REG) || (spaceIndex >= P9054_ADDR_EPROM))
{
printf("SpaceIndex out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
if(dwOffset >= pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].dwRange)
{
printf("Offset out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
if (pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].fIsMemory)
{
dwAddr = pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].dwPciBar + dwOffset;
*(UINT32 *)dwAddr = data;
return OK;
}
else
{/* 暂不支持I/O空间*/
return ERROR;
}
}
/*
PLX9054_EEPROM_Valid
判断PLX9054 的EEPROM 是否存在
*/
BOOL PLX9054_EEPROM_Valid(int index)
{
UINT32 data;
PLX9054_DRVCTRL * pDrvCtrl;
pDrvCtrl = pPlxDrvCtrl;
/* 输入参数判断*/
if( (index < 0) || (index > (pDrvCtrl->plxCardNum - 1)))
{
printf("Index out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &data);
return((data & BIT28)==BIT28);
}
/******************************************************************************
*
* Function : PLX9054_EepromReadDword
*
* Description: Read a Dword from the EEPROM at a specified offset
*
*/
STATUS PLX9054_EepromReadDword(int index, EEPROM_TYPE EepromType, UINT32 offset, UINT32 *pValue)
{
UCHAR BitPos;
UCHAR CommandShift;
UCHAR CommandLength;
UINT16 count;
UINT32 RegisterValue;
switch (EepromType)
{
case Eeprom93CS46:
CommandShift = 0;
CommandLength = EE46_CMD_LEN;
break;
case Eeprom93CS56:
CommandShift = 2;
CommandLength = EE56_CMD_LEN;
break;
case Eeprom93CS66:
CommandShift = 2;
CommandLength = EE66_CMD_LEN;
break;
default:
*pValue = (UINT32)-1;
return ERROR;
}
/*Send EEPROM read command and offset to EEPROM*/
PLX9054_EepromSendCommand(index, (EE_READ << CommandShift) | (offset / 2), CommandLength);
/*****************************************************
* Note: The EEPROM write ouput bit (26) is set here
* because it is required before EEPROM read
* operations on the 9054. It does not affect
* behavior of non-9054 chips.
*
* The EEDO Input enable bit (31) is required for
* some chips. Since it is a reserved bit in older
* chips, there is no harm in setting it for all.
****************************************************/
/* Set EEPROM write output bit*/
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
/* Set EEDO Input enable for some PLX chips*/
RegisterValue |= (1 << 31);
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 26));
/* Get 32-bit value from EEPROM - one bit at a time*/
for (BitPos = 0; BitPos < 32; BitPos++)
{
/* Trigger the EEPROM clock*/
PLX9054_EepromClock(index);
/*****************************************************
* Note: After the EEPROM clock, a delay is sometimes
* needed to let the data bit propagate from the
* EEPROM to the PLX chip. If a sleep mechanism
* is used, the result is an extremely slow EEPROM
* access since the delay resolution is large and
* is required for every data bit read.
*
* Rather than using the standard sleep mechanism,
* the code, instead, reads the PLX register
* multiple times. This is harmless and provides
* enough delay for the EEPROM data to propagate.
****************************************************/
for (count=0; count < 1; count++)
{
/* Get the result bit*/
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
}
/* Get bit value and shift into result*/
if (RegisterValue & (1 << 27))
{
*pValue = (*pValue << 1) | 1;
}
else
{
*pValue = (*pValue << 1);
}
}
/* Clear EEDO Input enable for some PLX chips*/
RegisterValue &= ~(1 << 31);
/* Clear Chip Select and all other EEPROM bits*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(0xF << 24));
return OK;
}
/******************************************************************************
Function : PLX9054_EepromWriteDword
Description: Write a value to the EEPROM at a specified offset
author: wang.qi
data: 2006-10-18
*/
STATUS PLX9054_EepromWriteDword(int index, EEPROM_TYPE EepromType, UINT32 offset, UINT32 value)
{
char i;
char BitPos;
char CommandShift;
char CommandLength;
UINT16 EepromValue;
int Timeout;
UINT32 RegisterValue;
switch (EepromType)
{
case Eeprom93CS46:
CommandShift = 0;
CommandLength = EE46_CMD_LEN;
break;
case Eeprom93CS56:
CommandShift = 2;
CommandLength = EE56_CMD_LEN;
break;
case Eeprom93CS66:
CommandShift = 2;
CommandLength = EE66_CMD_LEN;
break;
default:
return ERROR;
}
/* Write EEPROM 16-bits at a time*/
for (i=0; i<2; i++)
{
/* Set 16-bit value to write*/
if (i == 0)
{
EepromValue = (UINT16)(value >> 16);
}
else
{
EepromValue = (UINT16)value;
/*Update offset*/
offset = offset + sizeof(UINT16);
}
printf("0ffset=0x%02x, value=0x%04x\n", offset, (UINT16)EepromValue);
/* Send Write_Enable command to EEPROM */
PLX9054_EepromSendCommand(index, (EE_WREN << CommandShift), CommandLength);
/* Send EEPROM Write command and offset to EEPROM */
PLX9054_EepromSendCommand(index, (EE_WRITE << CommandShift) | (offset / 2), CommandLength);
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
/* Clear all EEPROM bits */
RegisterValue &= ~(0xF << 24);
/* Make sure EEDO Input is disabled for some PLX chips */
RegisterValue &= ~(1 << 31);
/* Enable EEPROM Chip Select */
RegisterValue |= (1 << 25);
/* Write 16-bit value to EEPROM - one bit at a time */
for (BitPos = 15; BitPos >= 0; BitPos--)
{
/* Get bit value and shift into result */
if (EepromValue & (1 << BitPos))
{
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 26));
}
else
{
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);
}
/* Trigger the EEPROM clock */
PLX9054_EepromClock(index);
}
/* Deselect Chip */
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(1 << 25));
/* Re-select Chip */
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 25));
/*****************************************************
* Note: After the clocking in the last data bit, a
* delay is needed to let the EEPROM internally
* complete the write operation. If a sleep
* mechanism is used, the result is an extremely
* slow EEPROM access since the delay resolution
* is too large.
*
* Rather than using the standard sleep mechanism,
* the code, instead, reads the PLX register
* multiple times. This is harmless and provides
* enough delay for the EEPROM write to complete.
****************************************************/
/* A small delay is needed to let EEPROM complete*/
Timeout = 0;
do
{
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
Timeout++;
}
while (((RegisterValue & (1 << 27)) == 0) && (Timeout < 20000));
/* Send Write_Disable command to EEPROM */
PLX9054_EepromSendCommand(index, EE_WDS << CommandShift, CommandLength);
/* Clear Chip Select and all other EEPROM bits */
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(0xF << 24));
}
return OK;
}
/******************************************************************************
*
* Function : PLX9054_EepromSendCommand
*
* Description: Sends a Command to the EEPROM
*
*/
void PLX9054_EepromSendCommand(int index, UINT32 EepromCommand, UCHAR DataLengthInBits)
{
char BitPos;
UINT32 RegisterValue;
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
/* 清所有与EEPROM 相关的位 */
RegisterValue &= ~(0xF << 24);
/* Toggle EEPROM's Chip select to get it out of Shift Register Mode*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);
/* Enable EEPROM Chip Select */
RegisterValue |= (1 << 25);
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);
/* Send EEPROM command - one bit at a time*/
for (BitPos = (char)(DataLengthInBits-1); BitPos >= 0; BitPos--)
{
/* Check if current bit is 0 or 1*/
if (EepromCommand & (1 << BitPos))
{
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 26));
}
else
{
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);
}
PLX9054_EepromClock(index);
}
}
/******************************************************************************
*
* Function : PLX9054_EepromClock
*
* Description: 输出EEPROM 时钟信号
*
*/
void PLX9054_EepromClock(int index)
{
UCHAR i;
UINT32 RegisterValue;
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
/* Set EEPROM clock High, EESK(pin165)输出高电平*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 24));
/* 保持高电平一段时间Need a small delay, perform dummy register reads */
for (i=0; i<5; i++)
{
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
}
/* Set EEPROM clock Low, EESK(pin165)输出低电平*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(1 << 24));
/* 保持低电平一段时间*/
for (i=0; i<5; i++)
{
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
}
}
/*****************************************************************************
PLX9054_SoftReset
软复位PLX9054 扩展卡,并通过LReseto#引脚复位CPLD
*/
void PLX9054_SoftReset(int index)
{
PLX9054_DRVCTRL * pDrvCtrl;
UINT32 dwData;
UCHAR EepromPresent;
UINT32 RegInterrupt;
if(0 != index)
{
index =0;
}
pDrvCtrl = PLX9054_GetDrvCtrl();
/* 输入参数判断*/
if( (index < 0) || (index > (pDrvCtrl->plxCardNum - 1)))
{
printf("Index out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return;
}
/* Clear any PCI errors */
PLX9054_Pci_Reg_Read(index, PCI_CR, &dwData, DATA_DWORD);
if (dwData & (0xf8 << 24))
{
/* Write value back to clear aborts */
PLX9054_Pci_Reg_Write(index, PCI_CR, dwData, DATA_DWORD);
}
/* Determine if an EEPROM is present */
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &dwData);
/* Make sure S/W Reset & EEPROM reload bits are clear */
dwData &= ~((1 << 30) | (1 << 29));
/* Remember if EEPROM is present */
EepromPresent = (UCHAR)((dwData >> 28) & (1 << 0));
/* Save interrupt line */
PLX9054_Pci_Reg_Read(index, PCI_ILR, &RegInterrupt, DATA_BYTE);
/* Save some registers if EEPROM present */
#if 0
if (EepromPresent)
{
PLX9054_Pci_Reg_Read(index,
PLX_PCI_REG_READ(
pdx,
PCI9054_HS_CAP_ID,
&RegHotSwap
);
PLX_PCI_REG_READ(
pdx,
PCI9054_PM_CSR,
&RegPowerMgmnt
);
}
#endif
PLX9054_Local_Reg_Read(index, P9054_CNTRL, &dwData);
/* 复位*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData |(1 << 30));
taskDelay(1);
/* 清复位*/
PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData);
/* 重新加载EEPROM */
PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData |(1 << 29));
taskDelay(1);
PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData);
/* restore interrupt line */
PLX9054_Pci_Reg_Write(index, PCI_ILR, RegInterrupt, DATA_BYTE);
}
/*************************************************************************
向DSP 写一个字节的数据
*/
void PLX9054_WriteByteToDsp(int index, UINT8 data)
{
PLX9054_DRVCTRL * pDrvCtrl;
pDrvCtrl = PLX9054_GetDrvCtrl( );
/* 按32 位输出数据,低8 位有效*/
*(UINT32 *)(pDrvCtrl->pDevice[index]->spaceDesc[AD_PCI_BAR3].dwPciBar) = (UINT32)data;
}
/*
PLX9054_GetDrvCtrl
获取设备驱动控制结构体指针
*/
PLX9054_DRVCTRL * PLX9054_GetDrvCtrl(void)
{
return(pPlxDrvCtrl);
}
/*
PLX9054_SetDrvCtrl
设置设备驱动控制结构体指针
*/
void PLX9054_SetDrvCtrl(PLX9054_DRVCTRL * pDrvCtrl)
{
pPlxDrvCtrl = pDrvCtrl;
}
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -