E1000ENetworkAdapter.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/MACAddress.h>
  7. #include <Kernel/Bus/PCI/IDs.h>
  8. #include <Kernel/Net/E1000ENetworkAdapter.h>
  9. #include <Kernel/Sections.h>
  10. namespace Kernel {
  11. #define REG_EEPROM 0x0014
  12. static bool is_valid_device_id(u16 device_id)
  13. {
  14. // Note: All ids listed here are valid, but only the ones that are verified working are set to 'true'
  15. switch (device_id) {
  16. case 0x10D3: // 82574L
  17. return true;
  18. case 0x1000: // 82542
  19. case 0x0438: // DH89XXCC_SGMII
  20. case 0x043A: // DH89XXCC_SERDES
  21. case 0x043C: // DH89XXCC_BACKPLANE
  22. case 0x0440: // DH89XXCC_SFP
  23. case 0x1001: // 82543GC_FIBER
  24. case 0x1004: // 82543GC_COPPER
  25. case 0x1008: // 82544EI_COPPER
  26. case 0x1009: // 82544EI_FIBER
  27. case 0x100C: // 82544GC_COPPER
  28. case 0x100D: // 82544GC_LOM
  29. case 0x100E: // 82540EM
  30. case 0x100F: // 82545EM_COPPER
  31. case 0x1010: // 82546EB_COPPER
  32. case 0x1011: // 82545EM_FIBER
  33. case 0x1012: // 82546EB_FIBER
  34. case 0x1013: // 82541EI
  35. case 0x1014: // 82541ER_LOM
  36. case 0x1015: // 82540EM_LOM
  37. case 0x1016: // 82540EP_LOM
  38. case 0x1017: // 82540EP
  39. case 0x1018: // 82541EI_MOBILE
  40. case 0x1019: // 82547EI
  41. case 0x101A: // 82547EI_MOBILE
  42. case 0x101D: // 82546EB_QUAD_COPPER
  43. case 0x101E: // 82540EP_LP
  44. case 0x1026: // 82545GM_COPPER
  45. case 0x1027: // 82545GM_FIBER
  46. case 0x1028: // 82545GM_SERDES
  47. case 0x1049: // ICH8_IGP_M_AMT
  48. case 0x104A: // ICH8_IGP_AMT
  49. case 0x104B: // ICH8_IGP_C
  50. case 0x104C: // ICH8_IFE
  51. case 0x104D: // ICH8_IGP_M
  52. case 0x105E: // 82571EB_COPPER
  53. case 0x105F: // 82571EB_FIBER
  54. case 0x1060: // 82571EB_SERDES
  55. case 0x1075: // 82547GI
  56. case 0x1076: // 82541GI
  57. case 0x1077: // 82541GI_MOBILE
  58. case 0x1078: // 82541ER
  59. case 0x1079: // 82546GB_COPPER
  60. case 0x107A: // 82546GB_FIBER
  61. case 0x107B: // 82546GB_SERDES
  62. case 0x107C: // 82541GI_LF
  63. case 0x107D: // 82572EI_COPPER
  64. case 0x107E: // 82572EI_FIBER
  65. case 0x107F: // 82572EI_SERDES
  66. case 0x108A: // 82546GB_PCIE
  67. case 0x108B: // 82573E
  68. case 0x108C: // 82573E_IAMT
  69. case 0x1096: // 80003ES2LAN_COPPER_DPT
  70. case 0x1098: // 80003ES2LAN_SERDES_DPT
  71. case 0x1099: // 82546GB_QUAD_COPPER
  72. case 0x109A: // 82573L
  73. case 0x10A4: // 82571EB_QUAD_COPPER
  74. case 0x10A5: // 82571EB_QUAD_FIBER
  75. case 0x10A7: // 82575EB_COPPER
  76. case 0x10A9: // 82575EB_FIBER_SERDES
  77. case 0x10B5: // 82546GB_QUAD_COPPER_KSP3
  78. case 0x10B9: // 82572EI
  79. case 0x10BA: // 80003ES2LAN_COPPER_SPT
  80. case 0x10BB: // 80003ES2LAN_SERDES_SPT
  81. case 0x10BC: // 82571EB_QUAD_COPPER_LP
  82. case 0x10BD: // ICH9_IGP_AMT
  83. case 0x10BF: // ICH9_IGP_M
  84. case 0x10C0: // ICH9_IFE
  85. case 0x10C2: // ICH9_IFE_G
  86. case 0x10C3: // ICH9_IFE_GT
  87. case 0x10C4: // ICH8_IFE_GT
  88. case 0x10C5: // ICH8_IFE_G
  89. case 0x10C9: // 82576
  90. case 0x10CA: // 82576_VF
  91. case 0x10CB: // ICH9_IGP_M_V
  92. case 0x10CC: // ICH10_R_BM_LM
  93. case 0x10CD: // ICH10_R_BM_LF
  94. case 0x10CE: // ICH10_R_BM_V
  95. case 0x10D5: // 82571PT_QUAD_COPPER
  96. case 0x10D6: // 82575GB_QUAD_COPPER
  97. case 0x10D9: // 82571EB_SERDES_DUAL
  98. case 0x10DA: // 82571EB_SERDES_QUAD
  99. case 0x10DE: // ICH10_D_BM_LM
  100. case 0x10DF: // ICH10_D_BM_LF
  101. case 0x10E5: // ICH9_BM
  102. case 0x10E6: // 82576_FIBER
  103. case 0x10E7: // 82576_SERDES
  104. case 0x10E8: // 82576_QUAD_COPPER
  105. case 0x10EA: // PCH_M_HV_LM
  106. case 0x10EB: // PCH_M_HV_LC
  107. case 0x10EF: // PCH_D_HV_DM
  108. case 0x10F0: // PCH_D_HV_DC
  109. case 0x10F5: // ICH9_IGP_M_AMT
  110. case 0x10F6: // 82574LA
  111. case 0x1501: // ICH8_82567V_3
  112. case 0x1502: // PCH2_LV_LM
  113. case 0x1503: // PCH2_LV_V
  114. case 0x150A: // 82576_NS
  115. case 0x150C: // 82583V
  116. case 0x150D: // 82576_SERDES_QUAD
  117. case 0x150E: // 82580_COPPER
  118. case 0x150F: // 82580_FIBER
  119. case 0x1510: // 82580_SERDES
  120. case 0x1511: // 82580_SGMII
  121. case 0x1516: // 82580_COPPER_DUAL
  122. case 0x1518: // 82576_NS_SERDES
  123. case 0x1520: // I350_VF
  124. case 0x1521: // I350_COPPER
  125. case 0x1522: // I350_FIBER
  126. case 0x1523: // I350_SERDES
  127. case 0x1524: // I350_SGMII
  128. case 0x1525: // ICH10_D_BM_V
  129. case 0x1526: // 82576_QUAD_COPPER_ET2
  130. case 0x1527: // 82580_QUAD_FIBER
  131. case 0x152D: // 82576_VF_HV
  132. case 0x152F: // I350_VF_HV
  133. case 0x1533: // I210_COPPER
  134. case 0x1534: // I210_COPPER_OEM1
  135. case 0x1535: // I210_COPPER_IT
  136. case 0x1536: // I210_FIBER
  137. case 0x1537: // I210_SERDES
  138. case 0x1538: // I210_SGMII
  139. case 0x1539: // I211_COPPER
  140. case 0x153A: // PCH_LPT_I217_LM
  141. case 0x153B: // PCH_LPT_I217_V
  142. case 0x1546: // I350_DA4
  143. case 0x1559: // PCH_LPTLP_I218_V
  144. case 0x155A: // PCH_LPTLP_I218_LM
  145. case 0x156F: // PCH_SPT_I219_LM
  146. case 0x1570: // PCH_SPT_I219_V
  147. case 0x157B: // I210_COPPER_FLASHLESS
  148. case 0x157C: // I210_SERDES_FLASHLESS
  149. case 0x15A0: // PCH_I218_LM2
  150. case 0x15A1: // PCH_I218_V2
  151. case 0x15A2: // PCH_I218_LM3
  152. case 0x15A3: // PCH_I218_V3
  153. case 0x15B7: // PCH_SPT_I219_LM2
  154. case 0x15B8: // PCH_SPT_I219_V2
  155. case 0x15B9: // PCH_LBG_I219_LM3
  156. case 0x15BB: // PCH_CNP_I219_LM7
  157. case 0x15BC: // PCH_CNP_I219_V7
  158. case 0x15BD: // PCH_CNP_I219_LM6
  159. case 0x15BE: // PCH_CNP_I219_V6
  160. case 0x15D6: // PCH_SPT_I219_V5
  161. case 0x15D7: // PCH_SPT_I219_LM4
  162. case 0x15D8: // PCH_SPT_I219_V4
  163. case 0x15DF: // PCH_ICP_I219_LM8
  164. case 0x15E0: // PCH_ICP_I219_V8
  165. case 0x15E1: // PCH_ICP_I219_LM9
  166. case 0x15E2: // PCH_ICP_I219_V9
  167. case 0x15E3: // PCH_SPT_I219_LM5
  168. case 0x1F40: // I354_BACKPLANE_1GBPS
  169. case 0x1F41: // I354_SGMII
  170. case 0x1F45: // I354_BACKPLANE_2_5GBPS
  171. case 0x294C: // ICH9_IGP_C
  172. return false;
  173. default:
  174. return false;
  175. }
  176. }
  177. UNMAP_AFTER_INIT RefPtr<E1000ENetworkAdapter> E1000ENetworkAdapter::try_to_initialize(PCI::Address address)
  178. {
  179. auto id = PCI::get_id(address);
  180. if (id.vendor_id != PCI::VendorID::Intel)
  181. return {};
  182. if (!is_valid_device_id(id.device_id))
  183. return {};
  184. u8 irq = PCI::get_interrupt_line(address);
  185. auto adapter = adopt_ref_if_nonnull(new (nothrow) E1000ENetworkAdapter(address, irq));
  186. if (!adapter)
  187. return {};
  188. if (adapter->initialize())
  189. return adapter;
  190. return {};
  191. }
  192. UNMAP_AFTER_INIT bool E1000ENetworkAdapter::initialize()
  193. {
  194. dmesgln("E1000e: Found @ {}", pci_address());
  195. m_io_base = IOAddress(PCI::get_BAR2(pci_address()) & ~1);
  196. enable_bus_mastering(pci_address());
  197. size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), 0);
  198. m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(pci_address()))), Memory::page_round_up(mmio_base_size), "E1000e MMIO", Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
  199. if (!m_mmio_region)
  200. return false;
  201. m_mmio_base = m_mmio_region->vaddr();
  202. m_use_mmio = true;
  203. m_interrupt_line = PCI::get_interrupt_line(pci_address());
  204. dmesgln("E1000e: port base: {}", m_io_base);
  205. dmesgln("E1000e: MMIO base: {}", PhysicalAddress(PCI::get_BAR0(pci_address()) & 0xfffffffc));
  206. dmesgln("E1000e: MMIO base size: {} bytes", mmio_base_size);
  207. dmesgln("E1000e: Interrupt line: {}", m_interrupt_line);
  208. detect_eeprom();
  209. dmesgln("E1000e: Has EEPROM? {}", m_has_eeprom);
  210. read_mac_address();
  211. const auto& mac = mac_address();
  212. dmesgln("E1000e: MAC address: {}", mac.to_string());
  213. initialize_rx_descriptors();
  214. initialize_tx_descriptors();
  215. setup_link();
  216. setup_interrupts();
  217. return true;
  218. }
  219. UNMAP_AFTER_INIT E1000ENetworkAdapter::E1000ENetworkAdapter(PCI::Address address, u8 irq)
  220. : E1000NetworkAdapter(address, irq)
  221. {
  222. }
  223. UNMAP_AFTER_INIT E1000ENetworkAdapter::~E1000ENetworkAdapter()
  224. {
  225. }
  226. UNMAP_AFTER_INIT void E1000ENetworkAdapter::detect_eeprom()
  227. {
  228. // FIXME: Try to find a way to detect if EEPROM exists instead of assuming it is
  229. m_has_eeprom = true;
  230. }
  231. UNMAP_AFTER_INIT u32 E1000ENetworkAdapter::read_eeprom(u8 address)
  232. {
  233. VERIFY(m_has_eeprom);
  234. u16 data = 0;
  235. u32 tmp = 0;
  236. if (m_has_eeprom) {
  237. out32(REG_EEPROM, ((u32)address << 2) | 1);
  238. while (!((tmp = in32(REG_EEPROM)) & (1 << 1)))
  239. ;
  240. } else {
  241. out32(REG_EEPROM, ((u32)address << 2) | 1);
  242. while (!((tmp = in32(REG_EEPROM)) & (1 << 1)))
  243. ;
  244. }
  245. data = (tmp >> 16) & 0xffff;
  246. return data;
  247. }
  248. }