/* Setup the receive address */
hw_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 */
hw_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);
}
/* Set the flow control receive threshold registers. Normally, *theseregisterswillbesettoadefaultthresholdthatmaybe *adjustedlaterbythedriver'sruntimecode.However,ifthe *abilitytotransmitpauseframesisnotenabled,thenthese *registerswillbesetto0.
*/ if (hw->fc.current_mode & igc_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 |= IGC_FCRTL_XONE;
/* In the case of the phy reset being blocked, we already have a link. *Wedonotneedtosetitupagain.
*/ if (igc_check_reset_block(hw)) goto out;
/* If requested flow control is set to default, set flow control *toboth'rx'and'tx'pauseframes.
*/ if (hw->fc.requested_mode == igc_fc_default)
hw->fc.requested_mode = igc_fc_full;
/* We want to save off the original Flow Control configuration just *incasewegetdisconnectedandthenreconnectedintoadifferent *huborswitchwithdifferentFlowControlcapabilities.
*/
hw->fc.current_mode = hw->fc.requested_mode;
hw_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) goto out;
/* Initialize the flow control address, type, and PAUSE timer *registerstotheirdefaultvalues.Thisisdoneevenifflow *controlisdisabled,becauseitdoesnothurtanythingto *initializetheseregisters.
*/
hw_dbg("Initializing the Flow Control address, type and timer regs\n");
wr32(IGC_FCT, FLOW_CONTROL_TYPE);
wr32(IGC_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
wr32(IGC_FCAL, FLOW_CONTROL_ADDRESS_LOW);
/* 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.
*/
hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
switch (hw->fc.current_mode) { case igc_fc_none:
ctrl &= (~(IGC_CTRL_TFCE | IGC_CTRL_RFCE)); break; case igc_fc_rx_pause:
ctrl &= (~IGC_CTRL_TFCE);
ctrl |= IGC_CTRL_RFCE; break; case igc_fc_tx_pause:
ctrl &= (~IGC_CTRL_RFCE);
ctrl |= IGC_CTRL_TFCE; break; case igc_fc_full:
ctrl |= (IGC_CTRL_TFCE | IGC_CTRL_RFCE); break; default:
hw_dbg("Flow control param set incorrectly\n");
ret_val = -IGC_ERR_CONFIG; goto out;
}
/* 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 |= IGC_RAH_AV;
/* Some bridges will combine consecutive 32-bit writes into *asingleburstwrite,whichwillmalfunctiononsomeparts. *Theflushesavoidthis.
*/
wr32(IGC_RAL(index), rar_low);
wrfl();
wr32(IGC_RAH(index), rar_high);
wrfl();
}
/* 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) {
ret_val = 0; goto out;
}
/* First we want to see if the MII Status Register reports *link.Ifso,thenwewanttogetthecurrentspeed/duplex *ofthePHY.
*/
ret_val = igc_phy_has_link(hw, 1, 0, &link); if (ret_val) goto out;
if (!link) goto out; /* No link detected */
mac->get_link_status = false;
/* Check if there was DownShift, must be checked *immediatelyafterlink-up
*/
igc_check_downshift(hw);
/* Auto-Neg is enabled. Auto Speed Detection takes care *ofMACspeed/duplexconfiguration.Soweonlyneedto *configureCollisionDistanceintheMAC.
*/
igc_config_collision_dist(hw);
/* Configure Flow Control now that Auto-Neg has completed. *First,weneedtorestorethedesiredflowcontrol *settingsbecausewemayhavehadtore-autonegwitha *differentlinkpartner.
*/
ret_val = igc_config_fc_after_link_up(hw); if (ret_val)
hw_dbg("Error configuring flow control\n");
out: /* Now that we are aware of our link settings, we can set the LTR *thresholds.
*/
ret_val = igc_set_ltr_i225(hw, link);
/* Check for the case where we have fiber media and auto-neg failed *sowehadtoforcelink.Inthiscase,weneedtoforcethe *configurationoftheMACtomatchthe"fc"parameter.
*/ if (mac->autoneg_failed)
ret_val = igc_force_mac_fc(hw);
if (ret_val) {
hw_dbg("Error forcing flow control settings\n"); goto out;
}
/* In auto-neg, we need to check and see if Auto-Neg has completed, *andifso,howthePHYandlinkpartnerhasflowcontrol *configured.
*/
/* Read the MII Status Register and check to see if AutoNeg *hascompleted.Wereadthistwicebecausethisreghas *some"sticky"(latched)bits.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
&mii_status_reg); if (ret_val) goto out;
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
&mii_status_reg); if (ret_val) goto out;
if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
hw_dbg("Copper PHY and Auto Neg has not completed.\n"); goto out;
}
/* The AutoNeg process has completed, so we now need to *readboththeAutoNegotiationAdvertisement *Register(Address4)andtheAuto_NegotiationBase *PageAbilityRegister(Address5)todeterminehow *flowcontrolwasnegotiated.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
&mii_nway_adv_reg); if (ret_val) goto out;
ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
&mii_nway_lp_ability_reg); if (ret_val) goto out; /* 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|igc_fc_none *0|1|0|DC|igc_fc_none *0|1|1|0|igc_fc_none *0|1|1|1|igc_fc_tx_pause *1|0|0|DC|igc_fc_none *1|DC|1|DC|igc_fc_full *1|1|0|0|igc_fc_none *1|1|0|1|igc_fc_rx_pause * *ArebothPAUSEbitssetto1?Ifso,thisimplies *SymmetricFlowControlisenabledatbothends.The *ASM_DIRbitsareirrelevantperthespec. * *ForSymmetricFlowControl: * *LOCALDEVICE|LINKPARTNER *PAUSE|ASM_DIR|PAUSE|ASM_DIR|Result *-------|---------|-------|---------|-------------------- *1|DC|1|DC|IGC_fc_full *
*/ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_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 == igc_fc_full) {
hw->fc.current_mode = igc_fc_full;
hw_dbg("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = igc_fc_rx_pause;
hw_dbg("Flow Control = RX PAUSE frames only.\n");
}
}
/* Now we need to do one last check... If we auto- *negotiatedtoHALFDUPLEX,flowcontrolshouldnotbe *enabledperIEEE802.3spec.
*/
ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex); if (ret_val) {
hw_dbg("Error getting link speed and duplex\n"); goto out;
}
if (duplex == HALF_DUPLEX)
hw->fc.current_mode = igc_fc_none;
/* Now we call a subroutine to actually force the MAC *controllertousethecorrectflowcontrolsettings.
*/
ret_val = igc_force_mac_fc(hw); if (ret_val) {
hw_dbg("Error forcing flow control settings\n"); goto out;
}
/* 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;
}
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.