diff --git a/Changelog.md b/Changelog.md index d5e00e5..0b807ad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,10 @@ IntelMausi Changelog * I219-V18 * I219-LM19 * I219-V19 +- Fixed WoL on I219 family devices +- Use Random RSS key hash generation instead of static +- Fix IRQ mask for Cannon-Point devices +- Adjusted debug log #### v1.0.4 - Added MacKernelSDK with Xcode 12 compatibility diff --git a/IntelMausiEthernet/IntelMausiEthernet.cpp b/IntelMausiEthernet/IntelMausiEthernet.cpp index 100feff..a1ecb96 100644 --- a/IntelMausiEthernet/IntelMausiEthernet.cpp +++ b/IntelMausiEthernet/IntelMausiEthernet.cpp @@ -26,48 +26,48 @@ static const struct intelDevice deviceTable[] = { { .pciDevId = E1000_DEV_ID_ICH8_IFE, .device = board_ich8lan, .deviceName = "82562V", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IFE_G, .device = board_ich8lan, .deviceName = "82562G", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IFE_GT, .device = board_ich8lan, .deviceName = "82562GT", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IGP_AMT, .device = board_ich8lan, .deviceName = "82566DM", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IGP_C, .device = board_ich8lan, .deviceName = "82566DC", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IGP_M, .device = board_ich8lan, .deviceName = "82566MC", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_IGP_M_AMT, .device = board_ich8lan, .deviceName = "82566MM", .deviceInfo = &e1000_ich8_info }, - { .pciDevId = E1000_DEV_ID_ICH8_82567V_3, .device = board_ich8lan, .deviceName = "82567V3", .deviceInfo = &e1000_ich8_info }, - - { .pciDevId = E1000_DEV_ID_ICH9_IFE, .device = board_ich9lan, .deviceName = "82562V2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IFE_G, .device = board_ich9lan, .deviceName = "82562G2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IFE_GT, .device = board_ich9lan, .deviceName = "82562GT2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IGP_AMT, .device = board_ich9lan, .deviceName = "82566DM2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IGP_C, .device = board_ich9lan, .deviceName = "82566DC2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_BM, .device = board_ich9lan, .deviceName = "82567LM4", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IGP_M, .device = board_ich9lan, .deviceName = "82567LF", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_AMT, .device = board_ich9lan, .deviceName = "82567LM", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_V, .device = board_ich9lan, .deviceName = "82567V", .deviceInfo = &e1000_ich9_info }, - - { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LM, .device = board_ich9lan, .deviceName = "82567LM2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LF, .device = board_ich9lan, .deviceName = "82567LF2", .deviceInfo = &e1000_ich9_info }, - { .pciDevId = E1000_DEV_ID_ICH10_R_BM_V, .device = board_ich9lan, .deviceName = "82567V2", .deviceInfo = &e1000_ich9_info }, - - { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LM, .device = board_ich10lan, .deviceName = "82567LM3", .deviceInfo = &e1000_ich10_info }, - { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LF, .device = board_ich10lan, .deviceName = "82567LF3", .deviceInfo = &e1000_ich10_info }, - { .pciDevId = E1000_DEV_ID_ICH10_D_BM_V, .device = board_ich10lan, .deviceName = "82567V4", .deviceInfo = &e1000_ich10_info }, - - { .pciDevId = E1000_DEV_ID_PCH_M_HV_LM, .device = board_pchlan, .deviceName = "82578LM", .deviceInfo = &e1000_pch_info }, - { .pciDevId = E1000_DEV_ID_PCH_M_HV_LC, .device = board_pchlan, .deviceName = "82578LC", .deviceInfo = &e1000_pch_info }, - { .pciDevId = E1000_DEV_ID_PCH_D_HV_DM, .device = board_pchlan, .deviceName = "82578DM", .deviceInfo = &e1000_pch_info }, - { .pciDevId = E1000_DEV_ID_PCH_D_HV_DC, .device = board_pchlan, .deviceName = "82578DC", .deviceInfo = &e1000_pch_info }, - - { .pciDevId = E1000_DEV_ID_PCH2_LV_LM, .device = board_pch2lan, .deviceName = "82579LM", .deviceInfo = &e1000_pch2_info }, - { .pciDevId = E1000_DEV_ID_PCH2_LV_V, .device = board_pch2lan, .deviceName = "82579V", .deviceInfo = &e1000_pch2_info }, - - { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_LM, .device = board_pch_lpt, .deviceName = "I217LM", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_V, .device = board_pch_lpt, .deviceName = "I217V", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_LM, .device = board_pch_lpt, .deviceName = "I218LM", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_V, .device = board_pch_lpt, .deviceName = "I218V", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_I218_LM2, .device = board_pch_lpt, .deviceName = "I218LM2", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_I218_V2, .device = board_pch_lpt, .deviceName = "I218V2", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_I218_LM3, .device = board_pch_lpt, .deviceName = "I218LM3", .deviceInfo = &e1000_pch_lpt_info }, - { .pciDevId = E1000_DEV_ID_PCH_I218_V3, .device = board_pch_lpt, .deviceName = "I218V3", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IFE_G, .device = board_ich8lan, .deviceName = "82562G", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IFE_GT, .device = board_ich8lan, .deviceName = "82562GT", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IGP_AMT, .device = board_ich8lan, .deviceName = "82566DM", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IGP_C, .device = board_ich8lan, .deviceName = "82566DC", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IGP_M, .device = board_ich8lan, .deviceName = "82566MC", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_IGP_M_AMT, .device = board_ich8lan, .deviceName = "82566MM", .deviceInfo = &e1000_ich8_info }, + { .pciDevId = E1000_DEV_ID_ICH8_82567V_3, .device = board_ich8lan, .deviceName = "82567V3", .deviceInfo = &e1000_ich8_info }, + + { .pciDevId = E1000_DEV_ID_ICH9_IFE, .device = board_ich9lan, .deviceName = "82562V2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IFE_G, .device = board_ich9lan, .deviceName = "82562G2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IFE_GT, .device = board_ich9lan, .deviceName = "82562GT2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IGP_AMT, .device = board_ich9lan, .deviceName = "82566DM2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IGP_C, .device = board_ich9lan, .deviceName = "82566DC2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_BM, .device = board_ich9lan, .deviceName = "82567LM4", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IGP_M, .device = board_ich9lan, .deviceName = "82567LF", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_AMT, .device = board_ich9lan, .deviceName = "82567LM", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_V, .device = board_ich9lan, .deviceName = "82567V", .deviceInfo = &e1000_ich9_info }, + + { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LM, .device = board_ich9lan, .deviceName = "82567LM2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LF, .device = board_ich9lan, .deviceName = "82567LF2", .deviceInfo = &e1000_ich9_info }, + { .pciDevId = E1000_DEV_ID_ICH10_R_BM_V, .device = board_ich9lan, .deviceName = "82567V2", .deviceInfo = &e1000_ich9_info }, + + { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LM, .device = board_ich10lan, .deviceName = "82567LM3", .deviceInfo = &e1000_ich10_info }, + { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LF, .device = board_ich10lan, .deviceName = "82567LF3", .deviceInfo = &e1000_ich10_info }, + { .pciDevId = E1000_DEV_ID_ICH10_D_BM_V, .device = board_ich10lan, .deviceName = "82567V4", .deviceInfo = &e1000_ich10_info }, + + { .pciDevId = E1000_DEV_ID_PCH_M_HV_LM, .device = board_pchlan, .deviceName = "82578LM", .deviceInfo = &e1000_pch_info }, + { .pciDevId = E1000_DEV_ID_PCH_M_HV_LC, .device = board_pchlan, .deviceName = "82578LC", .deviceInfo = &e1000_pch_info }, + { .pciDevId = E1000_DEV_ID_PCH_D_HV_DM, .device = board_pchlan, .deviceName = "82578DM", .deviceInfo = &e1000_pch_info }, + { .pciDevId = E1000_DEV_ID_PCH_D_HV_DC, .device = board_pchlan, .deviceName = "82578DC", .deviceInfo = &e1000_pch_info }, + + { .pciDevId = E1000_DEV_ID_PCH2_LV_LM, .device = board_pch2lan, .deviceName = "82579LM", .deviceInfo = &e1000_pch2_info }, + { .pciDevId = E1000_DEV_ID_PCH2_LV_V, .device = board_pch2lan, .deviceName = "82579V", .deviceInfo = &e1000_pch2_info }, + + { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_LM, .device = board_pch_lpt, .deviceName = "I217LM", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_V, .device = board_pch_lpt, .deviceName = "I217V", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_LM, .device = board_pch_lpt, .deviceName = "I218LM", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_V, .device = board_pch_lpt, .deviceName = "I218V", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_I218_LM2, .device = board_pch_lpt, .deviceName = "I218LM2", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_I218_V2, .device = board_pch_lpt, .deviceName = "I218V2", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_I218_LM3, .device = board_pch_lpt, .deviceName = "I218LM3", .deviceInfo = &e1000_pch_lpt_info }, + { .pciDevId = E1000_DEV_ID_PCH_I218_V3, .device = board_pch_lpt, .deviceName = "I218V3", .deviceInfo = &e1000_pch_lpt_info }, { .pciDevId = E1000_DEV_ID_PCH_SPT_I219_LM, .device = board_pch_spt, .deviceName = "I219LM", .deviceInfo = &e1000_pch_spt_info }, { .pciDevId = E1000_DEV_ID_PCH_SPT_I219_V, .device = board_pch_spt, .deviceName = "I219V", .deviceInfo = &e1000_pch_spt_info }, { .pciDevId = E1000_DEV_ID_PCH_SPT_I219_LM2, .device = board_pch_spt, .deviceName = "I219LM2", .deviceInfo = &e1000_pch_spt_info }, @@ -145,9 +145,9 @@ OSDefineMetaClassAndStructors(IntelMausi, super) bool IntelMausi::init(OSDictionary *properties) { bool result; - + result = super::init(properties); - + if (result) { workLoop = NULL; commandGate = NULL; @@ -190,6 +190,7 @@ bool IntelMausi::init(OSDictionary *properties) pciDeviceData.revision = 0; adapterData.pdev = &pciDeviceData; mtu = ETH_DATA_LEN; + isRssSet = false; wolCapable = false; wolActive = false; enableCSO6 = false; @@ -198,7 +199,7 @@ bool IntelMausi::init(OSDictionary *properties) debugger = NULL; hasDebugger = false; } - + done: return result; } @@ -206,9 +207,9 @@ bool IntelMausi::init(OSDictionary *properties) void IntelMausi::free() { UInt32 i; - - DebugLog("free() ===>\n"); - + + DebugLog("[IntelMausi]: free() ===>\n"); + if (workLoop) { if (interruptSource) { workLoop->removeEventSource(interruptSource); @@ -224,38 +225,38 @@ void IntelMausi::free() RELEASE(commandGate); RELEASE(txQueue); RELEASE(mediumDict); - + for (i = MEDIUM_INDEX_AUTO; i < MEDIUM_INDEX_COUNT; i++) mediumTable[i] = NULL; - + RELEASE(baseMap); baseAddr = NULL; adapterData.hw.hw_addr = NULL; - + RELEASE(flashMap); flashAddr = NULL; adapterData.hw.flash_address = NULL; RELEASE(pciDevice); freeDMADescriptors(); - + if (mcAddrList) { IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress)); mcAddrList = NULL; mcListCount = 0; } - - DebugLog("free() <===\n"); - + + DebugLog("[IntelMausi]: free() <===\n"); + super::free(); } bool IntelMausi::start(IOService *provider) { bool result; - + result = super::start(provider); - + if (!result) { IOLog("[IntelMausi]: IOEthernetController::start failed.\n"); goto done; @@ -264,15 +265,15 @@ bool IntelMausi::start(IOService *provider) promiscusMode = false; mcAddrList = NULL; mcListCount = 0; - + pciDevice = OSDynamicCast(IOPCIDevice, provider); - + if (!pciDevice) { IOLog("[IntelMausi]: No provider.\n"); goto done; } pciDevice->retain(); - + if (!pciDevice->open(this)) { IOLog("[IntelMausi]: Failed to open provider.\n"); goto error1; @@ -281,22 +282,22 @@ bool IntelMausi::start(IOService *provider) goto error2; } getParams(); - + if (!intelStart()) { goto error2; - } + } if (!setupMediumDict()) { IOLog("[IntelMausi]: Failed to setup medium dictionary.\n"); goto error2; } commandGate = getCommandGate(); - + if (!commandGate) { IOLog("[IntelMausi]: getCommandGate() failed.\n"); goto error2; } commandGate->retain(); - + if (!setupDMADescriptors()) { IOLog("[IntelMausi]: Error allocating DMA descriptors.\n"); goto error3; @@ -306,9 +307,9 @@ bool IntelMausi::start(IOService *provider) IOLog("[IntelMausi]: initEventSources() failed.\n"); goto error4; } - + result = attachInterface(reinterpret_cast(&netif)); - + if (!result) { IOLog("[IntelMausi]: attachInterface() failed.\n"); goto error4; @@ -318,16 +319,16 @@ bool IntelMausi::start(IOService *provider) done: return result; - + error4: freeDMADescriptors(); - + error3: RELEASE(commandGate); - + error2: pciDevice->close(this); - + error1: pciDevice->release(); pciDevice = NULL; @@ -337,7 +338,7 @@ bool IntelMausi::start(IOService *provider) void IntelMausi::stop(IOService *provider) { UInt32 i; - + if (netif) { /* * Let the firmware know that the network interface is now closed. @@ -362,12 +363,12 @@ void IntelMausi::stop(IOService *provider) RELEASE(commandGate); RELEASE(txQueue); RELEASE(mediumDict); - + for (i = MEDIUM_INDEX_AUTO; i < MEDIUM_INDEX_COUNT; i++) mediumTable[i] = NULL; - + freeDMADescriptors(); - + if (mcAddrList) { IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress)); mcAddrList = NULL; @@ -376,70 +377,70 @@ void IntelMausi::stop(IOService *provider) RELEASE(baseMap); baseAddr = NULL; adapterData.hw.hw_addr = NULL; - + RELEASE(flashMap); flashAddr = NULL; adapterData.hw.flash_address = NULL; - + RELEASE(pciDevice); - + super::stop(provider); } IOReturn IntelMausi::registerWithPolicyMaker(IOService *policyMaker) { - DebugLog("registerWithPolicyMaker() ===>\n"); - + DebugLog("[IntelMausi]: registerWithPolicyMaker() ===>\n"); + powerState = kPowerStateOn; - - DebugLog("registerWithPolicyMaker() <===\n"); - + + DebugLog("[IntelMausi]: registerWithPolicyMaker() <===\n"); + return policyMaker->registerPowerDriver(this, powerStateArray, kPowerStateCount); } IOReturn IntelMausi::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker) { IOReturn result = IOPMAckImplied; - - DebugLog("setPowerState() ===>\n"); - + + DebugLog("[IntelMausi]: setPowerState() ===>\n"); + if (powerStateOrdinal == powerState) { DebugLog("[IntelMausi]: Already in power state %lu.\n", powerStateOrdinal); goto done; } DebugLog("[IntelMausi]: switching to power state %lu.\n", powerStateOrdinal); - + if (powerStateOrdinal == kPowerStateOff) commandGate->runAction(setPowerStateSleepAction); else commandGate->runAction(setPowerStateWakeAction); - + powerState = powerStateOrdinal; - + done: - DebugLog("setPowerState() <===\n"); - + DebugLog("[IntelMausi]: setPowerState() <===\n"); + return result; } void IntelMausi::systemWillShutdown(IOOptionBits specifier) { - DebugLog("systemWillShutdown() ===>\n"); - + DebugLog("[IntelMausi]: systemWillShutdown() ===>\n"); + if ((kIOMessageSystemWillPowerOff | kIOMessageSystemWillRestart) & specifier) { disable(netif); - + /* Restore the original MAC address. */ adapterData.hw.mac.ops.rar_set(&adapterData.hw, adapterData.hw.mac.perm_addr, 0); - + /* * Let the firmware know that the network interface is now closed */ e1000e_release_hw_control(&adapterData); } - - DebugLog("systemWillShutdown() <===\n"); - + + DebugLog("[IntelMausi]: systemWillShutdown() <===\n"); + /* Must call super on shutdown or system will stall. */ super::systemWillShutdown(specifier); } @@ -564,7 +565,7 @@ void IntelMausi::receivePacket(void *pkt, UInt32 *pktSizeOut, UInt32 timeout) while (!isReceived && costTime < timeout) { while (!isReceived && (OSSwapLittleToHostInt32(desc->wb.upper.status_error) & E1000_RXD_STAT_DD)) { if (!(isEnabled && linkUp) || forceReset) { - DebugLog("[IntelMausi]:receivePacket Interface down. Waiting...\n"); + DebugLog("[IntelMausi]: receivePacket Interface down. Waiting...\n"); break; } @@ -590,13 +591,13 @@ void IntelMausi::receivePacket(void *pkt, UInt32 *pktSizeOut, UInt32 timeout) } if (usedSize != pktSize) { - DebugLog("[IntelMausi]:receivePacket invalid packet %u vs %u in %u chunks.\n", usedSize, pktSize, counter); + DebugLog("[IntelMausi]: receivePacket invalid packet %u vs %u in %u chunks.\n", usedSize, pktSize, counter); } else if (isKdpPacket((UInt8 *)pkt, usedSize)) { *pktSizeOut = usedSize; isReceived = true; } } else { - DebugLog("[IntelMausi]:receivePacket drop out of range packet pktSize %u.\n", pktSize); + DebugLog("[IntelMausi]: receivePacket drop out of range packet pktSize %u.\n", pktSize); } /* Update the descriptor and get the next one to examine. */ @@ -812,9 +813,9 @@ void IntelMausi::sendPacket(void *pkt, UInt32 pktSize) IOReturn IntelMausi::driverEnable() { IOReturn result = kIOReturnError; - - DebugLog("enable() ===>\n"); - + + DebugLog("[IntelMausi]: enable() ===>\n"); + if (isEnabled) { DebugLog("[IntelMausi]: Interface already enabled.\n"); result = kIOReturnSuccess; @@ -825,12 +826,12 @@ IOReturn IntelMausi::driverEnable() goto done; } pciDevice->open(this); - + intelEnable(); - + /* As we are using an msi the interrupt hasn't been enabled by start(). */ interruptSource->enable(); - + rxPacketHead = rxPacketTail = NULL; rxPacketSize = 0; @@ -849,8 +850,8 @@ IOReturn IntelMausi::driverEnable() eeeMode = 0; result = kIOReturnSuccess; - - DebugLog("enable() <===\n"); + + DebugLog("[IntelMausi]: enable() <===\n"); done: return result; @@ -859,12 +860,12 @@ IOReturn IntelMausi::driverEnable() IOReturn IntelMausi::driverDisable() { IOReturn result = kIOReturnSuccess; - - DebugLog("disable() ===>\n"); - + + DebugLog("[IntelMausi]: disable() ===>\n"); + if (!isEnabled) goto done; - + #ifdef __PRIVATE_SPI__ /* Stop output thread and flush txQueue */ netif->stopOutputThread(); @@ -884,12 +885,12 @@ IOReturn IntelMausi::driverDisable() timerSource->cancelTimeout(); txDescDoneCount = txDescDoneLast = 0; - + /* We are using MSI so that we have to disable the interrupt. */ interruptSource->disable(); - + intelDisable(); - + if (mcAddrList) { IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress)); mcAddrList = NULL; @@ -897,9 +898,9 @@ IOReturn IntelMausi::driverDisable() } if (pciDevice && pciDevice->isOpen()) pciDevice->close(this); - - DebugLog("disable() <===\n"); - + + DebugLog("[IntelMausi]: disable() <===\n"); + done: return result; } @@ -930,9 +931,9 @@ IOReturn IntelMausi::outputStart(IONetworkInterface *interface, IOOptionBits opt UInt16 i; UInt16 count; - //DebugLog("outputStart() ===>\n"); + //DebugLog("[IntelMausi]: outputStart() ===>\n"); count = 0; - + if (!(isEnabled && linkUp) || forceReset) { DebugLog("[IntelMausi]: Interface down. Dropping packets.\n"); goto done; @@ -947,48 +948,48 @@ IOReturn IntelMausi::outputStart(IONetworkInterface *interface, IOOptionBits opt ipConfig = 0; tcpConfig = 0; offloadFlags = 0; - + /* First prepare the header and the command bits. */ mbuf_get_csum_requested(m, &offloadFlags, &mss); - + if (offloadFlags & (kChecksumUDPIPv6 | kChecksumTCPIPv6 | kChecksumIP | kChecksumUDP | kChecksumTCP)) { numDescs = 1; cmd = (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); - + if (offloadFlags & kChecksumTCP) { ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart); tcpConfig = ((kTCPv4CSumEnd << 16) | (kTCPv4CSumOffset << 8) | kTCPv4CSumStart); len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP); mss = 0; - + word2 = (E1000_TXD_OPTS_TXSM | E1000_TXD_OPTS_IXSM); } else if (offloadFlags & kChecksumUDP) { ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart); tcpConfig = ((kUDPv4CSumEnd << 16) | (kUDPv4CSumOffset << 8) | kUDPv4CSumStart); len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP); mss = 0; - + word2 = (E1000_TXD_OPTS_TXSM | E1000_TXD_OPTS_IXSM); } else if (offloadFlags & kChecksumIP) { ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart); tcpConfig = 0; mss = 0; len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP); - + word2 = E1000_TXD_OPTS_IXSM; } else if (offloadFlags & kChecksumTCPIPv6) { ipConfig = ((kIPv6CSumEnd << 16) | (kIPv6CSumOffset << 8) | kIPv6CSumStart); tcpConfig = ((kTCPv6CSumEnd << 16) | (kTCPv6CSumOffset << 8) | kTCPv6CSumStart); len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TCP); mss = 0; - + word2 = E1000_TXD_OPTS_TXSM; } else if (offloadFlags & kChecksumUDPIPv6) { ipConfig = ((kIPv6CSumEnd << 16) | (kIPv6CSumOffset << 8) | kIPv6CSumStart); tcpConfig = ((kUDPv6CSumEnd << 16) | (kUDPv6CSumOffset << 8) | kUDPv6CSumStart); len = E1000_TXD_CMD_DEXT; mss = 0; - + word2 = E1000_TXD_OPTS_TXSM; } } @@ -1001,7 +1002,7 @@ IOReturn IntelMausi::outputStart(IONetworkInterface *interface, IOOptionBits opt /* Finally get the physical segments. */ numSegs = txMbufCursor->getPhysicalSegmentsWithCoalesce(m, &txSegments[0], kMaxSegs); numDescs += numSegs; - + if (!numSegs) { DebugLog("[IntelMausi]: getPhysicalSegmentsWithCoalesce() failed. Dropping packet.\n"); etherStats->dot3TxExtraEntry.resourceErrors++; @@ -1012,30 +1013,30 @@ IOReturn IntelMausi::outputStart(IONetworkInterface *interface, IOOptionBits opt index = txNextDescIndex; txNextDescIndex = (txNextDescIndex + numDescs) & kTxDescMask; lastSeg = numSegs - 1; - + /* Setup the context descriptor for checksum offload. */ if (offloadFlags) { contDesc = (struct e1000_context_desc *)&txDescArray[index]; - + txBufArray[index].mbuf = NULL; txBufArray[index].numDescs = 0; - + #ifdef DEBUG txBufArray[index].pad = numSegs; #endif - + contDesc->lower_setup.ip_config = OSSwapHostToLittleInt32(ipConfig); contDesc->upper_setup.tcp_config = OSSwapHostToLittleInt32(tcpConfig); contDesc->cmd_and_length = OSSwapHostToLittleInt32(len); contDesc->tcp_seg_setup.data = OSSwapHostToLittleInt32(mss); - + ++index &= kTxDescMask; } /* And finally fill in the data descriptors. */ for (i = 0; i < numSegs; i++) { desc = &txDescArray[index]; word1 = (cmd | (txSegments[i].length & 0x000fffff)); - + if (i == lastSeg) { word1 |= opts; txBufArray[index].mbuf = m; @@ -1044,26 +1045,26 @@ IOReturn IntelMausi::outputStart(IONetworkInterface *interface, IOOptionBits opt txBufArray[index].mbuf = NULL; txBufArray[index].numDescs = 0; } - + #ifdef DEBUG txBufArray[index].pad = (UInt32)txSegments[i].length; #endif - + desc->buffer_addr = OSSwapHostToLittleInt64(txSegments[i].location); desc->lower.data = OSSwapHostToLittleInt32(word1); desc->upper.data = OSSwapHostToLittleInt32(word2); - + ++index &= kTxDescMask; } count++; } if (count) intelUpdateTxDescTail(txNextDescIndex); - + result = (txNumFreeDesc >= (kMaxSegs + kTxSpareDescs)) ? kIOReturnSuccess : kIOReturnNoResources; - - //DebugLog("outputStart() <===\n"); - + + //DebugLog("[IntelMausi]: outputStart() <===\n"); + done: return result; } @@ -1092,7 +1093,7 @@ UInt32 IntelMausi::outputPacket(mbuf_t m, void *param) UInt16 vlanTag; UInt16 i; - //DebugLog("outputPacket() ===>\n"); + //DebugLog("[IntelMausi]: outputPacket() ===>\n"); if (!(isEnabled && linkUp) || forceReset) { DebugLog("[IntelMausi]: Interface down. Dropping packet.\n"); @@ -1249,7 +1250,7 @@ UInt32 IntelMausi::outputPacket(mbuf_t m, void *param) result = kIOReturnOutputSuccess; done: - //DebugLog("outputPacket() <===\n"); + //DebugLog("[IntelMausi]: outputPacket() <===\n"); return result; @@ -1262,37 +1263,37 @@ UInt32 IntelMausi::outputPacket(mbuf_t m, void *param) void IntelMausi::getPacketBufferConstraints(IOPacketBufferConstraints *constraints) const { - DebugLog("getPacketBufferConstraints() ===>\n"); - - constraints->alignStart = kIOPacketBufferAlign1; - constraints->alignLength = kIOPacketBufferAlign1; - - DebugLog("getPacketBufferConstraints() <===\n"); + DebugLog("[IntelMausi]: getPacketBufferConstraints() ===>\n"); + + constraints->alignStart = kIOPacketBufferAlign1; + constraints->alignLength = kIOPacketBufferAlign1; + + DebugLog("[IntelMausi]: getPacketBufferConstraints() <===\n"); } IOOutputQueue* IntelMausi::createOutputQueue() { - DebugLog("createOutputQueue() ===>\n"); - - DebugLog("createOutputQueue() <===\n"); - + DebugLog("[IntelMausi]: createOutputQueue() ===>\n"); + + DebugLog("[IntelMausi]: createOutputQueue() <===\n"); + return IOBasicOutputQueue::withTarget(this); } const OSString* IntelMausi::newVendorString() const { - DebugLog("newVendorString() ===>\n"); - - DebugLog("newVendorString() <===\n"); - + DebugLog("[IntelMausi]: newVendorString() ===>\n"); + + DebugLog("[IntelMausi]: newVendorString() <===\n"); + return OSString::withCString("Intel"); } const OSString* IntelMausi::newModelString() const { - DebugLog("newModelString() ===>\n"); - DebugLog("newModelString() <===\n"); - + DebugLog("[IntelMausi]: newModelString() ===>\n"); + DebugLog("[IntelMausi]: newModelString() <===\n"); + return OSString::withCString(deviceTable[chip].deviceName); } @@ -1305,20 +1306,20 @@ bool IntelMausi::configureInterface(IONetworkInterface *interface) #endif /* __PRIVATE_SPI__ */ bool result; - - DebugLog("configureInterface() ===>\n"); - + + DebugLog("[IntelMausi]: configureInterface() ===>\n"); + result = super::configureInterface(interface); - + if (!result) goto done; - + /* Get the generic network statistics structure. */ data = interface->getParameter(kIONetworkStatsKey); - + if (data) { netStats = (IONetworkStats *)data->getBuffer(); - + if (!netStats) { IOLog("[IntelMausi]: Error getting IONetworkStats\n."); result = false; @@ -1327,10 +1328,10 @@ bool IntelMausi::configureInterface(IONetworkInterface *interface) } /* Get the Ethernet statistics structure. */ data = interface->getParameter(kIOEthernetStatsKey); - + if (data) { etherStats = (IOEthernetStats *)data->getBuffer(); - + if (!etherStats) { IOLog("[IntelMausi]: Error getting IOEthernetStats\n."); result = false; @@ -1340,14 +1341,14 @@ bool IntelMausi::configureInterface(IONetworkInterface *interface) #ifdef __PRIVATE_SPI__ error = interface->configureOutputPullModel(384, 0, 0, IONetworkInterface::kOutputPacketSchedulingModelNormal); - + if (error != kIOReturnSuccess) { IOLog("[IntelMausi]: configureOutputPullModel() failed\n."); result = false; goto done; } error = interface->configureInputPacketPolling(kNumRxDesc, kIONetworkWorkLoopSynchronous); - + if (error != kIOReturnSuccess) { IOLog("[IntelMausi]: configureInputPacketPolling() failed\n."); result = false; @@ -1357,30 +1358,30 @@ bool IntelMausi::configureInterface(IONetworkInterface *interface) snprintf(modelName, kNameLenght, "Intel %s PCI Express Gigabit Ethernet", deviceTable[chip].deviceName); setProperty("model", modelName); - + done: - DebugLog("configureInterface() <===\n"); + DebugLog("[IntelMausi]: configureInterface() <===\n"); return result; } bool IntelMausi::createWorkLoop() { - DebugLog("createWorkLoop() ===>\n"); - + DebugLog("[IntelMausi]: createWorkLoop() ===>\n"); + workLoop = IOWorkLoop::workLoop(); - - DebugLog("createWorkLoop() <===\n"); - + + DebugLog("[IntelMausi]: createWorkLoop() <===\n"); + return workLoop ? true : false; } IOWorkLoop* IntelMausi::getWorkLoop() const { - DebugLog("getWorkLoop() ===>\n"); - - DebugLog("getWorkLoop() <===\n"); - + DebugLog("[IntelMausi]: getWorkLoop() ===>\n"); + + DebugLog("[IntelMausi]: getWorkLoop() <===\n"); + return workLoop; } @@ -1388,9 +1389,9 @@ IOReturn IntelMausi::setPromiscuousMode(bool active) { struct e1000_hw *hw = &adapterData.hw; UInt32 rxControl; - - DebugLog("setPromiscuousMode() ===>\n"); - + + DebugLog("[IntelMausi]: setPromiscuousMode() ===>\n"); + rxControl = intelReadMem32(E1000_RCTL); rxControl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); @@ -1404,8 +1405,8 @@ IOReturn IntelMausi::setPromiscuousMode(bool active) intelWriteMem32(E1000_RCTL, rxControl); promiscusMode = active; - DebugLog("setPromiscuousMode() <===\n"); - + DebugLog("[IntelMausi]: setPromiscuousMode() <===\n"); + return kIOReturnSuccess; } @@ -1414,11 +1415,11 @@ IOReturn IntelMausi::setMulticastMode(bool active) struct e1000_hw *hw = &adapterData.hw; UInt32 rxControl; - DebugLog("setMulticastMode() ===>\n"); + DebugLog("[IntelMausi]: setMulticastMode() ===>\n"); rxControl = intelReadMem32(E1000_RCTL); rxControl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); - + if (active) hw->mac.ops.update_mc_addr_list(hw, (UInt8 *)mcAddrList, mcListCount); else @@ -1427,8 +1428,8 @@ IOReturn IntelMausi::setMulticastMode(bool active) intelWriteMem32(E1000_RCTL, rxControl); multicastMode = active; - DebugLog("setMulticastMode() <===\n"); - + DebugLog("[IntelMausi]: setMulticastMode() <===\n"); + return kIOReturnSuccess; } @@ -1439,12 +1440,12 @@ IOReturn IntelMausi::setMulticastList(IOEthernetAddress *addrs, UInt32 count) vm_size_t newSize; IOReturn result = kIOReturnNoMemory; - DebugLog("setMulticastList() ===>\n"); + DebugLog("[IntelMausi]: setMulticastList() ===>\n"); if (count) { newSize = count * sizeof(IOEthernetAddress); newList = (IOEthernetAddress *)IOMalloc(newSize); - + if (newList) { if (mcAddrList) IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress)); @@ -1467,21 +1468,21 @@ IOReturn IntelMausi::setMulticastList(IOEthernetAddress *addrs, UInt32 count) result = kIOReturnSuccess; } - DebugLog("setMulticastList() <===\n"); - + DebugLog("[IntelMausi]: setMulticastList() <===\n"); + return result; } IOReturn IntelMausi::getChecksumSupport(UInt32 *checksumMask, UInt32 checksumFamily, bool isOutput) { IOReturn result = kIOReturnUnsupported; - - DebugLog("getChecksumSupport() ===>\n"); - + + DebugLog("[IntelMausi]: getChecksumSupport() ===>\n"); + if ((checksumFamily == kChecksumFamilyTCPIP) && checksumMask) { if (isOutput) { *checksumMask = (kChecksumTCP | kChecksumUDP | kChecksumIP); - + if (enableCSO6) *checksumMask |= (kChecksumTCPIPv6 | kChecksumUDPIPv6); } else { @@ -1489,61 +1490,61 @@ IOReturn IntelMausi::getChecksumSupport(UInt32 *checksumMask, UInt32 checksumFam } result = kIOReturnSuccess; } - DebugLog("getChecksumSupport() <===\n"); - + DebugLog("[IntelMausi]: getChecksumSupport() <===\n"); + return result; } UInt32 IntelMausi::getFeatures() const { UInt32 features = (kIONetworkFeatureMultiPages | kIONetworkFeatureHardwareVlan); - - DebugLog("getFeatures() ===>\n"); - - DebugLog("getFeatures() <===\n"); - + + DebugLog("[IntelMausi]: getFeatures() ===>\n"); + + DebugLog("[IntelMausi]: getFeatures() <===\n"); + return features; } IOReturn IntelMausi::setWakeOnMagicPacket(bool active) { IOReturn result = kIOReturnUnsupported; - - DebugLog("setWakeOnMagicPacket() ===>\n"); - + + DebugLog("[IntelMausi]: setWakeOnMagicPacket() ===>\n"); + if (wolCapable) { wolActive = active; DebugLog("[IntelMausi]: Wake on magic packet %s.\n", active ? "enabled" : "disabled"); result = kIOReturnSuccess; } - - DebugLog("setWakeOnMagicPacket() <===\n"); - + + DebugLog("[IntelMausi]: setWakeOnMagicPacket() <===\n"); + return result; } IOReturn IntelMausi::getPacketFilters(const OSSymbol *group, UInt32 *filters) const { IOReturn result = kIOReturnSuccess; - - DebugLog("getPacketFilters() ===>\n"); - + + DebugLog("[IntelMausi]: getPacketFilters() ===>\n"); + if ((group == gIOEthernetWakeOnLANFilterGroup) && wolCapable) { if (enableWoM) { *filters = (kIOEthernetWakeOnMagicPacket | kIOEthernetWakeOnPacketAddressMatch); - + DebugLog("[IntelMausi]: kIOEthernetWakeOnMagicPacket and kIOEthernetWakeOnPacketAddressMatch added to filters.\n"); } else { *filters = kIOEthernetWakeOnMagicPacket; - + DebugLog("[IntelMausi]: kIOEthernetWakeOnMagicPacket added to filters.\n"); } } else { result = super::getPacketFilters(group, filters); } - - DebugLog("getPacketFilters() <===\n"); - + + DebugLog("[IntelMausi]: getPacketFilters() <===\n"); + return result; } @@ -1551,19 +1552,19 @@ IOReturn IntelMausi::setHardwareAddress(const IOEthernetAddress *addr) { struct e1000_hw *hw = &adapterData.hw; IOReturn result = kIOReturnError; - - DebugLog("setHardwareAddress() ===>\n"); - + + DebugLog("[IntelMausi]: setHardwareAddress() ===>\n"); + if (addr && is_valid_ether_addr(&addr->bytes[0])) { memcpy(hw->mac.addr, &addr->bytes[0], kIOEthernetAddressSize); - + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - + result = kIOReturnSuccess; } - - DebugLog("setHardwareAddress() <===\n"); - + + DebugLog("[IntelMausi]: setHardwareAddress() <===\n"); + return result; } @@ -1571,78 +1572,78 @@ IOReturn IntelMausi::setHardwareAddress(const IOEthernetAddress *addr) IOReturn IntelMausi::getHardwareAddress(IOEthernetAddress *addr) { IOReturn result = kIOReturnError; - - DebugLog("getHardwareAddress() ===>\n"); - + + DebugLog("[IntelMausi]: getHardwareAddress() ===>\n"); + //IOLog("[IntelMausi]: RAH = 0x%x, RAL = 0x%x\n", intelReadMem32(E1000_RAH(0)), intelReadMem32(E1000_RAL(0))); - + if (addr) { memcpy(&addr->bytes[0], adapterData.hw.mac.addr, kIOEthernetAddressSize); - + if (is_valid_ether_addr(&addr->bytes[0])) result = kIOReturnSuccess; } - - DebugLog("getHardwareAddress() <===\n"); - + + DebugLog("[IntelMausi]: getHardwareAddress() <===\n"); + return result; } IOReturn IntelMausi::selectMedium(const IONetworkMedium *medium) { IOReturn result = kIOReturnSuccess; - - DebugLog("selectMedium() ===>\n"); + + DebugLog("[IntelMausi]: selectMedium() ===>\n"); if (medium) { intelSetupAdvForMedium(medium); setCurrentMedium(medium); - + timerSource->cancelTimeout(); updateStatistics(&adapterData); intelRestart(); } - DebugLog("selectMedium() <===\n"); - + DebugLog("[IntelMausi]: selectMedium() <===\n"); + done: return result; } IOReturn IntelMausi::getMaxPacketSize(UInt32 * maxSize) const { - DebugLog("getMaxPacketSize() ===>\n"); - + DebugLog("[IntelMausi]: getMaxPacketSize() ===>\n"); + *maxSize = kMaxPacketSize; - - DebugLog("getMaxPacketSize() <===\n"); - + + DebugLog("[IntelMausi]: getMaxPacketSize() <===\n"); + return kIOReturnSuccess; } IOReturn IntelMausi::setMaxPacketSize(UInt32 maxSize) { IOReturn result = kIOReturnError; - - DebugLog("setMaxPacketSize() ===>\n"); - + + DebugLog("[IntelMausi]: setMaxPacketSize() ===>\n"); + if (maxSize <= kMaxPacketSize) { mtu = maxSize - (ETH_HLEN + ETH_FCS_LEN); adapterData.max_frame_size = maxSize; DebugLog("[IntelMausi]: maxSize: %u, mtu: %u\n", maxSize, mtu); - + /* Force reinitialization. */ setLinkDown(); timerSource->cancelTimeout(); updateStatistics(&adapterData); intelRestart(); - + result = kIOReturnSuccess; } - - DebugLog("setMaxPacketSize() <===\n"); - + + DebugLog("[IntelMausi]: setMaxPacketSize() <===\n"); + return result; } @@ -1652,21 +1653,21 @@ void IntelMausi::txInterrupt(IOOptionBits options) { UInt32 descStatus; SInt32 cleaned; - + while (txDirtyIndex != txCleanBarrierIndex) { if (txBufArray[txDirtyIndex].mbuf) { descStatus = OSSwapLittleToHostInt32(txDescArray[txDirtyIndex].upper.data); - + if (!(descStatus & E1000_TXD_STAT_DD)) goto done; - + /* First free the attached mbuf and clean up the buffer info. */ freePacketEx(txBufArray[txDirtyIndex].mbuf, options); txBufArray[txDirtyIndex].mbuf = NULL; - + cleaned = txBufArray[txDirtyIndex].numDescs; txBufArray[txDirtyIndex].numDescs = 0; - + /* Finally update the number of free descriptors. */ OSAddAtomic(cleaned, &txNumFreeDesc); txDescDoneCount += cleaned; @@ -1676,7 +1677,7 @@ void IntelMausi::txInterrupt(IOOptionBits options) } //DebugLog("[IntelMausi]: txInterrupt oldIndex=%u newIndex=%u\n", oldDirtyIndex, txDirtyDescIndex); - + done: #ifdef __PRIVATE_SPI__ if (txNumFreeDesc > kTxQueueWakeTreshhold) @@ -1716,7 +1717,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, bufPkt = rxBufArray[rxNextDescIndex].mbuf; pktSize = OSSwapLittleToHostInt16(desc->wb.upper.length); vlanTag = (status & E1000_RXD_STAT_VP) ? (OSSwapLittleToHostInt16(desc->wb.upper.vlan) & E1000_RXD_SPC_VLAN_MASK) : 0; - + /* Skip bad packet. */ if (status & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { DebugLog("[IntelMausi]: Bad packet.\n"); @@ -1725,7 +1726,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, goto nextDesc; } newPkt = replaceOrCopyPacket(&bufPkt, pktSize, &replaced); - + if (!newPkt) { /* Allocation of a new packet failed so that we must leave the original packet in place. */ //DebugLog("[IntelMausi]: replaceOrCopyPacket() failed.\n"); @@ -1733,7 +1734,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, discardPacketFragment(true); goto nextDesc; } - + /* If the packet was replaced we have to update the descriptor's buffer address. */ if (replaced) { n = rxMbufCursor->getPhysicalSegments(bufPkt, &rxSegment, 1); @@ -1757,7 +1758,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, /* This is the last buffer of a jumbo frame. */ mbuf_setflags_mask(newPkt, 0, MBUF_PKTHDR); mbuf_setnext(rxPacketTail, newPkt); - + rxPacketSize += pktSize; rxPacketTail = newPkt; } else { @@ -1776,7 +1777,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, mbuf_pkthdr_setlen(rxPacketHead, rxPacketSize); interface->enqueueInputPacket(rxPacketHead, pollQueue); - + rxPacketHead = rxPacketTail = NULL; rxPacketSize = 0; @@ -1795,12 +1796,12 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, rxPacketSize = pktSize; } } - + /* Finally update the descriptor and get the next one to examine. */ nextDesc: desc->read.buffer_addr = OSSwapHostToLittleInt64(addr); desc->read.reserved = 0; - + ++rxNextDescIndex &= kRxDescMask; desc = &rxDescArray[rxNextDescIndex]; rxCleanedCount++; @@ -1814,7 +1815,7 @@ UInt32 IntelMausi::rxInterrupt(IONetworkInterface *interface, uint32_t maxCount, intelUpdateRxDescTail((rxNextDescIndex - 1) & kRxDescMask); else intelWriteMem32(E1000_RDT(0), (rxNextDescIndex - 1) & kRxDescMask); - + rxCleanedCount = 0; } return goodPkts; @@ -1915,9 +1916,9 @@ void IntelMausi::rxInterrupt() void IntelMausi::checkLinkStatus() { - struct e1000_hw *hw = &adapterData.hw; + struct e1000_hw *hw = &adapterData.hw; bool link; - + hw->mac.get_link_status = true; /* ICH8 workaround-- Call gig speed drop workaround on cable @@ -1929,7 +1930,7 @@ void IntelMausi::checkLinkStatus() } /* Now check the link state. */ link = intelCheckLink(&adapterData); - + DebugLog("[IntelMausi]: checkLinkStatus() returned %u.\n", link); if (linkUp) { @@ -1961,7 +1962,7 @@ void IntelMausi::checkLinkStatus() void IntelMausi::interruptOccurred(OSObject *client, IOInterruptEventSource *src, int count) { - struct e1000_hw *hw = &adapterData.hw; + struct e1000_hw *hw = &adapterData.hw; UInt32 icr = intelReadMem32(E1000_ICR); /* read ICR disables interrupts using IAM */ #ifdef __PRIVATE_SPI__ @@ -1992,7 +1993,7 @@ void IntelMausi::interruptOccurred(OSObject *client, IOInterruptEventSource *src } #endif /* __PRIVATE_SPI__ */ - /* Reset on uncorrectable ECC error */ + /* Reset on uncorrectable ECC error */ if ((icr & E1000_ICR_ECCER) && (hw->mac.type >= e1000_pch_lpt)) { UInt32 pbeccsts = intelReadMem32(E1000_PBECCSTS); @@ -2000,12 +2001,12 @@ void IntelMausi::interruptOccurred(OSObject *client, IOInterruptEventSource *src etherStats->dot3TxExtraEntry.resets++; IOLog("[IntelMausi]: Uncorrectable ECC error. Reseting chip.\n"); - intelRestart(); + intelRestart(); return; - } - if (icr & (E1000_ICR_LSC | E1000_IMS_RXSEQ)) { + } + if (icr & (E1000_ICR_LSC | E1000_IMS_RXSEQ)) { checkLinkStatus(); - } + } /* Reenable interrupts by setting the bits in the mask register. */ intelWriteMem32(E1000_IMS, icr); } @@ -2016,36 +2017,36 @@ void IntelMausi::interruptOccurred(OSObject *client, IOInterruptEventSource *src IOReturn IntelMausi::setInputPacketPollingEnable(IONetworkInterface *interface, bool enabled) { - //DebugLog("setInputPacketPollingEnable() ===>\n"); - + //DebugLog("[IntelMausi]: setInputPacketPollingEnable() ===>\n"); + if (isEnabled) { if (enabled) { intelWriteMem32(E1000_IMC, ~(E1000_ICR_LSC | E1000_IMS_RXSEQ)); intelFlush(); } else { - intelEnableIRQ(intrMask); + intelEnableIRQ(&adapterData); } polling = enabled; } - //DebugLog("input polling %s.\n", enabled ? "enabled" : "disabled"); - - //DebugLog("setInputPacketPollingEnable() <===\n"); - + //DebugLog("[IntelMausi]: input polling %s.\n", enabled ? "enabled" : "disabled"); + + //DebugLog("[IntelMausi]: setInputPacketPollingEnable() <===\n"); + return kIOReturnSuccess; } void IntelMausi::pollInputPackets(IONetworkInterface *interface, uint32_t maxCount, IOMbufQueue *pollQueue, void *context ) { - //DebugLog("pollInputPackets() ===>\n"); - + //DebugLog("[IntelMausi]: pollInputPackets() ===>\n"); + if (polling) { rxInterrupt(interface, maxCount, pollQueue, context); - + /* Finally cleanup the transmitter ring. */ txInterrupt(); } - - //DebugLog("pollInputPackets() <===\n"); + + //DebugLog("[IntelMausi]: pollInputPackets() <===\n"); } #endif /* __PRIVATE_SPI__ */ @@ -2055,7 +2056,7 @@ void IntelMausi::pollInputPackets(IONetworkInterface *interface, uint32_t maxCou void IntelMausi::setLinkUp() { struct e1000_hw *hw = &adapterData.hw; - struct e1000_phy_info *phy = &hw->phy; + struct e1000_phy_info *phy = &hw->phy; const char *flowName; const char *speedName; const char *duplexName; @@ -2065,20 +2066,20 @@ void IntelMausi::setLinkUp() UInt32 fcIndex; UInt32 tctl, rctl, ctrl; UInt32 rate; - + eeeMode = 0; eeeName = eeeNames[kEEETypeNo]; - + /* update snapshot of PHY registers on LSC */ intelPhyReadStatus(&adapterData); hw->mac.ops.get_link_up_info(hw, &adapterData.link_speed, &adapterData.link_duplex); - + /* check if SmartSpeed worked */ e1000e_check_downshift(hw); - + if (phy->speed_downgraded) IOLog("[IntelMausi]: Link Speed was downgraded by SmartSpeed\n"); - + /* On supported PHYs, check for duplex mismatch only * if link has autonegotiated at 10/100 half */ @@ -2086,29 +2087,29 @@ void IntelMausi::setLinkUp() hw->mac.autoneg && (adapterData.link_speed == SPEED_10 || adapterData.link_speed == SPEED_100) && (adapterData.link_duplex == HALF_DUPLEX)) { UInt16 autoneg_exp; - + e1e_rphy(hw, MII_EXPANSION, &autoneg_exp); - + if (!(autoneg_exp & EXPANSION_NWAY)) IOLog("[IntelMausi]: Autonegotiated half duplex but link partner cannot autoneg. Try forcing full duplex if link gets many collisions.\n"); } - + /* Get link speed, duplex and flow-control mode. */ ctrl = intelReadMem32(E1000_CTRL) & (E1000_CTRL_RFCE | E1000_CTRL_TFCE); - + switch (ctrl) { case (E1000_CTRL_RFCE | E1000_CTRL_TFCE): fcIndex = kFlowControlTypeRxTx; break; - + case E1000_CTRL_RFCE: fcIndex = kFlowControlTypeRx; break; - + case E1000_CTRL_TFCE: fcIndex = kFlowControlTypeTx; break; - + default: fcIndex = kFlowControlTypeNone; break; @@ -2211,7 +2212,7 @@ void IntelMausi::setLinkUp() if (phy->ops.cfg_on_link_up) phy->ops.cfg_on_link_up(hw); - intelEnableIRQ(intrMask); + intelEnableIRQ(&adapterData); linkUp = true; @@ -2263,7 +2264,7 @@ void IntelMausi::setLinkUp() if (chipType >= board_pch_lpt) setMaxLatency(adapterData.link_speed); - + DebugLog("[IntelMausi]: CTRL=0x%08x\n", intelReadMem32(E1000_CTRL)); DebugLog("[IntelMausi]: CTRL_EXT=0x%08x\n", intelReadMem32(E1000_CTRL_EXT)); DebugLog("[IntelMausi]: STATUS=0x%08x\n", intelReadMem32(E1000_STATUS)); @@ -2290,12 +2291,14 @@ void IntelMausi::setLinkUp() DebugLog("[IntelMausi]: MANC=0x%08x\n", intelReadMem32(E1000_MANC)); DebugLog("[IntelMausi]: MANC2H=0x%08x\n", intelReadMem32(E1000_MANC2H)); DebugLog("[IntelMausi]: LTRV=0x%08x\n", intelReadMem32(E1000_LTRV)); + DebugLog("[IntelMausi]: wolCapable=%u", wolCapable); + DebugLog("[IntelMausi]: wolActive=%u", wolActive); } void IntelMausi::setLinkDown() { deadlockWarn = 0; - + #ifdef __PRIVATE_SPI__ /* Stop output thread and flush output queue. */ netif->stopOutputThread(); @@ -2305,15 +2308,15 @@ void IntelMausi::setLinkDown() txQueue->stop(); txQueue->flush(); #endif /* __PRIVATE_SPI__ */ - + /* Update link status. */ linkUp = false; setLinkStatus(kIONetworkLinkValid); - + intelDown(&adapterData, true); intelConfigure(&adapterData); clear_bit(__E1000_DOWN, &adapterData.state); - intelEnableIRQ(intrMask); + intelEnableIRQ(&adapterData); DebugLog("[IntelMausi]: Link down on en%u\n", netif->getUnitNumber()); } @@ -2326,7 +2329,7 @@ inline void IntelMausi::intelGetChecksumResult(mbuf_t m, UInt32 status) if (status & E1000_RXD_STAT_IPPCS) performed |= (MBUF_CSUM_DID_IP | MBUF_CSUM_IP_GOOD); - + if (status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) { performed |= (MBUF_CSUM_DID_DATA | MBUF_CSUM_PSEUDO_HDR); value = 0xffff; // fake a valid checksum value @@ -2342,7 +2345,7 @@ bool IntelMausi::intelIdentifyChip() UInt32 i = 0; UInt16 id = deviceTable[i].pciDevId; bool result = false; - + while (id) { if (id == pciDeviceData.device) { chip = i; @@ -2356,17 +2359,17 @@ bool IntelMausi::intelIdentifyChip() adapterData.hw.mac.type = ei->mac; adapterData.max_hw_frame_size = ei->max_hw_frame_size; adapterData.bd_number = 0; - + /* Set default EEE advertisement */ if (adapterData.flags2 & FLAG2_HAS_EEE) adapterData.eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; - + result = true; break; } id = deviceTable[++i].pciDevId; } - + done: return result; } @@ -2376,17 +2379,17 @@ bool IntelMausi::intelStart() struct e1000_hw *hw = &adapterData.hw; const struct e1000_info *ei = adapterData.ei; struct e1000_mac_info *mac = &hw->mac; - SInt32 rval = 0; - UInt16 eepromData = 0; - UInt16 eepromApmeMask = E1000_EEPROM_APME; - int error, i; + s32 ret_val = 0; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + int err, i; bool result = false; - + /* Setup some default values. */ adapterData.rx_buffer_len = kRxBufferPktSize; - adapterData.max_frame_size = mtu + ETH_HLEN + ETH_FCS_LEN; - adapterData.min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - + adapterData.max_frame_size = mtu + ETH_HLEN + ETH_FCS_LEN; + adapterData.min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + adapterData.rx_int_delay = 0; adapterData.rx_abs_int_delay = 0; @@ -2399,159 +2402,162 @@ bool IntelMausi::intelStart() adapterData.flags2 |= (FLAG2_CRC_STRIPPING | FLAG2_DFLT_CRC_STRIPPING); adapterData.flags |= FLAG_READ_ONLY_NVM; - + if (adapterData.flags2 & FLAG2_HAS_EEE) hw->dev_spec.ich8lan.eee_disable = false; initPCIPowerManagment(pciDevice, ei); - - /* Explicitly disable IRQ since the NIC can be in any state. */ - intelDisableIRQ(); - - set_bit(__E1000_DOWN, &adapterData.state); - + + /* Explicitly disable IRQ since the NIC can be in any state. */ + intelDisableIRQ(); + + set_bit(__E1000_DOWN, &adapterData.state); + memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); - memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); - memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); - - if (hw->mac.type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - - hw->phy.autoneg_wait_to_complete = 0; - - error = ei->get_variants(&adapterData); - - if (error) { - IOLog("[IntelMausi]: Failed to get adapter data with error %d.\n", error); - goto done; - } - if ((adapterData.flags & FLAG_IS_ICH) && - (adapterData.flags & FLAG_READ_ONLY_NVM) && + memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); + memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); + + err = ei->get_variants(&adapterData); + if (err) { + IOLog("[IntelMausi]: Failed to get adapter data with error %d.\n", err); + goto done; + } + if ((adapterData.flags & FLAG_IS_ICH) && + (adapterData.flags & FLAG_READ_ONLY_NVM) && (hw->mac.type < e1000_pch_spt)) - e1000e_write_protect_nvm_ich8lan(hw); - - hw->phy.autoneg_wait_to_complete = 0; - - /* Copper options */ - if (hw->phy.media_type == e1000_media_type_copper) { - hw->phy.mdix = AUTO_ALL_MODES; - hw->phy.disable_polarity_correction = 0; - hw->phy.ms_type = e1000_ms_hw_default; - } - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - IOLog("[IntelMausi]: PHY reset is blocked due to SOL/IDER session.\n"); + e1000e_write_protect_nvm_ich8lan(hw); + + hw->mac.ops.get_bus_info(&adapterData.hw); + + hw->phy.autoneg_wait_to_complete = 0; + + /* Copper options */ + if (hw->phy.media_type == e1000_media_type_copper) { + hw->phy.mdix = AUTO_ALL_MODES; + hw->phy.disable_polarity_correction = 0; + hw->phy.ms_type = e1000_ms_hw_default; + } + + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) + IOLog("[IntelMausi]: PHY reset is blocked due to SOL/IDER session.\n"); if (intelEnableMngPassThru(hw)) - adapterData.flags |= FLAG_MNG_PT_ENABLED; - - /* before reading the NVM, reset the controller to - * put the device in a known good starting state - */ - hw->mac.ops.reset_hw(hw); - - /* systems with ASPM and others may see the checksum fail on the first - * attempt. Let's give it a few tries - */ - for (i = 0;; i++) { - if (e1000_validate_nvm_checksum(hw) >= 0) - break; - - if (i == 2) { - IOLog("[IntelMausi]: The NVM Checksum Is Not Valid.\n"); - goto error_eeprom; + adapterData.flags |= FLAG_MNG_PT_ENABLED; + + /* before reading the NVM, reset the controller to + * put the device in a known good starting state + */ + hw->mac.ops.reset_hw(hw); + + /* systems with ASPM and others may see the checksum fail on the first + * attempt. Let's give it a few tries + */ + for (i = 0;; i++) { + if (e1000_validate_nvm_checksum(hw) >= 0) + break; + if (i == 2) { + IOLog("[IntelMausi]: The NVM Checksum Is Not Valid.\n"); + goto error_eeprom; break; - } - } - //intelEEPROMChecks(&adapterData); - - /* copy the MAC address */ - if (e1000e_read_mac_addr(hw)) - IOLog("[IntelMausi]: NVM Read Error while reading MAC address.\n"); - - if (!is_valid_ether_addr(mac->addr)) { - IOLog("[IntelMausi]: Invalid MAC Address: %pM\n", mac->addr); - goto error_eeprom; - } - /* Initialize link parameters. User can change them with ethtool */ - hw->mac.autoneg = 1; - adapterData.fc_autoneg = true; - hw->fc.requested_mode = e1000_fc_default; - hw->fc.current_mode = e1000_fc_default; - hw->phy.autoneg_advertised = 0x2f; - - /* Initial Wake on LAN setting - If APM wake is enabled in - * the EEPROM, enable the ACPI Magic Packet filter - */ - if (adapterData.flags & FLAG_APME_IN_WUC) { - /* APME bit in EEPROM is mapped to WUC.APME */ - eepromData = intelReadMem32(E1000_WUC); - eepromApmeMask = E1000_WUC_APME; - - if ((hw->mac.type > e1000_ich10lan) && - (eepromData & E1000_WUC_PHY_WAKE)) - adapterData.flags2 |= FLAG2_HAS_PHY_WAKEUP; - } else if (adapterData.flags & FLAG_APME_IN_CTRL3) { - if (adapterData.flags & FLAG_APME_CHECK_PORT_B && (adapterData.hw.bus.func == 1)) - rval = e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eepromData); - else - rval = e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eepromData); - } - - /* fetch WoL from EEPROM */ - if (rval) - DebugLog("[IntelMausi]: NVM read error getting WoL initial values: %d\n", rval); - else if (eepromData & eepromApmeMask) - adapterData.eeprom_wol |= E1000_WUFC_MAG; - - /* now that we have the eeprom settings, apply the special cases - * where the eeprom may be wrong or the board simply won't support - * wake on lan on a particular port - */ - if (!(adapterData.flags & FLAG_HAS_WOL)) - adapterData.eeprom_wol = 0; - - /* initialize the wol settings based on the eeprom settings */ - adapterData.wol = adapterData.eeprom_wol; - - /* make sure adapter isn't asleep if manageability is enabled */ - if (adapterData.wol || (adapterData.flags & FLAG_MNG_PT_ENABLED) || (hw->mac.ops.check_mng_mode(hw))) + } + } + //intelEEPROMChecks(&adapterData); + + /* copy the MAC address */ + if (e1000e_read_mac_addr(hw)) + IOLog("[IntelMausi]: NVM Read Error while reading MAC address.\n"); + + if (!is_valid_ether_addr(mac->addr)) { + IOLog("[IntelMausi]: Invalid MAC Address: %pM\n", mac->addr); + goto error_eeprom; + } + /* Initialize link parameters. User can change them with ethtool */ + hw->mac.autoneg = 1; + adapterData.fc_autoneg = true; + hw->fc.requested_mode = e1000_fc_default; + hw->fc.current_mode = e1000_fc_default; + hw->phy.autoneg_advertised = 0x2f; + + /* Initial Wake on LAN setting - If APM wake is enabled in + * the EEPROM, enable the ACPI Magic Packet filter + */ + if (adapterData.flags & FLAG_APME_IN_WUC) { + /* APME bit in EEPROM is mapped to WUC.APME */ + eeprom_data = intelReadMem32(E1000_WUC); + eeprom_apme_mask = E1000_WUC_APME; + if ((hw->mac.type > e1000_ich10lan) && + (eeprom_data & E1000_WUC_PHY_WAKE)) + adapterData.flags2 |= FLAG2_HAS_PHY_WAKEUP; + } else if (adapterData.flags & FLAG_APME_IN_CTRL3) { + if (adapterData.flags & FLAG_APME_CHECK_PORT_B && + (adapterData.hw.bus.func == 1)) + ret_val = e1000_read_nvm(&adapterData.hw, + NVM_INIT_CONTROL3_PORT_B, + 1, &eeprom_data); + else + ret_val = e1000_read_nvm(&adapterData.hw, + NVM_INIT_CONTROL3_PORT_A, + 1, &eeprom_data); + } + + /* fetch WoL from EEPROM */ + if (ret_val) + DebugLog("[IntelMausi]: NVM read error getting WoL initial values: %d\n", ret_val); + else if (eeprom_data & eeprom_apme_mask) + adapterData.eeprom_wol |= E1000_WUFC_MAG; + + /* now that we have the eeprom settings, apply the special cases + * where the eeprom may be wrong or the board simply won't support + * wake on lan on a particular port + */ + if (!(adapterData.flags & FLAG_HAS_WOL)) + adapterData.eeprom_wol = 0; + + /* initialize the wol settings based on the eeprom settings */ + adapterData.wol = adapterData.eeprom_wol; + + /* make sure adapter isn't asleep if manageability is enabled */ + if (adapterData.wol || (adapterData.flags & FLAG_MNG_PT_ENABLED) || (hw->mac.ops.check_mng_mode(hw))) + //device_wakeup_enable(&pdev->dev); pciDevice->enablePCIPowerManagement(kPCIPMCSPowerStateD0); - - /* save off EEPROM version number */ - rval = e1000_read_nvm(hw, 5, 1, &adapterData.eeprom_vers); - - if (rval) { - DebugLog("[IntelMausi]: NVM read error getting EEPROM version: %d\n", rval); - adapterData.eeprom_vers = 0; - } - /* reset the hardware with the new settings */ - intelReset(&adapterData); - - /* Let the f/w know that the h/w is now under the control of the driver - * even in case the device has AMT in order to avoid problems after wakeup. - */ - e1000e_get_hw_control(&adapterData); - - intrMask = IMS_ENABLE_MASK; - - if ((hw->mac.type == e1000_pch_lpt) || (hw->mac.type == e1000_pch_spt)) { - intrMask |= E1000_IMS_ECCER; + + /* save off EEPROM version number */ + ret_val = e1000_read_nvm(hw, 5, 1, &adapterData.eeprom_vers); + + if (ret_val) { + DebugLog("[IntelMausi]: NVM read error getting EEPROM version: %d\n", ret_val); + adapterData.eeprom_vers = 0; } + + /* init PTP hardware clock */ + //e1000e_ptp_init(adapter); + + /* reset the hardware with the new settings */ + intelReset(&adapterData); + + /* Let the f/w know that the h/w is now under the control of the driver + * even in case the device has AMT in order to avoid problems after wakeup. + */ + e1000e_get_hw_control(&adapterData); + /* + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000e_get_hw_control(adapter); + */ + DebugLog("[IntelMausi]: %s (Rev. %u), %02x:%02x:%02x:%02x:%02x:%02x\n", deviceTable[chip].deviceName, pciDeviceData.revision, mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]); result = true; - + done: return result; - + error_eeprom: - if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) - e1000_phy_hw_reset(hw); - + if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) + e1000_phy_hw_reset(hw); + goto done; } - #pragma mark --- timer action methods --- void IntelMausi::timerAction(IOTimerEventSource *timer) @@ -2571,7 +2577,7 @@ void IntelMausi::timerAction(IOTimerEventSource *timer) /* Enable EEE on 82579 after link up. */ if (eeeMode) { e1000_get_phy_info(hw); - + if (hw->phy.type >= e1000_phy_82579) intelEnableEEE(hw, eeeMode); @@ -2579,71 +2585,71 @@ void IntelMausi::timerAction(IOTimerEventSource *timer) } updateStatistics(&adapterData); timerSource->setTimeoutMS(kTimeoutMS); - + done: txDescDoneLast = txDescDoneCount; - - //DebugLog("timerAction() <===\n"); + + //DebugLog("[IntelMausi]: timerAction() <===\n"); } void IntelMausi::updateStatistics(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - - adapter->stats.crcerrs += intelReadMem32(E1000_CRCERRS); - adapter->stats.gprc += intelReadMem32(E1000_GPRC); - adapter->stats.gorc += intelReadMem32(E1000_GORCL); - intelReadMem32(E1000_GORCH); /* Clear gorc */ - adapter->stats.bprc += intelReadMem32(E1000_BPRC); - adapter->stats.mprc += intelReadMem32(E1000_MPRC); - adapter->stats.roc += intelReadMem32(E1000_ROC); - - adapter->stats.mpc += intelReadMem32(E1000_MPC); - - /* Half-duplex statistics */ - if (adapter->link_duplex == HALF_DUPLEX) { - if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { - e1000e_update_phy_stats(adapter); - } else { - adapter->stats.scc += intelReadMem32(E1000_SCC); - adapter->stats.ecol += intelReadMem32(E1000_ECOL); - adapter->stats.mcc += intelReadMem32(E1000_MCC); - adapter->stats.latecol += intelReadMem32(E1000_LATECOL); - adapter->stats.dc += intelReadMem32(E1000_DC); - - hw->mac.collision_delta = intelReadMem32(E1000_COLC); - - if ((hw->mac.type != e1000_82574) && - (hw->mac.type != e1000_82583)) - adapter->stats.tncrs += intelReadMem32(E1000_TNCRS); - } - adapter->stats.colc += hw->mac.collision_delta; - } - - adapter->stats.xonrxc += intelReadMem32(E1000_XONRXC); - adapter->stats.xontxc += intelReadMem32(E1000_XONTXC); - adapter->stats.xoffrxc += intelReadMem32(E1000_XOFFRXC); - adapter->stats.xofftxc += intelReadMem32(E1000_XOFFTXC); - adapter->stats.gptc += intelReadMem32(E1000_GPTC); - adapter->stats.gotc += intelReadMem32(E1000_GOTCL); - intelReadMem32(E1000_GOTCH); /* Clear gotc */ - adapter->stats.rnbc += intelReadMem32(E1000_RNBC); - adapter->stats.ruc += intelReadMem32(E1000_RUC); - - adapter->stats.mptc += intelReadMem32(E1000_MPTC); - adapter->stats.bptc += intelReadMem32(E1000_BPTC); - - /* used for adaptive IFS */ - - hw->mac.tx_packet_delta = intelReadMem32(E1000_TPT); - adapter->stats.tpt += hw->mac.tx_packet_delta; - - adapter->stats.algnerrc += intelReadMem32(E1000_ALGNERRC); - adapter->stats.rxerrc += intelReadMem32(E1000_RXERRC); - adapter->stats.cexterr += intelReadMem32(E1000_CEXTERR); - adapter->stats.tsctc += intelReadMem32(E1000_TSCTC); - adapter->stats.tsctfc += intelReadMem32(E1000_TSCTFC); - + + adapter->stats.crcerrs += intelReadMem32(E1000_CRCERRS); + adapter->stats.gprc += intelReadMem32(E1000_GPRC); + adapter->stats.gorc += intelReadMem32(E1000_GORCL); + intelReadMem32(E1000_GORCH); /* Clear gorc */ + adapter->stats.bprc += intelReadMem32(E1000_BPRC); + adapter->stats.mprc += intelReadMem32(E1000_MPRC); + adapter->stats.roc += intelReadMem32(E1000_ROC); + + adapter->stats.mpc += intelReadMem32(E1000_MPC); + + /* Half-duplex statistics */ + if (adapter->link_duplex == HALF_DUPLEX) { + if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { + e1000e_update_phy_stats(adapter); + } else { + adapter->stats.scc += intelReadMem32(E1000_SCC); + adapter->stats.ecol += intelReadMem32(E1000_ECOL); + adapter->stats.mcc += intelReadMem32(E1000_MCC); + adapter->stats.latecol += intelReadMem32(E1000_LATECOL); + adapter->stats.dc += intelReadMem32(E1000_DC); + + hw->mac.collision_delta = intelReadMem32(E1000_COLC); + + if ((hw->mac.type != e1000_82574) && + (hw->mac.type != e1000_82583)) + adapter->stats.tncrs += intelReadMem32(E1000_TNCRS); + } + adapter->stats.colc += hw->mac.collision_delta; + } + + adapter->stats.xonrxc += intelReadMem32(E1000_XONRXC); + adapter->stats.xontxc += intelReadMem32(E1000_XONTXC); + adapter->stats.xoffrxc += intelReadMem32(E1000_XOFFRXC); + adapter->stats.xofftxc += intelReadMem32(E1000_XOFFTXC); + adapter->stats.gptc += intelReadMem32(E1000_GPTC); + adapter->stats.gotc += intelReadMem32(E1000_GOTCL); + intelReadMem32(E1000_GOTCH); /* Clear gotc */ + adapter->stats.rnbc += intelReadMem32(E1000_RNBC); + adapter->stats.ruc += intelReadMem32(E1000_RUC); + + adapter->stats.mptc += intelReadMem32(E1000_MPTC); + adapter->stats.bptc += intelReadMem32(E1000_BPTC); + + /* used for adaptive IFS */ + + hw->mac.tx_packet_delta = intelReadMem32(E1000_TPT); + adapter->stats.tpt += hw->mac.tx_packet_delta; + + adapter->stats.algnerrc += intelReadMem32(E1000_ALGNERRC); + adapter->stats.rxerrc += intelReadMem32(E1000_RXERRC); + adapter->stats.cexterr += intelReadMem32(E1000_CEXTERR); + adapter->stats.tsctc += intelReadMem32(E1000_TSCTC); + adapter->stats.tsctfc += intelReadMem32(E1000_TSCTFC); + netStats->inputPackets = (UInt32)adapter->stats.gprc; netStats->inputErrors = (UInt32)(adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc @@ -2662,21 +2668,21 @@ void IntelMausi::updateStatistics(struct e1000_adapter *adapter) etherStats->dot3StatsEntry.carrierSenseErrors = (UInt32)adapter->stats.cexterr; etherStats->dot3StatsEntry.frameTooLongs = (UInt32)adapter->stats.roc; etherStats->dot3StatsEntry.missedFrames = (UInt32)adapter->stats.mpc; - + etherStats->dot3RxExtraEntry.frameTooShorts = (UInt32)adapter->stats.ruc; } bool IntelMausi::checkForDeadlock() { bool deadlock = false; - + if (forceReset) { etherStats->dot3TxExtraEntry.resets++; intelRestart(); deadlock = true; eeeMode = 0; } - + if ((txDescDoneCount == txDescDoneLast) && (txNumFreeDesc < kNumTxDesc)) { if (++deadlockWarn >= kTxDeadlockTreshhold) { mbuf_t m = txBufArray[txDirtyIndex].mbuf; @@ -2688,7 +2694,7 @@ bool IntelMausi::checkForDeadlock() UInt16 stalledIndex = txDirtyIndex; #endif //UInt8 data; - + IOLog("[IntelMausi]: Tx stalled? Resetting chipset. txDirtyDescIndex=%u, STATUS=0x%08x, TCTL=0x%08x.\n", txDirtyIndex, intelReadMem32(E1000_STATUS), intelReadMem32(E1000_TCTL)); #ifdef DEBUG @@ -2709,14 +2715,14 @@ bool IntelMausi::checkForDeadlock() IOLog(" 0x%02x", data); } IOLog("\n"); - + IOLog("[IntelMausi]: IP-header: "); for (i = 14; i < 34; i++) { mbuf_copydata(m, i, 1, &data); IOLog(" 0x%02x", data); } IOLog("\n"); - + IOLog("[IntelMausi]: TCP-Header / Data: "); for (i = 34; i < 100; i++) { mbuf_copydata(m, i, 1, &data); diff --git a/IntelMausiEthernet/IntelMausiEthernet.h b/IntelMausiEthernet/IntelMausiEthernet.h index 63d68e8..66fdbfd 100644 --- a/IntelMausiEthernet/IntelMausiEthernet.h +++ b/IntelMausiEthernet/IntelMausiEthernet.h @@ -29,7 +29,7 @@ extern "C" { #define DebugLog(args...) #endif -#define RELEASE(x) if(x){(x)->release();(x)=NULL;} +#define RELEASE(x) if(x){(x)->release();(x)=NULL;} #define intelWriteMem8(reg, val8) _OSWriteInt8((baseAddr), (reg), (val8)) #define intelWriteMem16(reg, val16) OSWriteLittleInt16((baseAddr), (reg), (val16)) @@ -39,14 +39,17 @@ extern "C" { #define intelReadMem32(reg) OSReadLittleInt32((baseAddr), (reg)) #define intelFlush() OSReadLittleInt32((baseAddr), (E1000_STATUS)) +/* RSS keys are 40 or 52 bytes long */ +#define INTEL_RSS_KEY_LEN 52 + #define super IOEthernetController enum { - MEDIUM_INDEX_AUTO = 0, - MEDIUM_INDEX_10HD, - MEDIUM_INDEX_10FD, - MEDIUM_INDEX_100HD, + MEDIUM_INDEX_AUTO = 0, + MEDIUM_INDEX_10HD, + MEDIUM_INDEX_10FD, + MEDIUM_INDEX_100HD, MEDIUM_INDEX_100FD, MEDIUM_INDEX_100FDFC, MEDIUM_INDEX_1000FD, @@ -55,7 +58,7 @@ enum MEDIUM_INDEX_1000FDFCEEE, MEDIUM_INDEX_100FDEEE, MEDIUM_INDEX_100FDFCEEE, - MEDIUM_INDEX_COUNT + MEDIUM_INDEX_COUNT }; #define MBit 1000000 @@ -164,20 +167,20 @@ enum { /* mask to determine if packets should be dropped due to frame errors */ #define E1000_RXDLGC_ERR_FRAME_ERR_MASK ( \ - E1000_RXDLGC_ERR_CE | \ - E1000_RXDLGC_ERR_SE | \ - E1000_RXDLGC_ERR_SEQ | \ - E1000_RXDLGC_ERR_CXE | \ + E1000_RXDLGC_ERR_CE | \ + E1000_RXDLGC_ERR_SE | \ + E1000_RXDLGC_ERR_SEQ | \ + E1000_RXDLGC_ERR_CXE | \ E1000_RXDLGC_ERR_RXE) -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_NO_FCS 0x00000010 -#define E1000_TX_FLAGS_HWTSTAMP 0x00000020 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 +#define E1000_TX_FLAGS_CSUM 0x00000001 +#define E1000_TX_FLAGS_VLAN 0x00000002 +#define E1000_TX_FLAGS_TSO 0x00000004 +#define E1000_TX_FLAGS_IPV4 0x00000008 +#define E1000_TX_FLAGS_NO_FCS 0x00000010 +#define E1000_TX_FLAGS_HWTSTAMP 0x00000020 +#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 +#define E1000_TX_FLAGS_VLAN_SHIFT 16 #define E1000_TXD_OPTS_IXSM 0x00000100 #define E1000_TXD_OPTS_TXSM 0x00000200 @@ -299,22 +302,22 @@ struct IntelAddrData { class IntelMausi : public super { - - OSDeclareDefaultStructors(IntelMausi) - + + OSDeclareDefaultStructors(IntelMausi) + public: - /* IOService (or its superclass) methods. */ - virtual bool start(IOService *provider) APPLE_KEXT_OVERRIDE; - virtual void stop(IOService *provider) APPLE_KEXT_OVERRIDE; - virtual bool init(OSDictionary *properties) APPLE_KEXT_OVERRIDE; - virtual void free() APPLE_KEXT_OVERRIDE; - - /* Power Management Support */ - virtual IOReturn registerWithPolicyMaker(IOService *policyMaker) APPLE_KEXT_OVERRIDE; + /* IOService (or its superclass) methods. */ + virtual bool start(IOService *provider) APPLE_KEXT_OVERRIDE; + virtual void stop(IOService *provider) APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *properties) APPLE_KEXT_OVERRIDE; + virtual void free() APPLE_KEXT_OVERRIDE; + + /* Power Management Support */ + virtual IOReturn registerWithPolicyMaker(IOService *policyMaker) APPLE_KEXT_OVERRIDE; virtual IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker) APPLE_KEXT_OVERRIDE; - virtual void systemWillShutdown(IOOptionBits specifier) APPLE_KEXT_OVERRIDE; - - /* IONetworkController methods. */ + virtual void systemWillShutdown(IOOptionBits specifier) APPLE_KEXT_OVERRIDE; + + /* IONetworkController methods. */ virtual IOReturn enable(IONetworkInterface *netif) APPLE_KEXT_OVERRIDE; virtual IOReturn disable(IONetworkInterface *netif) APPLE_KEXT_OVERRIDE; virtual IOReturn enable(IOKernelDebugger *debugger) APPLE_KEXT_OVERRIDE; @@ -330,31 +333,31 @@ class IntelMausi : public super #else virtual UInt32 outputPacket(mbuf_t m, void *param) APPLE_KEXT_OVERRIDE; #endif /* __PRIVATE_SPI__ */ - - virtual void getPacketBufferConstraints(IOPacketBufferConstraints *constraints) const APPLE_KEXT_OVERRIDE; - - virtual IOOutputQueue* createOutputQueue() APPLE_KEXT_OVERRIDE; - - virtual const OSString* newVendorString() const APPLE_KEXT_OVERRIDE; - virtual const OSString* newModelString() const APPLE_KEXT_OVERRIDE; - - virtual IOReturn selectMedium(const IONetworkMedium *medium) APPLE_KEXT_OVERRIDE; - virtual bool configureInterface(IONetworkInterface *interface) APPLE_KEXT_OVERRIDE; - - virtual bool createWorkLoop() APPLE_KEXT_OVERRIDE; - virtual IOWorkLoop* getWorkLoop() const APPLE_KEXT_OVERRIDE; - - /* Methods inherited from IOEthernetController. */ - virtual IOReturn getHardwareAddress(IOEthernetAddress *addr) APPLE_KEXT_OVERRIDE; - virtual IOReturn setHardwareAddress(const IOEthernetAddress *addr) APPLE_KEXT_OVERRIDE; - virtual IOReturn setPromiscuousMode(bool active) APPLE_KEXT_OVERRIDE; - virtual IOReturn setMulticastMode(bool active) APPLE_KEXT_OVERRIDE; - virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count) APPLE_KEXT_OVERRIDE; - virtual IOReturn getChecksumSupport(UInt32 *checksumMask, UInt32 checksumFamily, bool isOutput) APPLE_KEXT_OVERRIDE; - virtual IOReturn getMinPacketSize(UInt32 *minSize) const APPLE_KEXT_OVERRIDE; + + virtual void getPacketBufferConstraints(IOPacketBufferConstraints *constraints) const APPLE_KEXT_OVERRIDE; + + virtual IOOutputQueue* createOutputQueue() APPLE_KEXT_OVERRIDE; + + virtual const OSString* newVendorString() const APPLE_KEXT_OVERRIDE; + virtual const OSString* newModelString() const APPLE_KEXT_OVERRIDE; + + virtual IOReturn selectMedium(const IONetworkMedium *medium) APPLE_KEXT_OVERRIDE; + virtual bool configureInterface(IONetworkInterface *interface) APPLE_KEXT_OVERRIDE; + + virtual bool createWorkLoop() APPLE_KEXT_OVERRIDE; + virtual IOWorkLoop* getWorkLoop() const APPLE_KEXT_OVERRIDE; + + /* Methods inherited from IOEthernetController. */ + virtual IOReturn getHardwareAddress(IOEthernetAddress *addr) APPLE_KEXT_OVERRIDE; + virtual IOReturn setHardwareAddress(const IOEthernetAddress *addr) APPLE_KEXT_OVERRIDE; + virtual IOReturn setPromiscuousMode(bool active) APPLE_KEXT_OVERRIDE; + virtual IOReturn setMulticastMode(bool active) APPLE_KEXT_OVERRIDE; + virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count) APPLE_KEXT_OVERRIDE; + virtual IOReturn getChecksumSupport(UInt32 *checksumMask, UInt32 checksumFamily, bool isOutput) APPLE_KEXT_OVERRIDE; + virtual IOReturn getMinPacketSize(UInt32 *minSize) const APPLE_KEXT_OVERRIDE; virtual IOReturn setWakeOnMagicPacket(bool active) APPLE_KEXT_OVERRIDE; virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const APPLE_KEXT_OVERRIDE; - + virtual UInt32 getFeatures() const APPLE_KEXT_OVERRIDE; virtual IOReturn getMaxPacketSize(UInt32 * maxSize) const APPLE_KEXT_OVERRIDE; virtual IOReturn setMaxPacketSize(UInt32 maxSize) APPLE_KEXT_OVERRIDE; @@ -390,17 +393,15 @@ class IntelMausi : public super void setLinkUp(); void setLinkDown(); bool checkForDeadlock(); - + /* Jumbo frame support methods */ void discardPacketFragment(bool extended = false); - + /* Hardware specific methods */ bool intelIdentifyChip(); bool intelStart(); void intelEEPROMChecks(struct e1000_adapter *adapter); - void intelInitTxRing(); - void intelInitRxRing(); - void intelEnableIRQ(UInt32 newMask); + void intelEnableIRQ(struct e1000_adapter *adapter); void intelDisableIRQ(); void intelUpdateTxDescTail(UInt32 index); void intelUpdateRxDescTail(UInt32 index); @@ -420,6 +421,7 @@ class IntelMausi : public super void intelUpdateAdaptive(struct e1000_hw *hw); void intelVlanStripDisable(struct e1000_adapter *adapter); void intelVlanStripEnable(struct e1000_adapter *adapter); + void intelRssKeyFill(void *buffer, size_t len); void intelSetupRssHash(struct e1000_adapter *adapter); void intelRestart(); @@ -434,33 +436,33 @@ class IntelMausi : public super void intelSetupAdvForMedium(const IONetworkMedium *medium); void intelFlushLPIC(); void setMaxLatency(UInt32 linkSpeed); - + UInt16 intelSupportsEEE(struct e1000_adapter *adapter); SInt32 intelEnableEEE(struct e1000_hw *hw, UInt16 mode); - + inline void intelGetChecksumResult(mbuf_t m, UInt32 status); void getAddressList(struct IntelAddrData *addr); /* timer action */ void timerAction(IOTimerEventSource *timer); - + private: - IOWorkLoop *workLoop; + IOWorkLoop *workLoop; IOCommandGate *commandGate; - IOPCIDevice *pciDevice; - OSDictionary *mediumDict; - IONetworkMedium *mediumTable[MEDIUM_INDEX_COUNT]; - IOBasicOutputQueue *txQueue; - - IOInterruptEventSource *interruptSource; - IOTimerEventSource *timerSource; - IOEthernetInterface *netif; - IOMemoryMap *baseMap; + IOPCIDevice *pciDevice; + OSDictionary *mediumDict; + IONetworkMedium *mediumTable[MEDIUM_INDEX_COUNT]; + IOBasicOutputQueue *txQueue; + + IOInterruptEventSource *interruptSource; + IOTimerEventSource *timerSource; + IOEthernetInterface *netif; + IOMemoryMap *baseMap; volatile void *baseAddr; - IOMemoryMap *flashMap; + IOMemoryMap *flashMap; volatile void *flashAddr; - + /* transmitter data */ IODMACommand *txDescDmaCmd; IOBufferMemoryDescriptor *txBufDesc; @@ -475,13 +477,13 @@ class IntelMausi : public super UInt16 txNextDescIndex; UInt16 txDirtyIndex; UInt16 txCleanBarrierIndex; - + /* receiver data */ IODMACommand *rxDescDmaCmd; IOBufferMemoryDescriptor *rxBufDesc; IOPhysicalAddress64 rxPhyAddr; union e1000_rx_desc_extended *rxDescArray; - IOMbufNaturalMemoryCursor *rxMbufCursor; + IOMbufNaturalMemoryCursor *rxMbufCursor; mbuf_t rxPacketHead; mbuf_t rxPacketTail; UInt32 rxPacketSize; @@ -489,18 +491,17 @@ class IntelMausi : public super UInt32 mcListCount; UInt16 rxNextDescIndex; UInt16 rxCleanedCount; - + /* power management data */ unsigned long powerState; - + /* statistics data */ UInt32 deadlockWarn; IONetworkStats *netStats; - IOEthernetStats *etherStats; - + IOEthernetStats *etherStats; + UInt32 chip; UInt32 chipType; - UInt32 intrMask; UInt32 intrThrValue10; UInt32 intrThrValue100; UInt32 intrThrValue1000; @@ -519,14 +520,17 @@ class IntelMausi : public super UInt8 pcieCapOffset; UInt8 pciPMCtrlOffset; + UInt8 rssHashKey[INTEL_RSS_KEY_LEN]; + #ifdef __PRIVATE_SPI__ IONetworkPacketPollingParameters pollParams; #endif /* __PRIVATE_SPI__ */ /* flags */ + bool isRssSet; bool isEnabled; - bool promiscusMode; - bool multicastMode; + bool promiscusMode; + bool multicastMode; bool linkUp; #ifdef __PRIVATE_SPI__ @@ -540,7 +544,7 @@ class IntelMausi : public super bool wolActive; bool enableCSO6; bool enableWoM; - + /* mbuf_t arrays */ struct intelTxBufferInfo txBufArray[kNumTxDesc]; struct intelRxBufferInfo rxBufArray[kNumRxDesc]; diff --git a/IntelMausiEthernet/IntelMausiEthernetV2-Prefix.pch b/IntelMausiEthernet/IntelMausiEthernetV2-Prefix.pch index 0c99ddf..c78512b 100644 --- a/IntelMausiEthernet/IntelMausiEthernetV2-Prefix.pch +++ b/IntelMausiEthernet/IntelMausiEthernetV2-Prefix.pch @@ -28,7 +28,7 @@ extern "C" { #include #include #include - + #ifdef __cplusplus } #endif // __cplusplus diff --git a/IntelMausiEthernet/IntelMausiHardware.cpp b/IntelMausiEthernet/IntelMausiHardware.cpp index 243cd6b..7a00cec 100644 --- a/IntelMausiEthernet/IntelMausiHardware.cpp +++ b/IntelMausiEthernet/IntelMausiHardware.cpp @@ -18,38 +18,46 @@ * This driver is based on Intel's E1000e driver for Linux. */ - +#include #include "IntelMausiEthernet.h" #pragma mark --- hardware initialization methods --- + +/** + * initPCIConfigSpace + */ bool IntelMausi::initPCIConfigSpace(IOPCIDevice *provider) { UInt32 lat1, lat2; bool result = false; - + /* Get vendor and device info. */ pciDeviceData.vendor = provider->extendedConfigRead16(kIOPCIConfigVendorID); pciDeviceData.device = provider->extendedConfigRead16(kIOPCIConfigDeviceID); pciDeviceData.subsystem_vendor = provider->extendedConfigRead16(kIOPCIConfigSubSystemVendorID); pciDeviceData.subsystem_device = provider->extendedConfigRead16(kIOPCIConfigSubSystemID); pciDeviceData.revision = provider->extendedConfigRead8(kIOPCIConfigRevisionID); - + /* Identify the chipset. */ if (!intelIdentifyChip()) goto done; - + if (chipType >= board_pch_lpt) { + /* + * Set platform power management values for + * Latency Tolerance Reporting (LTR) + */ pciDeviceData.maxSnoop = provider->extendedConfigRead16(E1000_PCI_LTR_CAP_LPT); pciDeviceData.maxNoSnoop = provider->extendedConfigRead16(E1000_PCI_LTR_CAP_LPT + 2); - + lat1 = (pciDeviceData.maxSnoop & 0x3ff) << (((pciDeviceData.maxSnoop >> 10) & 0x7) * 5); lat2 = (pciDeviceData.maxNoSnoop & 0x3ff) << (((pciDeviceData.maxNoSnoop >> 10) & 0x7) * 5); maxLatency = (lat1 > lat2) ? lat1 : lat2; - + if (maxLatency > kMaxDmaLatency) maxLatency = kMaxDmaLatency; - + DebugLog("[IntelMausi]: maxSnoop: 0x%04x (%uns), maxNoSnoop: 0x%04x (%uns).\n", pciDeviceData.maxSnoop, lat1, pciDeviceData.maxNoSnoop, lat2); } /* Get the bus information. */ @@ -58,9 +66,9 @@ bool IntelMausi::initPCIConfigSpace(IOPCIDevice *provider) /* Enable the device. */ intelEnablePCIDevice(provider); - + baseMap = provider->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0, kIOMapInhibitCache); - + if (!baseMap) { IOLog("[IntelMausi]: region #0 not an MMIO resource, aborting.\n"); goto done; @@ -68,10 +76,10 @@ bool IntelMausi::initPCIConfigSpace(IOPCIDevice *provider) baseAddr = reinterpret_cast(baseMap->getVirtualAddress()); adapterData.hw.hw_addr = (u8 __iomem *)baseAddr; adapterData.hw.flash_address = NULL; - + if ((adapterData.flags & FLAG_HAS_FLASH) && (adapterData.hw.mac.type < e1000_pch_spt)) { flashMap = provider->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress1, kIOMapInhibitCache); - + if (!flashMap) { IOLog("[IntelMausi]: region #1 not an MMIO resource, aborting.\n"); goto error; @@ -80,10 +88,10 @@ bool IntelMausi::initPCIConfigSpace(IOPCIDevice *provider) adapterData.hw.flash_address = (u8 __iomem *)flashAddr; } result = true; - + done: return result; - + error: RELEASE(baseMap); baseMap = NULL; @@ -91,6 +99,10 @@ bool IntelMausi::initPCIConfigSpace(IOPCIDevice *provider) goto done; } + +/** + * initPCIPowerManagment + */ void IntelMausi::initPCIPowerManagment(IOPCIDevice *provider, const struct e1000_info *ei) { #ifdef DEBUG @@ -100,12 +112,12 @@ void IntelMausi::initPCIPowerManagment(IOPCIDevice *provider, const struct e1000 UInt16 aspmDisable; UInt16 pmCap; UInt8 pmCapOffset; - + /* Setup power management. */ if (provider->findPCICapability(kIOPCIPowerManagementCapability, &pmCapOffset)) { pmCap = provider->extendedConfigRead16(pmCapOffset + kIOPCIPMCapability); DebugLog("[IntelMausi]: PCI power management capabilities: 0x%x.\n", pmCap); - + if (pmCap & (kPCIPMCPMESupportFromD3Cold | kPCIPMCPMESupportFromD3Hot)) { wolCapable = true; DebugLog("[IntelMausi]: PME# from D3 (cold/hot) supported.\n"); @@ -115,7 +127,7 @@ void IntelMausi::initPCIPowerManagment(IOPCIDevice *provider, const struct e1000 IOLog("[IntelMausi]: PCI power management unsupported.\n"); } provider->enablePCIPowerManagement(); - + /* Get PCIe link information. */ if (provider->findPCICapability(kIOPCIPCIExpressCapability, &pcieCapOffset)) { #ifdef DEBUG @@ -124,114 +136,155 @@ void IntelMausi::initPCIPowerManagment(IOPCIDevice *provider, const struct e1000 pcieLinkCtl = provider->extendedConfigRead16(pcieCapOffset + kIOPCIELinkControl); DebugLog("[IntelMausi]: PCIe link capabilities: 0x%08x, link control: 0x%04x.\n", pcieLinkCap, pcieLinkCtl); aspmDisable = 0; - + if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S) aspmDisable |= kIOPCIELinkCtlL0s; - + if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) aspmDisable |= kIOPCIELinkCtlL1; - if (aspmDisable) + if (aspmDisable) { provider->extendedConfigWrite16(pcieCapOffset + kIOPCIELinkControl, (pcieLinkCtl & ~aspmDisable)); + IOSleep(10); + } -#ifdef DEBUG pcieLinkCtl = provider->extendedConfigRead16(pcieCapOffset + kIOPCIELinkControl); - + if (pcieLinkCtl & (kIOPCIELinkCtlASPM | kIOPCIELinkCtlClkReqEn)) - IOLog("[IntelMausi]: PCIe ASPM enabled. link control: 0x%04x.\n", pcieLinkCtl); + DebugLog("[IntelMausi]: PCIe ASPM enabled. link control: 0x%04x.\n", pcieLinkCtl); else - IOLog("[IntelMausi]: PCIe ASPM disabled. link control: 0x%04x.\n", pcieLinkCtl); -#endif /* DEBUG */ + DebugLog("[IntelMausi]: PCIe ASPM disabled. link control: 0x%04x.\n", pcieLinkCtl); } } + +/** + * setPowerStateWakeAction + */ IOReturn IntelMausi::setPowerStateWakeAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) { IntelMausi *ethCtlr = OSDynamicCast(IntelMausi, owner); IOPCIDevice *dev; UInt16 val16; UInt8 offset; - + if (ethCtlr) { dev = ethCtlr->pciDevice; offset = ethCtlr->pciPMCtrlOffset; - + val16 = dev->extendedConfigRead16(offset); - + val16 &= ~(kPCIPMCSPowerStateMask | kPCIPMCSPMEStatus | kPCIPMCSPMEEnable); val16 |= kPCIPMCSPowerStateD0; - + dev->extendedConfigWrite16(offset, val16); - + + IOSleep(10); + /* Restore the PCI Command register. */ ethCtlr->intelEnablePCIDevice(dev); } return kIOReturnSuccess; } + +/** + * setPowerStateSleepAction + */ IOReturn IntelMausi::setPowerStateSleepAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) { IntelMausi *ethCtlr = OSDynamicCast(IntelMausi, owner); IOPCIDevice *dev; UInt16 val16; UInt8 offset; - + if (ethCtlr) { dev = ethCtlr->pciDevice; offset = ethCtlr->pciPMCtrlOffset; - + val16 = dev->extendedConfigRead16(offset); - + val16 &= ~(kPCIPMCSPowerStateMask | kPCIPMCSPMEStatus | kPCIPMCSPMEEnable); - + if (ethCtlr->wolActive) val16 |= (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD3); else val16 |= kPCIPMCSPowerStateD3; - + dev->extendedConfigWrite16(offset, val16); + + IOSleep(10); } return kIOReturnSuccess; } + +/** + * intelEEPROMChecks + * + * Reference: e1000_eeprom_checks(struct e1000_adapter *adapter) + */ void IntelMausi::intelEEPROMChecks(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - int ret_val; - u16 buf = 0; - - if (hw->mac.type != e1000_82573) - return; - - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); - le16_to_cpus(&buf); - - if (!ret_val && (!(buf & (1 << 0)))) { - /* Deep Smart Power Down (DSPD) */ - IOLog("[IntelMausi]: Warning: detected DSPD enabled in EEPROM.\n"); - } + struct e1000_hw *hw = &adapter->hw; + int ret_val; + u16 buf = 0; + + if (hw->mac.type != e1000_82573) + return; + + ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); + le16_to_cpus(&buf); + + if (!ret_val && (!(buf & BIT(0)))) { + /* Deep Smart Power Down (DSPD) */ + IOLog("[IntelMausi]: Warning: detected DSPD enabled in EEPROM.\n"); + } } -void IntelMausi::intelEnableIRQ(UInt32 newMask) + +/** + * intelEnableIRQ - Enable default interrupt generation settings + * + * Reference: e1000_irq_enable + */ +void IntelMausi::intelEnableIRQ(struct e1000_adapter *adapter) { - intelWriteMem32(E1000_IMC, ~newMask); - intelWriteMem32(E1000_IMS, newMask); + struct e1000_hw *hw = &adapter->hw; + + if (hw->mac.type >= e1000_pch_lpt) { + intelWriteMem32(E1000_IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); + } else { + intelWriteMem32(E1000_IMS, IMS_ENABLE_MASK); + } intelFlush(); } + +/** + * intelDisableIRQ - Mask off interrupt generation on the NIC + * + * Reference: e1000_irq_disable + */ void IntelMausi::intelDisableIRQ() { - intelWriteMem32(E1000_IMC, 0xFFFFFFFF); + intelWriteMem32(E1000_IMC, ~0); intelFlush(); } + +/** + * intelEnable + * + * Reference: __e1000_resume(struct pci_dev *pdev) + */ void IntelMausi::intelEnable() { struct e1000_hw *hw = &adapterData.hw; const IONetworkMedium *selectedMedium; selectedMedium = getSelectedMedium(); - + if (!selectedMedium) { DebugLog("[IntelMausi]: No medium selected. Falling back to autonegotiation.\n"); selectedMedium = mediumTable[MEDIUM_INDEX_AUTO]; @@ -248,60 +301,89 @@ void IntelMausi::intelEnable() setLinkStatus(kIONetworkLinkValid); #endif /* __PRIVATE_SPI__ */ -#ifdef DEBUG + intelSetupAdvForMedium(selectedMedium); + + if (hw->mac.type >= e1000_pch2lan) + e1000_resume_workarounds_pchlan(hw); + + e1000e_power_up_phy(&adapterData); + + /* report the system wakeup cause from S3/S4 */ if (adapterData.flags2 & FLAG2_HAS_PHY_WAKEUP) { - struct e1000_hw *hw = &adapterData.hw; - UInt16 phyData; - - hw->phy.ops.read_reg(hw, BM_WUS, &phyData); - hw->phy.ops.write_reg(hw, BM_WUS, ~0); - - IOLog("[IntelMausi]: WUS=0x%04x\n", phyData); + u16 phy_data; + + e1e_rphy(&adapterData.hw, BM_WUS, &phy_data); + if (phy_data) { + IOLog("[IntelMausi]: PHY Wakeup cause - %s\n", + phy_data & E1000_WUS_EX ? "Unicast Packet" : + phy_data & E1000_WUS_MC ? "Multicast Packet" : + phy_data & E1000_WUS_BC ? "Broadcast Packet" : + phy_data & E1000_WUS_MAG ? "Magic Packet" : + phy_data & E1000_WUS_LNKC ? + "Link Status Change" : "other"); + } + e1e_wphy(&adapterData.hw, BM_WUS, ~0); } else { - IOLog("[IntelMausi]: WUS=0x%08x\n", intelReadMem32(E1000_WUS)); - + u32 wus = intelReadMem32(E1000_WUS); + + if (wus) { + IOLog("[IntelMausi]: MAC Wakeup cause - %s\n", + wus & E1000_WUS_EX ? "Unicast Packet" : + wus & E1000_WUS_MC ? "Multicast Packet" : + wus & E1000_WUS_BC ? "Broadcast Packet" : + wus & E1000_WUS_MAG ? "Magic Packet" : + wus & E1000_WUS_LNKC ? "Link Status Change" : + "other"); + } intelWriteMem32(E1000_WUS, ~0); } -#endif - intelSetupAdvForMedium(selectedMedium); - - e1000_phy_hw_reset(hw); - - if (hw->mac.type >= e1000_pch2lan) - e1000_resume_workarounds_pchlan(hw); - - e1000e_power_up_phy(&adapterData); - intelReset(&adapterData); - -#if DISABLED_CODE - - /* DMA latency requirement to workaround jumbo issue */ - pm_qos_add_request(&adapter->netdev->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - -#endif /* DISABLED_CODE */ - - intelConfigure(&adapterData); - - /* From here on the code is the same as e1000e_up() */ - clear_bit(__E1000_DOWN, &adapterData.state); - - intelEnableIRQ(intrMask); - - hw->mac.get_link_status = true; + + intelInitManageabilityPt(&adapterData); + + /* Let the f/w know that the h/w is now under the control of the driver + * even in case the device has AMT in order to avoid problems after wakeup. + */ + e1000e_get_hw_control(&adapterData); + /* + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000e_get_hw_control(&adapterData); + */ + + /* From here on the code is the same as e1000e_up() */ + + /* hardware has been reset, we need to reload some things */ + intelConfigure(&adapterData); + + clear_bit(__E1000_DOWN, &adapterData.state); + + intelEnableIRQ(&adapterData); + + /* Tx queue started by watchdog timer when link is up */ + //e1000e_trigger_lsc(adapter); + + hw->mac.get_link_status = true; } + +/** + * intelDisable + * + * Reference: __e1000_shutdown(struct pci_dev *pdev, bool runtime) + */ void IntelMausi::intelDisable() { struct IntelAddrData addrData; struct e1000_hw *hw = &adapterData.hw; - UInt32 linkStatus = kIONetworkLinkValid; - UInt32 wufc = adapterData.wol; - UInt32 ctrl, ctrlExt, rctl, status; - int retval; - + u32 ctrl, ctrlExt, rctl, status; + u32 wufc = adapterData.wol, linkStatus = kIONetworkLinkValid; + int retval = 0; + + DebugLog("[IntelMausi]: intelDisable()<==="); + DebugLog("[IntelMausi]: wolCapable=%u",wolCapable); + DebugLog("[IntelMausi]: wolActive=%u",wolActive); + #ifdef __PRIVATE_SPI__ polling = false; #endif /* __PRIVATE_SPI__ */ @@ -310,7 +392,7 @@ void IntelMausi::intelDisable() intelFlushLPIC(); status = intelReadMem32(E1000_STATUS); - + if (status & E1000_STATUS_LU) wufc &= ~E1000_WUFC_LNKC; @@ -320,24 +402,24 @@ void IntelMausi::intelDisable() intelDown(&adapterData, false); intelSetupRxControl(&adapterData); - + rctl = intelReadMem32(E1000_RCTL); rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); - + intelWriteMem32(E1000_RCTL, rctl); + /* turn on all-multi mode if wake on multicast is enabled */ - if (wufc & E1000_WUFC_MC) + if (wufc & E1000_WUFC_MC) { + rctl = intelReadMem32(E1000_RCTL); rctl |= E1000_RCTL_MPE; - - intelWriteMem32(E1000_RCTL, rctl); + intelWriteMem32(E1000_RCTL, rctl); + } ctrl = intelReadMem32(E1000_CTRL); ctrl |= E1000_CTRL_ADVD3WUC; - if (!(adapterData.flags2 & FLAG2_HAS_PHY_WAKEUP)) ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; - intelWriteMem32(E1000_CTRL, ctrl); - + if (adapterData.hw.phy.media_type == e1000_media_type_fiber || adapterData.hw.phy.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ @@ -345,18 +427,17 @@ void IntelMausi::intelDisable() ctrlExt |= E1000_CTRL_EXT_SDP3_DATA; intelWriteMem32(E1000_CTRL_EXT, ctrlExt); } + if (adapterData.flags & FLAG_IS_ICH) e1000_suspend_workarounds_ich8lan(hw); - + if (adapterData.flags2 & FLAG2_HAS_PHY_WAKEUP) { /* enable wakeup by the PHY */ intelInitPhyWakeup(wufc, &addrData); - DebugLog("[IntelMausi]: Configure wakeup by PHY.\n"); } else { /* enable wakeup by the MAC */ intelInitMacWakeup(wufc, &addrData); - DebugLog("[IntelMausi]: Configure wakeup by MAC.\n"); } DebugLog("[IntelMausi]: WUFC=0x%08x.\n", wufc); @@ -365,26 +446,28 @@ void IntelMausi::intelDisable() intelWriteMem32(E1000_WUC, 0); intelWriteMem32(E1000_WUFC, 0); intelPowerDownPhy(&adapterData); + } - /* ULP seems to cause trouble on I218LM3 and I218V3. Enable it only for I219V/LM. */ - if (hw->mac.type >= e1000_pch_spt) { - if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) - /* ULP does not support wake from unicast, multicast - * or broadcast. - */ - e1000_enable_ulp_lpt_lp(hw, false); + if (adapterData.hw.phy.type == e1000_phy_igp_3) { + e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapterData.hw); + } else if (hw->mac.type >= e1000_pch_lpt) { + if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) { + /* ULP does not support wake from unicast, multicast or broadcast. */ + e1000_enable_ulp_lpt_lp(hw, false); } } - + /* Ensure that the appropriate bits are set in LPI_CTRL * for EEE in Sx */ - if ((hw->phy.type >= e1000_phy_i217) && adapterData.eee_advert && hw->dev_spec.ich8lan.eee_lp_ability) { - UInt16 lpi_ctrl = 0; - + if ((hw->phy.type >= e1000_phy_i217) && + adapterData.eee_advert && hw->dev_spec.ich8lan.eee_lp_ability) { + u16 lpi_ctrl = 0; + retval = hw->phy.ops.acquire(hw); if (!retval) { - retval = e1e_rphy_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); + retval = e1e_rphy_locked(hw, I82579_LPI_CTRL, + &lpi_ctrl); if (!retval) { if (adapterData.eee_advert & hw->dev_spec.ich8lan.eee_lp_ability & @@ -394,7 +477,7 @@ void IntelMausi::intelDisable() hw->dev_spec.ich8lan.eee_lp_ability & I82579_EEE_1000_SUPPORTED) lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; - + retval = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl); (void)retval; @@ -402,324 +485,455 @@ void IntelMausi::intelDisable() } hw->phy.ops.release(hw); } - + if (linkUp) { linkUp = false; setLinkStatus(linkStatus); DebugLog("[IntelMausi]: Link down on en%u\n", netif->getUnitNumber()); } + DebugLog("[IntelMausi]: intelDisable()===>"); } + /** * intelConfigure - configure the hardware for Rx and Tx * @adapter: private board structure - **/ + * + * Reference: e1000_configure (struct e1000_adapter *adapter) + */ void IntelMausi::intelConfigure(struct e1000_adapter *adapter) { setMulticastMode(true); + intelInitManageabilityPt(adapter); - + + /* Setup transmitter */ + intelConfigureTx(adapter); + intelSetupRssHash(adapter); intelVlanStripEnable(adapter); - intelConfigureTx(adapter); + + /* Setup reciever */ intelSetupRxControl(adapter); intelConfigureRx(adapter); } + /** * intelConfigureTx - Configure Transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset. - **/ + * + * Reference: e1000_configure_tx (struct e1000_adapter *adapter) + */ void IntelMausi::intelConfigureTx(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - UInt32 tctl, tarc; - UInt32 txdctl; - + struct e1000_hw *hw = &adapter->hw; + u64 tdba = txPhyAddr; + u32 tdlen = kTxDescSize, tctl, tarc; + u32 txdctl; + /* Setup the HW Tx Head and Tail descriptor pointers */ - intelInitTxRing(); - - /* Set the Tx Interrupt Delay register */ - intelWriteMem32(E1000_TIDV, adapter->tx_int_delay); - /* Tx irq moderation */ - intelWriteMem32(E1000_TADV, adapter->tx_abs_int_delay); - - txdctl = intelReadMem32(E1000_TXDCTL(0)); - - /* Fix TXDCTL to disable descriptor prefetch for 82579, I217, I218 and I219. */ - if (chipType >= board_pch2lan) { - txdctl = 0x01410000; + intelWriteMem32(E1000_TDBAL(0), (tdba & DMA_BIT_MASK(32))); + intelWriteMem32(E1000_TDBAH(0), (tdba >> 32)); + intelWriteMem32(E1000_TDLEN(0), tdlen); + intelWriteMem32(E1000_TDH(0), 0); + intelWriteMem32(E1000_TDT(0), 0); + + txNextDescIndex = txDirtyIndex = txCleanBarrierIndex = 0; + txNumFreeDesc = kNumTxDesc; + + intelUpdateTxDescTail(0); + + /* Set the Tx Interrupt Delay register */ + intelWriteMem32(E1000_TIDV, adapter->tx_int_delay); + /* Tx irq moderation */ + intelWriteMem32(E1000_TADV, adapter->tx_abs_int_delay); + + + if (adapter->flags2 & FLAG2_DMA_BURST) { + txdctl = intelReadMem32(E1000_TXDCTL(0)); + + txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH | + E1000_TXDCTL_WTHRESH); + /* set up some performance related parameters to encourage the + * hardware to use the bus more efficiently in bursts, depends + * on the tx_int_delay to be enabled, + * wthresh = 1 ==> burst write is disabled to avoid Tx stalls + * hthresh = 1 ==> prefetch when one or more available + * pthresh = 0x1f ==> prefetch if internal cache 31 or less + * BEWARE: this seems to work but should be considered first if + * there are Tx hangs or other Tx related bugs + */ + txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; + intelWriteMem32(E1000_TXDCTL(0), txdctl); + } else { + txdctl = intelReadMem32(E1000_TXDCTL(0)); intelWriteMem32(E1000_TXDCTL(0), txdctl); } + /* erratum work around: set txdctl the same for both queues */ intelWriteMem32(E1000_TXDCTL(1), txdctl); - /* Program the Transmit Control Register */ - tctl = intelReadMem32(E1000_TCTL); + /* Program the Transmit Control Register */ + tctl = intelReadMem32(E1000_TCTL); tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - /* errata: program both queues to unweighted RR */ - if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { - tarc = intelReadMem32(E1000_TARC(0)); - tarc |= 1; - intelWriteMem32(E1000_TARC(0), tarc); - tarc = intelReadMem32(E1000_TARC(1)); - tarc |= 1; - intelWriteMem32(E1000_TARC(1), tarc); - } - intelWriteMem32(E1000_TCTL, tctl); - - hw->mac.ops.config_collision_dist(hw); - - /* SPT Si errata workaround to avoid data corruption */ + tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | + (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + + if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { + tarc = intelReadMem32(E1000_TARC(0)); + /* set the speed mode bit, we'll clear it if we're not at + * gigabit link later + */ + tarc |= BIT(21); + intelWriteMem32(E1000_TARC(0), tarc); + } + + /* errata: program both queues to unweighted RR */ + if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { + tarc = intelReadMem32(E1000_TARC(0)); + tarc |= 1; + intelWriteMem32(E1000_TARC(0), tarc); + tarc = intelReadMem32(E1000_TARC(1)); + tarc |= 1; + intelWriteMem32(E1000_TARC(1), tarc); + } + + intelWriteMem32(E1000_TCTL, tctl); + + hw->mac.ops.config_collision_dist(hw); + + /* SPT and KBL Si errata workaround to avoid data corruption */ if (hw->mac.type == e1000_pch_spt) { - UInt32 val; - - val = intelReadMem32(E1000_IOSFPC); - val |= E1000_RCTL_RDMTS_HEX; - intelWriteMem32(E1000_IOSFPC, val); - + u32 reg_val; + + reg_val = intelReadMem32(E1000_IOSFPC); + reg_val |= E1000_RCTL_RDMTS_HEX; + intelWriteMem32(E1000_IOSFPC, reg_val); + + reg_val = intelReadMem32(E1000_TARC(0)); /* * SPT and KBL Si errata workaround to avoid Tx hang. * Dropping the number of outstanding requests from * 3 to 2 in order to avoid a buffer overrun. */ - val = intelReadMem32(E1000_TARC(0)); - val &= ~E1000_TARC0_CB_MULTIQ_3_REQ; - val |= E1000_TARC0_CB_MULTIQ_2_REQ; - intelWriteMem32(E1000_TARC(0), val); + reg_val &= ~E1000_TARC0_CB_MULTIQ_3_REQ; + reg_val |= E1000_TARC0_CB_MULTIQ_2_REQ; + intelWriteMem32(E1000_TARC(0), reg_val); } } + /** * intelSetupRxControl - configure the receive control registers * @adapter: Board private structure - **/ - + * + * Reference: e1000_setup_rctl (struct e1000_adapter *adapter) + */ void IntelMausi::intelSetupRxControl(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - u32 rctl, rfctl; - - /* Workaround Si errata on PCHx - configure jumbo frame flow. - * If jumbo frames not set, program related MAC/PHY registers - * to h/w defaults - */ - if (hw->mac.type >= e1000_pch2lan) { - s32 ret_val; - - if (mtu > ETH_DATA_LEN) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - - if (ret_val) - DebugLog("[IntelMausi]: failed to enable/disable jumbo frame workaround mode.\n"); - } - /* Program MC offset vector base */ - rctl = intelReadMem32(E1000_RCTL); - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); - - /* Do not Store bad packets */ - rctl &= ~E1000_RCTL_SBP; - - /* Enable Long Packet receive */ - if (mtu <= ETH_DATA_LEN) - rctl &= ~E1000_RCTL_LPE; - else - rctl |= E1000_RCTL_LPE; - - /* Some systems expect that the CRC is included in SMBUS traffic. The - * hardware strips the CRC before sending to both SMBUS (BMC) and to - * host memory when this is enabled + struct e1000_hw *hw = &adapter->hw; + u32 rctl, rfctl; + + /* Workaround Si errata on PCHx - configure jumbo frame flow. + * If jumbo frames not set, program related MAC/PHY registers + * to h/w defaults + */ + if (hw->mac.type >= e1000_pch2lan) { + s32 ret_val; + + if (mtu > ETH_DATA_LEN) + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); + else + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); + + if (ret_val) + DebugLog("[IntelMausi]: failed to enable/disable jumbo frame workaround mode.\n"); + } + + /* Program MC offset vector base */ + rctl = intelReadMem32(E1000_RCTL); + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | + E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | + (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + + /* Do not Store bad packets */ + rctl &= ~E1000_RCTL_SBP; + + /* Enable Long Packet receive */ + if (mtu <= ETH_DATA_LEN) + rctl &= ~E1000_RCTL_LPE; + else + rctl |= E1000_RCTL_LPE; + + /* Some systems expect that the CRC is included in SMBUS traffic. The + * hardware strips the CRC before sending to both SMBUS (BMC) and to + * host memory when this is enabled * * We setup hardware to always strip CRC as we want jumbo frame support * anyway even if it breaks management SMBUS traffic on some machines. - */ - rctl |= E1000_RCTL_SECRC; - - /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ - if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { - u16 phy_data; - - e1e_rphy(hw, PHY_REG(770, 26), &phy_data); - phy_data &= 0xfff8; - phy_data |= (1 << 2); - e1e_wphy(hw, PHY_REG(770, 26), phy_data); - - e1e_rphy(hw, 22, &phy_data); - phy_data &= 0x0fff; - phy_data |= (1 << 14); - e1e_wphy(hw, 0x10, 0x2823); - e1e_wphy(hw, 0x11, 0x0003); - e1e_wphy(hw, 22, phy_data); - } - - /* Set buffer sizes to 2048 */ - //rctl |= (0x2 << E1000_RCTL_FLXB_SHIFT); - rctl &= ~(E1000_RCTL_SZ_256 | E1000_RCTL_BSEX); - - /* Enable Extended Status in all Receive Descriptors */ - rfctl = intelReadMem32(E1000_RFCTL); - rfctl |= (E1000_RFCTL_NEW_IPV6_EXT_DIS | E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_EXTEN | E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); - intelWriteMem32(E1000_RFCTL, rfctl); - - intelWriteMem32(E1000_RCTL, rctl); + */ + + + rctl |= E1000_RCTL_SECRC; + // FIXME: Add option for disabling jumbo in favour of CRC header + /*if (adapter->flags2 & FLAG2_CRC_STRIPPING) + rctl |= E1000_RCTL_SECRC; + */ + + /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ + if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { + u16 phy_data; + + e1e_rphy(hw, PHY_REG(770, 26), &phy_data); + phy_data &= 0xfff8; + phy_data |= BIT(2); + e1e_wphy(hw, PHY_REG(770, 26), phy_data); + + e1e_rphy(hw, 22, &phy_data); + phy_data &= 0x0fff; + phy_data |= BIT(14); + e1e_wphy(hw, 0x10, 0x2823); + e1e_wphy(hw, 0x11, 0x0003); + e1e_wphy(hw, 22, phy_data); + } + + /* Setup buffer sizes */ + rctl &= ~E1000_RCTL_SZ_4096; + rctl |= E1000_RCTL_BSEX; + switch (adapter->rx_buffer_len) { + default: + case 2048: + rctl |= E1000_RCTL_SZ_2048; + rctl &= ~E1000_RCTL_BSEX; + break; + case 4096: + rctl |= E1000_RCTL_SZ_4096; + break; + case 8192: + rctl |= E1000_RCTL_SZ_8192; + break; + case 16384: + rctl |= E1000_RCTL_SZ_16384; + break; + } + + /* Enable Extended Status in all Receive Descriptors */ + rfctl = intelReadMem32(E1000_RFCTL); + + if (hw->mac.type == e1000_ich8lan) { + rfctl |= (E1000_RFCTL_NEW_IPV6_EXT_DIS | E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_EXTEN | E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); + } else { + rfctl |= E1000_RFCTL_EXTEN; + } + + intelWriteMem32(E1000_RFCTL, rfctl); + + intelWriteMem32(E1000_RCTL, rctl); + /* just started the receive unit, no need to restart */ + adapter->flags &= ~FLAG_RESTART_NOW; } + /** * intelConfigureRx - Configure Receive Unit after Reset * @adapter: board private structure * * Configure the Rx unit of the MAC after a reset. - **/ + * + * Reference: e1000_configure_rx + */ void IntelMausi::intelConfigureRx(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - u32 rctl, rxcsum, ctrl_ext; - - /* disable receives while setting up the descriptors */ - rctl = intelReadMem32(E1000_RCTL); - - intelFlush(); - usleep_range(10000, 20000); - - /* set the Receive Delay Timer Register */ - intelWriteMem32(E1000_RDTR, adapter->rx_int_delay); - - /* irq moderation */ - intelWriteMem32(E1000_RADV, adapter->rx_abs_int_delay); - + //struct e1000_hw *hw = &adapter->hw; + u64 rdba = rxPhyAddr; + u32 rctl, rxcsum, ctrl_ext, rdlen = kRxDescSize; + + /* disable receives while setting up the descriptors */ + rctl = intelReadMem32(E1000_RCTL); + if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) + intelWriteMem32(E1000_RCTL, rctl & ~E1000_RCTL_EN); + intelFlush(); + + usleep_range(10000, 11000); + + if (adapter->flags2 & FLAG2_DMA_BURST) { + /* set the writeback threshold (only takes effect if the RDTR + * is set). set GRAN=1 and write back up to 0x4 worth, and + * enable prefetching of 0x20 Rx descriptors + * granularity = 01 + * wthresh = 04, + * hthresh = 04, + * pthresh = 0x20 + */ + intelWriteMem32(E1000_RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE); + intelWriteMem32(E1000_RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE); + } + + /* set the Receive Delay Timer Register */ + intelWriteMem32(E1000_RDTR, adapter->rx_int_delay); + + /* irq moderation */ + intelWriteMem32(E1000_RADV, adapter->rx_abs_int_delay); + /* Set interrupt throttle value. */ intelWriteMem32(E1000_ITR, intrThrValue1000); - + /* Auto-Mask interrupts upon ICR access. */ - ctrl_ext = intelReadMem32(E1000_CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_IAME; - intelWriteMem32(E1000_IAM, 0xffffffff); - intelWriteMem32(E1000_CTRL_EXT, ctrl_ext); - e1e_flush(); - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring - */ - intelInitRxRing(); - - /* Enable Receive Checksum Offload for TCP and UDP */ - rxcsum = intelReadMem32(E1000_RXCSUM); + ctrl_ext = intelReadMem32(E1000_CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_IAME; + intelWriteMem32(E1000_IAM, 0xffffffff); + intelWriteMem32(E1000_CTRL_EXT, ctrl_ext); + + intelFlush(); + + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + intelWriteMem32(E1000_RDBAL(0), (rdba & DMA_BIT_MASK(32))); + intelWriteMem32(E1000_RDBAH(0), (rdba >> 32)); + intelWriteMem32(E1000_RDLEN(0), rdlen); + intelWriteMem32(E1000_RDH(0), 0); + intelWriteMem32(E1000_RDT(0), 0); + if (adapterData.flags2 & FLAG2_PCIM2PCI_ARBITER_WA) + intelUpdateRxDescTail(kRxLastDesc); + else + intelWriteMem32(E1000_RDT(0), kRxLastDesc); + + rxCleanedCount = rxNextDescIndex = 0; + + /* Enable Receive Checksum Offload for TCP and UDP */ + rxcsum = intelReadMem32(E1000_RXCSUM); rxcsum |= E1000_RXCSUM_TUOFL; - intelWriteMem32(E1000_RXCSUM, rxcsum); - - /* With jumbo frames, excessive C-state transition latencies result - * in dropped transactions. Latency requirements will be adjusted + intelWriteMem32(E1000_RXCSUM, rxcsum); + + /* With jumbo frames, excessive C-state transition latencies result + * in dropped transactions. Latency requirements will be adjusted * when the link has been established and speed is known. - */ - if ((mtu > ETH_DATA_LEN) && (adapter->flags & FLAG_IS_ICH)) { + */ + if ((mtu > ETH_DATA_LEN) && (adapter->flags & FLAG_IS_ICH)) { u32 rxdctl = intelReadMem32(E1000_RXDCTL(0)); - - intelWriteMem32(E1000_RXDCTL(0), rxdctl | 0x3); + intelWriteMem32(E1000_RXDCTL(0), rxdctl | 0x3 | BIT(8)); } - intelWriteMem32(E1000_RCTL, rctl); + + /* Enable Receives */ + intelWriteMem32(E1000_RCTL, rctl); } + /** * intelDown - quiesce the device and optionally reset the hardware * @adapter: board private structure * @reset: boolean flag to reset the hardware or not + * + * Reference: e1000e_down */ void IntelMausi::intelDown(struct e1000_adapter *adapter, bool reset) { - struct e1000_hw *hw = &adapter->hw; - UInt32 tctl, rctl; - - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer - */ - set_bit(__E1000_DOWN, &adapter->state); - - /* disable receives in the hardware */ - rctl = intelReadMem32(E1000_RCTL); - rctl &= ~E1000_RCTL_EN; - intelWriteMem32(E1000_RCTL, rctl); - - /* disable transmits in the hardware */ - tctl = intelReadMem32(E1000_TCTL); - tctl &= ~E1000_TCTL_EN; - intelWriteMem32(E1000_TCTL, tctl); - - /* flush both disables and wait for them to finish */ - intelFlush(); - usleep_range(10000, 20000); - - intelDisableIRQ(); + struct e1000_hw *hw = &adapter->hw; + u32 tctl, rctl; + + /* signal that we're down so the interrupt handler does not + * reschedule our watchdog timer + */ + set_bit(__E1000_DOWN, &adapter->state); + + /* disable receives in the hardware */ + rctl = intelReadMem32(E1000_RCTL); + if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) + intelWriteMem32(E1000_RCTL, rctl & ~E1000_RCTL_EN); + /* flush and sleep below */ + + /* disable transmits in the hardware */ + tctl = intelReadMem32(E1000_TCTL); + tctl &= ~E1000_TCTL_EN; + intelWriteMem32(E1000_TCTL, tctl); + + /* flush both disables and wait for them to finish */ + intelFlush(); + usleep_range(10000, 11000); + + intelDisableIRQ(); + + spin_lock(&adapter->stats64_lock); updateStatistics(adapter); - - adapter->link_speed = 0; - adapter->link_duplex = 0; - - /* Disable Si errata workaround on PCHx for jumbo frame flow */ - if ((hw->mac.type >= e1000_pch2lan) && (mtu > ETH_DATA_LEN) && e1000_lv_jumbo_workaround_ich8lan(hw, false)) - DebugLog("[IntelMausi]: failed to disable jumbo frame workaround mode\n"); - - if (reset) - intelReset(adapter); + spin_unlock(&adapter->stats64_lock); + + intelFlushDescriptors(); + + adapter->link_speed = 0; + adapter->link_duplex = 0; + + /* Disable Si errata workaround on PCHx for jumbo frame flow */ + if ((hw->mac.type >= e1000_pch2lan) && (mtu > ETH_DATA_LEN) && e1000_lv_jumbo_workaround_ich8lan(hw, false)) + DebugLog("[IntelMausi]: failed to disable jumbo frame workaround mode\n"); + + if (reset) + intelReset(adapter); else if (hw->mac.type >= e1000_pch_spt) intelFlushDescRings(adapter); - + + // Clean tx/rx rings clearDescriptors(); - + if (chipType >= board_pch_lpt) requireMaxBusStall(0); } + +/** + * intelInitManageabilityPt + * + * Reference: e1000_init_manageability_pt + */ void IntelMausi::intelInitManageabilityPt(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - u32 manc, manc2h, mdef, i, j; - - if (!(adapter->flags & FLAG_MNG_PT_ENABLED)) - return; - - manc = intelReadMem32(E1000_MANC); - - /* enable receiving management packets to the host. this will probably - * generate destination unreachable messages from the host OS, but - * the packets will be handled on SMBUS - */ - manc |= E1000_MANC_EN_MNG2HOST; - manc2h = intelReadMem32(E1000_MANC2H); - - switch (hw->mac.type) { + struct e1000_hw *hw = &adapter->hw; + u32 manc, manc2h, mdef, i, j; + + if (!(adapter->flags & FLAG_MNG_PT_ENABLED)) + return; + + manc = intelReadMem32(E1000_MANC); + + /* enable receiving management packets to the host. this will probably + * generate destination unreachable messages from the host OS, but + * the packets will be handled on SMBUS + */ + manc |= E1000_MANC_EN_MNG2HOST; + manc2h = intelReadMem32(E1000_MANC2H); + + switch (hw->mac.type) { default: manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664); break; - + case e1000_82574: case e1000_82583: - /* Check if IPMI pass-through decision filter already exists; + /* + * Check if IPMI pass-through decision filter already exists; * if so, enable it. */ for (i = 0, j = 0; i < 8; i++) { mdef = intelReadMem32(E1000_MDEF(i)); - + /* Ignore filters with anything other than IPMI ports */ if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) continue; - + /* Enable this decision filter in MANC2H */ if (mdef) manc2h |= (1 << i); - + j |= mdef; } - + if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) break; - + /* Create new decision filter in an empty filter */ for (i = 0, j = 0; i < 8; i++) if (intelReadMem32(E1000_MDEF(i)) == 0) { @@ -728,15 +942,16 @@ void IntelMausi::intelInitManageabilityPt(struct e1000_adapter *adapter) j++; break; } - + if (!j) IOLog("[IntelMausi]: Unable to create IPMI pass-through filter.\n"); break; - } - intelWriteMem32(E1000_MANC2H, manc2h); - intelWriteMem32(E1000_MANC, manc); + } + intelWriteMem32(E1000_MANC2H, manc2h); + intelWriteMem32(E1000_MANC, manc); } + /** * intelReset - bring the hardware into a known good state * @@ -744,77 +959,80 @@ void IntelMausi::intelInitManageabilityPt(struct e1000_adapter *adapter) * require a configuration cycle of the hardware - those cannot be * set/changed during runtime. After reset the device needs to be * properly configured for Rx, Tx etc. + * + * Reference: e1000e_reset */ void IntelMausi::intelReset(struct e1000_adapter *adapter) { - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_fc_info *fc = &adapter->hw.fc; - struct e1000_hw *hw = &adapter->hw; - u32 tx_space, min_tx_space, min_rx_space; - u32 pba = adapter->pba; - u16 hwm; - - /* reset Packet Buffer Allocation to default */ - intelWriteMem32(E1000_PBA, pba); - - if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { - /* To maintain wire speed transmits, the Tx FIFO should be - * large enough to accommodate two full transmit packets, - * rounded up to the next 1KB and expressed in KB. Likewise, - * the Rx FIFO should be large enough to accommodate at least - * one full receive packet and is similarly rounded up and - * expressed in KB. - */ - pba = intelReadMem32(E1000_PBA); - /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = pba >> 16; - /* lower 16 bits has Rx packet buffer allocation size in KB */ - pba &= 0xffff; - /* the Tx fifo also stores 16 bytes of information about the Tx - * but don't include ethernet FCS because hardware appends it - */ - min_tx_space = (adapter->max_frame_size + + struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_fc_info *fc = &adapter->hw.fc; + struct e1000_hw *hw = &adapter->hw; + u32 tx_space, min_tx_space, min_rx_space; + u32 pba = adapter->pba; + u16 hwm; + + /* reset Packet Buffer Allocation to default */ + intelWriteMem32(E1000_PBA, pba); + + if (adapter->max_frame_size > VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) { + /* To maintain wire speed transmits, the Tx FIFO should be + * large enough to accommodate two full transmit packets, + * rounded up to the next 1KB and expressed in KB. Likewise, + * the Rx FIFO should be large enough to accommodate at least + * one full receive packet and is similarly rounded up and + * expressed in KB. + */ + pba = intelReadMem32(E1000_PBA); + /* upper 16 bits has Tx packet buffer allocation size in KB */ + tx_space = pba >> 16; + /* lower 16 bits has Rx packet buffer allocation size in KB */ + pba &= 0xffff; + /* the Tx fifo also stores 16 bytes of information about the Tx + * but don't include ethernet FCS because hardware appends it + */ + min_tx_space = (adapter->max_frame_size + sizeof(struct e1000_tx_desc) - ETH_FCS_LEN) * 2; - min_tx_space = ALIGN(min_tx_space, 1024); - min_tx_space >>= 10; - /* software strips receive CRC, so leave room for it */ - min_rx_space = adapter->max_frame_size; - min_rx_space = ALIGN(min_rx_space, 1024); - min_rx_space >>= 10; - - /* If current Tx allocation is less than the min Tx FIFO size, - * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation - */ - if ((tx_space < min_tx_space) && - ((min_tx_space - tx_space) < pba)) { - pba -= min_tx_space - tx_space; - - /* if short on Rx space, Rx wins and must trump Tx - * adjustment - */ - if (pba < min_rx_space) - pba = min_rx_space; - } - intelWriteMem32(E1000_PBA, pba); - } - - /* flow control settings - * - * The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus one full frame - */ - if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) - fc->pause_time = 0xFFFF; - else - fc->pause_time = E1000_FC_PAUSE_TIME; - fc->send_xon = true; - fc->current_mode = fc->requested_mode; - - switch (hw->mac.type) { + min_tx_space = ALIGN(min_tx_space, 1024); + min_tx_space >>= 10; + /* software strips receive CRC, so leave room for it */ + min_rx_space = adapter->max_frame_size; + min_rx_space = ALIGN(min_rx_space, 1024); + min_rx_space >>= 10; + + /* If current Tx allocation is less than the min Tx FIFO size, + * and the min Tx FIFO size is less than the current Rx FIFO + * allocation, take space away from current Rx allocation + */ + if ((tx_space < min_tx_space) && + ((min_tx_space - tx_space) < pba)) { + pba -= min_tx_space - tx_space; + + /* if short on Rx space, Rx wins and must trump Tx + * adjustment + */ + if (pba < min_rx_space) + pba = min_rx_space; + } + + intelWriteMem32(E1000_PBA, pba); + } + + /* flow control settings + * + * The high water mark must be low enough to fit one full frame + * (or the size used for early receive) above it in the Rx FIFO. + * Set it to the lower of: + * - 90% of the Rx FIFO size, and + * - the full Rx FIFO size minus one full frame + */ + if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) + fc->pause_time = 0xFFFF; + else + fc->pause_time = E1000_FC_PAUSE_TIME; + fc->send_xon = true; + fc->current_mode = fc->requested_mode; + + switch (hw->mac.type) { case e1000_ich9lan: case e1000_ich10lan: if (mtu > ETH_DATA_LEN) { @@ -828,8 +1046,8 @@ void IntelMausi::intelReset(struct e1000_adapter *adapter) default: hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - adapter->max_frame_size)); - - fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ + + fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ fc->low_water = fc->high_water - 8; break; case e1000_pchlan: @@ -849,60 +1067,67 @@ void IntelMausi::intelReset(struct e1000_adapter *adapter) case e1000_pch_lpt: case e1000_pch_spt: case e1000_pch_cnp: - fc->refresh_time = 0x0400; - + case e1000_pch_tgp: + case e1000_pch_adp: + case e1000_pch_mtp: + fc->refresh_time = 0xFFFF; + fc->pause_time = 0xFFFF; + if (mtu <= ETH_DATA_LEN) { fc->high_water = 0x05C20; fc->low_water = 0x05048; - fc->pause_time = 0x0650; break; } - + pba = 14; intelWriteMem32(E1000_PBA, pba); fc->high_water = ((pba << 10) * 9 / 10) & E1000_FCRTH_RTH; fc->low_water = ((pba << 10) * 8 / 10) & E1000_FCRTL_RTL; break; - } - - /* Alignment of Tx data is on an arbitrary byte boundary with the - * maximum size per Tx descriptor limited only to the transmit - * allocation of the packet buffer minus 96 bytes with an upper - * limit of 24KB due to receive synchronization limitations. - */ - adapter->tx_fifo_limit = min_t(u32, ((intelReadMem32(E1000_PBA) >> 16) << 10) - 96, + } + + /* Alignment of Tx data is on an arbitrary byte boundary with the + * maximum size per Tx descriptor limited only to the transmit + * allocation of the packet buffer minus 96 bytes with an upper + * limit of 24KB due to receive synchronization limitations. + */ + adapter->tx_fifo_limit = min_t(u32, ((intelReadMem32(E1000_PBA) >> 16) << 10) - 96, 24 << 10); - + /* Set interrupt throttle value. */ intelWriteMem32(E1000_ITR, intrThrValue100); - + if (hw->mac.type >= e1000_pch_spt) intelFlushDescRings(adapter); + //e1000_flush_desc_rings(adapter); + + /* Allow time for pending master requests to run */ + mac->ops.reset_hw(hw); + + /* We force aknowlegment that the network interface is in control */ + e1000e_get_hw_control(adapter); + + intelWriteMem32(E1000_WUC, 0); + + if (mac->ops.init_hw(hw)) + IOLog("[IntelMausi]: Hardware Error.\n"); + + //e1000_update_mng_vlan(adapter); - /* Allow time for pending master requests to run */ - mac->ops.reset_hw(hw); - - intelWriteMem32(E1000_WUC, 0); - - if (mac->ops.init_hw(hw)) - IOLog("[IntelMausi]: Hardware Error.\n"); - - //e1000_update_mng_vlan(adapter); - - /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ - intelWriteMem32(E1000_VET, ETH_P_8021Q); - - intelResetAdaptive(hw); - - /* initialize systim and reset the ns time counter */ - //e1000e_config_hwtstamp(adapter, &adapter->hwtstamp_config); - - /* Set EEE advertisement as appropriate */ - if (adapter->flags2 & FLAG2_HAS_EEE) { - s32 ret_val; - u16 adv_addr; - - switch (hw->phy.type) { + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + intelWriteMem32(E1000_VET, ETH_P_8021Q); + + intelResetAdaptive(hw); + + /* restore systim and hwtstamp settings */ + //e1000e_systim_reset(adapter); + + /* Set EEE advertisement as appropriate */ + if (adapter->flags2 & FLAG2_HAS_EEE) { + s32 ret_val; + u16 adv_addr; + + switch (hw->phy.type) { case e1000_phy_82579: adv_addr = I82579_EEE_ADVERTISEMENT; break; @@ -912,209 +1137,256 @@ void IntelMausi::intelReset(struct e1000_adapter *adapter) default: IOLog("[IntelMausi]: Invalid PHY type setting EEE advertisement.\n"); return; - } - - ret_val = hw->phy.ops.acquire(hw); - - if (ret_val) { - IOLog("[IntelMausi]: EEE advertisement - unable to acquire PHY.\n"); - return; - } - e1000_write_emi_reg_locked(hw, adv_addr, hw->dev_spec.ich8lan.eee_disable ? 0 : adapter->eee_advert); - hw->phy.ops.release(hw); - } - e1000_get_phy_info(hw); - - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && !(adapter->flags & FLAG_SMART_POWER_DOWN)) { - u16 phy_data = 0; - /* speed up time to link by disabling smart power down, ignore - * the return value of this function because there is nothing - * different we would do if it failed - */ - e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - phy_data &= ~IGP02E1000_PM_SPD; - e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); - } + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + IOLog("[IntelMausi]: EEE advertisement - unable to acquire PHY.\n"); + return; + } + + e1000_write_emi_reg_locked(hw, adv_addr, + hw->dev_spec.ich8lan.eee_disable ? + 0 : adapter->eee_advert); + + hw->phy.ops.release(hw); + } + e1000_get_phy_info(hw); + + if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && + !(adapter->flags & FLAG_SMART_POWER_DOWN)) { + u16 phy_data = 0; + /* speed up time to link by disabling smart power down, ignore + * the return value of this function because there is nothing + * different we would do if it failed + */ + e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); + phy_data &= ~IGP02E1000_PM_SPD; + e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); + } } + /** * intelPowerDownPhy - Power down the PHY * * Power down the PHY so no link is implied when interface is down. * The PHY cannot be powered down if management or WoL is active. + * + * Reference: e1000_power_down_phy */ void IntelMausi::intelPowerDownPhy(struct e1000_adapter *adapter) { - if (adapter->hw.phy.ops.power_down) - adapter->hw.phy.ops.power_down(&adapter->hw); + if (adapter->hw.phy.ops.power_down) + adapter->hw.phy.ops.power_down(&adapter->hw); } + /** * intelEnableMngPassThru - Check if management passthrough is needed * @hw: pointer to the HW structure * * Verifies the hardware needs to leave interface enabled so that frames can * be directed to and from the management interface. - **/ + * + * Reference: e1000e_enable_mng_pass_thru + */ bool IntelMausi::intelEnableMngPassThru(struct e1000_hw *hw) { - u32 manc; - u32 fwsm, factps; - - manc = intelReadMem32(E1000_MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN)) - return false; - - if (hw->mac.has_fwsm) { - fwsm = intelReadMem32(E1000_FWSM); - factps = intelReadMem32(E1000_FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) - return true; - } else if ((manc & E1000_MANC_SMBUS_EN) && + u32 manc; + u32 fwsm, factps; + + manc = intelReadMem32(E1000_MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN)) + return false; + + if (hw->mac.has_fwsm) { + fwsm = intelReadMem32(E1000_FWSM); + factps = intelReadMem32(E1000_FACTPS); + + if (!(factps & E1000_FACTPS_MNGCG) && + ((fwsm & E1000_FWSM_MODE_MASK) == + (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) + return true; + } else if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) { - return true; - } - - return false; + return true; + } + + return false; } + /** * intelResetAdaptive - Reset Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Reset the Adaptive Interframe Spacing throttle to default values. + * + * Reference: e1000e_reset_adaptive **/ void IntelMausi::intelResetAdaptive(struct e1000_hw *hw) { - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - DebugLog("[IntelMausi]: Not in Adaptive IFS mode!\n"); - return; - } - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - intelWriteMem32(E1000_AIT, 0); + struct e1000_mac_info *mac = &hw->mac; + + if (!mac->adaptive_ifs) { + DebugLog("[IntelMausi]: Not in Adaptive IFS mode!\n"); + return; + } + mac->current_ifs_val = 0; + mac->ifs_min_val = IFS_MIN; + mac->ifs_max_val = IFS_MAX; + mac->ifs_step_size = IFS_STEP; + mac->ifs_ratio = IFS_RATIO; + + mac->in_ifs_mode = false; + intelWriteMem32(E1000_AIT, 0); } + /** * intelUpdateAdaptive - Update Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Update the Adaptive Interframe Spacing Throttle value based on the * time between transmitted packets and time between collisions. - **/ + * + * Reference: e1000e_update_adaptive + */ void IntelMausi::intelUpdateAdaptive(struct e1000_hw *hw) { - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - DebugLog("[IntelMausi]: Not in Adaptive IFS mode!\n"); - return; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += mac->ifs_step_size; - - intelWriteMem32(E1000_AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - intelWriteMem32(E1000_AIT, 0); - } - } + struct e1000_mac_info *mac = &hw->mac; + + if (!mac->adaptive_ifs) { + DebugLog("[IntelMausi]: Not in Adaptive IFS mode!\n"); + return; + } + + if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { + if (mac->tx_packet_delta > MIN_NUM_XMITS) { + mac->in_ifs_mode = true; + if (mac->current_ifs_val < mac->ifs_max_val) { + if (!mac->current_ifs_val) + mac->current_ifs_val = mac->ifs_min_val; + else + mac->current_ifs_val += mac->ifs_step_size; + + intelWriteMem32(E1000_AIT, mac->current_ifs_val); + } + } + } else { + if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { + mac->current_ifs_val = 0; + mac->in_ifs_mode = false; + intelWriteMem32(E1000_AIT, 0); + } + } } + /** * intelVlanStripDisable - helper to disable HW VLAN stripping * @adapter: board private structure to initialize - **/ + * + * Reference: e1000e_vlan_strip_disable + */ void IntelMausi::intelVlanStripDisable(struct e1000_adapter *adapter) { - UInt32 ctrl; - - /* disable VLAN tag insert/strip */ - ctrl = intelReadMem32(E1000_CTRL); - ctrl &= ~E1000_CTRL_VME; - intelWriteMem32(E1000_CTRL, ctrl); + u32 ctrl; + + /* disable VLAN tag insert/strip */ + ctrl = intelReadMem32(E1000_CTRL); + ctrl &= ~E1000_CTRL_VME; + intelWriteMem32(E1000_CTRL, ctrl); } + /** * intelVlanStripEnable - helper to enable HW VLAN stripping * @adapter: board private structure to initialize - **/ + * + * Reference: e1000e_vlan_strip_enable + */ void IntelMausi::intelVlanStripEnable(struct e1000_adapter *adapter) { - UInt32 ctrl; - - /* enable VLAN tag insert/strip */ - ctrl = intelReadMem32(E1000_CTRL); - ctrl |= E1000_CTRL_VME; - intelWriteMem32(E1000_CTRL, ctrl); + u32 ctrl; + + /* enable VLAN tag insert/strip */ + ctrl = intelReadMem32(E1000_CTRL); + ctrl |= E1000_CTRL_VME; + intelWriteMem32(E1000_CTRL, ctrl); +} + + +/** + * intelRssKeyFill - helper to fill RSS key hash + * @buffer: buffer to fill + * @len: size of buffer, should be <= INTEL_RSS_KEY_LEN (52) + * + * Reference: netdev_rss_key_fill + */ +void IntelMausi::intelRssKeyFill(void *buffer, size_t len) +{ + assert(len > sizeof(rssHashKey)); + if (isRssSet) { + memcpy(buffer, rssHashKey, len); + } else { + random_buf(rssHashKey, sizeof(rssHashKey)); + memcpy(buffer, rssHashKey, len); + isRssSet = true; + } } -static const u32 rsskey[10] = { - 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0, - 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe -}; +/** + * intelSetupRssHash + * + * Reference: e1000e_setup_rss_hash + */ void IntelMausi::intelSetupRssHash(struct e1000_adapter *adapter) { - UInt32 mrqc, rxcsum; - int i; - - for (i = 0; i < 10; i++) - intelWriteMem32(E1000_RSSRK(i), rsskey[i]); - - /* Direct all traffic to queue 0 */ - for (i = 0; i < 32; i++) - intelWriteMem32(E1000_RETA(i), 0); - - /* Disable raw packet checksumming so that RSS hash is placed in - * descriptor on writeback. - */ - rxcsum = intelReadMem32(E1000_RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - - intelWriteMem32(E1000_RXCSUM, rxcsum); - - mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | + u32 mrqc, rxcsum; + u32 rss_key[10]; + int i; + + intelRssKeyFill(rss_key, sizeof(rss_key)); + + for (i = 0; i < 10; i++) + intelWriteMem32(E1000_RSSRK(i), rss_key[i]); + + /* Direct all traffic to queue 0 */ + for (i = 0; i < 32; i++) + intelWriteMem32(E1000_RETA(i), 0); + + /* Disable raw packet checksumming so that RSS hash is placed in + * descriptor on writeback. + */ + rxcsum = intelReadMem32(E1000_RXCSUM); + rxcsum |= E1000_RXCSUM_PCSD; + + intelWriteMem32(E1000_RXCSUM, rxcsum); + + mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | E1000_MRQC_RSS_FIELD_IPV4_TCP | E1000_MRQC_RSS_FIELD_IPV6 | E1000_MRQC_RSS_FIELD_IPV6_TCP | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); - - mrqc |= 0x01; - intelWriteMem32(E1000_MRQC, mrqc); + + intelWriteMem32(E1000_MRQC, mrqc); } -/* Reset the NIC in case a tx deadlock or a pci error occurred. timerSource and txQueue +/** + * intelRestart + * + * Reset the NIC in case a tx deadlock or a pci error occurred. timerSource and txQueue * are stopped immediately but will be restarted by checkLinkStatus() when the link has * been reestablished. */ - void IntelMausi::intelRestart() { - + #ifdef __PRIVATE_SPI__ /* Stop output thread and flush txQueue */ netif->stopOutputThread(); @@ -1126,74 +1398,55 @@ void IntelMausi::intelRestart() #endif /* __PRIVATE_SPI__ */ /* Also set the link status to down. */ - if (linkUp) + if (linkUp) { DebugLog("[IntelMausi]: Link down on en%u\n", netif->getUnitNumber()); + } setLinkStatus(kIONetworkLinkValid); linkUp = false; /* Reset NIC and cleanup both descriptor rings. */ intelDisableIRQ(); - intelReset(&adapterData); - + intelReset(&adapterData); + clearDescriptors(); rxCleanedCount = rxNextDescIndex = 0; deadlockWarn = 0; forceReset = false; eeeMode = 0; + /* From here on the code is the same as e1000e_up() */ + /* Reinitialize NIC. */ intelConfigure(&adapterData); - - /* From here on the code is the same as e1000e_up() */ - clear_bit(__E1000_DOWN, &adapterData.state); - - intelEnableIRQ(intrMask); - - adapterData.hw.mac.get_link_status = true; -} -void IntelMausi::intelInitTxRing() -{ - intelWriteMem32(E1000_TDBAL(0), (txPhyAddr & 0xffffffff)); - intelWriteMem32(E1000_TDBAH(0), (txPhyAddr >> 32)); - intelWriteMem32(E1000_TDLEN(0), kTxDescSize); - intelWriteMem32(E1000_TDH(0), 0); - intelWriteMem32(E1000_TDT(0), 0); - txNextDescIndex = txDirtyIndex = txCleanBarrierIndex = 0; - txNumFreeDesc = kNumTxDesc; -} + clear_bit(__E1000_DOWN, &adapterData.state); -void IntelMausi::intelInitRxRing() -{ - intelWriteMem32(E1000_RDBAL(0), (rxPhyAddr & 0xffffffff)); - intelWriteMem32(E1000_RDBAH(0), (rxPhyAddr >> 32)); - intelWriteMem32(E1000_RDLEN(0), kRxDescSize); - intelWriteMem32(E1000_RDH(0), 0); - - if (adapterData.flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - intelUpdateRxDescTail(kRxLastDesc); - else - intelWriteMem32(E1000_RDT(0), kRxLastDesc); - - rxCleanedCount = rxNextDescIndex = 0; + intelEnableIRQ(&adapterData); + + adapterData.hw.mac.get_link_status = true; } + +/** + * intelUpdateTxDescTail + * + * Reference: e1000e_update_tdt_wa + */ void IntelMausi::intelUpdateTxDescTail(UInt32 index) { if (adapterData.flags2 & FLAG2_PCIM2PCI_ARBITER_WA) { struct e1000_hw *hw = &adapterData.hw; s32 ret = __ew32_prepare(hw); - + intelWriteMem32(E1000_TDT(0),index); - + if (!ret && (index != intelReadMem32(E1000_TDT(0)))) { - UInt32 tctl = intelReadMem32(E1000_TCTL); - + u32 tctl = intelReadMem32(E1000_TCTL); + intelWriteMem32(E1000_TCTL, tctl & ~E1000_TCTL_EN); - forceReset = true; - IOLog("[IntelMausi]: ME firmware caused invalid TDT - resetting.\n"); + forceReset = true; } } else { intelWriteMem32(E1000_TDT(0), index); @@ -1201,52 +1454,70 @@ void IntelMausi::intelUpdateTxDescTail(UInt32 index) txCleanBarrierIndex = txNextDescIndex; } + +/** + * intelUpdateRxDescTail + * + * Reference: e1000e_update_rdt_wa + */ void IntelMausi::intelUpdateRxDescTail(UInt32 index) { struct e1000_hw *hw = &adapterData.hw; - SInt32 ret = __ew32_prepare(hw); - + s32 ret = __ew32_prepare(hw); + intelWriteMem32(E1000_RDT(0),index); - + if (!ret && (index != intelReadMem32(E1000_RDT(0)))) { UInt32 rctl = intelReadMem32(E1000_RCTL); - + intelWriteMem32(E1000_RCTL, rctl & ~E1000_RCTL_EN); - forceReset = true; - IOLog("[IntelMausi]: ME firmware caused invalid RDT - resetting.\n"); + forceReset = true; } } + +/** + * intelEnablePCIDevice + */ inline void IntelMausi::intelEnablePCIDevice(IOPCIDevice *provider) { UInt16 cmdReg; - + cmdReg = provider->extendedConfigRead16(kIOPCIConfigCommand); cmdReg |= (kIOPCICommandBusMaster | kIOPCICommandMemorySpace); cmdReg &= ~kIOPCICommandIOSpace; - provider->extendedConfigWrite16(kIOPCIConfigCommand, cmdReg); + provider->extendedConfigWrite16(kIOPCIConfigCommand, cmdReg); + + IOSleep(10); } + +/** + * intelFlushDescriptors + * + * Reference: e1000e_flush_descriptors + */ void IntelMausi::intelFlushDescriptors() { /* flush pending descriptor writebacks to memory */ intelWriteMem32(E1000_TIDV, adapterData.tx_int_delay | E1000_TIDV_FPD); - //intelWriteMem32(E1000_RDTR, adapterData.rx_int_delay | E1000_RDTR_FPD); - + intelWriteMem32(E1000_RDTR, adapterData.rx_int_delay | E1000_RDTR_FPD); + /* execute the writes immediately */ intelFlush(); - + /* due to rare timing issues, write to TIDV/RDTR again to ensure the * write is successful */ intelWriteMem32(E1000_TIDV, adapterData.tx_int_delay | E1000_TIDV_FPD); - //intelWriteMem32(E1000_RDTR, adapterData.rx_int_delay | E1000_RDTR_FPD); - + intelWriteMem32(E1000_RDTR, adapterData.rx_int_delay | E1000_RDTR_FPD); + /* execute the writes immediately */ intelFlush(); } + /** * intelFlushTxRing - remove all descriptors from the tx_ring * @@ -1254,20 +1525,22 @@ void IntelMausi::intelFlushDescriptors() * zeroing happens when the HW reads the regs. We assign the ring itself as * the data of the next descriptor. We don't care about the data we are about * to reset the HW. + * + * Reference: e1000_flush_tx_ring(struct e1000_adapter *adapter) */ void IntelMausi::intelFlushTxRing(struct e1000_adapter *adapter) { struct e1000_data_desc *desc = NULL; - UInt32 tdt, tctl, txdLower = E1000_TXD_CMD_IFCS; - UInt16 size = 512; - + u32 tdt, tctl, txd_lower = E1000_TXD_CMD_IFCS; + u16 size = 512; + tctl = intelReadMem32(E1000_TCTL); intelWriteMem32(E1000_TCTL, tctl | E1000_TCTL_EN); tdt = intelReadMem32(E1000_TDT(0)); - + if (tdt != txNextDescIndex) { IOLog("[IntelMausi]: Failed to flush tx descriptor ring.\n"); - goto done; + return; } DebugLog("[IntelMausi]: Flushing tx descriptor ring.\n"); @@ -1276,42 +1549,42 @@ void IntelMausi::intelFlushTxRing(struct e1000_adapter *adapter) txNextDescIndex &= kTxDescMask; desc->buffer_addr = OSSwapHostToLittleInt64(txPhyAddr); - desc->lower.data = OSSwapHostToLittleInt32(txdLower | size); + desc->lower.data = OSSwapHostToLittleInt32(txd_lower | size); desc->upper.data = 0; - + intelWriteMem32(E1000_TDT(0), txNextDescIndex); intelFlush(); usleep_range(200, 250); - -done: - return; } + /** * intelFlushRxRing - remove all descriptors from the rx_ring * * Mark all descriptors in the RX ring as consumed and disable the rx ring + * + * Reference: e1000_flush_rx_ring(struct e1000_adapter *adapter) */ void IntelMausi::intelFlushRxRing(struct e1000_adapter *adapter) { - UInt32 rctl, rxdctl; - + u32 rctl, rxdctl; + DebugLog("[IntelMausi]: Flushing rx descriptor ring.\n"); rctl = intelReadMem32(E1000_RCTL); intelWriteMem32(E1000_RCTL, rctl & ~E1000_RCTL_EN); intelFlush(); usleep_range(100, 150); - + rxdctl = intelReadMem32(E1000_RXDCTL(0)); /* zero the lower 14 bits (prefetch and host thresholds) */ rxdctl &= 0xffffc000; - + /* update thresholds: prefetch threshold to 31, host threshold to 1 * and make sure the granularity is "descriptors" and not "cache lines" */ - rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC); - + rxdctl |= (0x1F | BIT(8) | E1000_RXDCTL_THRESH_UNIT_DESC); + intelWriteMem32(E1000_RXDCTL(0), rxdctl); /* momentarily enable the RX ring for the changes to take effect */ intelWriteMem32(E1000_RCTL, rctl | E1000_RCTL_EN); @@ -1320,6 +1593,7 @@ void IntelMausi::intelFlushRxRing(struct e1000_adapter *adapter) intelWriteMem32(E1000_RCTL, rctl & ~E1000_RCTL_EN); } + /** * intelFlushDescRings - remove all descriptors from the descriptor rings * @@ -1329,48 +1603,51 @@ void IntelMausi::intelFlushRxRing(struct e1000_adapter *adapter) * Failure to do this will cause the HW to enter a unit hang state which can * only be released by PCI reset on the device * + * Reference: e1000_flush_desc_rings */ - void IntelMausi::intelFlushDescRings(struct e1000_adapter *adapter) { - UInt16 hangState; + u16 hang_state; u32 fext_nvm11, tdlen; struct e1000_hw *hw = &adapter->hw; - + /* First, disable MULR fix in FEXTNVM11 */ fext_nvm11 = intelReadMem32(E1000_FEXTNVM11); fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; ew32(FEXTNVM11, fext_nvm11); /* do nothing if we're not in faulty state, or if the queue is empty */ tdlen = er32(TDLEN(0)); - hangState = pciDevice->extendedConfigRead16(PCICFG_DESC_RING_STATUS); + hang_state = pciDevice->extendedConfigRead16(PCICFG_DESC_RING_STATUS); + + if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen) + return; - if (!(hangState & FLUSH_DESC_REQUIRED) || !tdlen) - goto done; - intelFlushTxRing(adapter); /* recheck, maybe the fault is caused by the rx ring */ - hangState = pciDevice->extendedConfigRead16(PCICFG_DESC_RING_STATUS); + hang_state = pciDevice->extendedConfigRead16(PCICFG_DESC_RING_STATUS); - if (hangState & FLUSH_DESC_REQUIRED) + if (hang_state & FLUSH_DESC_REQUIRED) intelFlushRxRing(adapter); - -done: - return; } + +/** + * intelCheckLink + * + * Reference: e1000e_has_link + */ bool IntelMausi::intelCheckLink(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - bool link_active = false; - s32 ret_val = 0; - - /* get_link_status is set on LSC (link status) interrupt or - * Rx sequence error interrupt. get_link_status will stay - * false until the check_for_link establishes link - * for copper adapters ONLY - */ - switch (hw->phy.media_type) { + struct e1000_hw *hw = &adapter->hw; + bool link_active = false; + s32 ret_val = 0; + + /* get_link_status is set on LSC (link status) interrupt or + * Rx sequence error interrupt. get_link_status will stay + * true until the check_for_link establishes link + * for copper adapters ONLY + */ + switch (hw->phy.media_type) { case e1000_media_type_copper: if (hw->mac.get_link_status) { ret_val = hw->mac.ops.check_for_link(hw); @@ -1385,318 +1662,339 @@ bool IntelMausi::intelCheckLink(struct e1000_adapter *adapter) break; case e1000_media_type_internal_serdes: ret_val = hw->mac.ops.check_for_link(hw); - link_active = adapter->hw.mac.serdes_has_link; + link_active = hw->mac.serdes_has_link; break; default: case e1000_media_type_unknown: break; - } - if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && - (intelReadMem32(E1000_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { - /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ - IOLog("[IntelMausi]: Gigabit has been disabled, downgrading speed.\n"); - } - return link_active; + } + + if ((ret_val == -E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && + (intelReadMem32(E1000_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { + /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ + IOLog("[IntelMausi]: Gigabit has been disabled, downgrading speed.\n"); + } + + return link_active; } + /** * intelPhyReadStatus - Update the PHY register status snapshot * @adapter: board private structure - **/ + * + * Reference: e1000_phy_read_status(struct e1000_adapter *adapter) + */ void IntelMausi::intelPhyReadStatus(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - struct e1000_phy_regs *phy = &adapter->phy_regs; - - if ((intelReadMem32(E1000_STATUS) & E1000_STATUS_LU) && - (adapter->hw.phy.media_type == e1000_media_type_copper)) { - int ret_val; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); - ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); - ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); - ret_val |= e1e_rphy(hw, MII_LPA, &phy->lpa); - ret_val |= e1e_rphy(hw, MII_EXPANSION, &phy->expansion); - ret_val |= e1e_rphy(hw, MII_CTRL1000, &phy->ctrl1000); - ret_val |= e1e_rphy(hw, MII_STAT1000, &phy->stat1000); - ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); - - if (ret_val) - IOLog("[IntelMausi]: Error reading PHY register.\n"); - } else { - /* Do not read PHY registers if link is not up - * Set values to typical power-on defaults - */ - phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); - phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | + struct e1000_hw *hw = &adapter->hw; + struct e1000_phy_regs *phy = &adapter->phy_regs; + + + if ((intelReadMem32(E1000_STATUS) & E1000_STATUS_LU) && + (adapter->hw.phy.media_type == e1000_media_type_copper)) { + int ret_val; + + ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); + ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); + ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); + ret_val |= e1e_rphy(hw, MII_LPA, &phy->lpa); + ret_val |= e1e_rphy(hw, MII_EXPANSION, &phy->expansion); + ret_val |= e1e_rphy(hw, MII_CTRL1000, &phy->ctrl1000); + ret_val |= e1e_rphy(hw, MII_STAT1000, &phy->stat1000); + ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); + + if (ret_val) + IOLog("[IntelMausi]: Error reading PHY register.\n"); + } else { + /* Do not read PHY registers if link is not up + * Set values to typical power-on defaults + */ + phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); + phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | BMSR_ERCAP); - phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | + phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA); - phy->lpa = 0; - phy->expansion = EXPANSION_ENABLENPAGE; - phy->ctrl1000 = ADVERTISE_1000FULL; - phy->stat1000 = 0; - phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); - } + phy->lpa = 0; + phy->expansion = EXPANSION_ENABLENPAGE; + phy->ctrl1000 = ADVERTISE_1000FULL; + phy->stat1000 = 0; + phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); + } } + +/** + * intelInitPhyWakeup + * + * Reference: e1000_init_phy_wakeup + */ void IntelMausi::intelInitPhyWakeup(UInt32 wufc, struct IntelAddrData *addrData) { struct e1000_hw *hw = &adapterData.hw; - UInt32 i, mac_reg, wuc, ad, num; - int error; - UInt16 phy_reg, wuc_enable, av; - + u32 i, mac_reg, wuc; + u16 phy_reg, wuc_enable; + u16 av; + u32 ad, num; + int retval; + /* copy MAC RARs to PHY RARs */ e1000_copy_rx_addrs_to_phy_ich8lan(hw); - - error = hw->phy.ops.acquire(hw); - - if (error) { + + retval = hw->phy.ops.acquire(hw); + if (retval) { DebugLog("[IntelMausi]: Failed to acquire PHY.\n"); return; } - + /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */ - error = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - - if (error) { + retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable); + if (retval) { DebugLog("[IntelMausi]: Failed to access PHY wakeup registers.\n"); goto release; } - + /* copy MAC MTA to PHY MTA - only needed for pchlan */ - for (i = 0; i < hw->mac.mta_reg_count; i++) { + for (i = 0; i < adapterData.hw.mac.mta_reg_count; i++) { mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); hw->phy.ops.write_reg_page(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF)); } - + /* configure PHY Rx Control register */ - hw->phy.ops.read_reg_page(hw, BM_RCTL, &phy_reg); + hw->phy.ops.read_reg_page(&adapterData.hw, BM_RCTL, &phy_reg); mac_reg = intelReadMem32(E1000_RCTL); - if (mac_reg & E1000_RCTL_UPE) phy_reg |= BM_RCTL_UPE; - if (mac_reg & E1000_RCTL_MPE) phy_reg |= BM_RCTL_MPE; - phy_reg &= ~(BM_RCTL_MO_MASK); - if (mac_reg & E1000_RCTL_MO_3) - phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) << BM_RCTL_MO_SHIFT); - + phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) + << BM_RCTL_MO_SHIFT); if (mac_reg & E1000_RCTL_BAM) phy_reg |= BM_RCTL_BAM; - if (mac_reg & E1000_RCTL_PMCF) phy_reg |= BM_RCTL_PMCF; - mac_reg = intelReadMem32(E1000_CTRL); - if (mac_reg & E1000_CTRL_RFCE) phy_reg |= BM_RCTL_RFCE; - - /* Disable slave access to activate filters */ - phy_reg &= ~BM_RCTL_SAE; + + if (enableWoM) { + /* Disable slave access to activate filters */ + phy_reg &= ~BM_RCTL_SAE; + } + + /* Configure PHY rx control */ + DebugLog("[IntelMausi]: PHY RCTL = 0x%04x.\n", phy_reg); + hw->phy.ops.write_reg_page(hw, BM_RCTL, phy_reg); wuc = E1000_WUC_PME_EN; - if (wufc & (E1000_WUFC_MAG | E1000_WUFC_LNKC)) wuc |= E1000_WUC_APME; - - /* - * Enable wakeup by ARP request and directed IPv4/IPv6 packets. - */ - if (addrData->ipV4Count > 0) - wufc |= (E1000_WUFC_EX | E1000_WUFC_ARP | E1000_WUFC_IP4); - - if (addrData->ipV6Count > 0) - wufc |= (E1000_WUFC_EX | E1000_WUFC_IP6); + + if (enableWoM) { + /* + * Enable wakeup by ARP request and directed IPv4/IPv6 packets. + */ + if (addrData->ipV4Count > 0) + wufc |= (E1000_WUFC_EX | E1000_WUFC_ARP | E1000_WUFC_IP4); + + if (addrData->ipV6Count > 0) + wufc |= (E1000_WUFC_EX | E1000_WUFC_IP6); + } /* enable PHY wakeup in MAC register */ intelWriteMem32(E1000_WUFC, wufc); - intelWriteMem32(E1000_WUC, (E1000_WUC_PHY_WAKE | E1000_WUC_APMPME | E1000_WUC_PME_STATUS | wuc)); + intelWriteMem32(E1000_WUC, (E1000_WUC_PHY_WAKE | E1000_WUC_APMPME | + E1000_WUC_PME_STATUS | wuc)); - /* - * Setup IPv4 and IPv6 wakeup address registers with the - * retrieved address list. - */ - av = 0x0000; - num = (addrData->ipV4Count > kMaxAddrV4) ? kMaxAddrV4 : addrData->ipV4Count; - - for (i = 0; i < num; i++) { - //av |= BIT(i + 1); - ad = addrData->ipV4Addr[i]; - - hw->phy.ops.write_reg_page(hw, BM_IP4AT0(i), (u16)(ad & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_IP4AT1(i), (u16)((ad >> 16) & 0xFFFF)); - } - num = (addrData->ipV6Count > kMaxAddrV6) ? kMaxAddrV6 : addrData->ipV6Count; - - for (i = 0; i < num; i++) { - av |= BIT(7 - i); - - ad = addrData->ipV6Addr[i].s6_addr32[0]; - hw->phy.ops.write_reg_page(hw, BM_IP6AT0(i), (u16)(ad & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_IP6AT1(i), (u16)((ad >> 16) & 0xFFFF)); - - ad = addrData->ipV6Addr[i].s6_addr32[1]; - hw->phy.ops.write_reg_page(hw, BM_IP6AT2(i), (u16)(ad & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_IP6AT3(i), (u16)((ad >> 16) & 0xFFFF)); - - ad = addrData->ipV6Addr[i].s6_addr32[2]; - hw->phy.ops.write_reg_page(hw, BM_IP6AT4(i), (u16)(ad & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_IP6AT5(i), (u16)((ad >> 16) & 0xFFFF)); - - ad = addrData->ipV6Addr[i].s6_addr32[3]; - hw->phy.ops.write_reg_page(hw, BM_IP6AT6(i), (u16)(ad & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_IP6AT7(i), (u16)((ad >> 16) & 0xFFFF)); - } - /* - * Fix address valid mask as bit 15 is a duplicate of bit 7 - * and write to IPAV register. - */ - if (av & BIT(7)) { - av |= BIT(15); + if (enableWoM) { + /* + * Setup IPv4 and IPv6 wakeup address registers with the + * retrieved address list. + */ + av = 0x0000; + num = (addrData->ipV4Count > kMaxAddrV4) ? kMaxAddrV4 : addrData->ipV4Count; + + for (i = 0; i < num; i++) { + //av |= BIT(i + 1); + ad = addrData->ipV4Addr[i]; + + hw->phy.ops.write_reg_page(hw, BM_IP4AT0(i), (u16)(ad & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_IP4AT1(i), (u16)((ad >> 16) & 0xFFFF)); + } + num = (addrData->ipV6Count > kMaxAddrV6) ? kMaxAddrV6 : addrData->ipV6Count; + + for (i = 0; i < num; i++) { + av |= BIT(7 - i); + + ad = addrData->ipV6Addr[i].s6_addr32[0]; + hw->phy.ops.write_reg_page(hw, BM_IP6AT0(i), (u16)(ad & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_IP6AT1(i), (u16)((ad >> 16) & 0xFFFF)); + + ad = addrData->ipV6Addr[i].s6_addr32[1]; + hw->phy.ops.write_reg_page(hw, BM_IP6AT2(i), (u16)(ad & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_IP6AT3(i), (u16)((ad >> 16) & 0xFFFF)); + + ad = addrData->ipV6Addr[i].s6_addr32[2]; + hw->phy.ops.write_reg_page(hw, BM_IP6AT4(i), (u16)(ad & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_IP6AT5(i), (u16)((ad >> 16) & 0xFFFF)); + + ad = addrData->ipV6Addr[i].s6_addr32[3]; + hw->phy.ops.write_reg_page(hw, BM_IP6AT6(i), (u16)(ad & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_IP6AT7(i), (u16)((ad >> 16) & 0xFFFF)); + } + /* + * Fix address valid mask as bit 15 is a duplicate of bit 7 + * and write to IPAV register. + */ + if (av & BIT(7)) { + av |= BIT(15); + } + hw->phy.ops.write_reg_page(hw, BM_IPAV, av); + DebugLog("[IntelMausi]: PHY IPAV = 0x%04x.\n", av); } - hw->phy.ops.write_reg_page(hw, BM_IPAV, av); - DebugLog("[IntelMausi]: PHY IPAV = 0x%04x.\n", av); + DebugLog("[IntelMausi]: PHY WUFC = 0x%04x.\n", wufc); DebugLog("[IntelMausi]: PHY WUC = 0x%04x.\n", wuc); - /* Configure PHY rx control */ - DebugLog("[IntelMausi]: PHY RCTL = 0x%04x.\n", phy_reg); - hw->phy.ops.write_reg_page(hw, BM_RCTL, phy_reg); - /* Configure and enable PHY wakeup in PHY registers */ hw->phy.ops.write_reg_page(hw, BM_WUFC, wufc); hw->phy.ops.write_reg_page(hw, BM_WUC, wuc); - + /* activate PHY wakeup */ wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; - error = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - - if (error) { + retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); + + if (retval) { DebugLog("[IntelMausi]: Failed to set PHY Host Wakeup bit.\n"); } - + release: hw->phy.ops.release(hw); } + +/** + * intelInitMacWakeup + */ void IntelMausi::intelInitMacWakeup(UInt32 wufc, struct IntelAddrData *addrData) { - UInt32 av, num, i; - - /* Enable wakeup by ARP request and directed IPv4 packets. */ - if (addrData->ipV4Count > 0) - wufc |= (E1000_WUFC_EX | E1000_WUFC_ARP | E1000_WUFC_IP4); - - /* Configure IPv4 wakeup address registers. */ - av = 0; - num = (addrData->ipV4Count > kMaxAddrV4) ? kMaxAddrV4 : addrData->ipV4Count; - - for (i = 0; i < num; i++) { - av |= BIT(i + 1); - intelWriteMem32(E1000_IP4AT(i), addrData->ipV4Addr[i]); - } + if (enableWoM) { + u32 av, num, i; + /* Enable wakeup by ARP request and directed IPv4 packets. */ + if (addrData->ipV4Count > 0) + wufc |= (E1000_WUFC_EX | E1000_WUFC_ARP | E1000_WUFC_IP4); + + /* Configure IPv4 wakeup address registers. */ + av = 0; + num = (addrData->ipV4Count > kMaxAddrV4) ? kMaxAddrV4 : addrData->ipV4Count; + + for (i = 0; i < num; i++) { + av |= BIT(i + 1); + intelWriteMem32(E1000_IP4AT(i), addrData->ipV4Addr[i]); + } - /* Configure IPv6 wakeup address registers. */ - if (addrData->ipV6Count > 0) { - wufc |= (E1000_WUFC_EX | E1000_WUFC_IP6); - av |= BIT(16); + /* Configure IPv6 wakeup address registers. */ + if (addrData->ipV6Count > 0) { + wufc |= (E1000_WUFC_EX | E1000_WUFC_IP6); + av |= BIT(16); - for (i = 0; i < 4; i++) { - intelWriteMem32(E1000_IP6AT(i), addrData->ipV6Addr[0].s6_addr32[i]); + for (i = 0; i < 4; i++) { + intelWriteMem32(E1000_IP6AT(i), addrData->ipV6Addr[0].s6_addr32[i]); + } } + intelWriteMem32(E1000_IPAV, av); } - intelWriteMem32(E1000_IPAV, av); intelWriteMem32(E1000_WUFC, wufc); - intelWriteMem32(E1000_WUC, (E1000_WUC_PME_EN | E1000_WUC_PME_STATUS)); + intelWriteMem32(E1000_WUC, E1000_WUC_PME_EN); } + +/** + * intelSetupAdvForMedium + */ void IntelMausi::intelSetupAdvForMedium(const IONetworkMedium *medium) { struct e1000_hw *hw = &adapterData.hw; struct e1000_mac_info *mac = &hw->mac; - + if (adapterData.flags2 & FLAG2_HAS_EEE) hw->dev_spec.ich8lan.eee_disable = true; - + switch (medium->getIndex()) { case MEDIUM_INDEX_10HD: mac->forced_speed_duplex = ADVERTISE_10_HALF; hw->mac.autoneg = 0; break; - + case MEDIUM_INDEX_10FD: mac->forced_speed_duplex = ADVERTISE_10_FULL; hw->mac.autoneg = 0; break; - + case MEDIUM_INDEX_100HD: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Half; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_none; break; - + case MEDIUM_INDEX_100FD: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_none; break; - + case MEDIUM_INDEX_100FDFC: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_full; break; - + case MEDIUM_INDEX_1000FD: hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_none; break; - + case MEDIUM_INDEX_1000FDFC: hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_full; break; - + case MEDIUM_INDEX_1000FDEEE: hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_none; hw->dev_spec.ich8lan.eee_disable = false; break; - + case MEDIUM_INDEX_1000FDFCEEE: hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_full; hw->dev_spec.ich8lan.eee_disable = false; break; - + case MEDIUM_INDEX_100FDEEE: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_none; hw->dev_spec.ich8lan.eee_disable = false; break; - + case MEDIUM_INDEX_100FDFCEEE: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full; hw->mac.autoneg = 1; hw->fc.requested_mode = e1000_fc_full; hw->dev_spec.ich8lan.eee_disable = false; break; - + default: if (hw->phy.media_type == e1000_media_type_fiber) { hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Autoneg; @@ -1705,10 +2003,10 @@ void IntelMausi::intelSetupAdvForMedium(const IONetworkMedium *medium) ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_TP | ADVERTISED_MII); - + if (adapterData.fc_autoneg) hw->fc.requested_mode = e1000_fc_default; - + if (adapterData.flags2 & FLAG2_HAS_EEE) hw->dev_spec.ich8lan.eee_disable = false; } @@ -1719,46 +2017,55 @@ void IntelMausi::intelSetupAdvForMedium(const IONetworkMedium *medium) hw->phy.mdix = AUTO_ALL_MODES; } + +/** + * intelFlushLPIC + * + * Reference: e1000e_flush_lpic + */ void IntelMausi::intelFlushLPIC() { struct e1000_hw *hw = &adapterData.hw; - UInt32 error; + u32 ret_val; -#ifdef DEBUG - UInt32 lpic; -#endif - /* Flush LPIC. */ - error = hw->phy.ops.acquire(hw); - - if (error) + ret_val = hw->phy.ops.acquire(hw); + + if (ret_val) return; -#ifdef DEBUG - lpic = intelReadMem32(E1000_LPIC); - DebugLog("[IntelMausi]: LPIC=0x%08x.\n", lpic); -#endif + DebugLog("[IntelMausi]: LPIC=0x%08x.\n", intelReadMem32(E1000_LPIC)); + + DebugLog("[IntelMausi]: EEE TX LPI TIMER: 0x%08x.\n", intelReadMem32(E1000_LPIC) >> E1000_LPIC_LPIET_SHIFT); hw->phy.ops.release(hw); } + +/** + * setMaxLatency + */ void IntelMausi::setMaxLatency(UInt32 linkSpeed) { struct e1000_hw *hw = &adapterData.hw; UInt32 rxa = intelReadMem32(E1000_PBA) & E1000_PBA_RXA_MASK; UInt32 latency; - + rxa = rxa << 9; latency = (rxa > hw->adapter->max_frame_size) ? (rxa - hw->adapter->max_frame_size) * (16000 / linkSpeed) : 0; - + if (maxLatency && (latency > maxLatency)) latency = maxLatency; - + requireMaxBusStall(latency); - + DebugLog("[IntelMausi]: requireMaxBusStall(%uns).\n", latency); } + +/** + * intelSupportsEEE + */ UInt16 IntelMausi::intelSupportsEEE(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; @@ -1769,40 +2076,40 @@ UInt16 IntelMausi::intelSupportsEEE(struct e1000_adapter *adapter) if (!(adapter->flags2 & FLAG2_HAS_EEE)) goto done; - + dev_spec = &hw->dev_spec.ich8lan; - + if (hw->dev_spec.ich8lan.eee_disable) goto done; - + switch (hw->phy.type) { case e1000_phy_82579: lpa = I82579_EEE_LP_ABILITY; advAddr = I82579_EEE_ADVERTISEMENT; break; - + case e1000_phy_i217: lpa = I217_EEE_LP_ABILITY; advAddr = I217_EEE_ADVERTISEMENT; break; - + default: goto done; } error = hw->phy.ops.acquire(hw); - + if (error) goto done; /* Save off link partner's EEE ability */ error = e1000_read_emi_reg_locked(hw, lpa, &dev_spec->eee_lp_ability); - + if (error) goto release; - + /* Read EEE advertisement */ error = e1000_read_emi_reg_locked(hw, advAddr, &adv); - + if (error) goto release; @@ -1811,7 +2118,7 @@ UInt16 IntelMausi::intelSupportsEEE(struct e1000_adapter *adapter) */ if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) result |= I82579_LPI_CTRL_1000_ENABLE; - + if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) result |= I82579_LPI_CTRL_100_ENABLE; @@ -1824,6 +2131,10 @@ UInt16 IntelMausi::intelSupportsEEE(struct e1000_adapter *adapter) return result; } + +/** + * intelEnableEEE + */ SInt32 IntelMausi::intelEnableEEE(struct e1000_hw *hw, UInt16 mode) { SInt32 error = 0; @@ -1833,21 +2144,21 @@ SInt32 IntelMausi::intelEnableEEE(struct e1000_hw *hw, UInt16 mode) case e1000_phy_82579: pcsStatus = I82579_EEE_PCS_STATUS; break; - + case e1000_phy_i217: pcsStatus = I217_EEE_PCS_STATUS; break; - + default: goto done; } error = hw->phy.ops.acquire(hw); - + if (error) goto done; - + error = e1e_rphy_locked(hw, I82579_LPI_CTRL, &lpiCtrl); - + if (error) goto release; @@ -1856,28 +2167,28 @@ SInt32 IntelMausi::intelEnableEEE(struct e1000_hw *hw, UInt16 mode) /* Set the new EEE mode. */ lpiCtrl |= mode; - + if (hw->phy.type == e1000_phy_82579) { error = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, &data); - + if (error) goto release; - + data &= ~I82579_LPI_100_PLL_SHUT; e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, data); } - + /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ error = e1000_read_emi_reg_locked(hw, pcsStatus, &data); - + if (error) goto release; - + error = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpiCtrl); - + release: hw->phy.ops.release(hw); - + done: return error; } diff --git a/IntelMausiEthernet/IntelMausiSetup.cpp b/IntelMausiEthernet/IntelMausiSetup.cpp index e0637b1..e429177 100644 --- a/IntelMausiEthernet/IntelMausiSetup.cpp +++ b/IntelMausiEthernet/IntelMausiSetup.cpp @@ -74,13 +74,13 @@ void IntelMausi::getParams() versionString = OSDynamicCast(OSString, getProperty(kDriverVersionName)); params = OSDynamicCast(OSDictionary, getProperty(kParamName)); - + if (params) { csoV6 = OSDynamicCast(OSBoolean, params->getObject(kEnableCSO6Name)); enableCSO6 = (csoV6) ? csoV6->getValue() : false; - + DebugLog("[IntelMausi]: TCP/IPv6 checksum offload %s.\n", enableCSO6 ? onName : offName); - + wom = OSDynamicCast(OSBoolean, params->getObject(kEnableWoMName)); enableWoM = (wom) ? wom->getValue() : false; @@ -223,11 +223,11 @@ void IntelMausi::getParams() bool IntelMausi::setupMediumDict() { - IONetworkMedium *medium; + IONetworkMedium *medium; UInt32 count; UInt32 i; bool result = false; - + if (adapterData.hw.phy.media_type == e1000_media_type_fiber) { count = 1; } else if (adapterData.flags2 & FLAG2_HAS_EEE) { @@ -236,38 +236,38 @@ bool IntelMausi::setupMediumDict() count = MEDIUM_INDEX_COUNT - 4; } mediumDict = OSDictionary::withCapacity(count + 1); - + if (mediumDict) { for (i = MEDIUM_INDEX_AUTO; i < count; i++) { medium = IONetworkMedium::medium(mediumTypeArray[i], mediumSpeedArray[i], 0, i); - + if (!medium) goto error1; - + result = IONetworkMedium::addMedium(mediumDict, medium); medium->release(); - + if (!result) goto error1; - + mediumTable[i] = medium; } } result = publishMediumDictionary(mediumDict); - + if (!result) goto error1; - + done: return result; - + error1: IOLog("[IntelMausi]: Error creating medium dictionary.\n"); mediumDict->release(); - + for (i = MEDIUM_INDEX_AUTO; i < MEDIUM_INDEX_COUNT; i++) mediumTable[i] = NULL; - + goto done; } @@ -277,15 +277,15 @@ bool IntelMausi::initEventSources(IOService *provider) int intrIndex = 0; int intrType = 0; bool result = false; - + txQueue = reinterpret_cast(getOutputQueue()); - + if (txQueue == NULL) { IOLog("[IntelMausi]: Failed to get output queue.\n"); goto done; } txQueue->retain(); - + while (pciDevice->getInterruptType(intrIndex, &intrType) == kIOReturnSuccess) { if (intrType & kIOInterruptTypePCIMessaged){ msiIndex = intrIndex; @@ -295,7 +295,7 @@ bool IntelMausi::initEventSources(IOService *provider) } if (msiIndex != -1) { DebugLog("[IntelMausi]: MSI interrupt index: %d\n", msiIndex); - + interruptSource = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &IntelMausi::interruptOccurred), provider, msiIndex); } if (!interruptSource) { @@ -303,24 +303,24 @@ bool IntelMausi::initEventSources(IOService *provider) goto error1; } workLoop->addEventSource(interruptSource); - + timerSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &IntelMausi::timerAction)); - + if (!timerSource) { IOLog("[IntelMausi]: Failed to create IOTimerEventSource.\n"); goto error2; } workLoop->addEventSource(timerSource); - + result = true; - + done: return result; - + error2: workLoop->removeEventSource(interruptSource); RELEASE(interruptSource); - + error1: IOLog("[IntelMausi]: Error initializing event sources.\n"); txQueue->release(); @@ -339,10 +339,10 @@ bool IntelMausi::setupDMADescriptors() UInt32 i; UInt32 n; bool result = false; - + /* Create transmitter descriptor array. */ txBufDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, (kIODirectionInOut | kIOMemoryPhysicallyContiguous | kIOMapInhibitCache), kTxDescSize, 0xFFFFFFFFFFFFF000ULL); - + if (!txBufDesc) { IOLog("[IntelMausi]: Couldn't alloc txBufDesc.\n"); goto done; @@ -352,20 +352,20 @@ bool IntelMausi::setupDMADescriptors() goto error1; } txDescArray = (struct e1000_data_desc *)txBufDesc->getBytesNoCopy(); - + /* I don't know if it's really necessary but the documenation says so and Apple's drivers are also doing it this way. */ txDescDmaCmd = IODMACommand::withSpecification(kIODMACommandOutputHost64, 64, 0, IODMACommand::kMapped, 0, 1); - + if (!txDescDmaCmd) { IOLog("[IntelMausi]: Couldn't alloc txDescDmaCmd.\n"); goto error2; } - + if (txDescDmaCmd->setMemoryDescriptor(txBufDesc) != kIOReturnSuccess) { IOLog("[IntelMausi]: setMemoryDescriptor() failed.\n"); goto error3; } - + if (txDescDmaCmd->gen64IOVMSegments(&offset, &seg, &numSegs) != kIOReturnSuccess) { IOLog("[IntelMausi]: gen64IOVMSegments() failed.\n"); goto error4; @@ -375,7 +375,7 @@ bool IntelMausi::setupDMADescriptors() /* Initialize txDescArray. */ bzero(txDescArray, kTxDescSize); - + for (i = 0; i < kNumTxDesc; i++) { txBufArray[i].mbuf = NULL; txBufArray[i].numDescs = 0; @@ -384,59 +384,59 @@ bool IntelMausi::setupDMADescriptors() txNextDescIndex = txDirtyIndex = txCleanBarrierIndex = 0; txNumFreeDesc = kNumTxDesc; txMbufCursor = IOMbufNaturalMemoryCursor::withSpecification(0x4000, kMaxSegs); - + if (!txMbufCursor) { IOLog("[IntelMausi]: Couldn't create txMbufCursor.\n"); goto error4; } - + /* Create receiver descriptor array. */ rxBufDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, (kIODirectionInOut | kIOMemoryPhysicallyContiguous | kIOMapInhibitCache), kRxDescSize, 0xFFFFFFFFFFFFF000ULL); - + if (!rxBufDesc) { IOLog("[IntelMausi]: Couldn't alloc rxBufDesc.\n"); goto error5; } - + if (rxBufDesc->prepare() != kIOReturnSuccess) { IOLog("[IntelMausi]: rxBufDesc->prepare() failed.\n"); goto error6; } rxDescArray = (union e1000_rx_desc_extended *)rxBufDesc->getBytesNoCopy(); - + /* I don't know if it's really necessary but the documenation says so and Apple's drivers are also doing it this way. */ rxDescDmaCmd = IODMACommand::withSpecification(kIODMACommandOutputHost64, 64, 0, IODMACommand::kMapped, 0, 1); - + if (!rxDescDmaCmd) { IOLog("[IntelMausi]: Couldn't alloc rxDescDmaCmd.\n"); goto error7; } - + if (rxDescDmaCmd->setMemoryDescriptor(rxBufDesc) != kIOReturnSuccess) { IOLog("[IntelMausi]: setMemoryDescriptor() failed.\n"); goto error8; } offset = 0; numSegs = 1; - + if (rxDescDmaCmd->gen64IOVMSegments(&offset, &seg, &numSegs) != kIOReturnSuccess) { IOLog("[IntelMausi]: gen64IOVMSegments() failed.\n"); goto error9; } /* And the rx ring's physical address too. */ rxPhyAddr = seg.fIOVMAddr; - + /* Initialize rxDescArray. */ bzero((void *)rxDescArray, kRxDescSize); - + for (i = 0; i < kNumRxDesc; i++) { rxBufArray[i].mbuf = NULL; rxBufArray[i].phyAddr = 0; } rxCleanedCount = rxNextDescIndex = 0; - + rxMbufCursor = IOMbufNaturalMemoryCursor::withSpecification(PAGE_SIZE, 1); - + if (!rxMbufCursor) { IOLog("[IntelMausi]: Couldn't create rxMbufCursor.\n"); goto error9; @@ -444,15 +444,15 @@ bool IntelMausi::setupDMADescriptors() /* Alloc receive buffers. */ for (i = 0; i < kNumRxDesc; i++) { m = allocatePacket(kRxBufferPktSize); - + if (!m) { IOLog("[IntelMausi]: Couldn't alloc receive buffer.\n"); goto error10; } rxBufArray[i].mbuf = m; - + n = rxMbufCursor->getPhysicalSegments(m, &rxSegment, 1); - + if ((n != 1) || (rxSegment.location & 0x07ff)) { IOLog("[IntelMausi]: getPhysicalSegments() for receive buffer failed.\n"); goto error10; @@ -463,7 +463,7 @@ bool IntelMausi::setupDMADescriptors() * prepared for reuse. */ rxBufArray[i].phyAddr = rxSegment.location; - + rxDescArray[i].read.buffer_addr = OSSwapHostToLittleInt64(rxSegment.location); rxDescArray[i].read.reserved = 0; } @@ -472,16 +472,16 @@ bool IntelMausi::setupDMADescriptors() */ for (i = 0; i < kRxNumSpareMbufs; i++) spareMbuf[i] = allocatePacket(kRxBufferPktSize); - + for (i = 0; i < kRxNumSpareMbufs; i++) { if (spareMbuf[i]) freePacket(spareMbuf[i]); } result = true; - + done: return result; - + error10: for (i = 0; i < kNumRxDesc; i++) { if (rxBufArray[i].mbuf) { @@ -490,7 +490,7 @@ bool IntelMausi::setupDMADescriptors() } } RELEASE(rxMbufCursor); - + error9: rxDescDmaCmd->clearMemoryDescriptor(); @@ -499,24 +499,24 @@ bool IntelMausi::setupDMADescriptors() error7: rxBufDesc->complete(); - + error6: rxBufDesc->release(); rxDescArray = NULL; rxBufDesc = NULL; - + error5: RELEASE(txMbufCursor); - + error4: txDescDmaCmd->clearMemoryDescriptor(); - + error3: RELEASE(txDescDmaCmd); - + error2: txBufDesc->complete(); - + error1: txBufDesc->release(); txBufDesc = NULL; @@ -526,7 +526,7 @@ bool IntelMausi::setupDMADescriptors() void IntelMausi::freeDMADescriptors() { UInt32 i; - + if (txBufDesc) { txBufDesc->complete(); txBufDesc->release(); @@ -539,7 +539,7 @@ void IntelMausi::freeDMADescriptors() txDescDmaCmd = NULL; } RELEASE(txMbufCursor); - + if (rxBufDesc) { rxBufDesc->complete(); rxBufDesc->release(); @@ -553,7 +553,7 @@ void IntelMausi::freeDMADescriptors() rxDescDmaCmd = NULL; } RELEASE(rxMbufCursor); - + for (i = 0; i < kNumRxDesc; i++) { if (rxBufArray[i].mbuf) { freePacket(rxBufArray[i].mbuf); @@ -566,13 +566,13 @@ void IntelMausi::clearDescriptors() { mbuf_t m; UInt32 i; - - DebugLog("clearDescriptors() ===>\n"); - + + DebugLog("[IntelMausi]: clearDescriptors() ===>\n"); + /* First cleanup the tx descriptor ring. */ for (i = 0; i < kNumTxDesc; i++) { m = txBufArray[i].mbuf; - + if (m) { freePacket(m); txBufArray[i].mbuf = NULL; @@ -581,7 +581,7 @@ void IntelMausi::clearDescriptors() } txNextDescIndex = txDirtyIndex = txCleanBarrierIndex = 0; txNumFreeDesc = kNumTxDesc; - + /* On descriptor writeback the buffer addresses are overwritten so that * we must restore them in order to make sure that we leave the ring in * a usable state. @@ -596,8 +596,8 @@ void IntelMausi::clearDescriptors() /* Free packet fragments which haven't been upstreamed yet. */ discardPacketFragment(); - - DebugLog("clearDescriptors() <===\n"); + + DebugLog("[IntelMausi]: clearDescriptors() <===\n"); } void IntelMausi::discardPacketFragment(bool extended) @@ -612,7 +612,7 @@ void IntelMausi::discardPacketFragment(bool extended) else freePacket(rxPacketHead); } - + rxPacketHead = rxPacketTail = NULL; rxPacketSize = 0; } @@ -634,41 +634,41 @@ void IntelMausi::getAddressList(struct IntelAddrData *addrData) struct sockaddr_in6 addr6; sa_family_t family; u_int32_t i = 0, prefix; - + addrData->ipV6Count = 0; addrData->ipV4Count = 0; - + if (enableWoM) { if (!ifnet_get_address_list(interface, &addresses)) { while ((addr = addresses[i++]) != NULL) { family = ifaddr_address_family(addr); - + switch (family) { case AF_INET: if (!ifaddr_address(addr, (struct sockaddr *) &addr4, sizeof(struct sockaddr_in))) { if (addrData->ipV4Count < kMaxAddrV4) { addrData->ipV4Addr[addrData->ipV4Count++] = addr4.sin_addr.s_addr; - + DebugLog("[IntelMausi]: IPv4 address 0x%08x.\n", OSSwapBigToHostInt32(addr4.sin_addr.s_addr)); } } break; - + case AF_INET6: if (!ifaddr_address(addr, (struct sockaddr *) &addr6, sizeof(struct sockaddr_in6))) { prefix = OSSwapBigToHostInt32(addr6.sin6_addr.s6_addr32[0]); - + if ((addrData->ipV6Count < kMaxAddrV6) && (((prefix & kULAMask) == kULAPrefix) || ((prefix & kLLAMask) == kLLAPrefix))) { addrData->ipV6Addr[addrData->ipV6Count].s6_addr32[0] = addr6.sin6_addr.s6_addr32[0]; addrData->ipV6Addr[addrData->ipV6Count].s6_addr32[1] = addr6.sin6_addr.s6_addr32[1]; addrData->ipV6Addr[addrData->ipV6Count].s6_addr32[2] = addr6.sin6_addr.s6_addr32[2]; addrData->ipV6Addr[addrData->ipV6Count++].s6_addr32[3] = addr6.sin6_addr.s6_addr32[3]; - + DebugLog("[IntelMausi]: IPv6 address 0x%08x 0x%08x 0x%08x 0x%08x.\n", OSSwapBigToHostInt32(addr6.sin6_addr.s6_addr32[0]), OSSwapBigToHostInt32(addr6.sin6_addr.s6_addr32[1]), OSSwapBigToHostInt32(addr6.sin6_addr.s6_addr32[2]), OSSwapBigToHostInt32(addr6.sin6_addr.s6_addr32[3])); } } break; - + default: break; } diff --git a/IntelMausiEthernet/defines.h b/IntelMausiEthernet/defines.h index efabd05..960b1e3 100644 --- a/IntelMausiEthernet/defines.h +++ b/IntelMausiEthernet/defines.h @@ -8,6 +8,10 @@ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) + +#define DMA_MASK_NONE 0x0ULL + /* Definitions for power management and wakeup registers */ /* Wake Up Control */ #define E1000_WUC_APME 0x00000001 /* APM Enable */