📄 eeprom_9000.c
字号:
/*******************************************************************************
* Copyright (c) 2005 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:
*
* Eeprom_9000.c
*
* Description:
*
* This file contains 9000-series EEPROM support functions.
*
* Revision History:
*
* 06-01-05 : PCI SDK v4.40
*
******************************************************************************/
#include "Eeprom_9000.h"
#include "SupportFunc.h"
/**********************************************
* Definitions
**********************************************/
// EEPROM Control register offset
#if !defined(REG_EEPROM_CTRL)
#error ERROR: 'REG_EEPROM_CTRL' not defined
#endif
/******************************************************************************
*
* Function : Pci9000_EepromReadByOffset
*
* Description: Read a value from the EEPROM at a specified offset
*
******************************************************************************/
void
Pci9000_EepromReadByOffset(
DEVICE_EXTENSION *pdx,
EEPROM_TYPE EepromType,
U16 offset,
U32 *pValue
)
{
S8 BitPos;
S8 CommandShift;
S8 CommandLength;
U16 count;
U32 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 = (U32)-1;
return;
}
// Send EEPROM read command and offset to EEPROM
Pci9000_EepromSendCommand(
pdx,
(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
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
// Set EEDO Input enable for some PLX chips
RegisterValue |= (1 << 31);
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue | (1 << 26)
);
// Get 32-bit value from EEPROM - one bit at a time
for (BitPos = 0; BitPos < 32; BitPos++)
{
// Trigger the EEPROM clock
Pci9000_EepromClock(
pdx
);
/*****************************************************
* 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 < 20; count++)
{
// Get the result bit
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
}
// 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
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue & ~(0xF << 24)
);
}
/******************************************************************************
*
* Function : Pci9000_EepromWriteByOffset
*
* Description: Write a value to the EEPROM at a specified offset
*
******************************************************************************/
void
Pci9000_EepromWriteByOffset(
DEVICE_EXTENSION *pdx,
EEPROM_TYPE EepromType,
U16 offset,
U32 value
)
{
S8 i;
S8 BitPos;
S8 CommandShift;
S8 CommandLength;
U16 EepromValue;
S32 Timeout;
U32 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;
}
// Write EEPROM 16-bits at a time
for (i=0; i<2; i++)
{
// Set 16-bit value to write
if (i == 0)
{
EepromValue = (U16)(value >> 16);
}
else
{
EepromValue = (U16)value;
// Update offset
offset = offset + sizeof(U16);
}
// Send Write_Enable command to EEPROM
Pci9000_EepromSendCommand(
pdx,
(EE_WREN << CommandShift),
CommandLength
);
// Send EEPROM Write command and offset to EEPROM
Pci9000_EepromSendCommand(
pdx,
(EE_WRITE << CommandShift) | (offset / 2),
CommandLength
);
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
// 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))
{
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue | (1 << 26)
);
}
else
{
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue
);
}
// Trigger the EEPROM clock
Pci9000_EepromClock(
pdx
);
}
// Deselect Chip
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue & ~(1 << 25)
);
// Re-select Chip
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
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
{
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
Timeout++;
}
while (((RegisterValue & (1 << 27)) == 0) && (Timeout < 20000));
// Send Write_Disable command to EEPROM
Pci9000_EepromSendCommand(
pdx,
EE_WDS << CommandShift,
CommandLength
);
// Clear Chip Select and all other EEPROM bits
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue & ~(0xF << 24)
);
}
}
/******************************************************************************
*
* Function : Pci9000_EepromSendCommand
*
* Description: Sends a Command to the EEPROM
*
******************************************************************************/
void
Pci9000_EepromSendCommand(
DEVICE_EXTENSION *pdx,
U32 EepromCommand,
U8 DataLengthInBits
)
{
S8 BitPos;
U32 RegisterValue;
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
// Clear all EEPROM bits
RegisterValue &= ~(0xF << 24);
// Toggle EEPROM's Chip select to get it out of Shift Register Mode
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue
);
// Enable EEPROM Chip Select
RegisterValue |= (1 << 25);
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue
);
// Send EEPROM command - one bit at a time
for (BitPos = (S8)(DataLengthInBits-1); BitPos >= 0; BitPos--)
{
// Check if current bit is 0 or 1
if (EepromCommand & (1 << BitPos))
{
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue | (1 << 26)
);
}
else
{
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue
);
}
Pci9000_EepromClock(
pdx
);
}
}
/******************************************************************************
*
* Function : Pci9000_EepromClock
*
* Description: Sends the clocking sequence to the EEPROM
*
******************************************************************************/
void
Pci9000_EepromClock(
DEVICE_EXTENSION *pdx
)
{
S8 i;
U32 RegisterValue;
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
// Set EEPROM clock High
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue | (1 << 24)
);
// Need a small delay, perform dummy register reads
for (i=0; i<20; i++)
{
RegisterValue =
PLX_REG_READ(
pdx,
REG_EEPROM_CTRL
);
}
// Set EEPROM clock Low
PLX_REG_WRITE(
pdx,
REG_EEPROM_CTRL,
RegisterValue & ~(1 << 24)
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -