/* The status register reports the correct function number *forthedeviceregardlessoffunctionswapstate.
*/
reg = er32(STATUS);
bus->func = FIELD_GET(E1000_STATUS_FUNC_MASK, reg);
}
/* Setup the receive address */
e_dbg("Programming MAC Address into RAR[0]\n");
hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
/* Zero out the other (rar_entry_count - 1) receive addresses */
e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); for (i = 1; i < rar_count; i++)
hw->mac.ops.rar_set(hw, mac_addr, i);
}
/* if multicast bit is set, the alternate address will not be used */ if (is_multicast_ether_addr(alt_mac_addr)) {
e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); return0;
}
/* We have a valid alternate MAC address, and we want to treat it the *sameasthenormalpermanentMACaddressstoredbytheHWintothe *RAR.DothisbymappingthisaddressintoRAR0.
*/
hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
/* HW expects these in little endian so we reverse the byte order *fromnetworkorder(bigendian)tolittleendian
*/
rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
((u32)addr[2] << 16) | ((u32)addr[3] << 24));
rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
/* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high)
rar_high |= E1000_RAH_AV;
/* Some bridges will combine consecutive 32-bit writes into *asingleburstwrite,whichwillmalfunctiononsomeparts. *Theflushesavoidthis.
*/
ew32(RAL(index), rar_low);
e1e_flush();
ew32(RAH(index), rar_high);
e1e_flush();
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
/* For a mc_filter_type of 0, bit_shift is the number of left-shifts *where0xFFwouldstillfallwithinthehashmask.
*/ while (hash_mask >> bit_shift != 0xFF)
bit_shift++;
/* The portion of the address that is used for the hash table *isdeterminedbythemc_filter_typesetting. *Thealgorithmissuchthatthereisatotalof8bitsofshifting. *Thebit_shiftforamc_filter_typeof0representsthenumberof *left-shiftswheretheMSBofmc_addr[5]wouldstillfallwithin *thehash_mask.Case0doesthisexactly.Sincethereareatotal *of8bitsofshifting,thenmc_addr[4]willshiftrightthe *remainingnumberofbits.Thus8-bit_shift.Therestofthe *casesareavariationofthisalgorithm...essentiallyraisingthe *numberofbitstoshiftmc_addr[5]left,whilestillkeepingthe *8-bitshiftingtotal. * *Forexample,giventhefollowingDestinationMACAddressandan *mtaregistercountof128(thusa4096-bitvectorand0xFFFmask), *wecanseethatthebit_shiftforcase0is4.Thesearethehash *valuesresultingfromeachmc_filter_type... *[0][1][2][3][4][5] *01AA00123456 *LSBMSB * *case0:hash_value=((0x34>>4)|(0x56<<4))&0xFFF=0x563 *case1:hash_value=((0x34>>3)|(0x56<<5))&0xFFF=0xAC6 *case2:hash_value=((0x34>>2)|(0x56<<6))&0xFFF=0x163 *case3:hash_value=((0x34>>0)|(0x56<<8))&0xFFF=0x634
*/ switch (hw->mac.mc_filter_type) { default: case0: break; case1:
bit_shift += 1; break; case2:
bit_shift += 2; break; case3:
bit_shift += 4; break;
}
/* We only want to go out to the PHY registers to see if Auto-Neg *hascompletedand/orifourlinkstatushaschanged.The *get_link_statusflagissetuponreceivingaLinkStatus *ChangeorRxSequenceErrorinterrupt.
*/ if (!mac->get_link_status) return0;
mac->get_link_status = false;
/* First we want to see if the MII Status Register reports *link.Ifso,thenwewanttogetthecurrentspeed/duplex *ofthePHY.
*/
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); if (ret_val || !link) goto out;
/* Check if there was DownShift, must be checked *immediatelyafterlink-up
*/
e1000e_check_downshift(hw);
/* If we are forcing speed/duplex, then we simply return since *wehavealreadydeterminedwhetherwehavelinkornot.
*/ if (!mac->autoneg) return -E1000_ERR_CONFIG;
/* Auto-Neg is enabled. Auto Speed Detection takes care *ofMACspeed/duplexconfiguration.Soweonlyneedto *configureCollisionDistanceintheMAC.
*/
mac->ops.config_collision_dist(hw);
/* Configure Flow Control now that Auto-Neg has completed. *First,weneedtorestorethedesiredflowcontrol *settingsbecausewemayhavehadtore-autonegwitha *differentlinkpartner.
*/
ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val)
e_dbg("Error configuring flow control\n");
ctrl = er32(CTRL);
status = er32(STATUS);
rxcw = er32(RXCW);
/* If we don't have link (auto-negotiation failed or link partner *cannotauto-negotiate),thecableispluggedin(wehavesignal), *andourlinkpartnerisnottryingtoauto-negotiatewithus(we *arereceivingidlesordata),weneedtoforcelinkup.Wealso *needtogiveauto-negotiationtimetocomplete,incasethecable *wasjustpluggedin.Theautoneg_failedflagdoesthis.
*/ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) &&
!(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) {
mac->autoneg_failed = true; return0;
}
e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
/* Force link-up and also force full-duplex. */
ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
ew32(CTRL, ctrl);
/* Configure Flow Control after forcing link up. */
ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val) {
e_dbg("Error configuring flow control\n"); return ret_val;
}
} elseif ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered *sets,re-enableauto-negotiationintheTXCWregister *anddisableforcedlinkintheDeviceControlregister *inanattempttoauto-negotiatewithourlinkpartner.
*/
e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
ew32(TXCW, mac->txcw);
ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
ctrl = er32(CTRL);
status = er32(STATUS);
rxcw = er32(RXCW);
/* If we don't have link (auto-negotiation failed or link partner *cannotauto-negotiate),andourlinkpartnerisnottryingto *auto-negotiatewithus(wearereceivingidlesordata), *weneedtoforcelinkup.Wealsoneedtogiveauto-negotiation *timetocomplete.
*/ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) {
mac->autoneg_failed = true; return0;
}
e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
/* Force link-up and also force full-duplex. */
ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
ew32(CTRL, ctrl);
/* Configure Flow Control after forcing link up. */
ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val) {
e_dbg("Error configuring flow control\n"); return ret_val;
}
} elseif ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered *sets,re-enableauto-negotiationintheTXCWregister *anddisableforcedlinkintheDeviceControlregister *inanattempttoauto-negotiatewithourlinkpartner.
*/
e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
ew32(TXCW, mac->txcw);
ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
mac->serdes_has_link = true;
} elseif (!(E1000_TXCW_ANE & er32(TXCW))) { /* If we force link for non-auto-negotiation switch, check *linkstatusbasedonMACsynchronizationforinternal *serdesmediatype.
*/ /* SYNCH bit and IV bit are sticky. */
usleep_range(10, 20);
rxcw = er32(RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) {
mac->serdes_has_link = true;
e_dbg("SERDES: Link up - forced.\n");
}
} else {
mac->serdes_has_link = false;
e_dbg("SERDES: Link down - force failed.\n");
}
}
if (E1000_TXCW_ANE & er32(TXCW)) {
status = er32(STATUS); if (status & E1000_STATUS_LU) { /* SYNCH bit and IV bit are sticky, so reread rxcw. */
usleep_range(10, 20);
rxcw = er32(RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) {
mac->serdes_has_link = true;
e_dbg("SERDES: Link up - autoneg completed successfully.\n");
} else {
mac->serdes_has_link = false;
e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n");
}
} else {
mac->serdes_has_link = false;
e_dbg("SERDES: Link down - no sync.\n");
}
} else {
mac->serdes_has_link = false;
e_dbg("SERDES: Link down - autoneg failed\n");
}
}
/* Read and store word 0x0F of the EEPROM. This word contains bits *thatdeterminethehardware'sdefaultPAUSE(flowcontrol)mode, *abitthatdetermineswhethertheHWdefaultstoenablingor *disablingauto-negotiation,andthedirectionofthe *SWdefinedpins.IfthereisnoSWover-rideoftheflow *controlsetting,thenthevariablehw->fcwill *beinitializedbasedonavalueintheEEPROM.
*/
ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
if (ret_val) {
e_dbg("NVM Read Error\n"); return ret_val;
}
/* In the case of the phy reset being blocked, we already have a link. *Wedonotneedtosetitupagain.
*/ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return0;
/* If requested flow control is set to default, set flow control *basedontheEEPROMflowcontrolsettings.
*/ if (hw->fc.requested_mode == e1000_fc_default) {
ret_val = e1000_set_default_fc_generic(hw); if (ret_val) return ret_val;
}
/* Save off the requested flow control mode for use later. Depending *onthelinkpartner'scapabilities,wemayormaynotusethismode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode);
/* Call the necessary media_type subroutine to configure the link. */
ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) return ret_val;
/* Initialize the flow control address, type, and PAUSE timer *registerstotheirdefaultvalues.Thisisdoneevenifflow *controlisdisabled,becauseitdoesnothurtanythingto *initializetheseregisters.
*/
e_dbg("Initializing the Flow Control address, type and timer regs\n");
ew32(FCT, FLOW_CONTROL_TYPE);
ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
/* Check for a software override of the flow control settings, and *setupthedeviceaccordingly.Ifauto-negotiationisenabled,then *softwarewillhavetosetthe"PAUSE"bitstothecorrectvaluein *theTransmitConfigWordRegister(TXCW)andre-startauto- *negotiation.However,ifauto-negotiationisdisabled,then *softwarewillhavetomanuallyconfigurethetwoflowcontrolenable *bitsintheCTRLregister. * *Thepossiblevaluesofthe"fc"parameterare: *0:Flowcontroliscompletelydisabled *1:Rxflowcontrolisenabled(wecanreceivepauseframes, *butnotsendpauseframes). *2:Txflowcontrolisenabled(wecansendpauseframesbutwe *donotsupportreceivingpauseframes). *3:BothRxandTxflowcontrol(symmetric)areenabled.
*/ switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control completely disabled by a software over-ride. */
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: /* Rx Flow control is enabled and Tx Flow control is disabled *byasoftwareover-ride.Sincetherereallyisn'tawayto *advertisethatwearecapableofRxPauseONLY,wewill *advertisethatwesupportbothsymmetricandasymmetricRx *PAUSE.Later,wewilldisabletheadapter'sabilitytosend *PAUSEframes.
*/
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is disabled, *byasoftwareover-ride.
*/
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: /* Flow control (both Rx and Tx) is enabled by a software *over-ride.
*/
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; default:
e_dbg("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG;
}
/* If we have a signal (the cable is plugged in, or assumed true for *serdesmedia)thenpollfora"Link-Up"indicationintheDevice *StatusRegister.Time-outifalinkisn'tseenin500milliseconds *seconds(Auto-negotiationshouldcompleteinlessthan500 *millisecondseveniftheotherendisdoingitinSW).
*/ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
usleep_range(10000, 11000);
status = er32(STATUS); if (status & E1000_STATUS_LU) break;
} if (i == FIBER_LINK_UP_LIMIT) {
e_dbg("Never got a valid link from auto-neg!!!\n");
mac->autoneg_failed = true; /* AutoNeg failed to achieve a link, so we'll call *mac->check_for_link.Thisroutinewillforcethe *linkupifwedetectasignal.Thiswillallowusto *communicatewithnon-autonegotiatinglinkpartners.
*/
ret_val = mac->ops.check_for_link(hw); if (ret_val) {
e_dbg("Error while checking for link\n"); return ret_val;
}
mac->autoneg_failed = false;
} else {
mac->autoneg_failed = false;
e_dbg("Valid Link Found\n");
}
/* Take the link out of reset */
ctrl &= ~E1000_CTRL_LRST;
hw->mac.ops.config_collision_dist(hw);
ret_val = e1000_commit_fc_settings_generic(hw); if (ret_val) return ret_val;
/* Since auto-negotiation is enabled, take the link out of reset (the *linkwillbeinreset,becausewepreviouslyresetthechip).This *willrestartauto-negotiation.Ifauto-negotiationissuccessful *thenthelink-upstatusbitwillbesetandtheflowcontrolenable *bits(RFCEandTFCE)willbesetaccordingtotheirnegotiatedvalue.
*/
e_dbg("Auto-negotiation enabled\n");
/* For these adapters, the SW definable pin 1 is set when the optics *detectasignal.Ifwehaveasignal,thenpollfora"Link-Up" *indication.
*/ if (hw->phy.media_type == e1000_media_type_internal_serdes ||
(er32(CTRL) & E1000_CTRL_SWDPIN1)) {
ret_val = e1000_poll_fiber_serdes_link_generic(hw);
} else {
e_dbg("No signal detected\n");
}
/* Set the flow control receive threshold registers. Normally, *theseregisterswillbesettoadefaultthresholdthatmaybe *adjustedlaterbythedriver'sruntimecode.However,ifthe *abilitytotransmitpauseframesisnotenabled,thenthese *registerswillbesetto0.
*/ if (hw->fc.current_mode & e1000_fc_tx_pause) { /* We need to set up the Receive Threshold high and low water *marksaswellas(optionally)enablingthetransmissionof *XONframes.
*/
fcrtl = hw->fc.low_water; if (hw->fc.send_xon)
fcrtl |= E1000_FCRTL_XONE;
/* Because we didn't get link via the internal auto-negotiation *mechanism(weeitherforcedlinkorwegotlinkviaPHY *auto-neg),wehavetomanuallyenable/disabletransmitan *receiveflowcontrol. * *The"Case"statementbelowenables/disableflowcontrol *accordingtothe"hw->fc.current_mode"parameter. * *Thepossiblevaluesofthe"fc"parameterare: *0:Flowcontroliscompletelydisabled *1:Rxflowcontrolisenabled(wecanreceivepause *framesbutnotsendpauseframes). *2:Txflowcontrolisenabled(wecansendpauseframes *butwedonotreceivepauseframes). *3:BothRxandTxflowcontrol(symmetric)isenabled. *other:Noothervaluesshouldbepossibleatthispoint.
*/
e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
switch (hw->fc.current_mode) { case e1000_fc_none:
ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; case e1000_fc_rx_pause:
ctrl &= (~E1000_CTRL_TFCE);
ctrl |= E1000_CTRL_RFCE; break; case e1000_fc_tx_pause:
ctrl &= (~E1000_CTRL_RFCE);
ctrl |= E1000_CTRL_TFCE; break; case e1000_fc_full:
ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default:
e_dbg("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG;
}
/* Check for the case where we have fiber media and auto-neg failed *sowehadtoforcelink.Inthiscase,weneedtoforcethe *configurationoftheMACtomatchthe"fc"parameter.
*/ if (mac->autoneg_failed) { if (hw->phy.media_type == e1000_media_type_fiber ||
hw->phy.media_type == e1000_media_type_internal_serdes)
ret_val = e1000e_force_mac_fc(hw);
} else { if (hw->phy.media_type == e1000_media_type_copper)
ret_val = e1000e_force_mac_fc(hw);
}
if (ret_val) {
e_dbg("Error forcing flow control settings\n"); return ret_val;
}
/* Check for the case where we have copper media and auto-neg is *enabled.Inthiscase,weneedtocheckandseeifAuto-Neg *hascompleted,andifso,howthePHYandlinkpartnerhas *flowcontrolconfigured.
*/ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { /* Read the MII Status Register and check to see if AutoNeg *hascompleted.Wereadthistwicebecausethisreghas *some"sticky"(latched)bits.
*/
ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); if (ret_val) return ret_val;
ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); if (ret_val) return ret_val;
if (!(mii_status_reg & BMSR_ANEGCOMPLETE)) {
e_dbg("Copper PHY and Auto Neg has not completed.\n"); return ret_val;
}
/* The AutoNeg process has completed, so we now need to *readboththeAutoNegotiationAdvertisement *Register(Address4)andtheAuto_NegotiationBase *PageAbilityRegister(Address5)todeterminehow *flowcontrolwasnegotiated.
*/
ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_nway_adv_reg); if (ret_val) return ret_val;
ret_val = e1e_rphy(hw, MII_LPA, &mii_nway_lp_ability_reg); if (ret_val) return ret_val;
/* Two bits in the Auto Negotiation Advertisement Register *(Address4)andtwobitsintheAutoNegotiationBase *PageAbilityRegister(Address5)determineflowcontrol *forboththePHYandthelinkpartner.Thefollowing *table,takenoutoftheIEEE802.3ab/D6.0datedMarch25, *1999,describesthesePAUSEresolutionbitsandhowflow *controlisdeterminedbaseduponthesesettings. *NOTE:DC=Don'tCare * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|NICResolution *-------|---------|-------|---------|-------------------- *0|0|DC|DC|e1000_fc_none *0|1|0|DC|e1000_fc_none *0|1|1|0|e1000_fc_none *0|1|1|1|e1000_fc_tx_pause *1|0|0|DC|e1000_fc_none *1|DC|1|DC|e1000_fc_full *1|1|0|0|e1000_fc_none *1|1|0|1|e1000_fc_rx_pause * *ArebothPAUSEbitssetto1?Ifso,thisimplies *SymmetricFlowControlisenabledatbothends.The *ASM_DIRbitsareirrelevantperthespec. * *ForSymmetricFlowControl: * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *1|DC|1|DC|E1000_fc_full *
*/ if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) &&
(mii_nway_lp_ability_reg & LPA_PAUSE_CAP)) { /* Now we need to check if the user selected Rx ONLY *ofpauseframes.Inthiscase,wehadtoadvertise *FULLflowcontrolbecausewecouldnotadvertiseRx *ONLY.Hence,wemustnowchecktoseeifweneedto *turnOFFtheTRANSMISSIONofPAUSEframes.
*/ if (hw->fc.requested_mode == e1000_fc_full) {
hw->fc.current_mode = e1000_fc_full;
e_dbg("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = e1000_fc_rx_pause;
e_dbg("Flow Control = Rx PAUSE frames only.\n");
}
} /* For receiving PAUSE frames ONLY. * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *0|1|1|1|e1000_fc_tx_pause
*/ elseif (!(mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) &&
(mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) &&
(mii_nway_lp_ability_reg & LPA_PAUSE_CAP) &&
(mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) {
hw->fc.current_mode = e1000_fc_tx_pause;
e_dbg("Flow Control = Tx PAUSE frames only.\n");
} /* For transmitting PAUSE frames ONLY. * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *1|1|0|1|e1000_fc_rx_pause
*/ elseif ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) &&
(mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) &&
!(mii_nway_lp_ability_reg & LPA_PAUSE_CAP) &&
(mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) {
hw->fc.current_mode = e1000_fc_rx_pause;
e_dbg("Flow Control = Rx PAUSE frames only.\n");
} else { /* Per the IEEE spec, at this point flow control *shouldbedisabled.
*/
hw->fc.current_mode = e1000_fc_none;
e_dbg("Flow Control = NONE.\n");
}
/* Now we need to do one last check... If we auto- *negotiatedtoHALFDUPLEX,flowcontrolshouldnotbe *enabledperIEEE802.3spec.
*/
ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) {
e_dbg("Error getting link speed and duplex\n"); return ret_val;
}
if (duplex == HALF_DUPLEX)
hw->fc.current_mode = e1000_fc_none;
/* Now we call a subroutine to actually force the MAC *controllertousethecorrectflowcontrolsettings.
*/
ret_val = e1000e_force_mac_fc(hw); if (ret_val) {
e_dbg("Error forcing flow control settings\n"); return ret_val;
}
}
/* Check for the case where we have SerDes media and auto-neg is *enabled.Inthiscase,weneedtocheckandseeifAuto-Neg *hascompleted,andifso,howthePHYandlinkpartnerhas *flowcontrolconfigured.
*/ if ((hw->phy.media_type == e1000_media_type_internal_serdes) &&
mac->autoneg) { /* Read the PCS_LSTS and check to see if AutoNeg *hascompleted.
*/
pcs_status_reg = er32(PCS_LSTAT);
if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
e_dbg("PCS Auto Neg has not completed.\n"); return ret_val;
}
/* The AutoNeg process has completed, so we now need to *readboththeAutoNegotiationAdvertisement *Register(PCS_ANADV)andtheAuto_NegotiationBase *PageAbilityRegister(PCS_LPAB)todeterminehow *flowcontrolwasnegotiated.
*/
pcs_adv_reg = er32(PCS_ANADV);
pcs_lp_ability_reg = er32(PCS_LPAB);
/* Two bits in the Auto Negotiation Advertisement Register *(PCS_ANADV)andtwobitsintheAutoNegotiationBase *PageAbilityRegister(PCS_LPAB)determineflowcontrol *forboththePHYandthelinkpartner.Thefollowing *table,takenoutoftheIEEE802.3ab/D6.0datedMarch25, *1999,describesthesePAUSEresolutionbitsandhowflow *controlisdeterminedbaseduponthesesettings. *NOTE:DC=Don'tCare * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|NICResolution *-------|---------|-------|---------|-------------------- *0|0|DC|DC|e1000_fc_none *0|1|0|DC|e1000_fc_none *0|1|1|0|e1000_fc_none *0|1|1|1|e1000_fc_tx_pause *1|0|0|DC|e1000_fc_none *1|DC|1|DC|e1000_fc_full *1|1|0|0|e1000_fc_none *1|1|0|1|e1000_fc_rx_pause * *ArebothPAUSEbitssetto1?Ifso,thisimplies *SymmetricFlowControlisenabledatbothends.The *ASM_DIRbitsareirrelevantperthespec. * *ForSymmetricFlowControl: * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *1|DC|1|DC|e1000_fc_full *
*/ if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
(pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { /* Now we need to check if the user selected Rx ONLY *ofpauseframes.Inthiscase,wehadtoadvertise *FULLflowcontrolbecausewecouldnotadvertiseRx *ONLY.Hence,wemustnowchecktoseeifweneedto *turnOFFtheTRANSMISSIONofPAUSEframes.
*/ if (hw->fc.requested_mode == e1000_fc_full) {
hw->fc.current_mode = e1000_fc_full;
e_dbg("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = e1000_fc_rx_pause;
e_dbg("Flow Control = Rx PAUSE frames only.\n");
}
} /* For receiving PAUSE frames ONLY. * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *0|1|1|1|e1000_fc_tx_pause
*/ elseif (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
(pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
(pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_tx_pause;
e_dbg("Flow Control = Tx PAUSE frames only.\n");
} /* For transmitting PAUSE frames ONLY. * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *1|1|0|1|e1000_fc_rx_pause
*/ elseif ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
(pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
!(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
(pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_rx_pause;
e_dbg("Flow Control = Rx PAUSE frames only.\n");
} else { /* Per the IEEE spec, at this point flow control *shouldbedisabled.
*/
hw->fc.current_mode = e1000_fc_none;
e_dbg("Flow Control = NONE.\n");
}
/* Now we call a subroutine to actually force the MAC *controllertousethecorrectflowcontrolsettings.
*/
pcs_ctrl_reg = er32(PCS_LCTL);
pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
ew32(PCS_LCTL, pcs_ctrl_reg);
ret_val = e1000e_force_mac_fc(hw); if (ret_val) {
e_dbg("Error forcing flow control settings\n"); return ret_val;
}
}
for (i = 0; i < 4; i++) {
temp = (data >> (i << 2)) & led_mask; switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2:
mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
mac->ledctl_mode1 |= ledctl_on << (i << 3); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2:
mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
mac->ledctl_mode1 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break;
} switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2:
mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
mac->ledctl_mode2 |= ledctl_on << (i << 3); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2:
mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
mac->ledctl_mode2 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.