if_i82544.c

来自「eCos操作系统源码」· C语言 代码 · 共 2,128 行 · 第 1/5 页

C
2,128
字号
}#endif#ifdef DEBUG// dump out the PHY registersstatic 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#endifstatic 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 intget_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 intread_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 booli82544_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);#else // ! CYGHWR_DEVS_ETH_INTEL_I82544_GET_ESA#ifndef CYGHWR_DEVS_ETH_INTEL_I82544_HAS_NO_EEPROM        int addr_length, i;        cyg_uint16 checksum;        // read eeprom and get 82544's mac address        addr_length = get_eeprom_size(p_i82544);        // (this is the length of the *EEPROM*s address, not MAC address)        // If length is 1, it _probably_ means there's no EEPROM        // present.  Couldn't find an explicit mention of this in the        // docs, but length=1 appears to be the behaviour in that case.        if (1 == addr_length) {#ifdef DEBUG_EE            os_printf("Error: No EEPROM present for device %d\n",                       p_i82544->index);#endif        } else {            for (checksum = 0, i = 0, count = 0; count < 64; count++) {                cyg_uint16 value;                // read word from eeprom                value = read_eeprom_word(p_i82544, addr_length, count);#ifdef DEBUG_EE                os_printf( "%02x: %04x\n", count, value );#endif                checksum += value;                if (count < 3) {                    mac_address[i++] = value & 0xFF;                    mac_address[i++] = (value >> 8) & 0xFF;                }            }#ifndef CYGHWR_DEVS_ETH_INTEL_I82544_HAS_ONE_EEPROM_WITHOUT_CRC            // If the EEPROM checksum is wrong, the MAC address read            // from the EEPROM is probably wrong as well. In that            // case, we don't set mac_addr_ok, but continue the            // initialization. If then somebody calls i82544_start            // without calling eth_set_mac_address() first, we refuse            // to bring up the interface, because running with an            // invalid MAC address is not a very brilliant idea.                    if ((checksum & 0xFFFF) != 0xBABA)  {                // selftest verified checksum, verify again

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?