📄 if_i82559.c
字号:
#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_RESET_TIMEOUT#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_TIMEOUT_FIRED int ints = Mask82559Interrupt(p_i82559); if ( p_i82559->tx_in_progress && (p_i82559->tx_descriptor_timeout == p_i82559->tx_descriptor_active) ) { if ( CYGHWR_DEVS_ETH_INTEL_I82559_TIMEOUT_FIRED( p_i82559->platform_timeout ) ) { // Then reset the device; the TX unit is locked up. cyg_uint32 ioaddr = p_i82559->io_address; // Wait some time afterwards for chip to settle. OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort);#ifdef CYGDBG_USE_ASSERTS missed_interrupt.lockup_timeouts++;#endif udelay(20); } } else { // All is well: CYGHWR_DEVS_ETH_INTEL_I82559_RESET_TIMEOUT( p_i82559->platform_timeout ); p_i82559->tx_descriptor_timeout = p_i82559->tx_descriptor_active; } UnMask82559Interrupt(p_i82559,ints);#endif#endif}// ------------------------------------------------------------------------// Memory management//// Simply carve off from the front of the PCI mapped window into real memorystatic void*pciwindow_mem_alloc(int size){ void *p_memory; int _size = size; CYG_ASSERT( (CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE <= (int)i82559_heap_free) && ((CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE + CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE) > (int)i82559_heap_free) && (0 < i82559_heap_size) && (CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE >= i82559_heap_size) && (CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE == (int)i82559_heap_base), "Heap variables corrupted" ); p_memory = (void *)0; size = (size + 3) & ~3; if ( (i82559_heap_free+size) < (i82559_heap_base+i82559_heap_size) ) { cyg_uint32 *p; p_memory = (void *)i82559_heap_free; i82559_heap_free += size; for ( p = (cyg_uint32 *)p_memory; _size > 0; _size -= 4 ) *p++ = 0; }#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_PCIMEM_DISCONTIGUOUS // Then the underlying physical address can have breaks in it. // We cannot use such a block, clearly, so we just discard and re-do. if ( p_memory ) { char *bpm = (char *)VIRT_TO_BUS( p_memory ); char *bmf = (char *)VIRT_TO_BUS( i82559_heap_free ); if ( bpm + size != bmf ) { // then we found a break; retry: if ( (i82559_heap_free+size) < (i82559_heap_base+i82559_heap_size) ) { cyg_uint32 *p; p_memory = (void *)i82559_heap_free; i82559_heap_free += size; for ( p = (cyg_uint32 *)p_memory; _size > 0; _size -= 4 ) *p++ = 0; } } }#endif CYG_ASSERT( NULL == p_memory || VIRT_TO_BUS( p_memory ) + size == VIRT_TO_BUS( i82559_heap_free ), "Discontiguous PCI memory in real addresses" ); return p_memory;}// ------------------------------------------------------------------------//// GET EEPROM SIZE//// ------------------------------------------------------------------------#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROMstatic intget_eeprom_size(long ioaddr){ unsigned short retval = 0; int ee_addr = ioaddr + SCBeeprom; int i, addrbits; // Should already be not-selected, but anyway: OUTW(EE_ENB & ~EE_CS, ee_addr); eeprom_delay(EEPROM_ENABLE_DELAY); OUTW(EE_ENB, ee_addr); eeprom_delay(EEPROM_ENABLE_DELAY); // Shift the read command bits out. for (i = 2; i >= 0; i--) { short dataval = (6 & (1 << i)) ? EE_DATA_WRITE : 0; OUTW(EE_ENB | dataval , ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB | dataval , ee_addr); eeprom_delay(EEPROM_SK_DELAY); } // Now clock out address zero, looking for the dummy 0 data bit for ( i = 1; i <= 12; i++ ) { OUTW(EE_ENB , ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB , ee_addr); eeprom_delay(EEPROM_SK_DELAY); retval = INW(ee_addr) & EE_DATA_READ; if ( 0 == retval ) break; // The dummy zero est arrive' }#ifdef DEBUG_EE os_printf( "eeprom data bits %d (ioaddr %x)\n", i, ee_addr );#endif if ( 6 != i && 8 != i && 1 != i) {#ifdef DEBUG_EE os_printf( "*****EEPROM data bits not 6, 8 or 1*****\n" );#endif i = 6; // guess, to complete this routine addrbits = 1; // Flag no eeprom here. } else addrbits = i; // clear the dataval, leave the clock low to read in the data regardless OUTW(EE_ENB, ee_addr); eeprom_delay(1); retval = INW(ee_addr); if ( (EE_DATA_READ & retval) != 0 ) {#ifdef DEBUG_EE os_printf( "Size EEPROM: Dummy data bit not 0, reg %x\n" , retval );#endif } eeprom_delay(1); for (i = EE_TOP_DATA_BIT; i >= 0; i--) { OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(EEPROM_SK_DELAY); retval = INW(ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB, ee_addr); eeprom_delay(EEPROM_SK_DELAY); } // Terminate the EEPROM access. OUTW(EE_ENB & ~EE_CS, ee_addr); eeprom_delay(EEPROM_DONE_DELAY); return addrbits;}// ------------------------------------------------------------------------//// READ EEPROM//// ------------------------------------------------------------------------static intread_eeprom(long ioaddr, int location, int addr_len){ unsigned short retval = 0; int ee_addr = ioaddr + SCBeeprom; int read_cmd = location | EE_READ_CMD(addr_len); int i, tries = 10; try_again: // Should already be not-selected, but anyway: OUTW(EE_ENB & ~EE_CS, ee_addr); eeprom_delay(EEPROM_ENABLE_DELAY); OUTW(EE_ENB, ee_addr); eeprom_delay(EEPROM_ENABLE_DELAY); // Shift the read command bits out, changing only one bit per time. for (i = EE_TOP_CMD_BIT(addr_len); i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; OUTW(EE_ENB | dataval , ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB | dataval , ee_addr); eeprom_delay(EEPROM_SK_DELAY); } // clear the dataval, leave the clock low OUTW(EE_ENB, ee_addr); eeprom_delay(1); retval = INW(ee_addr); // This should show a zero in the data read bit to confirm that the // address transfer is compelete. If not, go to the start and try // again! if ( (0 != (retval & EE_DATA_READ)) && (tries-- > 0) ) { // Terminate the EEPROM access. OUTW(EE_ENB & ~EE_CS, ee_addr); eeprom_delay(EEPROM_DONE_DELAY);#ifdef DEBUG_EE os_printf( "Warning: Retrying EEPROM read word %d, address %x, try %d\n", location, ee_addr, tries+1 );#endif goto try_again; } // This fires with one device on one of the customer boards! // (but is OK on all other h/w. Worrying huh.) if ( (EE_DATA_READ & retval) != 0 ) {#ifdef DEBUG_EE os_printf( "Read EEPROM: Dummy data bit not 0, reg %x\n" , retval );#endif } eeprom_delay(1); retval = 0; for (i = EE_TOP_DATA_BIT; i >= 0; i--) { OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(EEPROM_SK_DELAY); retval = (retval << 1) | ((INW(ee_addr) & EE_DATA_READ) ? 1 : 0); eeprom_delay(EEPROM_SK_DELAY); OUTW(EE_ENB, ee_addr); eeprom_delay(EEPROM_SK_DELAY); } // Terminate the EEPROM access. OUTW(EE_ENB & ~EE_CS, ee_addr); eeprom_delay(EEPROM_DONE_DELAY); return retval;}static intread_eeprom_esa(struct i82559 *p_i82559, char *addr){ int addr_length, i, count; cyg_uint16 checksum; cyg_uint32 ioaddr = p_i82559->io_address; // read eeprom and get 82559's mac address addr_length = get_eeprom_size(ioaddr); // (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_i82559->index);#endif } else { for (checksum = 0, i = 0, count = 0; count < (1 << addr_length); count++) { cyg_uint16 value; // read word from eeprom value = read_eeprom(ioaddr, count, addr_length);#ifdef DEBUG_EE os_printf( "%2d: %04x\n", count, value );#endif checksum += value; if (count < 3) { addr[i++] = value & 0xFF; addr[i++] = (value >> 8) & 0xFF; } }#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_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 i82559_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#ifdef DEBUG_EE os_printf("Warning: Invalid EEPROM checksum %04X for device %d\n", checksum, p_i82559->index);#endif } else // trailing block#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC {#ifdef DEBUG_EE os_printf("Valid EEPROM checksum\n");#endif return 1; } } return 0;}#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM// ------------------------------------------------------------------------//// NETWORK INTERFACE INITIALIZATION//// Function : Init82559//// 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 booli82559_init(struct cyg_netdevtab_entry * ndp){ static int initialized = 0; // only probe PCI et al *once* struct eth_drv_sc *sc; cyg_uint32 selftest; volatile cyg_uint32 *p_selftest; cyg_uint32 ioaddr; int count; int ints; struct i82559 *p_i82559; cyg_uint8 mac_address[ETHER_ADDR_LEN];#ifdef DEBUG // db_printf("intel_i82559_init\n");#endif sc = (struct eth_drv_sc *)(ndp->device_instance); p_i82559 = (struct i82559 *)(sc->driver_private); IF_BAD_82559( p_i82559 ) {#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_82559s() ) {#ifdef DEBUG os_printf( "pci_init_find_82559s failed\n" );#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -