switch (hw->mac.type) { case e1000_82571: case e1000_82572:
phy->type = e1000_phy_igp_2; break; case e1000_82573:
phy->type = e1000_phy_m88; break; case e1000_82574: case e1000_82583:
phy->type = e1000_phy_bm;
phy->ops.acquire = e1000_get_hw_semaphore_82574;
phy->ops.release = e1000_put_hw_semaphore_82574;
phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574; break; default: return -E1000_ERR_PHY;
}
/* This can only be done after all function pointers are setup. */
ret_val = e1000_get_phy_id_82571(hw); if (ret_val) {
e_dbg("Error getting PHY ID\n"); return ret_val;
}
/* Verify phy id */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: if (phy->id != IGP01E1000_I_PHY_ID)
ret_val = -E1000_ERR_PHY; break; case e1000_82573: if (phy->id != M88E1111_I_PHY_ID)
ret_val = -E1000_ERR_PHY; break; case e1000_82574: case e1000_82583: if (phy->id != BME1000_E_PHY_ID_R2)
ret_val = -E1000_ERR_PHY; break; default:
ret_val = -E1000_ERR_PHY; break;
}
if (ret_val)
e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id);
/* Ensure that the inter-port SWSM.SMBI lock bit is clear before *firstNVMorPHYaccess.Thisshouldbedoneforsingle-port *devices,andforoneportonlyondual-portdevicessothat *forthosedeviceswecanstillusetheSMBIlocktosynchronize *inter-portaccessestothePHY&NVM.
*/ switch (hw->mac.type) { case e1000_82571: case e1000_82572:
swsm2 = er32(SWSM2);
if (!(swsm2 & E1000_SWSM2_LOCK)) { /* Only do this for the first interface on this card */
ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK);
force_clear_smbi = true;
} else {
force_clear_smbi = false;
} break; default:
force_clear_smbi = true; break;
}
if (force_clear_smbi) { /* Make sure SWSM.SMBI is clear */
swsm = er32(SWSM); if (swsm & E1000_SWSM_SMBI) { /* This bit should not be set on a first interface, and *indicatesthatthebootagentorEFIcodehas *improperlyleftthisbitenabled
*/
e_dbg("Please update your 82571 Bootagent\n");
}
ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
}
/* Initialize device specific counter of SMBI acquisition timeouts. */
hw->dev_spec.e82571.smb_counter = 0;
return0;
}
static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
{ struct e1000_hw *hw = &adapter->hw; staticint global_quad_port_a; /* global port a indication */ struct pci_dev *pdev = adapter->pdev; int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
s32 rc;
rc = e1000_init_mac_params_82571(hw); if (rc) return rc;
rc = e1000_init_nvm_params_82571(hw); if (rc) return rc;
rc = e1000_init_phy_params_82571(hw); if (rc) return rc;
/* tag quad port adapters first, it's used below */ switch (pdev->device) { case E1000_DEV_ID_82571EB_QUAD_COPPER: case E1000_DEV_ID_82571EB_QUAD_FIBER: case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: case E1000_DEV_ID_82571PT_QUAD_COPPER:
adapter->flags |= FLAG_IS_QUAD_PORT; /* mark the first port */ if (global_quad_port_a == 0)
adapter->flags |= FLAG_IS_QUAD_PORT_A; /* Reset for multiple quad port adapters */
global_quad_port_a++; if (global_quad_port_a == 4)
global_quad_port_a = 0; break; default: break;
}
switch (adapter->hw.mac.type) { case e1000_82571: /* these dual ports don't have WoL on port B at all */ if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) ||
(pdev->device == E1000_DEV_ID_82571EB_SERDES) ||
(pdev->device == E1000_DEV_ID_82571EB_COPPER)) &&
(is_port_b))
adapter->flags &= ~FLAG_HAS_WOL; /* quad ports only support WoL on port A */ if (adapter->flags & FLAG_IS_QUAD_PORT &&
(!(adapter->flags & FLAG_IS_QUAD_PORT_A)))
adapter->flags &= ~FLAG_HAS_WOL; /* Does not support WoL on any port */ if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)
adapter->flags &= ~FLAG_HAS_WOL; break; case e1000_82573: if (pdev->device == E1000_DEV_ID_82573L) {
adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
adapter->max_hw_frame_size = DEFAULT_JUMBO;
} break; default: break;
}
switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* The 82571 firmware may still be configuring the PHY. *Inthiscase,wecannotaccessthePHYuntilthe *configurationisdone.Soweexplicitlysetthe *PHYID.
*/
phy->id = IGP01E1000_I_PHY_ID; break; case e1000_82573: return e1000e_get_phy_id(hw); case e1000_82574: case e1000_82583:
ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); if (ret_val) return ret_val;
/* If we have timedout 3 times on trying to acquire *theinter-portSMBIsemaphore,thereisoldcode *operatingontheotherport,anditisnot *releasingSMBI.Modifythenumberoftimesthat *wetryforthesemaphoretointerworkwiththis *oldercode.
*/ if (hw->dev_spec.e82571.smb_counter > 2)
sw_timeout = 1;
/* Get the SW semaphore */ while (i < sw_timeout) {
swsm = er32(SWSM); if (!(swsm & E1000_SWSM_SMBI)) break;
usleep_range(50, 100);
i++;
}
if (i == sw_timeout) {
e_dbg("Driver can't access device - SMBI bit is set.\n");
hw->dev_spec.e82571.smb_counter++;
} /* Get the FW semaphore. */ for (i = 0; i < fw_timeout; i++) {
swsm = er32(SWSM);
ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
/* Semaphore acquired if bit latched */ if (er32(SWSM) & E1000_SWSM_SWESMBI) break;
usleep_range(50, 100);
}
if (i == fw_timeout) { /* Release semaphores */
e1000_put_hw_semaphore_82571(hw);
e_dbg("Driver can't access the NVM\n"); return -E1000_ERR_NVM;
}
ret_val = e1000e_update_nvm_checksum_generic(hw); if (ret_val) return ret_val;
/* If our nvm is an EEPROM, then we're done *otherwise,committhechecksumtotheflashNVM.
*/ if (hw->nvm.type != e1000_nvm_flash_hw) return0;
/* Check for pending operations. */ for (i = 0; i < E1000_FLASH_UPDATES; i++) {
usleep_range(1000, 2000); if (!(er32(EECD) & E1000_EECD_FLUPD)) break;
}
if (i == E1000_FLASH_UPDATES) return -E1000_ERR_NVM;
/* Reset the firmware if using STM opcode. */ if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { /* The enabling of and the actual reset must be done *intwowritecycles.
*/
ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
e1e_flush();
ew32(HICR, E1000_HICR_FW_RESET);
}
/* Commit the write to flash */
eecd = er32(EECD) | E1000_EECD_FLUPD;
ew32(EECD, eecd);
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
usleep_range(1000, 2000); if (!(er32(EECD) & E1000_EECD_FLUPD)) break;
}
if (i == E1000_FLASH_UPDATES) return -E1000_ERR_NVM;
/* A check for invalid values: offset too large, too many words, *andnotenoughwords.
*/ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
e_dbg("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM;
}
for (i = 0; i < words; i++) {
eewr = ((data[i] << E1000_NVM_RW_REG_DATA) |
((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |
E1000_NVM_RW_REG_START);
ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); if (ret_val) break;
ew32(EEWR, eewr);
ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); if (ret_val) break;
}
while (timeout) { if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) break;
usleep_range(1000, 2000);
timeout--;
} if (!timeout) {
e_dbg("MNG configuration cycle has not completed.\n"); return -E1000_ERR_RESET;
}
ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) return ret_val;
if (active) {
data |= IGP02E1000_PM_D0_LPLU;
ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val;
} else {
data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used *duringDxstateswherethepowerconservationismost *important.Duringdriveractivityweshouldenable *SmartSpeed,soperformanceismaintained.
*/ if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
&data); if (ret_val) return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
data); if (ret_val) return ret_val;
} elseif (phy->smart_speed == e1000_smart_speed_off) {
ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
&data); if (ret_val) return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
data); if (ret_val) return ret_val;
}
}
/* Prevent the PCI-E bus from sticking if there is no TLP connection *onthelastTLPread/writetransactionwhenMACisreset.
*/
ret_val = e1000e_disable_pcie_master(hw); if (ret_val)
e_dbg("PCI-E Master disable polling has failed.\n");
e_dbg("Masking off all interrupts\n");
ew32(IMC, 0xffffffff);
/* Must acquire the MDIO ownership before MAC reset. *Ownershipdefaultstofirmwareafterareset.
*/ switch (hw->mac.type) { case e1000_82573:
ret_val = e1000_get_hw_semaphore_82573(hw); break; case e1000_82574: case e1000_82583:
ret_val = e1000_get_hw_semaphore_82574(hw); break; default: break;
}
ctrl = er32(CTRL);
e_dbg("Issuing a global reset to MAC\n");
ew32(CTRL, ctrl | E1000_CTRL_RST);
/* Must release MDIO ownership and mutex after MAC reset. */ switch (hw->mac.type) { case e1000_82573: /* Release mutex only if the hw semaphore is acquired */ if (!ret_val)
e1000_put_hw_semaphore_82573(hw); break; case e1000_82574: case e1000_82583: /* Release mutex only if the hw semaphore is acquired */ if (!ret_val)
e1000_put_hw_semaphore_82574(hw); break; default: break;
}
ret_val = e1000e_get_auto_rd_done(hw); if (ret_val) /* We don't want to continue accessing MAC registers. */ return ret_val;
/* Phy configuration from NVM just starts after EECD_AUTO_RD is set. *NeedtowaitforPhyconfigurationcompletionbeforeaccessing *NVMandPhy.
*/
switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* REQ and GNT bits need to be cleared when using AUTO_RD *toaccesstheEEPROM.
*/
eecd = er32(EECD);
eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT);
ew32(EECD, eecd); break; case e1000_82573: case e1000_82574: case e1000_82583:
msleep(25); break; default: break;
}
/* Clear any pending interrupt events. */
ew32(IMC, 0xffffffff);
er32(ICR);
if (hw->mac.type == e1000_82571) { /* Install any alternate MAC address into RAR0 */
ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) return ret_val;
e1000e_set_laa_state_82571(hw, true);
}
/* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes)
hw->mac.serdes_link_state = e1000_serdes_link_down;
/* Initialize identification LED */
ret_val = mac->ops.id_led_init(hw); /* An error is not fatal and we should not stop init due to this */ if (ret_val)
e_dbg("Error initializing identification LED\n");
/* Disabling VLAN filtering */
e_dbg("Initializing the IEEE VLAN\n");
mac->ops.clear_vfta(hw);
/* Setup the receive address. *If,however,alocallyadministeredaddresswasassignedtothe *82571,wemustreserveaRARforittoworkaroundanissuewhere *resettingoneportwillreloadtheMAContheotherport.
*/ if (e1000e_get_laa_state_82571(hw))
rar_count--;
e1000e_init_rx_addrs(hw, rar_count);
/* Zero out the Multicast HASH table */
e_dbg("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
/* Setup link and flow control */
ret_val = mac->ops.setup_link(hw);
/* Clear all of the statistics registers (clear on read). It is *importantthatwedothisafterwehavetriedtoestablishlink *becausethesymbolerrorcountwillincrementwildlyifthere *isnolink.
*/
e1000_clear_hw_cntrs_82571(hw);
switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (hw->mng_cookie.vlan_id != 0) { /* The VFTA is a 4096b bit-field, each identifying *asingleVLANID.Thefollowingoperations *determinewhich32bentry(i.e.offset)intothe *arraywewanttosettheVLANID(i.e.bit)of *themanageabilityunit.
*/
vfta_offset = (hw->mng_cookie.vlan_id >>
E1000_VFTA_ENTRY_SHIFT) &
E1000_VFTA_ENTRY_MASK;
vfta_bit_in_reg =
BIT(hw->mng_cookie.vlan_id &
E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
} break; default: break;
} for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { /* If the offset we want to clear is the same offset of the *manageabilityVLANID,thenclearallbitsexceptthatof *themanageabilityunit.
*/
vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
e1e_flush();
}
}
ctrl = hw->mac.ledctl_mode2; if (!(E1000_STATUS_LU & er32(STATUS))) { /* If no link, then turn LED on by setting the invert bit *foreachLEDthat's"on"(0x0E)inledctl_mode2.
*/ for (i = 0; i < 4; i++) if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
E1000_LEDCTL_MODE_LED_ON)
ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
}
ew32(LEDCTL, ctrl);
/* Read PHY Receive Error counter first, if its is max - all F's then *readtheBase1000TstatusregisterIfbotharemaxthenPHYishung.
*/
ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); if (ret_val) returnfalse; if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); if (ret_val) returnfalse; if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
E1000_IDLE_ERROR_COUNT_MASK) returntrue;
}
returnfalse;
}
/** *e1000_setup_link_82571-Setupflowcontrolandlinksettings *@hw:pointertotheHWstructure * *Determineswhichflowcontrolsettingstouse,thenconfiguresflow *control.Callstheappropriatemedia-specificlinkconfiguration *function.Assumingtheadapterhasavalidlinkpartner,avalidlink *shouldbeestablished.Assumesthehardwarehaspreviouslybeenreset *andthetransmitterandreceiverarenotenabled.
**/ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
{ /* 82573 does not have a word in the NVM to determine *thedefaultflowcontrolsetting,soweexplicitly *setittofull.
*/ switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (hw->fc.requested_mode == e1000_fc_default)
hw->fc.requested_mode = e1000_fc_full; break; default: break;
}
ctrl = er32(CTRL);
status = er32(STATUS);
er32(RXCW); /* SYNCH bit and IV bit are sticky */
usleep_range(10, 20);
rxcw = er32(RXCW);
if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { /* Receiver is synchronized with no invalid bits. */ switch (mac->serdes_link_state) { case e1000_serdes_link_autoneg_complete: if (!(status & E1000_STATUS_LU)) { /* We have lost link, retry autoneg before *reportinglinkfailure
*/
mac->serdes_link_state =
e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = false;
e_dbg("AN_UP -> AN_PROG\n");
} else {
mac->serdes_has_link = true;
} break;
case e1000_serdes_link_forced_up: /* If we are receiving /C/ ordered sets, re-enable *auto-negotiationintheTXCWregisteranddisable *forcedlinkintheDeviceControlregisterinan *attempttoauto-negotiatewithourlinkpartner.
*/ if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */
ew32(TXCW, mac->txcw);
ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
mac->serdes_link_state =
e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = false;
e_dbg("FORCED_UP -> AN_PROG\n");
} else {
mac->serdes_has_link = true;
} break;
case e1000_serdes_link_autoneg_progress: if (rxcw & E1000_RXCW_C) { /* We received /C/ ordered sets, meaning the *linkpartnerhasautonegotiated,andwecan *trusttheLinkUp(LU)statusbit.
*/ if (status & E1000_STATUS_LU) {
mac->serdes_link_state =
e1000_serdes_link_autoneg_complete;
e_dbg("AN_PROG -> AN_UP\n");
mac->serdes_has_link = true;
} else { /* Autoneg completed, but failed. */
mac->serdes_link_state =
e1000_serdes_link_down;
e_dbg("AN_PROG -> DOWN\n");
}
} else { /* The link partner did not autoneg. *Forcelinkupandfullduplex,andchange *statetoforced.
*/
ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
ew32(CTRL, ctrl);
/* Configure Flow Control after link up. */
ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val) {
e_dbg("Error config flow control\n"); break;
}
mac->serdes_link_state =
e1000_serdes_link_forced_up;
mac->serdes_has_link = true;
e_dbg("AN_PROG -> FORCED_UP\n");
} break;
case e1000_serdes_link_down: default: /* The link was down but the receiver has now gained *validsync,soletsseeifwecanbringthelink *up.
*/
ew32(TXCW, mac->txcw);
ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
mac->serdes_link_state =
e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = false;
e_dbg("DOWN -> AN_PROG\n"); break;
}
} else { if (!(rxcw & E1000_RXCW_SYNCH)) {
mac->serdes_has_link = false;
mac->serdes_link_state = e1000_serdes_link_down;
e_dbg("ANYSTATE -> DOWN\n");
} else { /* Check several times, if SYNCH bit and CONFIG *bitbothareconsistently1thensimplyignore *theIVbitandrestartAutoneg
*/ for (i = 0; i < AN_RETRY_COUNT; i++) {
usleep_range(10, 20);
rxcw = er32(RXCW); if ((rxcw & E1000_RXCW_SYNCH) &&
(rxcw & E1000_RXCW_C)) continue;
/* If workaround is activated... */ if (state) /* Hold a copy of the LAA in RAR[14] This is done so that *betweenthetimeRAR[0]getsclobberedandthetimeit *getsfixed,theactualLAAisinoneoftheRARsandno *incomingpacketsdirectedtothisportaredropped. *EventuallytheLAAwillbeinRAR[0]andRAR[14].
*/
hw->mac.ops.rar_set(hw, hw->mac.addr,
hw->mac.rar_entry_count - 1);
}
/* Check bit 4 of word 10h. If it is 0, firmware is done updating *10h-12h.Checksummayneedtobefixed.
*/
ret_val = e1000_read_nvm(hw, 0x10, 1, &data); if (ret_val) return ret_val;
if (!(data & 0x10)) { /* Read 0x23 and check bit 15. This bit is a 1 *whenthechecksumhasalreadybeenfixed.If *thechecksumisstillwrongandthisbitisa *1,weneedtoreturnbadchecksum.Otherwise, *weneedtosetthisbittoa1andupdatethe *checksum.
*/
ret_val = e1000_read_nvm(hw, 0x23, 1, &data); if (ret_val) return ret_val;
if (!(data & 0x8000)) {
data |= 0x8000;
ret_val = e1000_write_nvm(hw, 0x23, 1, &data); if (ret_val) return ret_val;
ret_val = e1000e_update_nvm_checksum(hw); if (ret_val) return ret_val;
}
}
/* If there's an alternate MAC address place it in RAR0 *sothatitwilloverridetheSiinstalleddefaultperm *address.
*/
ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) return ret_val;
}
/* If the management interface is not enabled, then power down */ if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
e1000_power_down_phy_copper(hw);
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.51Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-03)
¤
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.