E1000NetworkAdapter.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include <Kernel/E1000NetworkAdapter.h>
  2. #include <Kernel/PCI.h>
  3. #include <Kernel/IO.h>
  4. #define REG_CTRL 0x0000
  5. #define REG_STATUS 0x0008
  6. #define REG_EEPROM 0x0014
  7. #define REG_CTRL_EXT 0x0018
  8. #define REG_IMASK 0x00D0
  9. #define REG_RCTRL 0x0100
  10. #define REG_RXDESCLO 0x2800
  11. #define REG_RXDESCHI 0x2804
  12. #define REG_RXDESCLEN 0x2808
  13. #define REG_RXDESCHEAD 0x2810
  14. #define REG_RXDESCTAIL 0x2818
  15. #define REG_TCTRL 0x0400
  16. #define REG_TXDESCLO 0x3800
  17. #define REG_TXDESCHI 0x3804
  18. #define REG_TXDESCLEN 0x3808
  19. #define REG_TXDESCHEAD 0x3810
  20. #define REG_TXDESCTAIL 0x3818
  21. #define REG_RDTR 0x2820 // RX Delay Timer Register
  22. #define REG_RXDCTL 0x3828 // RX Descriptor Control
  23. #define REG_RADV 0x282C // RX Int. Absolute Delay Timer
  24. #define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt
  25. #define REG_TIPG 0x0410 // Transmit Inter Packet Gap
  26. OwnPtr<E1000NetworkAdapter> E1000NetworkAdapter::autodetect()
  27. {
  28. static const PCI::ID qemu_bochs_vbox_id = { 0x8086, 0x100e };
  29. PCI::Address found_address;
  30. PCI::enumerate_all([&] (const PCI::Address& address, PCI::ID id) {
  31. if (id == qemu_bochs_vbox_id) {
  32. found_address = address;
  33. return;
  34. }
  35. });
  36. if (found_address.is_null())
  37. return nullptr;
  38. byte irq = PCI::get_interrupt_line(found_address);
  39. return make<E1000NetworkAdapter>(found_address, irq);
  40. }
  41. E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, byte irq)
  42. : IRQHandler(irq)
  43. , m_pci_address(pci_address)
  44. {
  45. kprintf("E1000: Found at PCI address %b:%b:%b\n", pci_address.bus(), pci_address.slot(), pci_address.function());
  46. m_mmio_base = PhysicalAddress(PCI::get_BAR0(m_pci_address));
  47. MM.map_for_kernel(LinearAddress(m_mmio_base.get()), m_mmio_base);
  48. m_use_mmio = true;
  49. m_io_base = PCI::get_BAR1(m_pci_address) & ~1;
  50. m_interrupt_line = PCI::get_interrupt_line(m_pci_address);
  51. kprintf("E1000: IO port base: %w\n", m_io_base);
  52. kprintf("E1000: MMIO base: P%x\n", m_mmio_base);
  53. kprintf("E1000: Interrupt line: %u\n", m_interrupt_line);
  54. detect_eeprom();
  55. kprintf("E1000: Has EEPROM? %u\n", m_has_eeprom);
  56. read_mac_address();
  57. const auto& mac = mac_address();
  58. kprintf("E1000: MAC address: %b:%b:%b:%b:%b:%b\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  59. enable_irq();
  60. }
  61. E1000NetworkAdapter::~E1000NetworkAdapter()
  62. {
  63. }
  64. void E1000NetworkAdapter::handle_irq()
  65. {
  66. kprintf("E1000: IRQ!\n");
  67. }
  68. void E1000NetworkAdapter::detect_eeprom()
  69. {
  70. out32(REG_EEPROM, 0x1);
  71. for (volatile int i = 0; i < 999; ++i) {
  72. dword data = in32(REG_EEPROM);
  73. if (data & 0x10) {
  74. m_has_eeprom = true;
  75. return;
  76. }
  77. }
  78. m_has_eeprom = false;
  79. }
  80. dword E1000NetworkAdapter::read_eeprom(byte address)
  81. {
  82. word data = 0;
  83. dword tmp = 0;
  84. if (m_has_eeprom) {
  85. out32(REG_EEPROM, ((dword)address << 8) | 1);
  86. while (!((tmp = in32(REG_EEPROM)) & (1 << 4)))
  87. ;
  88. } else {
  89. out32(REG_EEPROM, ((dword)address << 2) | 1);
  90. while (!((tmp = in32(REG_EEPROM)) & (1 << 1)))
  91. ;
  92. }
  93. data = (tmp >> 16) & 0xffff;
  94. return data;
  95. }
  96. void E1000NetworkAdapter::read_mac_address()
  97. {
  98. if (m_has_eeprom) {
  99. byte mac[6];
  100. dword tmp = read_eeprom(0);
  101. mac[0] = tmp & 0xff;
  102. mac[1] = tmp >> 8;
  103. tmp = read_eeprom(1);
  104. mac[2] = tmp & 0xff;
  105. mac[3] = tmp >> 8;
  106. tmp = read_eeprom(2);
  107. mac[4] = tmp & 0xff;
  108. mac[5] = tmp >> 8;
  109. set_mac_address(mac);
  110. } else {
  111. ASSERT_NOT_REACHED();
  112. }
  113. }
  114. void E1000NetworkAdapter::out8(word address, byte data)
  115. {
  116. if (m_use_mmio) {
  117. auto* ptr = (volatile byte*)(m_mmio_base.get() + address);
  118. *ptr = data;
  119. return;
  120. }
  121. IO::out8(m_io_base + address, data);
  122. }
  123. void E1000NetworkAdapter::out16(word address, word data)
  124. {
  125. if (m_use_mmio) {
  126. auto* ptr = (volatile word*)(m_mmio_base.get() + address);
  127. *ptr = data;
  128. return;
  129. }
  130. IO::out16(m_io_base + address, data);
  131. }
  132. void E1000NetworkAdapter::out32(word address, dword data)
  133. {
  134. if (m_use_mmio) {
  135. auto* ptr = (volatile dword*)(m_mmio_base.get() + address);
  136. *ptr = data;
  137. return;
  138. }
  139. IO::out32(m_io_base + address, data);
  140. }
  141. byte E1000NetworkAdapter::in8(word address)
  142. {
  143. if (m_use_mmio)
  144. return *(volatile byte*)(m_mmio_base.get() + address);
  145. return IO::in8(m_io_base + address);
  146. }
  147. word E1000NetworkAdapter::in16(word address)
  148. {
  149. if (m_use_mmio)
  150. return *(volatile word*)(m_mmio_base.get() + address);
  151. return IO::in16(m_io_base + address);
  152. }
  153. dword E1000NetworkAdapter::in32(word address)
  154. {
  155. if (m_use_mmio)
  156. return *(volatile dword*)(m_mmio_base.get() + address);
  157. return IO::in32(m_io_base + address);
  158. }