diff --git a/Kernel/E1000NetworkAdapter.cpp b/Kernel/E1000NetworkAdapter.cpp index 976a2e2415..2f04d572bc 100644 --- a/Kernel/E1000NetworkAdapter.cpp +++ b/Kernel/E1000NetworkAdapter.cpp @@ -157,9 +157,9 @@ void E1000NetworkAdapter::handle_irq() kprintf("E1000: threshold\n"); } if (status & 0x80) { - //receive(); + kprintf("E1000: receive...\n"); + receive(); } - ASSERT_NOT_REACHED(); } void E1000NetworkAdapter::detect_eeprom() @@ -282,7 +282,6 @@ void E1000NetworkAdapter::out32(word address, dword data) { if (m_use_mmio) { auto* ptr = (volatile dword*)(m_mmio_base.get() + address); - kprintf("ptr <-- %p\n", ptr); *ptr = data; return; } @@ -310,7 +309,7 @@ dword E1000NetworkAdapter::in32(word address) return IO::in32(m_io_base + address); } -void E1000NetworkAdapter::send(const byte* data, int length) +void E1000NetworkAdapter::send_raw(const byte* data, int length) { kprintf("E1000: Sending packet (%d bytes)\n", length); auto& descriptor = m_tx_descriptors[m_tx_current]; @@ -323,3 +322,18 @@ void E1000NetworkAdapter::send(const byte* data, int length) ; kprintf("E1000: Sent packet!\n"); } + +void E1000NetworkAdapter::receive() +{ + while (m_rx_descriptors[m_rx_current].status & 1) { + auto* buffer = (byte*)m_rx_descriptors[m_rx_current].addr; + word length = m_rx_descriptors[m_rx_current].length; + + kprintf("E1000: Received 1 packet @ %p (%u) bytes!\n", buffer, length); + + m_rx_descriptors[m_rx_current].status = 0; + auto old_current = m_rx_current; + m_rx_current = (m_rx_current + 1) % number_of_rx_descriptors; + out32(REG_RXDESCTAIL, old_current); + } +} diff --git a/Kernel/E1000NetworkAdapter.h b/Kernel/E1000NetworkAdapter.h index 9740f05082..55390561ce 100644 --- a/Kernel/E1000NetworkAdapter.h +++ b/Kernel/E1000NetworkAdapter.h @@ -15,7 +15,7 @@ public: E1000NetworkAdapter(PCI::Address, byte irq); virtual ~E1000NetworkAdapter() override; - virtual void send(const byte*, int) override; + virtual void send_raw(const byte*, int) override; private: virtual void handle_irq() override; @@ -57,6 +57,8 @@ private: word in16(word address); dword in32(word address); + void receive(); + PCI::Address m_pci_address; word m_io_base { 0 }; PhysicalAddress m_mmio_base; diff --git a/Kernel/EthernetFrameHeader.h b/Kernel/EthernetFrameHeader.h index 2211ce5195..a90ca5503b 100644 --- a/Kernel/EthernetFrameHeader.h +++ b/Kernel/EthernetFrameHeader.h @@ -16,13 +16,14 @@ public: word ether_type() const { return (m_ether_type & 0xff) << 16 | ((m_ether_type >> 16) & 0xff); } void set_ether_type(word ether_type) { m_ether_type = (ether_type & 0xff) << 16 | ((ether_type >> 16) & 0xff); } - const void* raw() const { return this; } - void* raw() { return this; } + const void* payload() const { return &m_payload[0]; } + void* payload() { return &m_payload[0]; } private: MACAddress m_destination; MACAddress m_source; word m_ether_type { 0 }; + dword m_payload[0]; }; static_assert(sizeof(EthernetFrameHeader) == 14); diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 3df6a60845..bbd81491b5 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -99,6 +99,7 @@ void MemoryManager::initialize_paging() dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get()); dbgprintf("MM: Installing page directory\n"); #endif + asm volatile("movl %%eax, %%cr3"::"a"(kernel_page_directory().cr3())); asm volatile( "movl %%cr0, %%eax\n" @@ -442,6 +443,12 @@ void MemoryManager::enter_process_paging_scope(Process& process) asm volatile("movl %%eax, %%cr3"::"a"(process.page_directory().cr3()):"memory"); } +void MemoryManager::enter_kernel_paging_scope() +{ + InterruptDisabler disabler; + asm volatile("movl %%eax, %%cr3"::"a"(kernel_page_directory().cr3()):"memory"); +} + void MemoryManager::flush_entire_tlb() { asm volatile( diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 6c14e6a4db..a045ff1270 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -242,6 +242,7 @@ public: void populate_page_directory(PageDirectory&); void enter_process_paging_scope(Process&); + void enter_kernel_paging_scope(); bool validate_user_read(const Process&, LinearAddress) const; bool validate_user_write(const Process&, LinearAddress) const; @@ -413,3 +414,8 @@ struct ProcessPagingScope { ProcessPagingScope(Process& process) { MM.enter_process_paging_scope(process); } ~ProcessPagingScope() { MM.enter_process_paging_scope(*current); } }; + +struct KernelPagingScope { + KernelPagingScope() { MM.enter_kernel_paging_scope(); } + ~KernelPagingScope() { MM.enter_process_paging_scope(*current); } +}; diff --git a/Kernel/NetworkAdapter.cpp b/Kernel/NetworkAdapter.cpp index ffbeabc0a8..8fef2f89db 100644 --- a/Kernel/NetworkAdapter.cpp +++ b/Kernel/NetworkAdapter.cpp @@ -1,12 +1,23 @@ #include #include +#include +#include NetworkAdapter::NetworkAdapter() { - memset(&m_mac_address, 0, sizeof(m_mac_address)); } NetworkAdapter::~NetworkAdapter() { } +void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet) +{ + int size_in_bytes = sizeof(EthernetFrameHeader) + sizeof(ARPPacket) + 4; + auto* eth = (EthernetFrameHeader*)kmalloc(size_in_bytes); + eth->set_source(mac_address()); + eth->set_destination(destination); + memcpy(eth->payload(), &packet, sizeof(ARPPacket)); + send_raw((byte*)eth, size_in_bytes); + kfree(eth); +} diff --git a/Kernel/NetworkAdapter.h b/Kernel/NetworkAdapter.h index 2a572fc1f1..2bc80329f9 100644 --- a/Kernel/NetworkAdapter.h +++ b/Kernel/NetworkAdapter.h @@ -2,6 +2,7 @@ #include #include +#include class NetworkAdapter { public: @@ -10,11 +11,12 @@ public: virtual const char* class_name() const = 0; MACAddress mac_address() { return m_mac_address; } - virtual void send(const byte*, int) = 0; + void send(const MACAddress&, const ARPPacket&); protected: NetworkAdapter(); void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; } + virtual void send_raw(const byte*, int) = 0; private: MACAddress m_mac_address; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 2d09825b37..0740a99cf0 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1922,6 +1922,16 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) int Process::sys$ioctl(int fd, unsigned request, unsigned arg) { + if (auto* e1000 = E1000NetworkAdapter::the()) { + ARPPacket arp; + arp.hardware_type = 1; // Ethernet + arp.hardware_address_length = 6; // MAC length + arp.protocol_type = 0x0800; // IPv4 + arp.protocol_address_length = 4; // IP length + arp.operation = 1; // 1 (request) + e1000->send(MACAddress(), arp); + } + auto* descriptor = file_descriptor(fd); if (!descriptor) return -EBADF;