if_i82544.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 2,053 行 · 第 1/5 页
C
2,053 行
if( p_i82544->device == 0x1004 )
{
// An 82543, write MII register via software defined pins in
// CTRL register.
MII_INIT();
MII_WRITE_PREAMBLE();
MII_WRITE_START();
MII_WRITE_WRITE_CMD();
MII_WRITE_PHY_ADDR(phy);
MII_WRITE_REGNUM( regnum );
MII_WRITE_TURNAROUND();
MII_WRITE_REGVAL( value );
MII_IDLE();
}
else
{
// Others, write MII register via MDIC register.
cyg_uint32 mdic = (1<<26) | (phy<<21) | (regnum<<16) | (value&0xFFFF);
OUTL( mdic, ioaddr + I82544_MDIC );
// Wait for ready
do
{
mdic = INL( ioaddr + I82544_MDIC );
} while( (mdic & (1<<28)) == 0 );
}
}
#endif
#ifdef DEBUG
// dump out the PHY registers
static void show_phy( struct i82544 *p_i82544, int phy )
{
int i;
os_printf("PHY %d regs:",phy);
for( i = 0; i < 32; i++ )
{
cyg_uint32 mdic;
mdic = mii_read_register( p_i82544, phy, i );
if( (i%8)==0 ) os_printf("\n");
os_printf("%04x ",mdic);
}
os_printf("\n");
}
#endif
// ------------------------------------------------------------------------
//
// GET EEPROM SIZE
//
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
//
// Serial EEPROM access - much like the other Intel ethernet
//
// CYGACC_CALL_IF_DELAY_US() drags in huge amounts of scheduler locking and
// the like 'cos it's a VV call! Waste of time, mostly.
#define EE_DELAY() do { int z; for ( z = 0; z < 10000; z++ ) ; } while (0)
#if 0
# define EE_PRINTF diag_printf
# define EE_STUFF "%4s | %4s | %4s | %4s [%08x]\n", \
(l & EE_SHIFT_CLK) ? "CLK" : "clk", \
(l & EE_CS) ? "eeCS" : "--", \
(l & EE_DATA_WRITE) ? "eeDW" : "---", \
(l & EE_DATA_READ) ? "eeDR" : "---", \
l & 0xfffff
#else
# define EE_PRINTF( foo )
# define EE_STUFF
#endif
static inline void ee_select( int ioaddr, struct i82544 *p_i82544 )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD );
if (p_i82544->device == 0x1010 ||
p_i82544->device == 0x100e) {
// i82546 requires REQ/GNT before EEPROM access
l |= EE_REQ;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
while ((l & EE_GNT) == 0)
l = INL( ioaddr + I82544_EECD );
}
l &= ~0x3f;
l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
l |= EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_select : " EE_STUFF );
EE_DELAY();
}
static inline void ee_deselect( int ioaddr )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD ) & ~0x3f;
l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_PRINTF( "ee_deselect 1 : " EE_STUFF );
EE_DELAY();
EE_DELAY();
EE_DELAY();
l &= ~EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_deselect 2 : " EE_STUFF );
EE_DELAY();
EE_DELAY();
EE_DELAY();
if (l & EE_REQ) {
l &= ~EE_REQ;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
}
}
static inline void ee_clock_up( int ioaddr )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD );
l |= EE_SHIFT_CLK;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_clock_up : " EE_STUFF );
EE_DELAY();
}
static inline void ee_clock_down( int ioaddr )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD );
l &=~ EE_SHIFT_CLK;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_clock_down : " EE_STUFF );
EE_DELAY();
}
static inline int ee_read_data_bit( int ioaddr )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_read_data : " EE_STUFF );
return EE_DATA_READ == (EE_DATA_READ & l);
}
static inline void ee_write_data_bit( int ioaddr, int databit )
{
cyg_uint32 l;
l = INL( ioaddr + I82544_EECD );
if ( databit )
l |= EE_DATA_WRITE;
else
l &= ~EE_DATA_WRITE;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_write_data : " EE_STUFF );
EE_DELAY();
}
// Pass ioaddr around "invisibly"
#define EE_SELECT() ee_select(ioaddr, p_i82544)
#define EE_DESELECT() ee_deselect(ioaddr)
#define EE_CLOCK_UP() ee_clock_up(ioaddr)
#define EE_CLOCK_DOWN() ee_clock_down(ioaddr)
#define EE_READ_DATA_BIT() ee_read_data_bit(ioaddr)
#define EE_WRITE_DATA_BIT( _d_ ) ee_write_data_bit(ioaddr,(_d_))
// ------------------------------------------------------------------------
static int
get_eeprom_size( struct i82544 *p_i82544 )
{
cyg_uint32 l, ioaddr = p_i82544->io_address;
int i, tmp, addrbits;
l = INL( ioaddr + I82544_EECD );
#ifdef DEBUG_EE
diag_printf( "get_eeprom_size\n" );
#endif
if (p_i82544->device == 0x1010 ||
p_i82544->device == 0x100e) {
l |= EE_REQ;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
while ((l & EE_GNT) == 0)
l = INL( ioaddr + I82544_EECD );
l &= ~0x3f;
l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
l |= EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_DELAY();
for (i = 3; i >= 0; i--) { // Doc says to shift out a zero then:
tmp = (6 & (1 << i)) ? 1 : 0; // "6" is the "read" command.
EE_WRITE_DATA_BIT(tmp);
EE_CLOCK_UP();
EE_CLOCK_DOWN();
}
// Now clock out address zero, looking for the dummy 0 data bit
for ( i = 1; i <= 10; i++ ) {
EE_WRITE_DATA_BIT(0);
EE_CLOCK_UP();
EE_CLOCK_DOWN();
if (EE_READ_DATA_BIT() == 0)
break; // The dummy zero est arrive'
}
if (6 != i && 8 != i)
diag_printf("no EEPROM found\n");
addrbits = i;
tmp = 0;
for (i = 15; i >= 0; i--) {
EE_CLOCK_UP();
if (EE_READ_DATA_BIT())
tmp |= (1<<i);
EE_CLOCK_DOWN();
}
l = INL( ioaddr + I82544_EECD ) & ~0x3f;
l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
EE_DELAY();
EE_DELAY();
l &= ~EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_DELAY();
EE_DELAY();
EE_DELAY();
l &= ~EE_REQ;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
return addrbits;
}
return 6;
}
static int
read_eeprom_word( struct i82544 *p_i82544, int addrbits, int address )
{
int i, tmp;
cyg_uint32 ioaddr = p_i82544->io_address;
// Should already be not-selected, but anyway:
EE_SELECT();
// Shift the read command bits out.
for (i = 3; i >= 0; i--) { // Doc says to shift out a zero then:
tmp = (6 & (1 << i)) ? 1 : 0; // "6" is the "read" command.
EE_WRITE_DATA_BIT(tmp);
EE_CLOCK_UP();
EE_CLOCK_DOWN();
}
// Now clock out address
for ( i = addrbits - 1; i >= 0 ; i-- ) {
tmp = (address & (1<<i)) ? 1 : 0;
EE_WRITE_DATA_BIT(tmp);
EE_CLOCK_UP();
tmp = EE_READ_DATA_BIT();
EE_CLOCK_DOWN();
// CYG_ASSERT( (0 == tmp) == (0 == i), "Looking for zero handshake bit" );
}
// read in the data
tmp = 0;
for (i = 15; i >= 0; i--) {
EE_CLOCK_UP();
if ( EE_READ_DATA_BIT() )
tmp |= (1<<i);
EE_CLOCK_DOWN();
}
// Terminate the EEPROM access.
EE_DESELECT();
#ifdef DEBUG_EE
// diag_printf( "eeprom address %4x: data %4x\n", address, tmp );
#endif
return tmp;
}
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
//
// NETWORK INTERFACE INITIALIZATION
//
// Function : Init82544
//
// Description :
// This routine resets, configures, and initializes the chip.
// It also clears the ethernet statistics structure, and selects
// which statistics are supported by this driver.
//
// ------------------------------------------------------------------------
static bool
i82544_init(struct cyg_netdevtab_entry * ndp)
{
static int initialized = 0; // only probe PCI et al *once*
struct eth_drv_sc *sc;
cyg_uint32 ioaddr;
int count;
struct i82544 *p_i82544;
cyg_uint8 mac_address[ETHER_ADDR_LEN];
#ifdef DEBUG
db_printf("i82544_init\n");
#endif
sc = (struct eth_drv_sc *)(ndp->device_instance);
p_i82544 = (struct i82544 *)(sc->driver_private);
IF_BAD_82544( p_i82544 ) {
#ifdef DEBUG
os_printf( "Bad device private pointer %x\n", sc->driver_private );
#endif
return 0;
}
CHECK_NDP_SC_LINK();
if ( 0 == initialized++ ) {
// then this is the first time ever:
if ( ! pci_init_find_82544s() ) {
#ifdef DEBUG
os_printf( "pci_init_find_82544s failed\n" );
#endif
return 0;
}
}
// If this device is not present, exit
if (0 == p_i82544->found)
return 0;
p_i82544->mac_addr_ok = 0;
ioaddr = p_i82544->io_address; // get I/O address for 82544
#ifdef DEBUG
os_printf("Init82544 %d @ %x\n", p_i82544->index, (int)ndp);
#endif
// Reset device
i82544_reset(p_i82544);
i82544_setup(p_i82544);
InitRxRing(p_i82544);
InitTxRing(p_i82544);
if (p_i82544->hardwired_esa) {
// Hardwire the address without consulting the EEPROM.
// When this flag is set, the p_i82544 will already contain
// the ESA. Copy it to a mac_address for call to set_mac_addr
mac_address[0] = p_i82544->mac_address[0];
mac_address[1] = p_i82544->mac_address[1];
mac_address[2] = p_i82544->mac_address[2];
mac_address[3] = p_i82544->mac_address[3];
mac_address[4] = p_i82544->mac_address[4];
mac_address[5] = p_i82544->mac_address[5];
eth_set_mac_address(p_i82544, mac_address, 0);
} else {
// Acquire the ESA either from extenal means (probably RedBoot
// variables) or from the attached EEPROM - if there is one.
#ifdef CYGHWR_DEVS_ETH_INTEL_I82544_GET_ESA
int ok = false;
CYGHWR_DEVS_ETH_INTEL_I82544_GET_ESA( p_i82544, mac_address, ok );
if ( ok )
eth_set_mac_address(p_i82544, mac_address, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?