📄 if_i82559.c
字号:
return 0; } } // If this device is not present, exit if (0 == p_i82559->found) return 0; p_i82559->mac_addr_ok = 0; ioaddr = p_i82559->io_address; // get I/O address for 82559#ifdef DEBUG os_printf("Init82559 %d @ %x\n82559 Self Test\n", p_i82559->index, (int)ndp);#endif ints = Mask82559Interrupt(p_i82559); // Reset device i82559_reset(p_i82559); // Perform a system self-test. (get enough mem to round address) if ( (selftest = (cyg_uint32)pciwindow_mem_alloc(32) ) == 0) return (0); p_selftest = (cyg_uint32 *) ((selftest + 15) & ~0xf); p_selftest[0] = p_selftest[1] = -1; OUTL( (VIRT_TO_BUS(p_selftest)) | I82559_SELFTEST, ioaddr + SCBPort); count = 0x7FFFF; // Timeout for self-test. do { udelay(10); } while ( (p_selftest[1] == -1) && (--count >= 0) ); // Reset device again after selftest i82559_reset(p_i82559); Acknowledge82559Interrupt(p_i82559); UnMask82559Interrupt(p_i82559, ints ); if (count < 0) { // Test timed out.#ifdef DEBUG os_printf("Self test failed\n");#endif return (0); }#ifdef DEBUG os_printf(" General self-test: %s.\n" " Serial sub-system self-test: %s.\n" " Internal registers self-test: %s.\n" " ROM checksum self-test: %s (%08X).\n", HAL_LE32TOC(p_selftest[1]) & 0x1000 ? "failed" : "passed", HAL_LE32TOC(p_selftest[1]) & 0x0020 ? "failed" : "passed", HAL_LE32TOC(p_selftest[1]) & 0x0008 ? "failed" : "passed", HAL_LE32TOC(p_selftest[1]) & 0x0004 ? "failed" : "passed", HAL_LE32TOC(p_selftest[0]));#endif // free self-test memory? // No, there's no point: this "heap" does not support free. if (p_i82559->hardwired_esa) { // Hardwire the address without consulting the EEPROM. // When this flag is set, the p_i82559 will already contain // the ESA. Copy it to a mac_address for call to set_mac_addr mac_address[0] = p_i82559->mac_address[0]; mac_address[1] = p_i82559->mac_address[1]; mac_address[2] = p_i82559->mac_address[2]; mac_address[3] = p_i82559->mac_address[3]; mac_address[4] = p_i82559->mac_address[4]; mac_address[5] = p_i82559->mac_address[5]; eth_set_mac_address(p_i82559, 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_I82559_GET_ESA int ok = false; int wflag = 0; CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA( p_i82559, mac_address, ok ); if ( ok ) {#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM if ( CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM == p_i82559->index )#endif // CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM { cyg_uint8 tmp_addr[ETHER_ADDR_LEN]; // write eeprom address unless it is already there wflag = 1; if (read_eeprom_esa(p_i82559, tmp_addr)) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) if (tmp_addr[i] != mac_address[i]) break; if (i >= ETHER_ADDR_LEN) wflag = 0; } }#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM eth_set_mac_address(p_i82559, mac_address, wflag); }#else // ! CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM if ( CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM == p_i82559->index ) {#endif // CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM if (read_eeprom_esa(p_i82559, mac_address)) { // record the MAC address in the device structure p_i82559->mac_address[0] = mac_address[0]; p_i82559->mac_address[1] = mac_address[1]; p_i82559->mac_address[2] = mac_address[2]; p_i82559->mac_address[3] = mac_address[3]; p_i82559->mac_address[4] = mac_address[4]; p_i82559->mac_address[5] = mac_address[5]; p_i82559->mac_addr_ok = 1; eth_set_mac_address(p_i82559, mac_address, 0); }#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM } else { // We are now "in" another device#if 1 < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT struct i82559 *other; // The one that *is* set up from EEPROM other = i82559_priv_array[CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM]; if ( other->mac_addr_ok ) { mac_address[0] = other->mac_address[0]; mac_address[1] = other->mac_address[1]; mac_address[2] = other->mac_address[2]; mac_address[3] = other->mac_address[3]; mac_address[4] = other->mac_address[4]; mac_address[5] = other->mac_address[5];#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_MAC_ADJUST mac_address[5] += CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_MAC_ADJUST;#endif eth_set_mac_address(p_i82559, mac_address, 0); }#endif // 1 < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT }#endif // CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA }#ifdef DEBUG os_printf("i82559_init: MAC Address = %02X %02X %02X %02X %02X %02X\n", p_i82559->mac_address[0], p_i82559->mac_address[1], p_i82559->mac_address[2], p_i82559->mac_address[3], p_i82559->mac_address[4], p_i82559->mac_address[5]);#endif // and record the net dev pointer p_i82559->ndp = (void *)ndp; p_i82559->within_send = 0; // init recursion level p_i82559->promisc = 0; // None of these initially p_i82559->multicast_all = 0; p_i82559->oversized = 1; // Enable this for VLAN mode by default InitRxRing(p_i82559); InitTxRing(p_i82559); CheckRxRing(p_i82559,__FUNCTION__,__LINE__); // Initialize upper level driver if ( p_i82559->mac_addr_ok ) (sc->funs->eth_drv->init)(sc, &(p_i82559->mac_address[0]) ); else (sc->funs->eth_drv->init)(sc, NULL ); CheckRxRing(p_i82559,__FUNCTION__,__LINE__); return (1);}// ------------------------------------------------------------------------//// Function : i82559_start//// ------------------------------------------------------------------------static void i82559_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ){ struct i82559 *p_i82559; cyg_uint32 ioaddr;#ifdef KEEP_STATISTICS void *p_statistics;#endif#ifdef CYGPKG_NET struct ifnet *ifp = &sc->sc_arpcom.ac_if;#endif p_i82559 = (struct i82559 *)sc->driver_private; ioaddr = p_i82559->io_address; // get 82559's I/O address IF_BAD_82559( p_i82559 ) {#ifdef DEBUG os_printf( "i82559_start: Bad device pointer %x\n", p_i82559 );#endif return; } if ( ! p_i82559->mac_addr_ok ) {#ifdef DEBUG os_printf("i82559_start %d: invalid MAC address, " "can't bring up interface\n", p_i82559->index );#endif return; } if ( p_i82559->active ) i82559_stop( sc );#ifdef KEEP_STATISTICS#ifdef CYGDBG_DEVS_ETH_INTEL_I82559_KEEP_STATISTICS p_statistics = p_i82559->p_statistics; memset(p_statistics, 0xFFFFFFFF, sizeof(I82559_COUNTERS)); // set statistics dump address wait_for_cmd_done(ioaddr, WAIT_CU); OUTL(VIRT_TO_BUS(p_statistics), ioaddr + SCBPointer); OUTW(SCB_M | CU_STATSADDR, ioaddr + SCBCmd); // Start dump command wait_for_cmd_done(ioaddr, WAIT_CU); OUTW(SCB_M | CU_DUMPSTATS, ioaddr + SCBCmd); // start register dump // ...and wait for it to complete operation // The code to wait was bogus; it was looking at the structure in the // wrong way. In any case, there is no need to wait, the // wait_for_cmd_done() in any following activity is good enough.#endif#endif // Enable device p_i82559->active = 1; /* Enable promiscuous mode if requested, reception of oversized frames always. * The latter is needed for VLAN support and shouldn't hurt even if we're not * using VLANs. Reset multicastALL reception choice. */ p_i82559->promisc = 0#ifdef CYGPKG_NET || !!(ifp->if_flags & IFF_PROMISC)#endif#ifdef ETH_DRV_FLAGS_PROMISC_MODE || !!(flags & ETH_DRV_FLAGS_PROMISC_MODE)#endif ; p_i82559->multicast_all = 0; i82559_configure(p_i82559, p_i82559->promisc, p_i82559->oversized, p_i82559->multicast_all );#ifdef DEBUG { int status = i82559_status( sc ); os_printf("i82559_start %d flg %x Link = %s, %s Mbps, %s Duplex\n", p_i82559->index, *(int *)p_i82559, status & GEN_STATUS_LINK ? "Up" : "Down", status & GEN_STATUS_100MBPS ? "100" : "10", status & GEN_STATUS_FDX ? "Full" : "Half"); }#endif i82559_restart(p_i82559); CheckRxRing(p_i82559,__FUNCTION__,__LINE__);}static void i82559_restart(struct i82559 *p_i82559){ cyg_uint32 ioaddr; ioaddr = p_i82559->io_address; // get 82559's I/O address // Load pointer to Rx Ring and enable receiver wait_for_cmd_done(ioaddr, WAIT_RU); OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), ioaddr + SCBPointer); OUTW(RUC_START, ioaddr + SCBCmd);}// ------------------------------------------------------------------------//// Function : i82559_status//// ------------------------------------------------------------------------inti82559_status( struct eth_drv_sc *sc ){ int status; struct i82559 *p_i82559; cyg_uint32 ioaddr; p_i82559 = (struct i82559 *)sc->driver_private; IF_BAD_82559( p_i82559 ) {#ifdef DEBUG os_printf( "i82559_status: Bad device pointer %x\n", p_i82559 );#endif return 0; } ioaddr = p_i82559->io_address; // get 82559's I/O address status = INB(ioaddr + SCBGenStatus); return status;}// ------------------------------------------------------------------------//// Function : BringDown82559//// ------------------------------------------------------------------------static voidi82559_stop( struct eth_drv_sc *sc ){ struct i82559 *p_i82559; p_i82559 = (struct i82559 *)sc->driver_private; IF_BAD_82559( p_i82559 ) {#ifdef DEBUG os_printf( "i82559_stop: Bad device pointer %x\n", p_i82559 );#endif return; } #ifdef DEBUG os_printf("i82559_stop %d flg %x\n", p_i82559->index, *(int *)p_i82559 );#endif p_i82559->active = 0; // stop people tormenting it i82559_reset(p_i82559); // that should stop it // Now that it's inactive, return all pending tx status to the higher // layers: // "Done" txen are from here to active, OR // the remove one if the queue is full AND its status is nonz
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -