1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:17:44 +00:00

Kernel: Ensure E1000NetworkAdapter uses virtual memory correctly

This commit is contained in:
Liav A 2020-03-06 21:40:36 +02:00 committed by Andreas Kling
parent d6e122fd3a
commit 9dbc273675
2 changed files with 25 additions and 32 deletions

View file

@ -136,6 +136,8 @@ void E1000NetworkAdapter::detect(const PCI::Address& address)
E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq) E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq)
: PCI::Device(address, irq) : PCI::Device(address, irq)
, m_io_base(PCI::get_BAR1(pci_address()) & ~1) , m_io_base(PCI::get_BAR1(pci_address()) & ~1)
, m_rx_descriptors_region(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(sizeof(e1000_rx_desc) * number_of_rx_descriptors + 16), "E1000 RX", Region::Access::Read | Region::Access::Write))
, m_tx_descriptors_region(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(sizeof(e1000_tx_desc) * number_of_tx_descriptors + 16), "E1000 TX", Region::Access::Read | Region::Access::Write))
{ {
set_interface_name("e1k"); set_interface_name("e1k");
@ -250,21 +252,15 @@ bool E1000NetworkAdapter::link_up()
void E1000NetworkAdapter::initialize_rx_descriptors() void E1000NetworkAdapter::initialize_rx_descriptors()
{ {
auto ptr = (FlatPtr)kmalloc_eternal(sizeof(e1000_rx_desc) * number_of_rx_descriptors + 16); auto* rx_descriptors = (e1000_tx_desc*)m_rx_descriptors_region->vaddr().as_ptr();
// Make sure it's 16-byte aligned.
if (ptr % 16)
ptr = (ptr + 16) - (ptr % 16);
m_rx_descriptors = (e1000_rx_desc*)ptr;
for (int i = 0; i < number_of_rx_descriptors; ++i) { for (int i = 0; i < number_of_rx_descriptors; ++i) {
auto& descriptor = m_rx_descriptors[i]; auto& descriptor = rx_descriptors[i];
auto addr = (FlatPtr)kmalloc_eternal(8192 + 16); m_rx_buffers_regions.append(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(8192), "E1000 RX buffer", Region::Access::Read | Region::Access::Write));
if (addr % 16) descriptor.addr = m_rx_buffers_regions[i]->vmobject().physical_pages()[0]->paddr().get();
addr = (addr + 16) - (addr % 16);
descriptor.addr = addr - 0xc0000000;
descriptor.status = 0; descriptor.status = 0;
} }
out32(REG_RXDESCLO, (u32)ptr - 0xc0000000); out32(REG_RXDESCLO, m_rx_descriptors_region->vmobject().physical_pages()[0]->paddr().get());
out32(REG_RXDESCHI, 0); out32(REG_RXDESCHI, 0);
out32(REG_RXDESCLEN, number_of_rx_descriptors * sizeof(e1000_rx_desc)); out32(REG_RXDESCLEN, number_of_rx_descriptors * sizeof(e1000_rx_desc));
out32(REG_RXDESCHEAD, 0); out32(REG_RXDESCHEAD, 0);
@ -275,21 +271,15 @@ void E1000NetworkAdapter::initialize_rx_descriptors()
void E1000NetworkAdapter::initialize_tx_descriptors() void E1000NetworkAdapter::initialize_tx_descriptors()
{ {
auto ptr = (FlatPtr)kmalloc_eternal(sizeof(e1000_tx_desc) * number_of_tx_descriptors + 16); auto* tx_descriptors = (e1000_tx_desc*)m_tx_descriptors_region->vaddr().as_ptr();
// Make sure it's 16-byte aligned.
if (ptr % 16)
ptr = (ptr + 16) - (ptr % 16);
m_tx_descriptors = (e1000_tx_desc*)ptr;
for (int i = 0; i < number_of_tx_descriptors; ++i) { for (int i = 0; i < number_of_tx_descriptors; ++i) {
auto& descriptor = m_tx_descriptors[i]; auto& descriptor = tx_descriptors[i];
auto addr = (FlatPtr)kmalloc_eternal(8192 + 16); m_tx_buffers_regions.append(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(8192), "E1000 TX buffer", Region::Access::Read | Region::Access::Write));
if (addr % 16) descriptor.addr = m_tx_buffers_regions[i]->vmobject().physical_pages()[0]->paddr().get();
addr = (addr + 16) - (addr % 16);
descriptor.addr = addr - 0xc0000000;
descriptor.cmd = 0; descriptor.cmd = 0;
} }
out32(REG_TXDESCLO, (u32)ptr - 0xc0000000); out32(REG_TXDESCLO, m_tx_descriptors_region->vmobject().physical_pages()[0]->paddr().get());
out32(REG_TXDESCHI, 0); out32(REG_TXDESCHI, 0);
out32(REG_TXDESCLEN, number_of_tx_descriptors * sizeof(e1000_tx_desc)); out32(REG_TXDESCLEN, number_of_tx_descriptors * sizeof(e1000_tx_desc));
out32(REG_TXDESCHEAD, 0); out32(REG_TXDESCHEAD, 0);
@ -375,9 +365,10 @@ void E1000NetworkAdapter::send_raw(const u8* data, size_t length)
#ifdef E1000_DEBUG #ifdef E1000_DEBUG
klog() << "E1000: Sending packet (" << length << " bytes)"; klog() << "E1000: Sending packet (" << length << " bytes)";
#endif #endif
auto& descriptor = m_tx_descriptors[tx_current]; auto* tx_descriptors = (e1000_tx_desc*)m_tx_descriptors_region->vaddr().as_ptr();
auto& descriptor = tx_descriptors[tx_current];
ASSERT(length <= 8192); ASSERT(length <= 8192);
auto* vptr = (void*)(descriptor.addr + 0xc0000000); auto* vptr = (void*)m_tx_buffers_regions[tx_current]->vaddr().as_ptr();
memcpy(vptr, data, length); memcpy(vptr, data, length);
descriptor.length = length; descriptor.length = length;
descriptor.status = 0; descriptor.status = 0;
@ -397,27 +388,28 @@ void E1000NetworkAdapter::send_raw(const u8* data, size_t length)
Thread::current->wait_on(m_wait_queue); Thread::current->wait_on(m_wait_queue);
} }
#ifdef E1000_DEBUG #ifdef E1000_DEBUG
klog() << "E1000: Sent packet, status is now " << String::format("%b",descriptor.status) << "!"; klog() << "E1000: Sent packet, status is now " << String::format("%b", descriptor.status) << "!";
#endif #endif
} }
void E1000NetworkAdapter::receive() void E1000NetworkAdapter::receive()
{ {
auto* rx_descriptors = (e1000_tx_desc*)m_rx_descriptors_region->vaddr().as_ptr();
u32 rx_current; u32 rx_current;
for (;;) { for (;;) {
rx_current = in32(REG_RXDESCTAIL); rx_current = in32(REG_RXDESCTAIL);
if (rx_current == in32(REG_RXDESCHEAD)) if (rx_current == in32(REG_RXDESCHEAD))
return; return;
rx_current = (rx_current + 1) % number_of_rx_descriptors; rx_current = (rx_current + 1) % number_of_rx_descriptors;
if (!(m_rx_descriptors[rx_current].status & 1)) if (!(rx_descriptors[rx_current].status & 1))
break; break;
auto* buffer = (u8*)(m_rx_descriptors[rx_current].addr + 0xc0000000); auto* buffer = m_rx_buffers_regions[rx_current]->vaddr().as_ptr();
u16 length = m_rx_descriptors[rx_current].length; u16 length = rx_descriptors[rx_current].length;
#ifdef E1000_DEBUG #ifdef E1000_DEBUG
klog() << "E1000: Received 1 packet @ " << buffer << " (" << length << ") bytes!"; klog() << "E1000: Received 1 packet @ " << buffer << " (" << length << ") bytes!";
#endif #endif
did_receive(buffer, length); did_receive(buffer, length);
m_rx_descriptors[rx_current].status = 0; rx_descriptors[rx_current].status = 0;
out32(REG_RXDESCTAIL, rx_current); out32(REG_RXDESCTAIL, rx_current);
} }
} }

View file

@ -94,6 +94,10 @@ private:
IOAddress m_io_base; IOAddress m_io_base;
VirtualAddress m_mmio_base; VirtualAddress m_mmio_base;
OwnPtr<Region> m_rx_descriptors_region;
OwnPtr<Region> m_tx_descriptors_region;
Vector<OwnPtr<Region>> m_rx_buffers_regions;
Vector<OwnPtr<Region>> m_tx_buffers_regions;
OwnPtr<Region> m_mmio_region; OwnPtr<Region> m_mmio_region;
u8 m_interrupt_line { 0 }; u8 m_interrupt_line { 0 };
bool m_has_eeprom { false }; bool m_has_eeprom { false };
@ -102,9 +106,6 @@ private:
static const int number_of_rx_descriptors = 32; static const int number_of_rx_descriptors = 32;
static const int number_of_tx_descriptors = 8; static const int number_of_tx_descriptors = 8;
e1000_rx_desc* m_rx_descriptors;
e1000_tx_desc* m_tx_descriptors;
WaitQueue m_wait_queue; WaitQueue m_wait_queue;
}; };
} }