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 + -
显示快捷键?