Advertisement
Guest User

Untitled

a guest
Mar 12th, 2015
317
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 69.17 KB | None | 0 0
  1. #include "mydriver.h"
  2.  
  3. #pragma mark --- function prototypes ---
  4.  
  5. static inline void prepareTSO4(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize);
  6. static inline void prepareTSO6(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize);
  7.  
  8. #pragma mark --- private data ---
  9.  
  10. static const struct intelDevice deviceTable[] = {
  11. { .pciDevId = E1000_DEV_ID_ICH8_IFE, .device = board_ich8lan, .deviceName = "82562V", .deviceInfo = &e1000_ich8_info },
  12. { .pciDevId = E1000_DEV_ID_ICH8_IFE_G, .device = board_ich8lan, .deviceName = "82562G", .deviceInfo = &e1000_ich8_info },
  13. { .pciDevId = E1000_DEV_ID_ICH8_IFE_GT, .device = board_ich8lan, .deviceName = "82562GT", .deviceInfo = &e1000_ich8_info },
  14. { .pciDevId = E1000_DEV_ID_ICH8_IGP_AMT, .device = board_ich8lan, .deviceName = "82566DM", .deviceInfo = &e1000_ich8_info },
  15. { .pciDevId = E1000_DEV_ID_ICH8_IGP_C, .device = board_ich8lan, .deviceName = "82566DC", .deviceInfo = &e1000_ich8_info },
  16. { .pciDevId = E1000_DEV_ID_ICH8_IGP_M, .device = board_ich8lan, .deviceName = "82566MC", .deviceInfo = &e1000_ich8_info },
  17. { .pciDevId = E1000_DEV_ID_ICH8_IGP_M_AMT, .device = board_ich8lan, .deviceName = "82566MM", .deviceInfo = &e1000_ich8_info },
  18. { .pciDevId = E1000_DEV_ID_ICH8_82567V_3, .device = board_ich8lan, .deviceName = "82567V3", .deviceInfo = &e1000_ich8_info },
  19.  
  20. { .pciDevId = E1000_DEV_ID_ICH9_IFE, .device = board_ich9lan, .deviceName = "82562V2", .deviceInfo = &e1000_ich9_info },
  21. { .pciDevId = E1000_DEV_ID_ICH9_IFE_G, .device = board_ich9lan, .deviceName = "82562G2", .deviceInfo = &e1000_ich9_info },
  22. { .pciDevId = E1000_DEV_ID_ICH9_IFE_GT, .device = board_ich9lan, .deviceName = "82562GT2", .deviceInfo = &e1000_ich9_info },
  23. { .pciDevId = E1000_DEV_ID_ICH9_IGP_AMT, .device = board_ich9lan, .deviceName = "82566DM2", .deviceInfo = &e1000_ich9_info },
  24. { .pciDevId = E1000_DEV_ID_ICH9_IGP_C, .device = board_ich9lan, .deviceName = "82566DC2", .deviceInfo = &e1000_ich9_info },
  25. { .pciDevId = E1000_DEV_ID_ICH9_BM, .device = board_ich9lan, .deviceName = "82567LM4", .deviceInfo = &e1000_ich9_info },
  26. { .pciDevId = E1000_DEV_ID_ICH9_IGP_M, .device = board_ich9lan, .deviceName = "82567LF", .deviceInfo = &e1000_ich9_info },
  27. { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_AMT, .device = board_ich9lan, .deviceName = "82567LM", .deviceInfo = &e1000_ich9_info },
  28. { .pciDevId = E1000_DEV_ID_ICH9_IGP_M_V, .device = board_ich9lan, .deviceName = "82567V", .deviceInfo = &e1000_ich9_info },
  29.  
  30. { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LM, .device = board_ich9lan, .deviceName = "82567LM2", .deviceInfo = &e1000_ich9_info },
  31. { .pciDevId = E1000_DEV_ID_ICH10_R_BM_LF, .device = board_ich9lan, .deviceName = "82567LF2", .deviceInfo = &e1000_ich9_info },
  32. { .pciDevId = E1000_DEV_ID_ICH10_R_BM_V, .device = board_ich9lan, .deviceName = "82567V2", .deviceInfo = &e1000_ich9_info },
  33.  
  34. { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LM, .device = board_ich10lan, .deviceName = "82567LM3", .deviceInfo = &e1000_ich10_info },
  35. { .pciDevId = E1000_DEV_ID_ICH10_D_BM_LF, .device = board_ich10lan, .deviceName = "82567LF3", .deviceInfo = &e1000_ich10_info },
  36. { .pciDevId = E1000_DEV_ID_ICH10_D_BM_V, .device = board_ich10lan, .deviceName = "82567V4", .deviceInfo = &e1000_ich10_info },
  37.  
  38. { .pciDevId = E1000_DEV_ID_PCH_M_HV_LM, .device = board_pchlan, .deviceName = "82578LM", .deviceInfo = &e1000_pch_info },
  39. { .pciDevId = E1000_DEV_ID_PCH_M_HV_LC, .device = board_pchlan, .deviceName = "82578LC", .deviceInfo = &e1000_pch_info },
  40. { .pciDevId = E1000_DEV_ID_PCH_D_HV_DM, .device = board_pchlan, .deviceName = "82578DM", .deviceInfo = &e1000_pch_info },
  41. { .pciDevId = E1000_DEV_ID_PCH_D_HV_DC, .device = board_pchlan, .deviceName = "82578DC", .deviceInfo = &e1000_pch_info },
  42.  
  43. { .pciDevId = E1000_DEV_ID_PCH2_LV_LM, .device = board_pch2lan, .deviceName = "82579LM", .deviceInfo = &e1000_pch2_info },
  44. { .pciDevId = E1000_DEV_ID_PCH2_LV_V, .device = board_pch2lan, .deviceName = "82579V", .deviceInfo = &e1000_pch2_info },
  45.  
  46. { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_LM, .device = board_pch_lpt, .deviceName = "I217LM", .deviceInfo = &e1000_pch_lpt_info },
  47. { .pciDevId = E1000_DEV_ID_PCH_LPT_I217_V, .device = board_pch_lpt, .deviceName = "I217V", .deviceInfo = &e1000_pch_lpt_info },
  48. { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_LM, .device = board_pch_lpt, .deviceName = "I218LM", .deviceInfo = &e1000_pch_lpt_info },
  49. { .pciDevId = E1000_DEV_ID_PCH_LPTLP_I218_V, .device = board_pch_lpt, .deviceName = "I218V", .deviceInfo = &e1000_pch_lpt_info },
  50. { .pciDevId = E1000_DEV_ID_PCH_I218_LM2, .device = board_pch_lpt, .deviceName = "I218LM2", .deviceInfo = &e1000_pch_lpt_info },
  51. { .pciDevId = E1000_DEV_ID_PCH_I218_V2, .device = board_pch_lpt, .deviceName = "I218V2", .deviceInfo = &e1000_pch_lpt_info },
  52. { .pciDevId = E1000_DEV_ID_PCH_I218_LM3, .device = board_pch_lpt, .deviceName = "I218LM3", .deviceInfo = &e1000_pch_lpt_info },
  53. { .pciDevId = E1000_DEV_ID_PCH_I218_V3, .device = board_pch_lpt, .deviceName = "I218V3", .deviceInfo = &e1000_pch_lpt_info },
  54.  
  55. /* end of table */
  56. { .pciDevId = 0, .device = 0, .deviceName = NULL, .deviceInfo = NULL }
  57. };
  58.  
  59. /* Power Management Support */
  60. static IOPMPowerState powerStateArray[kPowerStateCount] =
  61. {
  62. {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  63. {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
  64. };
  65.  
  66.  
  67. static const char *speed1GName = "1-Gigabit";
  68. static const char *speed100MName = "100-Megabit";
  69. static const char *speed10MName = "10-Megabit";
  70. static const char *duplexFullName = "Full-duplex";
  71. static const char *duplexHalfName = "Half-duplex";
  72.  
  73. static const char *flowControlNames[kFlowControlTypeCount] = {
  74. "No flow-control",
  75. "Rx flow-control",
  76. "Tx flow-control",
  77. "Rx/Tx flow-control",
  78. };
  79.  
  80. static const char* eeeNames[kEEETypeCount] = {
  81. "",
  82. ", EEE"
  83. };
  84.  
  85. #pragma mark --- public methods ---
  86.  
  87. OSDefineMetaClassAndStructors(IntelMausi, super)
  88.  
  89. /* IOService (or its superclass) methods. */
  90.  
  91. bool IntelMausi::init(OSDictionary *properties)
  92. {
  93. bool result;
  94.  
  95. result = super::init(properties);
  96.  
  97. if (result) {
  98. workLoop = NULL;
  99. commandGate = NULL;
  100. pciDevice = NULL;
  101. mediumDict = NULL;
  102. txQueue = NULL;
  103. interruptSource = NULL;
  104. timerSource = NULL;
  105. netif = NULL;
  106. netStats = NULL;
  107. etherStats = NULL;
  108. baseMap = NULL;
  109. baseAddr = NULL;
  110. flashMap = NULL;
  111. flashAddr = NULL;
  112. rxMbufCursor = NULL;
  113. txMbufCursor = NULL;
  114. mcAddrList = NULL;
  115. mcListCount = 0;
  116. isEnabled = false;
  117. promiscusMode = false;
  118. multicastMode = false;
  119. linkUp = false;
  120. stalled = false;
  121. forceReset = false;
  122. eeeMode = 0;
  123. chip = 0;
  124. powerState = 0;
  125. pciDeviceData.vendor = 0;
  126. pciDeviceData.device = 0;
  127. pciDeviceData.subsystem_vendor = 0;
  128. pciDeviceData.subsystem_device = 0;
  129. pciDeviceData.revision = 0;
  130. adapterData.pdev = &pciDeviceData;
  131. mtu = ETH_DATA_LEN;
  132. wolCapable = false;
  133. wolActive = false;
  134. enableTSO4 = false;
  135. enableTSO6 = false;
  136. enableCSO6 = false;
  137. pciPMCtrlOffset = 0;
  138. }
  139.  
  140. done:
  141. return result;
  142. }
  143.  
  144. void IntelMausi::free()
  145. {
  146. UInt32 i;
  147.  
  148. DebugLog("free() ===>\n");
  149.  
  150. if (workLoop) {
  151. if (interruptSource) {
  152. workLoop->removeEventSource(interruptSource);
  153. RELEASE(interruptSource);
  154. }
  155. if (timerSource) {
  156. workLoop->removeEventSource(timerSource);
  157. RELEASE(timerSource);
  158. }
  159. workLoop->release();
  160. workLoop = NULL;
  161. }
  162. RELEASE(commandGate);
  163. RELEASE(txQueue);
  164. RELEASE(mediumDict);
  165.  
  166. for (i = MEDIUM_INDEX_AUTO; i < MEDIUM_INDEX_COUNT; i++)
  167. mediumTable[i] = NULL;
  168.  
  169. RELEASE(baseMap);
  170. baseAddr = NULL;
  171. adapterData.hw.hw_addr = NULL;
  172.  
  173. RELEASE(flashMap);
  174. flashAddr = NULL;
  175. adapterData.hw.flash_address = NULL;
  176.  
  177. RELEASE(pciDevice);
  178. freeDMADescriptors();
  179.  
  180. if (mcAddrList) {
  181. IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress));
  182. mcAddrList = NULL;
  183. mcListCount = 0;
  184. }
  185.  
  186. DebugLog("free() <===\n");
  187.  
  188. super::free();
  189. }
  190.  
  191. bool IntelMausi::start(IOService *provider)
  192. {
  193. bool result;
  194.  
  195. result = super::start(provider);
  196.  
  197. if (!result) {
  198. IOLog("Ethernet [IntelMausi]: IOEthernetController::start failed.\n");
  199. goto done;
  200. }
  201. multicastMode = false;
  202. promiscusMode = false;
  203. mcAddrList = NULL;
  204. mcListCount = 0;
  205.  
  206. pciDevice = OSDynamicCast(IOPCIDevice, provider);
  207.  
  208. if (!pciDevice) {
  209. IOLog("Ethernet [IntelMausi]: No provider.\n");
  210. goto done;
  211. }
  212. pciDevice->retain();
  213.  
  214. if (!pciDevice->open(this)) {
  215. IOLog("Ethernet [IntelMausi]: Failed to open provider.\n");
  216. goto error1;
  217. }
  218. if (!initPCIConfigSpace(pciDevice)) {
  219. goto error2;
  220. }
  221. getParams();
  222.  
  223. if (!intelStart()) {
  224. goto error2;
  225. }
  226. if (!setupMediumDict()) {
  227. IOLog("Ethernet [IntelMausi]: Failed to setup medium dictionary.\n");
  228. goto error2;
  229. }
  230. commandGate = getCommandGate();
  231.  
  232. if (!commandGate) {
  233. IOLog("Ethernet [IntelMausi]: getCommandGate() failed.\n");
  234. goto error3;
  235. }
  236. commandGate->retain();
  237.  
  238. if (!initEventSources(provider)) {
  239. IOLog("Ethernet [IntelMausi]: initEventSources() failed.\n");
  240. goto error3;
  241. }
  242.  
  243. result = attachInterface(reinterpret_cast<IONetworkInterface**>(&netif));
  244.  
  245. if (!result) {
  246. IOLog("Ethernet [IntelMausi]: attachInterface() failed.\n");
  247. goto error3;
  248. }
  249. pciDevice->close(this);
  250. result = true;
  251.  
  252. done:
  253. return result;
  254.  
  255. error3:
  256. RELEASE(commandGate);
  257.  
  258. error2:
  259. pciDevice->close(this);
  260.  
  261. error1:
  262. pciDevice->release();
  263. pciDevice = NULL;
  264. goto done;
  265. }
  266.  
  267. void IntelMausi::stop(IOService *provider)
  268. {
  269. UInt32 i;
  270.  
  271. if (netif) {
  272. detachInterface(netif);
  273. netif = NULL;
  274. }
  275. if (workLoop) {
  276. if (interruptSource) {
  277. workLoop->removeEventSource(interruptSource);
  278. RELEASE(interruptSource);
  279. }
  280. if (timerSource) {
  281. workLoop->removeEventSource(timerSource);
  282. RELEASE(timerSource);
  283. }
  284. workLoop->release();
  285. workLoop = NULL;
  286. }
  287. RELEASE(commandGate);
  288. RELEASE(txQueue);
  289. RELEASE(mediumDict);
  290.  
  291. for (i = MEDIUM_INDEX_AUTO; i < MEDIUM_INDEX_COUNT; i++)
  292. mediumTable[i] = NULL;
  293.  
  294. freeDMADescriptors();
  295.  
  296. if (mcAddrList) {
  297. IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress));
  298. mcAddrList = NULL;
  299. mcListCount = 0;
  300. }
  301. RELEASE(baseMap);
  302. baseAddr = NULL;
  303. adapterData.hw.hw_addr = NULL;
  304.  
  305. RELEASE(flashMap);
  306. flashAddr = NULL;
  307. adapterData.hw.flash_address = NULL;
  308.  
  309. RELEASE(pciDevice);
  310.  
  311. super::stop(provider);
  312. }
  313.  
  314. IOReturn IntelMausi::registerWithPolicyMaker(IOService *policyMaker)
  315. {
  316. DebugLog("registerWithPolicyMaker() ===>\n");
  317.  
  318. powerState = kPowerStateOn;
  319.  
  320. DebugLog("registerWithPolicyMaker() <===\n");
  321.  
  322. return policyMaker->registerPowerDriver(this, powerStateArray, kPowerStateCount);
  323. }
  324.  
  325. IOReturn IntelMausi::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)
  326. {
  327. IOReturn result = IOPMAckImplied;
  328.  
  329. DebugLog("setPowerState() ===>\n");
  330.  
  331. if (powerStateOrdinal == powerState) {
  332. DebugLog("Ethernet [IntelMausi]: Already in power state %lu.\n", powerStateOrdinal);
  333. goto done;
  334. }
  335. DebugLog("Ethernet [IntelMausi]: switching to power state %lu.\n", powerStateOrdinal);
  336.  
  337. if (powerStateOrdinal == kPowerStateOff)
  338. commandGate->runAction(setPowerStateSleepAction);
  339. else
  340. commandGate->runAction(setPowerStateWakeAction);
  341.  
  342. powerState = powerStateOrdinal;
  343.  
  344. done:
  345. DebugLog("setPowerState() <===\n");
  346.  
  347. return result;
  348. }
  349.  
  350. void IntelMausi::systemWillShutdown(IOOptionBits specifier)
  351. {
  352. DebugLog("systemWillShutdown() ===>\n");
  353.  
  354. if ((kIOMessageSystemWillPowerOff | kIOMessageSystemWillRestart) & specifier) {
  355. disable(netif);
  356.  
  357. /* Restore the original MAC address. */
  358. adapterData.hw.mac.ops.rar_set(&adapterData.hw, adapterData.hw.mac.perm_addr, 0);
  359.  
  360. /* If AMT is enabled, let the firmware know that the network
  361. * interface is now closed
  362. */
  363. if ((adapterData.flags & FLAG_HAS_AMT))
  364. e1000e_release_hw_control(&adapterData);
  365. }
  366.  
  367. DebugLog("systemWillShutdown() <===\n");
  368.  
  369. /* Must call super on shutdown or system will stall. */
  370. super::systemWillShutdown(specifier);
  371. }
  372.  
  373. /* IONetworkController methods. */
  374.  
  375. IOReturn IntelMausi::enable(IONetworkInterface *netif)
  376. {
  377. const IONetworkMedium *selectedMedium;
  378. IOReturn result = kIOReturnError;
  379.  
  380. DebugLog("enable() ===>\n");
  381.  
  382. if (isEnabled) {
  383. DebugLog("Ethernet [IntelMausi]: Interface already enabled.\n");
  384. result = kIOReturnSuccess;
  385. goto done;
  386. }
  387. if (!pciDevice || pciDevice->isOpen()) {
  388. IOLog("Ethernet [IntelMausi]: Unable to open PCI device.\n");
  389. goto done;
  390. }
  391. pciDevice->open(this);
  392.  
  393. if (!setupDMADescriptors()) {
  394. IOLog("Ethernet [IntelMausi]: Error allocating DMA descriptors.\n");
  395. goto done;
  396. }
  397. selectedMedium = getSelectedMedium();
  398.  
  399. if (!selectedMedium) {
  400. DebugLog("Ethernet [IntelMausi]: No medium selected. Falling back to autonegotiation.\n");
  401. selectedMedium = mediumTable[MEDIUM_INDEX_AUTO];
  402. }
  403. selectMedium(selectedMedium);
  404. setLinkStatus(kIONetworkLinkValid);
  405. intelEnable();
  406.  
  407. /* In case we are using an msi the interrupt hasn't been enabled by start(). */
  408. interruptSource->enable();
  409.  
  410. txDescDoneCount = txDescDoneLast = 0;
  411. deadlockWarn = 0;
  412. txQueue->setCapacity(kTransmitQueueCapacity);
  413. isEnabled = true;
  414. stalled = false;
  415. forceReset = false;
  416. eeeMode = 0;
  417.  
  418. result = kIOReturnSuccess;
  419.  
  420. DebugLog("enable() <===\n");
  421.  
  422. done:
  423. return result;
  424. }
  425.  
  426. IOReturn IntelMausi::disable(IONetworkInterface *netif)
  427. {
  428. IOReturn result = kIOReturnSuccess;
  429.  
  430. DebugLog("disable() ===>\n");
  431.  
  432. if (!isEnabled)
  433. goto done;
  434.  
  435. txQueue->stop();
  436. txQueue->flush();
  437. txQueue->setCapacity(0);
  438. isEnabled = false;
  439. stalled = false;
  440. forceReset = false;
  441. eeeMode = 0;
  442.  
  443. timerSource->cancelTimeout();
  444. txDescDoneCount = txDescDoneLast = 0;
  445.  
  446. /* In case we are using msi disable the interrupt. */
  447. interruptSource->disable();
  448.  
  449. intelDisable();
  450.  
  451. if (linkUp)
  452. IOLog("Ethernet [IntelMausi]: Link down on en%u\n", netif->getUnitNumber());
  453.  
  454. linkUp = false;
  455. setLinkStatus(kIONetworkLinkValid);
  456.  
  457. if (mcAddrList) {
  458. IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress));
  459. mcAddrList = NULL;
  460. mcListCount = 0;
  461. }
  462. if (pciDevice && pciDevice->isOpen())
  463. pciDevice->close(this);
  464.  
  465. freeDMADescriptors();
  466.  
  467. DebugLog("disable() <===\n");
  468.  
  469. done:
  470. return result;
  471. }
  472.  
  473. UInt32 IntelMausi::outputPacket(mbuf_t m, void *param)
  474. {
  475. IOPhysicalSegment txSegments[kMaxSegs];
  476. struct e1000_data_desc *desc;
  477. struct e1000_context_desc *contDesc;
  478. UInt32 result = kIOReturnOutputDropped;
  479. UInt32 numDescs = 0;
  480. UInt32 cmd1 = 0;
  481. UInt32 cmd2 = 0;
  482. UInt32 len = 0;
  483. UInt32 mss = 0;
  484. UInt32 ipConfig = 0;
  485. UInt32 tcpConfig = 0;
  486. UInt32 word1;
  487. UInt32 numSegs;
  488. UInt32 lastSeg;
  489. UInt32 index;
  490. UInt32 offloadFlags = 0;
  491. UInt16 vlanTag;
  492. UInt16 i;
  493.  
  494. //DebugLog("outputPacket() ===>\n");
  495.  
  496. if (!(isEnabled && linkUp) || forceReset) {
  497. DebugLog("Ethernet [IntelMausi]: Interface down. Dropping packet.\n");
  498. goto error;
  499. }
  500. if (mbuf_get_tso_requested(m, &offloadFlags, &mss)) {
  501. DebugLog("Ethernet [IntelMausi]: mbuf_get_tso_requested() failed. Dropping packet.\n");
  502. goto done;
  503. }
  504. /* First prepare the header and the command bits. */
  505. if (offloadFlags & (MBUF_TSO_IPV4 | MBUF_TSO_IPV6)) {
  506. numDescs = 1;
  507.  
  508. if (offloadFlags & MBUF_TSO_IPV4) {
  509. /* Correct the pseudo header checksum and extract the header size. */
  510. prepareTSO4(m, &mss, &len);
  511.  
  512. /* Prepare the context descriptor. */
  513. ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart);
  514. tcpConfig = ((kTCPv4CSumEnd << 16) | (kTCPv4CSumOffset << 8) | kTCPv4CSumStart);
  515. len |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP);
  516.  
  517. //DebugLog("Ethernet [IntelMausi]: TSO4 mssHeaderLen=0x%08x, payload=0x%08x\n", mss, len);
  518.  
  519. /* Setup the command bits for TSO over IPv4. */
  520. cmd1 = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | E1000_TXD_DTYP_D);
  521. cmd2 = (E1000_TXD_OPTS_TXSM | E1000_TXD_OPTS_IXSM);
  522. } else {
  523. /* Correct the pseudo header checksum and extract the header size. */
  524. prepareTSO6(m, &mss, &len);
  525.  
  526. /* Prepare the context descriptor. */
  527. ipConfig = ((kIPv6CSumEnd << 16) | (kIPv6CSumOffset << 8) | kIPv6CSumStart);
  528. tcpConfig = ((kTCPv6CSumEnd << 16) | (kTCPv6CSumOffset << 8) | kTCPv6CSumStart);
  529. len |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | E1000_TXD_CMD_TCP);
  530.  
  531. /* Setup the command bits for TSO over IPv6. */
  532. cmd1 = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | E1000_TXD_DTYP_D);
  533. cmd2 = E1000_TXD_OPTS_TXSM;
  534. }
  535. } else {
  536. mbuf_get_csum_requested(m, &offloadFlags, &mss);
  537.  
  538. if (offloadFlags & (kChecksumUDPIPv6 | kChecksumTCPIPv6 | kChecksumIP | kChecksumUDP | kChecksumTCP)) {
  539. numDescs = 1;
  540. cmd1 = (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
  541.  
  542. if (offloadFlags & kChecksumTCP) {
  543. ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart);
  544. tcpConfig = ((kTCPv4CSumEnd << 16) | (kTCPv4CSumOffset << 8) | kTCPv4CSumStart);
  545. len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP);
  546. mss = 0;
  547.  
  548. cmd2 = (E1000_TXD_OPTS_TXSM | E1000_TXD_OPTS_IXSM);
  549. } else if (offloadFlags & kChecksumUDP) {
  550. ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart);
  551. tcpConfig = ((kUDPv4CSumEnd << 16) | (kUDPv4CSumOffset << 8) | kUDPv4CSumStart);
  552. len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP);
  553. mss = 0;
  554.  
  555. cmd2 = (E1000_TXD_OPTS_TXSM | E1000_TXD_OPTS_IXSM);
  556. } else if (offloadFlags & kChecksumIP) {
  557. ipConfig = ((kIPv4CSumEnd << 16) | (kIPv4CSumOffset << 8) | kIPv4CSumStart);
  558. tcpConfig = 0;
  559. mss = 0;
  560. len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_IP);
  561.  
  562. cmd2 = E1000_TXD_OPTS_IXSM;
  563. } else if (offloadFlags & kChecksumTCPIPv6) {
  564. ipConfig = ((kIPv6CSumEnd << 16) | (kIPv6CSumOffset << 8) | kIPv6CSumStart);
  565. tcpConfig = ((kTCPv6CSumEnd << 16) | (kTCPv6CSumOffset << 8) | kTCPv6CSumStart);
  566. len = (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TCP);
  567. mss = 0;
  568.  
  569. cmd2 = E1000_TXD_OPTS_TXSM;
  570. } else if (offloadFlags & kChecksumUDPIPv6) {
  571. ipConfig = ((kIPv6CSumEnd << 16) | (kIPv6CSumOffset << 8) | kIPv6CSumStart);
  572. tcpConfig = ((kUDPv6CSumEnd << 16) | (kUDPv6CSumOffset << 8) | kUDPv6CSumStart);
  573. len = E1000_TXD_CMD_DEXT;
  574. mss = 0;
  575.  
  576. cmd2 = E1000_TXD_OPTS_TXSM;
  577. }
  578. }
  579. }
  580. /* Next get the VLAN tag and command bit. */
  581. if (!mbuf_get_vlan_tag(m, &vlanTag)) {
  582. cmd1 |= E1000_TXD_CMD_VLE;
  583. cmd2 |= (vlanTag << E1000_TX_FLAGS_VLAN_SHIFT);
  584. }
  585. /* Finally get the physical segments. */
  586. numSegs = txMbufCursor->getPhysicalSegmentsWithCoalesce(m, &txSegments[0], kMaxSegs);
  587. numDescs += numSegs;
  588.  
  589. if (!numSegs) {
  590. DebugLog("Ethernet [IntelMausi]: getPhysicalSegmentsWithCoalesce() failed. Dropping packet.\n");
  591. etherStats->dot3TxExtraEntry.resourceErrors++;
  592. goto error;
  593. }
  594. /* Alloc required number of descriptors. We leave at least kTxSpareDescs unused. */
  595. if ((txNumFreeDesc <= (numDescs + kTxSpareDescs))) {
  596. DebugLog("Ethernet [IntelMausi]: Not enough descriptors. Stalling.\n");
  597. result = kIOReturnOutputStall;
  598. stalled = true;
  599. goto done;
  600. }
  601. OSAddAtomic(-numDescs, &txNumFreeDesc);
  602. index = txNextDescIndex;
  603. txNextDescIndex = (txNextDescIndex + numDescs) & kTxDescMask;
  604. lastSeg = numSegs - 1;
  605.  
  606. /* Setup the context descriptor for TSO or checksum offload. */
  607. if (offloadFlags) {
  608. contDesc = (struct e1000_context_desc *)&txDescArray[index];
  609.  
  610. txBufArray[index].mbuf = NULL;
  611. txBufArray[index].numDescs = 0;
  612.  
  613. contDesc->lower_setup.ip_config = OSSwapHostToLittleInt32(ipConfig);
  614. contDesc->upper_setup.tcp_config = OSSwapHostToLittleInt32(tcpConfig);
  615. contDesc->cmd_and_length = OSSwapHostToLittleInt32(len);
  616. contDesc->tcp_seg_setup.data = OSSwapHostToLittleInt32(mss);
  617.  
  618. ++index &= kTxDescMask;
  619. }
  620. /* And finally fill in the data descriptors. */
  621. for (i = 0; i < numSegs; i++) {
  622. desc = &txDescArray[index];
  623. word1 = (cmd1 | (txSegments[i].length & 0x000fffff));
  624.  
  625. if (i == lastSeg) {
  626. word1 |= (E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS);
  627. txBufArray[index].mbuf = m;
  628. txBufArray[index].numDescs = numDescs;
  629. } else {
  630. word1 |= E1000_TXD_CMD_IFCS;
  631. txBufArray[index].mbuf = NULL;
  632. txBufArray[index].numDescs = 0;
  633. }
  634. desc->buffer_addr = OSSwapHostToLittleInt64(txSegments[i].location);
  635. desc->lower.data = OSSwapHostToLittleInt32(word1);
  636. desc->upper.data = OSSwapHostToLittleInt32(cmd2);
  637.  
  638. ++index &= kTxDescMask;
  639. }
  640. /* flush updates before updating hardware */
  641. OSSynchronizeIO();
  642. txCleanBarrierIndex = txNextDescIndex;
  643.  
  644. if (adapterData.flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
  645. intelUpdateTxDescTail(txNextDescIndex);
  646. else
  647. intelWriteMem32(E1000_TDT(0), txNextDescIndex);
  648.  
  649. result = kIOReturnOutputSuccess;
  650.  
  651. done:
  652. //DebugLog("outputPacket() <===\n");
  653.  
  654. return result;
  655.  
  656. error:
  657. freePacket(m);
  658. goto done;
  659. }
  660.  
  661. void IntelMausi::getPacketBufferConstraints(IOPacketBufferConstraints *constraints) const
  662. {
  663. DebugLog("getPacketBufferConstraints() ===>\n");
  664.  
  665. constraints->alignStart = kIOPacketBufferAlign8;
  666. constraints->alignLength = kIOPacketBufferAlign8;
  667.  
  668. DebugLog("getPacketBufferConstraints() <===\n");
  669. }
  670.  
  671. IOOutputQueue* IntelMausi::createOutputQueue()
  672. {
  673. DebugLog("createOutputQueue() ===>\n");
  674.  
  675. DebugLog("createOutputQueue() <===\n");
  676.  
  677. return IOBasicOutputQueue::withTarget(this);
  678. }
  679.  
  680. const OSString* IntelMausi::newVendorString() const
  681. {
  682. DebugLog("newVendorString() ===>\n");
  683.  
  684. DebugLog("newVendorString() <===\n");
  685.  
  686. return OSString::withCString("Intel");
  687. }
  688.  
  689. const OSString* IntelMausi::newModelString() const
  690. {
  691. DebugLog("newModelString() ===>\n");
  692. DebugLog("newModelString() <===\n");
  693.  
  694. return OSString::withCString(deviceTable[chip].deviceName);
  695. }
  696.  
  697. bool IntelMausi::configureInterface(IONetworkInterface *interface)
  698. {
  699. char modelName[kNameLenght];
  700. IONetworkData *data;
  701. bool result;
  702.  
  703. DebugLog("configureInterface() ===>\n");
  704.  
  705. result = super::configureInterface(interface);
  706.  
  707. if (!result)
  708. goto done;
  709.  
  710. /* Get the generic network statistics structure. */
  711. data = interface->getParameter(kIONetworkStatsKey);
  712.  
  713. if (data) {
  714. netStats = (IONetworkStats *)data->getBuffer();
  715.  
  716. if (!netStats) {
  717. IOLog("Ethernet [IntelMausi]: Error getting IONetworkStats\n.");
  718. result = false;
  719. goto done;
  720. }
  721. }
  722. /* Get the Ethernet statistics structure. */
  723. data = interface->getParameter(kIOEthernetStatsKey);
  724.  
  725. if (data) {
  726. etherStats = (IOEthernetStats *)data->getBuffer();
  727.  
  728. if (!etherStats) {
  729. IOLog("Ethernet [IntelMausi]: Error getting IOEthernetStats\n.");
  730. result = false;
  731. goto done;
  732. }
  733. }
  734. snprintf(modelName, kNameLenght, "Intel %s PCI Express Gigabit Ethernet", deviceTable[chip].deviceName);
  735. setProperty("model", modelName);
  736.  
  737. DebugLog("configureInterface() <===\n");
  738.  
  739. done:
  740. return result;
  741. }
  742.  
  743. bool IntelMausi::createWorkLoop()
  744. {
  745. DebugLog("createWorkLoop() ===>\n");
  746.  
  747. workLoop = IOWorkLoop::workLoop();
  748.  
  749. DebugLog("createWorkLoop() <===\n");
  750.  
  751. return workLoop ? true : false;
  752. }
  753.  
  754. IOWorkLoop* IntelMausi::getWorkLoop() const
  755. {
  756. DebugLog("getWorkLoop() ===>\n");
  757.  
  758. DebugLog("getWorkLoop() <===\n");
  759.  
  760. return workLoop;
  761. }
  762.  
  763. IOReturn IntelMausi::setPromiscuousMode(bool active)
  764. {
  765. struct e1000_hw *hw = &adapterData.hw;
  766. UInt32 rxControl;
  767.  
  768. DebugLog("setPromiscuousMode() ===>\n");
  769.  
  770. rxControl = intelReadMem32(E1000_RCTL);
  771. rxControl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
  772.  
  773. if (active) {
  774. DebugLog("Ethernet [IntelMausi]: Promiscuous mode enabled.\n");
  775. rxControl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
  776. } else {
  777. DebugLog("Ethernet [IntelMausi]: Promiscuous mode disabled.\n");
  778. hw->mac.ops.update_mc_addr_list(hw, (UInt8 *)mcAddrList, mcListCount);
  779. }
  780. intelWriteMem32(E1000_RCTL, rxControl);
  781. promiscusMode = active;
  782.  
  783. DebugLog("setPromiscuousMode() <===\n");
  784.  
  785. return kIOReturnSuccess;
  786. }
  787.  
  788. IOReturn IntelMausi::setMulticastMode(bool active)
  789. {
  790. struct e1000_hw *hw = &adapterData.hw;
  791. UInt32 rxControl;
  792.  
  793. DebugLog("setMulticastMode() ===>\n");
  794.  
  795. rxControl = intelReadMem32(E1000_RCTL);
  796. rxControl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
  797.  
  798. if (active)
  799. hw->mac.ops.update_mc_addr_list(hw, (UInt8 *)mcAddrList, mcListCount);
  800. else
  801. hw->mac.ops.update_mc_addr_list(hw, NULL, 0);
  802.  
  803. intelWriteMem32(E1000_RCTL, rxControl);
  804. multicastMode = active;
  805.  
  806. DebugLog("setMulticastMode() <===\n");
  807.  
  808. return kIOReturnSuccess;
  809. }
  810.  
  811. IOReturn IntelMausi::setMulticastList(IOEthernetAddress *addrs, UInt32 count)
  812. {
  813. struct e1000_hw *hw = &adapterData.hw;
  814. IOEthernetAddress *newList;
  815. vm_size_t newSize;
  816. IOReturn result = kIOReturnNoMemory;
  817.  
  818. DebugLog("setMulticastList() ===>\n");
  819.  
  820. if (count) {
  821. newSize = count * sizeof(IOEthernetAddress);
  822. newList = (IOEthernetAddress *)IOMalloc(newSize);
  823.  
  824. if (newList) {
  825. if (mcAddrList)
  826. IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress));
  827.  
  828. memcpy(newList, addrs, newSize);
  829. mcAddrList = newList;
  830. mcListCount = count;
  831. hw->mac.ops.update_mc_addr_list(hw, (UInt8 *)newList, count);
  832.  
  833. result = kIOReturnSuccess;
  834. }
  835. } else {
  836. if (mcAddrList) {
  837. IOFree(mcAddrList, mcListCount * sizeof(IOEthernetAddress));
  838. mcAddrList = NULL;
  839. mcListCount = 0;
  840. }
  841. hw->mac.ops.update_mc_addr_list(hw, NULL, 0);
  842.  
  843. result = kIOReturnSuccess;
  844. }
  845.  
  846. DebugLog("setMulticastList() <===\n");
  847.  
  848. return result;
  849. }
  850.  
  851. IOReturn IntelMausi::getChecksumSupport(UInt32 *checksumMask, UInt32 checksumFamily, bool isOutput)
  852. {
  853. IOReturn result = kIOReturnUnsupported;
  854.  
  855. DebugLog("getChecksumSupport() ===>\n");
  856.  
  857. if ((checksumFamily == kChecksumFamilyTCPIP) && checksumMask) {
  858. if (isOutput) {
  859. *checksumMask = (kChecksumTCP | kChecksumUDP | kChecksumIP);
  860.  
  861. if (enableCSO6)
  862. *checksumMask |= (kChecksumTCPIPv6 | kChecksumUDPIPv6);
  863. } else {
  864. *checksumMask = (kChecksumTCP | kChecksumUDP | kChecksumIP | kChecksumTCPIPv6 | kChecksumUDPIPv6);
  865. }
  866. result = kIOReturnSuccess;
  867. }
  868. DebugLog("getChecksumSupport() <===\n");
  869.  
  870. return result;
  871. }
  872.  
  873. UInt32 IntelMausi::getFeatures() const
  874. {
  875. UInt32 features = (kIONetworkFeatureMultiPages | kIONetworkFeatureHardwareVlan);
  876.  
  877. DebugLog("getFeatures() ===>\n");
  878.  
  879. if (enableTSO4)
  880. features |= kIONetworkFeatureTSOIPv4;
  881.  
  882. if (enableTSO6)
  883. features |= kIONetworkFeatureTSOIPv6;
  884.  
  885. DebugLog("getFeatures() <===\n");
  886.  
  887. return features;
  888. }
  889.  
  890. IOReturn IntelMausi::setWakeOnMagicPacket(bool active)
  891. {
  892. IOReturn result = kIOReturnUnsupported;
  893.  
  894. DebugLog("setWakeOnMagicPacket() ===>\n");
  895.  
  896. if (wolCapable) {
  897. wolActive = active;
  898. DebugLog("Ethernet [IntelMausi]: Wake on magic packet %s.\n", active ? "enabled" : "disabled");
  899. result = kIOReturnSuccess;
  900. }
  901.  
  902. DebugLog("setWakeOnMagicPacket() <===\n");
  903.  
  904. return result;
  905. }
  906.  
  907. IOReturn IntelMausi::getPacketFilters(const OSSymbol *group, UInt32 *filters) const
  908. {
  909. IOReturn result = kIOReturnSuccess;
  910.  
  911. DebugLog("getPacketFilters() ===>\n");
  912.  
  913. if ((group == gIOEthernetWakeOnLANFilterGroup) && wolCapable) {
  914. *filters = kIOEthernetWakeOnMagicPacket;
  915. DebugLog("Ethernet [IntelMausi]: kIOEthernetWakeOnMagicPacket added to filters.\n");
  916. } else {
  917. result = super::getPacketFilters(group, filters);
  918. }
  919.  
  920. DebugLog("getPacketFilters() <===\n");
  921.  
  922. return result;
  923. }
  924.  
  925. IOReturn IntelMausi::setHardwareAddress(const IOEthernetAddress *addr)
  926. {
  927. struct e1000_hw *hw = &adapterData.hw;
  928. IOReturn result = kIOReturnError;
  929.  
  930. DebugLog("setHardwareAddress() ===>\n");
  931.  
  932. if (addr && is_valid_ether_addr(&addr->bytes[0])) {
  933. memcpy(hw->mac.addr, &addr->bytes[0], kIOEthernetAddressSize);
  934.  
  935. hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
  936.  
  937. result = kIOReturnSuccess;
  938. }
  939.  
  940. DebugLog("setHardwareAddress() <===\n");
  941.  
  942. return result;
  943. }
  944.  
  945. /* Methods inherited from IOEthernetController. */
  946. IOReturn IntelMausi::getHardwareAddress(IOEthernetAddress *addr)
  947. {
  948. IOReturn result = kIOReturnError;
  949.  
  950. DebugLog("getHardwareAddress() ===>\n");
  951.  
  952. //IOLog("Ethernet [IntelMausi]: RAH = 0x%x, RAL = 0x%x\n", intelReadMem32(E1000_RAH(0)), intelReadMem32(E1000_RAL(0)));
  953.  
  954. if (addr) {
  955. memcpy(&addr->bytes[0], adapterData.hw.mac.addr, kIOEthernetAddressSize);
  956.  
  957. if (is_valid_ether_addr(&addr->bytes[0]))
  958. result = kIOReturnSuccess;
  959. }
  960.  
  961. DebugLog("getHardwareAddress() <===\n");
  962.  
  963. return result;
  964. }
  965.  
  966. IOReturn IntelMausi::selectMedium(const IONetworkMedium *medium)
  967. {
  968. struct e1000_hw *hw = &adapterData.hw;
  969. struct e1000_mac_info *mac = &hw->mac;
  970. IOReturn result = kIOReturnSuccess;
  971.  
  972. DebugLog("selectMedium() ===>\n");
  973.  
  974. if (adapterData.flags2 & FLAG2_HAS_EEE)
  975. hw->dev_spec.ich8lan.eee_disable = true;
  976.  
  977. if (medium) {
  978. switch (medium->getIndex()) {
  979. case MEDIUM_INDEX_AUTO:
  980. if (hw->phy.media_type == e1000_media_type_fiber) {
  981. hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Autoneg;
  982. } else {
  983. hw->phy.autoneg_advertised = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
  984. ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half |
  985. ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg |
  986. ADVERTISED_TP | ADVERTISED_MII);
  987.  
  988. if (adapterData.fc_autoneg)
  989. hw->fc.requested_mode = e1000_fc_default;
  990.  
  991. if (adapterData.flags2 & FLAG2_HAS_EEE)
  992. hw->dev_spec.ich8lan.eee_disable = false;
  993. }
  994. hw->mac.autoneg = 1;
  995. break;
  996.  
  997. case MEDIUM_INDEX_10HD:
  998. mac->forced_speed_duplex = ADVERTISE_10_HALF;
  999. hw->mac.autoneg = 0;
  1000. break;
  1001.  
  1002. case MEDIUM_INDEX_10FD:
  1003. mac->forced_speed_duplex = ADVERTISE_10_FULL;
  1004. hw->mac.autoneg = 0;
  1005. break;
  1006.  
  1007. case MEDIUM_INDEX_100HD:
  1008. hw->phy.autoneg_advertised = ADVERTISED_100baseT_Half;
  1009. hw->mac.autoneg = 1;
  1010. hw->fc.requested_mode = e1000_fc_none;
  1011. break;
  1012.  
  1013. case MEDIUM_INDEX_100FD:
  1014. hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full;
  1015. hw->mac.autoneg = 1;
  1016. hw->fc.requested_mode = e1000_fc_none;
  1017. break;
  1018.  
  1019. case MEDIUM_INDEX_100FDFC:
  1020. hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full;
  1021. hw->mac.autoneg = 1;
  1022. hw->fc.requested_mode = e1000_fc_full;
  1023. break;
  1024.  
  1025. case MEDIUM_INDEX_1000FD:
  1026. hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full;
  1027. hw->mac.autoneg = 1;
  1028. hw->fc.requested_mode = e1000_fc_none;
  1029. break;
  1030.  
  1031. case MEDIUM_INDEX_1000FDFC:
  1032. hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full;
  1033. hw->mac.autoneg = 1;
  1034. hw->fc.requested_mode = e1000_fc_full;
  1035. break;
  1036.  
  1037. case MEDIUM_INDEX_1000FDEEE:
  1038. hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full;
  1039. hw->mac.autoneg = 1;
  1040. hw->fc.requested_mode = e1000_fc_none;
  1041. hw->dev_spec.ich8lan.eee_disable = false;
  1042. break;
  1043.  
  1044. case MEDIUM_INDEX_1000FDFCEEE:
  1045. hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full;
  1046. hw->mac.autoneg = 1;
  1047. hw->fc.requested_mode = e1000_fc_full;
  1048. hw->dev_spec.ich8lan.eee_disable = false;
  1049. break;
  1050.  
  1051. case MEDIUM_INDEX_100FDEEE:
  1052. hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full;
  1053. hw->mac.autoneg = 1;
  1054. hw->fc.requested_mode = e1000_fc_none;
  1055. hw->dev_spec.ich8lan.eee_disable = false;
  1056. break;
  1057.  
  1058. case MEDIUM_INDEX_100FDFCEEE:
  1059. hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full;
  1060. hw->mac.autoneg = 1;
  1061. hw->fc.requested_mode = e1000_fc_full;
  1062. hw->dev_spec.ich8lan.eee_disable = false;
  1063. break;
  1064. }
  1065. /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */
  1066. hw->phy.mdix = AUTO_ALL_MODES;
  1067.  
  1068. setCurrentMedium(medium);
  1069.  
  1070. timerSource->cancelTimeout();
  1071. updateStatistics(&adapterData);
  1072. intelRestart();
  1073. }
  1074.  
  1075. DebugLog("selectMedium() <===\n");
  1076.  
  1077. done:
  1078. return result;
  1079. }
  1080.  
  1081.  
  1082. #pragma mark --- common interrupt methods ---
  1083.  
  1084. void IntelMausi::txInterrupt()
  1085. {
  1086. UInt32 descStatus;
  1087. SInt32 cleaned;
  1088.  
  1089. while (txDirtyIndex != txCleanBarrierIndex) {
  1090. if (txBufArray[txDirtyIndex].mbuf) {
  1091. descStatus = OSSwapLittleToHostInt32(txDescArray[txDirtyIndex].upper.data);
  1092.  
  1093. if (!(descStatus & E1000_TXD_STAT_DD))
  1094. goto done;
  1095.  
  1096. /* First free the attached mbuf and clean up the buffer info. */
  1097. freePacket(txBufArray[txDirtyIndex].mbuf);
  1098. txBufArray[txDirtyIndex].mbuf = NULL;
  1099.  
  1100. cleaned = txBufArray[txDirtyIndex].numDescs;
  1101. txBufArray[txDirtyIndex].numDescs = 0;
  1102.  
  1103. /* Finally update the number of free descriptors. */
  1104. OSAddAtomic(cleaned, &txNumFreeDesc);
  1105. txDescDoneCount += cleaned;
  1106. }
  1107. /* Increment txDirtyIndex. */
  1108. ++txDirtyIndex &= kTxDescMask;
  1109. }
  1110. //DebugLog("Ethernet [IntelMausi]: txInterrupt oldIndex=%u newIndex=%u\n", oldDirtyIndex, txDirtyDescIndex);
  1111.  
  1112. done:
  1113. if (stalled && (txNumFreeDesc > kTxQueueWakeTreshhold)) {
  1114. DebugLog("Ethernet [IntelMausi]: Restart stalled queue!\n");
  1115. txQueue->service(IOBasicOutputQueue::kServiceAsync);
  1116. stalled = false;
  1117. }
  1118. etherStats->dot3TxExtraEntry.interrupts++;
  1119. }
  1120.  
  1121. void IntelMausi::rxInterrupt()
  1122. {
  1123. IOPhysicalSegment rxSegment;
  1124. union e1000_rx_desc_extended *desc = &rxDescArray[rxNextDescIndex];
  1125. mbuf_t bufPkt, newPkt;
  1126. UInt64 addr;
  1127. UInt32 status;
  1128. UInt32 goodPkts = 0;
  1129. UInt32 crcSize = (adapterData.flags2 & FLAG2_CRC_STRIPPING) ? 0 : kIOEthernetCRCSize;
  1130. UInt32 pktSize;
  1131. UInt16 vlanTag;
  1132. bool replaced;
  1133.  
  1134. while ((status = OSSwapLittleToHostInt32(desc->wb.upper.status_error)) & E1000_RXD_STAT_DD) {
  1135. addr = rxBufArray[rxNextDescIndex].phyAddr;
  1136. bufPkt = rxBufArray[rxNextDescIndex].mbuf;
  1137.  
  1138. /* As we don't support jumbo frames we consider fragmented packets as errors. */
  1139. if (!(status & E1000_RXD_STAT_EOP)) {
  1140. DebugLog("Ethernet [IntelMausi]: Fragmented packet.\n");
  1141. etherStats->dot3StatsEntry.frameTooLongs++;
  1142. goto nextDesc;
  1143. }
  1144. pktSize = OSSwapLittleToHostInt16(desc->wb.upper.length) - crcSize;
  1145. vlanTag = (status & E1000_RXD_STAT_VP) ? (OSSwapLittleToHostInt16(desc->wb.upper.vlan) & E1000_RXD_SPC_VLAN_MASK) : 0;
  1146.  
  1147. /* Skip bad packet. */
  1148. if (status & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
  1149. DebugLog("Ethernet [IntelMausi]: Bad packet.\n");
  1150. etherStats->dot3StatsEntry.internalMacReceiveErrors++;
  1151. goto nextDesc;
  1152. }
  1153. newPkt = replaceOrCopyPacket(&bufPkt, pktSize, &replaced);
  1154.  
  1155. if (!newPkt) {
  1156. /* Allocation of a new packet failed so that we must leave the original packet in place. */
  1157. DebugLog("Ethernet [IntelMausi]: replaceOrCopyPacket() failed.\n");
  1158. etherStats->dot3RxExtraEntry.resourceErrors++;
  1159. goto nextDesc;
  1160. }
  1161.  
  1162. /* If the packet was replaced we have to update the descriptor's buffer address. */
  1163. if (replaced) {
  1164. if (rxMbufCursor->getPhysicalSegmentsWithCoalesce(bufPkt, &rxSegment, 1) != 1) {
  1165. DebugLog("Ethernet [IntelMausi]: getPhysicalSegmentsWithCoalesce() failed.\n");
  1166. etherStats->dot3RxExtraEntry.resourceErrors++;
  1167. freePacket(bufPkt);
  1168. goto nextDesc;
  1169. }
  1170. addr = rxSegment.location;
  1171. rxBufArray[rxNextDescIndex].mbuf = bufPkt;
  1172. rxBufArray[rxNextDescIndex].phyAddr = addr;
  1173. }
  1174. intelGetChecksumResult(newPkt, status);
  1175.  
  1176. /* Also get the VLAN tag if there is any. */
  1177. if (vlanTag)
  1178. setVlanTag(newPkt, vlanTag);
  1179.  
  1180. netif->inputPacket(newPkt, pktSize, IONetworkInterface::kInputOptionQueuePacket);
  1181. goodPkts++;
  1182.  
  1183. /* Finally update the descriptor and get the next one to examine. */
  1184. nextDesc:
  1185. desc->read.buffer_addr = OSSwapHostToLittleInt64(addr);
  1186. desc->read.reserved = 0;
  1187.  
  1188. ++rxNextDescIndex &= kRxDescMask;
  1189. desc = &rxDescArray[rxNextDescIndex];
  1190. rxCleanedCount++;
  1191. }
  1192. if (goodPkts)
  1193. netif->flushInputQueue();
  1194.  
  1195. if (rxCleanedCount >= E1000_RX_BUFFER_WRITE) {
  1196. /*
  1197. * Prevent the tail from reaching the head in order to avoid a false
  1198. * buffer queue full condition.
  1199. */
  1200. if (adapterData.flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
  1201. intelUpdateRxDescTail((rxNextDescIndex - 1) & kRxDescMask);
  1202. else
  1203. intelWriteMem32(E1000_RDT(0), (rxNextDescIndex - 1) & kRxDescMask);
  1204.  
  1205. rxCleanedCount = 0;
  1206. }
  1207. etherStats->dot3RxExtraEntry.interrupts++;
  1208. }
  1209.  
  1210. void IntelMausi::checkLinkStatus()
  1211. {
  1212. struct e1000_hw *hw = &adapterData.hw;
  1213. bool link;
  1214.  
  1215. hw->mac.get_link_status = true;
  1216.  
  1217. /* ICH8 workaround-- Call gig speed drop workaround on cable
  1218. * disconnect (LSC) before accessing any PHY registers
  1219. */
  1220. if ((adapterData.flags & FLAG_LSC_GIG_SPEED_DROP) && (!(intelReadMem32(E1000_STATUS) & E1000_STATUS_LU))) {
  1221. if (!test_bit(__E1000_DOWN, &adapterData.state))
  1222. e1000e_gig_downshift_workaround_ich8lan(hw);
  1223. }
  1224. /* Now check the link state. */
  1225. link = intelCheckLink(&adapterData);
  1226.  
  1227. DebugLog("Ethernet [IntelMausi]: checkLinkStatus() returned %u.\n", link);
  1228.  
  1229. if (linkUp) {
  1230. if (link) {
  1231. /* The link partner must have changed some setting. Initiate renegotiation
  1232. * of the link parameters to make sure that the MAC is programmed correctly.
  1233. */
  1234. timerSource->cancelTimeout();
  1235. updateStatistics(&adapterData);
  1236. intelRestart();
  1237. } else {
  1238. /* Stop watchdog and statistics updates. */
  1239. timerSource->cancelTimeout();
  1240. setLinkDown();
  1241. }
  1242. } else {
  1243. if (link) {
  1244. /* Start rx/tx and inform upper layers that the link is up now. */
  1245. setLinkUp();
  1246. timerSource->setTimeoutMS(kTimeoutMS);
  1247. }
  1248. }
  1249. }
  1250.  
  1251. void IntelMausi::interruptOccurred(OSObject *client, IOInterruptEventSource *src, int count)
  1252. {
  1253. struct e1000_hw *hw = &adapterData.hw;
  1254. UInt32 icr = intelReadMem32(E1000_ICR); /* read ICR disables interrupts using IAM */
  1255.  
  1256. /* Handle transmit descriptors. */
  1257. if (icr & (E1000_ICR_TXDW | E1000_ICR_TXQ0)) {
  1258. txInterrupt();
  1259. }
  1260. /* Handle receive descriptors. */
  1261. if (icr & (E1000_ICR_RXQ0 | E1000_ICR_RXT0 | E1000_ICR_RXDMT0)) {
  1262. rxInterrupt();
  1263. }
  1264.  
  1265. #if DISABLED_CODE
  1266. if (icr & (E1000_ICR_TXDW | E1000_ICR_TXQE | E1000_ICR_TXQ0 | E1000_ICR_RXQ0 | E1000_ICR_RXT0 | E1000_ICR_RXDMT0)) {
  1267. txInterrupt();
  1268. rxInterrupt();
  1269. }
  1270. #endif /* DISABLED_CODE */
  1271.  
  1272. /* Reset on uncorrectable ECC error */
  1273. if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
  1274. UInt32 pbeccsts = intelReadMem32(E1000_PBECCSTS);
  1275.  
  1276. etherStats->dot3StatsEntry.internalMacReceiveErrors += (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
  1277. etherStats->dot3TxExtraEntry.resets++;
  1278.  
  1279. IOLog("Ethernet [IntelMausi]: Uncorrectable ECC error. Reseting chip.\n");
  1280. intelRestart();
  1281. return;
  1282. }
  1283. if (icr & (E1000_ICR_LSC | E1000_IMS_RXSEQ)) {
  1284. checkLinkStatus();
  1285. }
  1286. /* Reenable interrupts by setting the bits in the mask register. */
  1287. intelWriteMem32(E1000_IMS, icr);
  1288. }
  1289.  
  1290. #pragma mark --- hardware specific methods ---
  1291.  
  1292. void IntelMausi::setLinkUp()
  1293. {
  1294. struct e1000_hw *hw = &adapterData.hw;
  1295. struct e1000_phy_info *phy = &hw->phy;
  1296. const char *flowName;
  1297. const char *speedName;
  1298. const char *duplexName;
  1299. const char *eeeName;
  1300. UInt64 mediumSpeed;
  1301. UInt32 mediumIndex = MEDIUM_INDEX_AUTO;
  1302. UInt32 fcIndex;
  1303. UInt32 tctl, rctl, ctrl;
  1304.  
  1305. eeeMode = 0;
  1306. eeeName = eeeNames[kEEETypeNo];
  1307.  
  1308. /* update snapshot of PHY registers on LSC */
  1309. intelPhyReadStatus(&adapterData);
  1310. hw->mac.ops.get_link_up_info(hw, &adapterData.link_speed, &adapterData.link_duplex);
  1311.  
  1312. /* check if SmartSpeed worked */
  1313. e1000e_check_downshift(hw);
  1314.  
  1315. if (phy->speed_downgraded)
  1316. IOLog("Ethernet [IntelMausi]: Link Speed was downgraded by SmartSpeed\n");
  1317.  
  1318. /* On supported PHYs, check for duplex mismatch only
  1319. * if link has autonegotiated at 10/100 half
  1320. */
  1321. if ((hw->phy.type == e1000_phy_igp_3 || hw->phy.type == e1000_phy_bm) &&
  1322. hw->mac.autoneg && (adapterData.link_speed == SPEED_10 || adapterData.link_speed == SPEED_100) &&
  1323. (adapterData.link_duplex == HALF_DUPLEX)) {
  1324. UInt16 autoneg_exp;
  1325.  
  1326. e1e_rphy(hw, MII_EXPANSION, &autoneg_exp);
  1327.  
  1328. if (!(autoneg_exp & EXPANSION_NWAY))
  1329. IOLog("Ethernet [IntelMausi]: Autonegotiated half duplex but link partner cannot autoneg. Try forcing full duplex if link gets many collisions.\n");
  1330. }
  1331. /* Enable transmits in the hardware. */
  1332. tctl = intelReadMem32(E1000_TCTL);
  1333. tctl |= E1000_TCTL_EN;
  1334. intelWriteMem32(E1000_TCTL, tctl);
  1335.  
  1336. /* Enable the receiver too. */
  1337. rctl = intelReadMem32(E1000_RCTL);
  1338. rctl |= E1000_RCTL_EN;
  1339. intelWriteMem32(E1000_RCTL, rctl);
  1340.  
  1341. /* Perform any post-link-up configuration before
  1342. * reporting link up.
  1343. */
  1344. if (phy->ops.cfg_on_link_up)
  1345. phy->ops.cfg_on_link_up(hw);
  1346.  
  1347. intelEnableIRQ(intrMask);
  1348.  
  1349. /* Get link speed, duplex and flow-control mode. */
  1350. ctrl = intelReadMem32(E1000_CTRL) & (E1000_CTRL_RFCE | E1000_CTRL_TFCE);
  1351.  
  1352. switch (ctrl) {
  1353. case (E1000_CTRL_RFCE | E1000_CTRL_TFCE):
  1354. fcIndex = kFlowControlTypeRxTx;
  1355. break;
  1356.  
  1357. case E1000_CTRL_RFCE:
  1358. fcIndex = kFlowControlTypeRx;
  1359. break;
  1360.  
  1361. case E1000_CTRL_TFCE:
  1362. fcIndex = kFlowControlTypeTx;
  1363. break;
  1364.  
  1365. default:
  1366. fcIndex = kFlowControlTypeNone;
  1367. break;
  1368. }
  1369. flowName = flowControlNames[fcIndex];
  1370.  
  1371. if (adapterData.link_speed == SPEED_1000) {
  1372. mediumSpeed = kSpeed1000MBit;
  1373. speedName = speed1GName;
  1374. duplexName = duplexFullName;
  1375.  
  1376. eeeMode = intelSupportsEEE(&adapterData);
  1377.  
  1378. if (fcIndex == kFlowControlTypeNone) {
  1379. if (eeeMode) {
  1380. mediumIndex = MEDIUM_INDEX_1000FDEEE;
  1381. eeeName = eeeNames[kEEETypeYes];
  1382. } else {
  1383. mediumIndex = MEDIUM_INDEX_1000FD;
  1384. }
  1385. } else {
  1386. if (eeeMode) {
  1387. mediumIndex = MEDIUM_INDEX_1000FDFCEEE;
  1388. eeeName = eeeNames[kEEETypeYes];
  1389. } else {
  1390. mediumIndex = MEDIUM_INDEX_1000FDFC;
  1391. }
  1392. }
  1393. } else if (adapterData.link_speed == SPEED_100) {
  1394. mediumSpeed = kSpeed100MBit;
  1395. speedName = speed100MName;
  1396.  
  1397. if (adapterData.link_duplex != DUPLEX_FULL) {
  1398. duplexName = duplexFullName;
  1399.  
  1400. eeeMode = intelSupportsEEE(&adapterData);
  1401.  
  1402. if (fcIndex == kFlowControlTypeNone) {
  1403. if (eeeMode) {
  1404. mediumIndex = MEDIUM_INDEX_100FDEEE;
  1405. eeeName = eeeNames[kEEETypeYes];
  1406. } else {
  1407. mediumIndex = MEDIUM_INDEX_100FD;
  1408. }
  1409. } else {
  1410. if (eeeMode) {
  1411. mediumIndex = MEDIUM_INDEX_100FDFCEEE;
  1412. eeeName = eeeNames[kEEETypeYes];
  1413. } else {
  1414. mediumIndex = MEDIUM_INDEX_100FDFC;
  1415. }
  1416. }
  1417. } else {
  1418. mediumIndex = MEDIUM_INDEX_100HD;
  1419. duplexName = duplexHalfName;
  1420. }
  1421. } else {
  1422. mediumSpeed = kSpeed10MBit;
  1423. speedName = speed10MName;
  1424.  
  1425. if (adapterData.link_duplex != DUPLEX_FULL) {
  1426. mediumIndex = MEDIUM_INDEX_10FD;
  1427. duplexName = duplexFullName;
  1428. } else {
  1429. mediumIndex = MEDIUM_INDEX_10HD;
  1430. duplexName = duplexHalfName;
  1431. }
  1432. }
  1433. linkUp = true;
  1434. setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, mediumTable[mediumIndex], mediumSpeed, NULL);
  1435.  
  1436. /* Restart txQueue, statistics updates and watchdog. */
  1437. txQueue->start();
  1438.  
  1439. if (stalled) {
  1440. txQueue->service();
  1441. stalled = false;
  1442. DebugLog("Ethernet [IntelMausi]: Restart stalled queue!\n");
  1443. }
  1444. IOLog("Ethernet [IntelMausi]: Link up on en%u, %s, %s, %s%s\n", netif->getUnitNumber(), speedName, duplexName, flowName, eeeName);
  1445.  
  1446. DebugLog("Ethernet [IntelMausi]: CTRL=0x%08x\n", intelReadMem32(E1000_CTRL));
  1447. DebugLog("Ethernet [IntelMausi]: CTRL_EXT=0x%08x\n", intelReadMem32(E1000_CTRL_EXT));
  1448. DebugLog("Ethernet [IntelMausi]: STATUS=0x%08x\n", intelReadMem32(E1000_STATUS));
  1449. DebugLog("Ethernet [IntelMausi]: GCR=0x%08x\n", intelReadMem32(E1000_GCR));
  1450. DebugLog("Ethernet [IntelMausi]: GCR2=0x%08x\n", intelReadMem32(E1000_GCR2));
  1451. DebugLog("Ethernet [IntelMausi]: RCTL=0x%08x\n", intelReadMem32(E1000_RCTL));
  1452. DebugLog("Ethernet [IntelMausi]: PSRCTL=0x%08x\n", intelReadMem32(E1000_PSRCTL));
  1453. DebugLog("Ethernet [IntelMausi]: FCRTL=0x%08x\n", intelReadMem32(E1000_FCRTL));
  1454. DebugLog("Ethernet [IntelMausi]: FCRTH=0x%08x\n", intelReadMem32(E1000_FCRTH));
  1455. DebugLog("Ethernet [IntelMausi]: RDLEN(0)=0x%08x\n", intelReadMem32(E1000_RDLEN(0)));
  1456. DebugLog("Ethernet [IntelMausi]: RDTR=0x%08x\n", intelReadMem32(E1000_RDTR));
  1457. DebugLog("Ethernet [IntelMausi]: RADV=0x%08x\n", intelReadMem32(E1000_RADV));
  1458. DebugLog("Ethernet [IntelMausi]: RXCSUM=0x%08x\n", intelReadMem32(E1000_RXCSUM));
  1459. DebugLog("Ethernet [IntelMausi]: RFCTL=0x%08x\n", intelReadMem32(E1000_RFCTL));
  1460. DebugLog("Ethernet [IntelMausi]: RXDCTL(0)=0x%08x\n", intelReadMem32(E1000_RXDCTL(0)));
  1461. DebugLog("Ethernet [IntelMausi]: RAL(0)=0x%08x\n", intelReadMem32(E1000_RAL(0)));
  1462. DebugLog("Ethernet [IntelMausi]: RAH(0)=0x%08x\n", intelReadMem32(E1000_RAH(0)));
  1463. DebugLog("Ethernet [IntelMausi]: MRQC=0x%08x\n", intelReadMem32(E1000_MRQC));
  1464. DebugLog("Ethernet [IntelMausi]: TARC(0)=0x%08x\n", intelReadMem32(E1000_TARC(0)));
  1465. DebugLog("Ethernet [IntelMausi]: TCTL=0x%08x\n", intelReadMem32(E1000_TCTL));
  1466. DebugLog("Ethernet [IntelMausi]: TXDCTL(0)=0x%08x\n", intelReadMem32(E1000_TXDCTL(0)));
  1467. DebugLog("Ethernet [IntelMausi]: TADV=0x%08x\n", intelReadMem32(E1000_TADV));
  1468. DebugLog("Ethernet [IntelMausi]: TIDV=0x%08x\n", intelReadMem32(E1000_TIDV));
  1469. DebugLog("Ethernet [IntelMausi]: MANC=0x%08x\n", intelReadMem32(E1000_MANC));
  1470. DebugLog("Ethernet [IntelMausi]: MANC2H=0x%08x\n", intelReadMem32(E1000_MANC2H));
  1471. }
  1472.  
  1473. void IntelMausi::setLinkDown()
  1474. {
  1475. deadlockWarn = 0;
  1476.  
  1477. /* Stop txQueue. */
  1478. txQueue->stop();
  1479. txQueue->flush();
  1480.  
  1481. /* Update link status. */
  1482. linkUp = false;
  1483. setLinkStatus(kIONetworkLinkValid);
  1484.  
  1485. intelDown(&adapterData, true);
  1486. intelConfigure(&adapterData);
  1487. clear_bit(__E1000_DOWN, &adapterData.state);
  1488. intelEnableIRQ(intrMask);
  1489.  
  1490. IOLog("Ethernet [IntelMausi]: Link down on en%u\n", netif->getUnitNumber());
  1491. }
  1492.  
  1493. inline void IntelMausi::intelGetChecksumResult(mbuf_t m, UInt32 status)
  1494. {
  1495. if (!(status & (E1000_RXDEXT_STATERR_IPE | E1000_RXDEXT_STATERR_TCPE))) {
  1496. mbuf_csum_performed_flags_t performed = 0;
  1497. UInt32 value = 0;
  1498.  
  1499. if (status & E1000_RXD_STAT_IPPCS)
  1500. performed |= (MBUF_CSUM_DID_IP | MBUF_CSUM_IP_GOOD);
  1501.  
  1502. if (status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) {
  1503. performed |= (MBUF_CSUM_DID_DATA | MBUF_CSUM_PSEUDO_HDR);
  1504. value = 0xffff; // fake a valid checksum value
  1505. }
  1506. if (performed)
  1507. mbuf_set_csum_performed(m, performed, value);
  1508. }
  1509. }
  1510.  
  1511. bool IntelMausi::intelIdentifyChip()
  1512. {
  1513. const struct e1000_info *ei;
  1514. UInt32 i = 0;
  1515. UInt16 id = deviceTable[i].pciDevId;
  1516. bool result = false;
  1517.  
  1518. while (id) {
  1519. if (id == pciDeviceData.device) {
  1520. chip = i;
  1521. chipType = deviceTable[i].device;
  1522. ei = deviceTable[i].deviceInfo;
  1523. adapterData.ei = ei;
  1524. adapterData.pba = ei->pba;
  1525. adapterData.flags = ei->flags;
  1526. adapterData.flags2 = ei->flags2;
  1527. adapterData.hw.adapter = &adapterData;
  1528. adapterData.hw.mac.type = ei->mac;
  1529. adapterData.max_hw_frame_size = ei->max_hw_frame_size;
  1530. adapterData.bd_number = 0;
  1531.  
  1532. /* Set default EEE advertisement */
  1533. if (adapterData.flags2 & FLAG2_HAS_EEE)
  1534. adapterData.eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T;
  1535.  
  1536. result = true;
  1537. break;
  1538. }
  1539. id = deviceTable[++i].pciDevId;
  1540. }
  1541.  
  1542. done:
  1543. return result;
  1544. }
  1545.  
  1546. bool IntelMausi::intelStart()
  1547. {
  1548. struct e1000_hw *hw = &adapterData.hw;
  1549. const struct e1000_info *ei = adapterData.ei;
  1550. struct e1000_mac_info *mac = &hw->mac;
  1551. SInt32 rval = 0;
  1552. UInt16 eepromData = 0;
  1553. UInt16 eepromApmeMask = E1000_EEPROM_APME;
  1554. int error, i;
  1555. bool result = false;
  1556.  
  1557. /* Setup some default values. */
  1558. adapterData.rx_buffer_len = ETH_FRAME_LEN + ETH_FCS_LEN;
  1559. adapterData.max_frame_size = mtu + ETH_HLEN + ETH_FCS_LEN;
  1560. adapterData.min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
  1561.  
  1562. adapterData.rx_int_delay = 0;
  1563. adapterData.rx_abs_int_delay = 0;
  1564.  
  1565. adapterData.tx_int_delay = 0x1c;
  1566. adapterData.tx_abs_int_delay = 0x1c;
  1567.  
  1568. if ((adapterData.flags & FLAG_HAS_SMART_POWER_DOWN))
  1569. adapterData.flags |= FLAG_SMART_POWER_DOWN;
  1570.  
  1571. adapterData.flags2 |= (FLAG2_CRC_STRIPPING | FLAG2_DFLT_CRC_STRIPPING);
  1572. adapterData.flags |= FLAG_READ_ONLY_NVM;
  1573.  
  1574. if (adapterData.flags2 & FLAG2_HAS_EEE)
  1575. hw->dev_spec.ich8lan.eee_disable = false;
  1576.  
  1577. initPCIPowerManagment(pciDevice, ei);
  1578.  
  1579. /* Explicitly disable IRQ since the NIC can be in any state. */
  1580. intelDisableIRQ();
  1581.  
  1582. set_bit(__E1000_DOWN, &adapterData.state);
  1583.  
  1584. memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
  1585. memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops));
  1586. memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
  1587.  
  1588. if (hw->mac.type == e1000_ich8lan)
  1589. e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
  1590.  
  1591. hw->phy.autoneg_wait_to_complete = 0;
  1592.  
  1593. error = ei->get_variants(&adapterData);
  1594.  
  1595. if (error) {
  1596. IOLog("Ethernet [IntelMausi]: Failed to get adapter data with error %d.\n", error);
  1597. goto done;
  1598. }
  1599. if ((adapterData.flags & FLAG_IS_ICH) &&
  1600. (adapterData.flags & FLAG_READ_ONLY_NVM))
  1601. e1000e_write_protect_nvm_ich8lan(hw);
  1602.  
  1603. hw->phy.autoneg_wait_to_complete = 0;
  1604.  
  1605. /* Copper options */
  1606. if (hw->phy.media_type == e1000_media_type_copper) {
  1607. hw->phy.mdix = AUTO_ALL_MODES;
  1608. hw->phy.disable_polarity_correction = 0;
  1609. hw->phy.ms_type = e1000_ms_hw_default;
  1610. }
  1611. if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
  1612. IOLog("Ethernet [IntelMausi]: PHY reset is blocked due to SOL/IDER session.\n");
  1613.  
  1614. if (intelEnableMngPassThru(hw))
  1615. adapterData.flags |= FLAG_MNG_PT_ENABLED;
  1616.  
  1617. /* before reading the NVM, reset the controller to
  1618. * put the device in a known good starting state
  1619. */
  1620. hw->mac.ops.reset_hw(hw);
  1621.  
  1622. /* systems with ASPM and others may see the checksum fail on the first
  1623. * attempt. Let's give it a few tries
  1624. */
  1625. for (i = 0;; i++) {
  1626. if (e1000_validate_nvm_checksum(hw) >= 0)
  1627. break;
  1628.  
  1629. if (i == 2) {
  1630. IOLog("Ethernet [IntelMausi]: The NVM Checksum Is Not Valid.\n");
  1631. break;
  1632. goto error_eeprom;
  1633. }
  1634. }
  1635. intelEEPROMChecks(&adapterData);
  1636.  
  1637. /* copy the MAC address */
  1638. if (e1000e_read_mac_addr(hw))
  1639. IOLog("Ethernet [IntelMausi]: NVM Read Error while reading MAC address.\n");
  1640.  
  1641. if (!is_valid_ether_addr(mac->addr)) {
  1642. IOLog("Ethernet [IntelMausi]: Invalid MAC Address: %pM\n", mac->addr);
  1643. goto error_eeprom;
  1644. }
  1645. /* Initialize link parameters. User can change them with ethtool */
  1646. hw->mac.autoneg = 1;
  1647. adapterData.fc_autoneg = true;
  1648. hw->fc.requested_mode = e1000_fc_default;
  1649. hw->fc.current_mode = e1000_fc_default;
  1650. hw->phy.autoneg_advertised = 0x2f;
  1651.  
  1652. /* Initial Wake on LAN setting - If APM wake is enabled in
  1653. * the EEPROM, enable the ACPI Magic Packet filter
  1654. */
  1655. if (adapterData.flags & FLAG_APME_IN_WUC) {
  1656. /* APME bit in EEPROM is mapped to WUC.APME */
  1657. eepromData = intelReadMem32(E1000_WUC);
  1658. eepromApmeMask = E1000_WUC_APME;
  1659.  
  1660. if ((hw->mac.type > e1000_ich10lan) &&
  1661. (eepromData & E1000_WUC_PHY_WAKE))
  1662. adapterData.flags2 |= FLAG2_HAS_PHY_WAKEUP;
  1663. } else if (adapterData.flags & FLAG_APME_IN_CTRL3) {
  1664. if (adapterData.flags & FLAG_APME_CHECK_PORT_B && (adapterData.hw.bus.func == 1))
  1665. rval = e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eepromData);
  1666. else
  1667. rval = e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eepromData);
  1668. }
  1669.  
  1670. /* fetch WoL from EEPROM */
  1671. if (rval)
  1672. DebugLog("Ethernet [IntelMausi]: NVM read error getting WoL initial values: %d\n", rval);
  1673. else if (eepromData & eepromApmeMask)
  1674. adapterData.eeprom_wol |= E1000_WUFC_MAG;
  1675.  
  1676. /* now that we have the eeprom settings, apply the special cases
  1677. * where the eeprom may be wrong or the board simply won't support
  1678. * wake on lan on a particular port
  1679. */
  1680. if (!(adapterData.flags & FLAG_HAS_WOL))
  1681. adapterData.eeprom_wol = 0;
  1682.  
  1683. /* initialize the wol settings based on the eeprom settings */
  1684. adapterData.wol = adapterData.eeprom_wol;
  1685.  
  1686. /* make sure adapter isn't asleep if manageability is enabled */
  1687. if (adapterData.wol || (adapterData.flags & FLAG_MNG_PT_ENABLED) || (hw->mac.ops.check_mng_mode(hw)))
  1688. pciDevice->enablePCIPowerManagement(kPCIPMCSPowerStateD0);
  1689.  
  1690. /* save off EEPROM version number */
  1691. rval = e1000_read_nvm(hw, 5, 1, &adapterData.eeprom_vers);
  1692.  
  1693. if (rval) {
  1694. DebugLog("Ethernet [IntelMausi]: NVM read error getting EEPROM version: %d\n", rval);
  1695. adapterData.eeprom_vers = 0;
  1696. }
  1697. /* reset the hardware with the new settings */
  1698. intelReset(&adapterData);
  1699.  
  1700. /* If the controller has AMT, do not set DRV_LOAD until the interface
  1701. * is up. For all other cases, let the f/w know that the h/w is now
  1702. * under the control of the driver.
  1703. */
  1704. if (!(adapterData.flags & FLAG_HAS_AMT))
  1705. e1000e_get_hw_control(&adapterData);
  1706.  
  1707. intrMask = IMS_ENABLE_MASK;
  1708.  
  1709. if (hw->mac.type == e1000_pch_lpt)
  1710. intrMask |= E1000_IMS_ECCER;
  1711.  
  1712. IOLog("Ethernet [IntelMausi]: %s (Rev. %u) at 0x%lx, %02x:%02x:%02x:%02x:%02x:%02x\n",
  1713. deviceTable[chip].deviceName, pciDeviceData.revision, (unsigned long)baseAddr,
  1714. mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]);
  1715. result = true;
  1716.  
  1717. done:
  1718. return result;
  1719.  
  1720. error_eeprom:
  1721. if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw))
  1722. e1000_phy_hw_reset(hw);
  1723.  
  1724. goto done;
  1725. }
  1726.  
  1727. #pragma mark --- timer action methods ---
  1728.  
  1729. void IntelMausi::timerAction(IOTimerEventSource *timer)
  1730. {
  1731. struct e1000_hw *hw = &adapterData.hw;
  1732.  
  1733. if (!linkUp) {
  1734. DebugLog("Ethernet [IntelMausi]: Timer fired while link down.\n");
  1735. goto done;
  1736. }
  1737. intelUpdateAdaptive(&adapterData.hw);
  1738.  
  1739. /* Check for tx deadlock. */
  1740. if (checkForDeadlock())
  1741. goto done;
  1742.  
  1743. /* Enable EEE on 82579 after link up. */
  1744. if (eeeMode) {
  1745. e1000_get_phy_info(hw);
  1746.  
  1747. if (hw->phy.type >= e1000_phy_82579)
  1748. intelEnableEEE(hw, eeeMode);
  1749.  
  1750. eeeMode = 0;
  1751. }
  1752. updateStatistics(&adapterData);
  1753. timerSource->setTimeoutMS(kTimeoutMS);
  1754.  
  1755. done:
  1756. txDescDoneLast = txDescDoneCount;
  1757.  
  1758. //DebugLog("timerAction() <===\n");
  1759. }
  1760.  
  1761. void IntelMausi::updateStatistics(struct e1000_adapter *adapter)
  1762. {
  1763. struct e1000_hw *hw = &adapter->hw;
  1764.  
  1765. adapter->stats.crcerrs += intelReadMem32(E1000_CRCERRS);
  1766. adapter->stats.gprc += intelReadMem32(E1000_GPRC);
  1767. adapter->stats.gorc += intelReadMem32(E1000_GORCL);
  1768. intelReadMem32(E1000_GORCH); /* Clear gorc */
  1769. adapter->stats.bprc += intelReadMem32(E1000_BPRC);
  1770. adapter->stats.mprc += intelReadMem32(E1000_MPRC);
  1771. adapter->stats.roc += intelReadMem32(E1000_ROC);
  1772.  
  1773. adapter->stats.mpc += intelReadMem32(E1000_MPC);
  1774.  
  1775. /* Half-duplex statistics */
  1776. if (adapter->link_duplex == HALF_DUPLEX) {
  1777. if (adapter->flags2 & FLAG2_HAS_PHY_STATS) {
  1778. e1000e_update_phy_stats(adapter);
  1779. } else {
  1780. adapter->stats.scc += intelReadMem32(E1000_SCC);
  1781. adapter->stats.ecol += intelReadMem32(E1000_ECOL);
  1782. adapter->stats.mcc += intelReadMem32(E1000_MCC);
  1783. adapter->stats.latecol += intelReadMem32(E1000_LATECOL);
  1784. adapter->stats.dc += intelReadMem32(E1000_DC);
  1785.  
  1786. hw->mac.collision_delta = intelReadMem32(E1000_COLC);
  1787.  
  1788. if ((hw->mac.type != e1000_82574) &&
  1789. (hw->mac.type != e1000_82583))
  1790. adapter->stats.tncrs += intelReadMem32(E1000_TNCRS);
  1791. }
  1792. adapter->stats.colc += hw->mac.collision_delta;
  1793. }
  1794.  
  1795. adapter->stats.xonrxc += intelReadMem32(E1000_XONRXC);
  1796. adapter->stats.xontxc += intelReadMem32(E1000_XONTXC);
  1797. adapter->stats.xoffrxc += intelReadMem32(E1000_XOFFRXC);
  1798. adapter->stats.xofftxc += intelReadMem32(E1000_XOFFTXC);
  1799. adapter->stats.gptc += intelReadMem32(E1000_GPTC);
  1800. adapter->stats.gotc += intelReadMem32(E1000_GOTCL);
  1801. intelReadMem32(E1000_GOTCH); /* Clear gotc */
  1802. adapter->stats.rnbc += intelReadMem32(E1000_RNBC);
  1803. adapter->stats.ruc += intelReadMem32(E1000_RUC);
  1804.  
  1805. adapter->stats.mptc += intelReadMem32(E1000_MPTC);
  1806. adapter->stats.bptc += intelReadMem32(E1000_BPTC);
  1807.  
  1808. /* used for adaptive IFS */
  1809.  
  1810. hw->mac.tx_packet_delta = intelReadMem32(E1000_TPT);
  1811. adapter->stats.tpt += hw->mac.tx_packet_delta;
  1812.  
  1813. adapter->stats.algnerrc += intelReadMem32(E1000_ALGNERRC);
  1814. adapter->stats.rxerrc += intelReadMem32(E1000_RXERRC);
  1815. adapter->stats.cexterr += intelReadMem32(E1000_CEXTERR);
  1816. adapter->stats.tsctc += intelReadMem32(E1000_TSCTC);
  1817. adapter->stats.tsctfc += intelReadMem32(E1000_TSCTFC);
  1818.  
  1819. netStats->inputPackets = (UInt32)adapter->stats.gprc;
  1820. netStats->inputErrors = (UInt32)(adapter->stats.rxerrc + adapter->stats.crcerrs
  1821. + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc
  1822. + adapter->stats.cexterr);
  1823. netStats->outputPackets = (UInt32)adapter->stats.gptc;
  1824. netStats->outputErrors = (UInt32)(adapter->stats.ecol + adapter->stats.latecol);
  1825. netStats->collisions = (UInt32)adapter->stats.colc;
  1826.  
  1827. etherStats->dot3StatsEntry.alignmentErrors = (UInt32)adapter->stats.algnerrc;
  1828. etherStats->dot3StatsEntry.fcsErrors = (UInt32)adapter->stats.crcerrs;
  1829. etherStats->dot3StatsEntry.singleCollisionFrames = (UInt32)adapter->stats.scc;
  1830. etherStats->dot3StatsEntry.multipleCollisionFrames = (UInt32)adapter->stats.mcc;
  1831. etherStats->dot3StatsEntry.deferredTransmissions = (UInt32)adapter->stats.dc ;
  1832. etherStats->dot3StatsEntry.lateCollisions = (UInt32)adapter->stats.latecol;
  1833. etherStats->dot3StatsEntry.excessiveCollisions = (UInt32)adapter->stats.ecol;
  1834. etherStats->dot3StatsEntry.carrierSenseErrors = (UInt32)adapter->stats.cexterr;
  1835. etherStats->dot3StatsEntry.frameTooLongs = (UInt32)adapter->stats.roc;
  1836. etherStats->dot3StatsEntry.missedFrames = (UInt32)adapter->stats.mpc;
  1837.  
  1838. etherStats->dot3RxExtraEntry.frameTooShorts = (UInt32)adapter->stats.ruc;
  1839. }
  1840.  
  1841. bool IntelMausi::checkForDeadlock()
  1842. {
  1843. bool deadlock = false;
  1844.  
  1845. /* Force detection of hung controller every watchdog period */
  1846. adapterData.detect_tx_hung = true;
  1847.  
  1848. if (forceReset) {
  1849. etherStats->dot3TxExtraEntry.resets++;
  1850. intelRestart();
  1851. deadlock = true;
  1852. eeeMode = 0;
  1853. }
  1854.  
  1855. if (((txDescDoneCount == txDescDoneLast) && (txNumFreeDesc < kNumTxDesc)) || (adapterData.phy_hang_count > 1)) {
  1856. if (++deadlockWarn >= kTxDeadlockTreshhold) {
  1857. mbuf_t m = txBufArray[txDirtyIndex].mbuf;
  1858. UInt32 pktSize;
  1859. UInt16 i, index;
  1860. UInt16 stalledIndex = txDirtyIndex;
  1861. UInt8 data;
  1862.  
  1863. IOLog("Ethernet [IntelMausi]: Tx stalled? Resetting chipset. txDirtyDescIndex=%u.\n", txDirtyIndex);
  1864.  
  1865. for (i = 0; i < 30; i++) {
  1866. index = ((stalledIndex - 10 + i) & kTxDescMask);
  1867. IOLog("Ethernet [IntelMausi]: desc[%u]: lower=0x%08x, upper=0x%08x, addr=0x%016llx, mbuf=0x%016llx.\n", index, txDescArray[index].lower.data, txDescArray[index].upper.data, txDescArray[index].buffer_addr, (UInt64)txBufArray[index].mbuf);
  1868. }
  1869. if (m) {
  1870. pktSize = (UInt32)mbuf_pkthdr_len(m);
  1871. IOLog("Ethernet [IntelMausi]: packet size=%u, header size=%u.\n", pktSize, (UInt32)mbuf_len(m));
  1872.  
  1873. IOLog("Ethernet [IntelMausi]: MAC-header: ");
  1874. for (i = 0; i < 14; i++) {
  1875. mbuf_copydata(m, i, 1, &data);
  1876. IOLog(" 0x%02x", data);
  1877. }
  1878. IOLog("\n");
  1879.  
  1880. IOLog("Ethernet [IntelMausi]: IP-header: ");
  1881. for (i = 14; i < 34; i++) {
  1882. mbuf_copydata(m, i, 1, &data);
  1883. IOLog(" 0x%02x", data);
  1884. }
  1885. IOLog("\n");
  1886.  
  1887. IOLog("Ethernet [IntelMausi]: TCP-Header / Data: ");
  1888. for (i = 34; i < 100; i++) {
  1889. mbuf_copydata(m, i, 1, &data);
  1890. IOLog(" 0x%02x", data);
  1891. }
  1892. IOLog("\n");
  1893. }
  1894. etherStats->dot3TxExtraEntry.resets++;
  1895. intelRestart();
  1896. deadlock = true;
  1897. } else {
  1898. DebugLog("Ethernet [IntelMausi]: Check tx ring for progress. txNumFreeDesc=%u\n", txNumFreeDesc);
  1899.  
  1900. /* Check the transmitter ring. */
  1901. txInterrupt();
  1902. }
  1903. } else {
  1904. deadlockWarn = 0;
  1905. }
  1906. return deadlock;
  1907. }
  1908.  
  1909. #pragma mark --- miscellaneous functions ---
  1910.  
  1911. static inline void prepareTSO4(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize)
  1912. {
  1913. struct iphdr *ipHdr = (struct iphdr *)((UInt8 *)mbuf_data(m) + ETHER_HDR_LEN);
  1914. struct tcphdr *tcpHdr = (struct tcphdr *)((UInt8 *)ipHdr + sizeof(struct iphdr));
  1915. UInt16 *addr = (UInt16 *)&ipHdr->saddr;
  1916. UInt32 csum32 = 6;
  1917. UInt32 plen = (UInt32)mbuf_pkthdr_len(m);
  1918. UInt32 hlen = (tcpHdr->th_off << 2) + kMinL4HdrOffsetV4;
  1919.  
  1920. ipHdr->tot_len = 0;
  1921.  
  1922. csum32 += ntohs(*addr++);
  1923. csum32 += ntohs(*addr++);
  1924. csum32 += ntohs(*addr++);
  1925. csum32 += ntohs(*addr);
  1926. csum32 += (csum32 >> 16);
  1927. tcpHdr->th_sum = htons((UInt16)csum32);
  1928.  
  1929. *mssHeaderSize = ((*mssHeaderSize << 16) | (hlen << 8));
  1930. *payloadSize = plen - hlen;
  1931. }
  1932. /*
  1933. static inline void prepareTSO4(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize)
  1934. {
  1935. struct iphdr *ipHdr = (struct iphdr *)((UInt8 *)mbuf_data(m) + ETHER_HDR_LEN);
  1936. struct tcphdr *tcpHdr = (struct tcphdr *)((UInt8 *)ipHdr + sizeof(struct iphdr));
  1937. UInt32 plen = ntohs(ipHdr->tot_len) - sizeof(struct iphdr);
  1938. UInt32 csum = ntohs(tcpHdr->th_sum) - plen;
  1939. UInt32 hlen = tcpHdr->th_off << 2;
  1940.  
  1941. //DebugLog("Ethernet [IntelMausi]: hlen=%u, mss=%u\n", hlen, *mssHeaderSize);
  1942.  
  1943. csum += (csum >> 16);
  1944. tcpHdr->th_sum = htons((UInt16)csum);
  1945.  
  1946. *mssHeaderSize = ((*mssHeaderSize << 16) | ((hlen + kMinL4HdrOffsetV4) << 8));
  1947. *payloadSize = plen - hlen;
  1948. }
  1949. */
  1950. static inline void prepareTSO6(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize)
  1951. {
  1952. struct ip6_hdr *ip6Hdr = (struct ip6_hdr *)((UInt8 *)mbuf_data(m) + ETHER_HDR_LEN);
  1953. struct tcphdr *tcpHdr = (struct tcphdr *)((UInt8 *)ip6Hdr + sizeof(struct ip6_hdr));
  1954. UInt16 *addr = (UInt16 *)&ip6Hdr->ip6_src;
  1955. UInt32 csum32 = 6;
  1956. UInt32 plen = (UInt32)mbuf_pkthdr_len(m);
  1957. UInt32 hlen = (tcpHdr->th_off << 2) + kMinL4HdrOffsetV6;
  1958. UInt32 i;
  1959.  
  1960. ip6Hdr->ip6_ctlun.ip6_un1.ip6_un1_plen = 0;
  1961.  
  1962. for (i = 0; i < 16; i++)
  1963. csum32 += ntohs(*addr++);
  1964.  
  1965. csum32 += (csum32 >> 16);
  1966. tcpHdr->th_sum = htons((UInt16)csum32);
  1967.  
  1968. //DebugLog("Ethernet [IntelMausi]: csum=0x%llx\n", csum64);
  1969.  
  1970. *mssHeaderSize = ((*mssHeaderSize << 16) | (hlen << 8));
  1971. *payloadSize = plen - hlen;
  1972. }
  1973. /*
  1974. static inline void prepareTSO6(mbuf_t m, UInt32 *mssHeaderSize, UInt32 *payloadSize)
  1975. {
  1976. struct ip6_hdr *ip6Hdr = (struct ip6_hdr *)((UInt8 *)mbuf_data(m) + ETHER_HDR_LEN);
  1977. struct tcphdr *tcpHdr = (struct tcphdr *)((UInt8 *)ip6Hdr + sizeof(struct ip6_hdr));
  1978. UInt32 plen = ntohs(ip6Hdr->ip6_ctlun.ip6_un1.ip6_un1_plen);
  1979. UInt32 csum = ntohs(tcpHdr->th_sum) - plen;
  1980. UInt32 hlen = tcpHdr->th_off << 2;
  1981.  
  1982. csum += (csum >> 16);
  1983. ip6Hdr->ip6_ctlun.ip6_un1.ip6_un1_plen = 0;
  1984. tcpHdr->th_sum = htons((UInt16)csum);
  1985.  
  1986. //DebugLog("Ethernet [IntelMausi]: csum=0x%04x\n", (UInt16)(csum & 0xffff));
  1987.  
  1988. *mssHeaderSize = ((*mssHeaderSize << 16) | ((hlen + kMinL4HdrOffsetV6) << 8));
  1989. *payloadSize = plen - hlen;
  1990. }
  1991. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement