mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel: Ensure RTL8139NetworkAdapter uses virtual memory correctly
This commit is contained in:
parent
9dbc273675
commit
4479e874da
Notes:
sideshowbarker
2024-07-19 08:49:49 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/4479e874daa Pull-request: https://github.com/SerenityOS/serenity/pull/1366 Reviewed-by: https://github.com/awesomekling
2 changed files with 18 additions and 19 deletions
|
@ -140,7 +140,10 @@ void RTL8139NetworkAdapter::detect(const PCI::Address& address)
|
|||
RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address address, u8 irq)
|
||||
: PCI::Device(address, irq)
|
||||
, m_io_base(PCI::get_BAR0(pci_address()) & ~1)
|
||||
, m_rx_buffer(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(RX_BUFFER_SIZE + PACKET_SIZE_MAX), "RTL8139 RX", Region::Access::Read | Region::Access::Write))
|
||||
, m_packet_buffer(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(PACKET_SIZE_MAX), "RTL8139 Packet buffer", Region::Access::Read | Region::Access::Write))
|
||||
{
|
||||
m_tx_buffers.ensure_capacity(RTL8139_TX_BUFFER_COUNT);
|
||||
set_interface_name("rtl8139");
|
||||
|
||||
klog() << "RTL8139: Found at PCI address " << String::format("%w", pci_address().seg()) << ":" << String::format("%b", pci_address().bus()) << ":" << String::format("%b", pci_address().slot()) << "." << String::format("%b", pci_address().function());
|
||||
|
@ -154,17 +157,13 @@ RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address address, u8 irq)
|
|||
// we add space to account for overhang from the last packet - the rtl8139
|
||||
// can optionally guarantee that packets will be contiguous by
|
||||
// purposefully overrunning the rx buffer
|
||||
m_rx_buffer_addr = (FlatPtr)virtual_to_low_physical(kmalloc_aligned(RX_BUFFER_SIZE + PACKET_SIZE_MAX, 16));
|
||||
klog() << "RTL8139: RX buffer: " << PhysicalAddress(m_rx_buffer_addr);
|
||||
klog() << "RTL8139: RX buffer: " << m_rx_buffer->vmobject().physical_pages()[0]->paddr();
|
||||
|
||||
auto tx_buffer_addr = (FlatPtr)virtual_to_low_physical(kmalloc_aligned(TX_BUFFER_SIZE * 4, 16));
|
||||
for (int i = 0; i < RTL8139_TX_BUFFER_COUNT; i++) {
|
||||
m_tx_buffer_addr[i] = tx_buffer_addr + TX_BUFFER_SIZE * i;
|
||||
klog() << "RTL8139: TX buffer " << i << ": " << PhysicalAddress(m_tx_buffer_addr[i]);
|
||||
m_tx_buffers.append(MM.allocate_contiguous_kernel_region(PAGE_ROUND_UP(TX_BUFFER_SIZE), "RTL8139 TX", Region::Access::Write | Region::Access::Read));
|
||||
klog() << "RTL8139: TX buffer " << i << ": " << m_tx_buffers[i]->vmobject().physical_pages()[0]->paddr();
|
||||
}
|
||||
|
||||
m_packet_buffer = (FlatPtr)kmalloc(PACKET_SIZE_MAX);
|
||||
|
||||
reset();
|
||||
|
||||
read_mac_address();
|
||||
|
@ -250,7 +249,7 @@ void RTL8139NetworkAdapter::reset()
|
|||
// device might be in sleep mode, this will take it out
|
||||
out8(REG_CONFIG1, 0);
|
||||
// set up rx buffer
|
||||
out32(REG_RXBUF, m_rx_buffer_addr);
|
||||
out32(REG_RXBUF, m_rx_buffer->vmobject().physical_pages()[0]->paddr().get());
|
||||
// reset missed packet counter
|
||||
out8(REG_MPC, 0);
|
||||
// "basic mode control register" options - 100mbit, full duplex, auto
|
||||
|
@ -268,7 +267,7 @@ void RTL8139NetworkAdapter::reset()
|
|||
out32(REG_TXCFG, TXCFG_TXRR_ZERO | TXCFG_MAX_DMA_1K | TXCFG_IFG11);
|
||||
// tell the chip where we want it to DMA from for outgoing packets.
|
||||
for (int i = 0; i < 4; i++)
|
||||
out32(REG_TXADDR0 + (i * 4), m_tx_buffer_addr[i]);
|
||||
out32(REG_TXADDR0 + (i * 4), m_tx_buffers[i]->vmobject().physical_pages()[0]->paddr().get());
|
||||
// re-lock config registers
|
||||
out8(REG_CFG9346, CFG9346_NONE);
|
||||
// enable rx/tx again in case they got turned off (apparently some cards
|
||||
|
@ -320,8 +319,8 @@ void RTL8139NetworkAdapter::send_raw(const u8* data, size_t length)
|
|||
m_tx_next_buffer = (hw_buffer + 1) % 4;
|
||||
}
|
||||
|
||||
memcpy((void*)low_physical_to_virtual(m_tx_buffer_addr[hw_buffer]), data, length);
|
||||
memset((void*)(low_physical_to_virtual(m_tx_buffer_addr[hw_buffer]) + length), 0, TX_BUFFER_SIZE - length);
|
||||
memcpy(m_tx_buffers[hw_buffer]->vaddr().as_ptr(), data, length);
|
||||
memset(m_tx_buffers[hw_buffer]->vaddr().as_ptr() + length, 0, TX_BUFFER_SIZE - length);
|
||||
|
||||
// the rtl8139 will not actually emit packets onto the network if they're
|
||||
// smaller than 64 bytes. the rtl8139 adds a checksum to the end of each
|
||||
|
@ -339,17 +338,17 @@ void RTL8139NetworkAdapter::send_raw(const u8* data, size_t length)
|
|||
|
||||
void RTL8139NetworkAdapter::receive()
|
||||
{
|
||||
auto* start_of_packet = (const u8*)(low_physical_to_virtual(m_rx_buffer_addr) + m_rx_buffer_offset);
|
||||
auto* start_of_packet = m_rx_buffer->vaddr().as_ptr() + m_rx_buffer_offset;
|
||||
|
||||
u16 status = *(const u16*)(start_of_packet + 0);
|
||||
u16 length = *(const u16*)(start_of_packet + 2);
|
||||
|
||||
#ifdef RTL8139_DEBUG
|
||||
klog() << "RTL8139NetworkAdapter::receive status=0x" << String::format("%x",status) << " length=" << length << " offset=" << m_rx_buffer_offset;
|
||||
klog() << "RTL8139NetworkAdapter::receive status=0x" << String::format("%x", status) << " length=" << length << " offset=" << m_rx_buffer_offset;
|
||||
#endif
|
||||
|
||||
if (!(status & RX_OK) || (status & (RX_INVALID_SYMBOL_ERROR | RX_CRC_ERROR | RX_FRAME_ALIGNMENT_ERROR)) || (length >= PACKET_SIZE_MAX) || (length < PACKET_SIZE_MIN)) {
|
||||
klog() << "RTL8139NetworkAdapter::receive got bad packet status=0x" << String::format("%x",status) << " length=" << length;
|
||||
klog() << "RTL8139NetworkAdapter::receive got bad packet status=0x" << String::format("%x", status) << " length=" << length;
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
@ -357,13 +356,13 @@ void RTL8139NetworkAdapter::receive()
|
|||
// we never have to worry about the packet wrapping around the buffer,
|
||||
// since we set RXCFG_WRAP_INHIBIT, which allows the rtl8139 to write data
|
||||
// past the end of the alloted space.
|
||||
memcpy((u8*)m_packet_buffer, (const u8*)(start_of_packet + 4), length - 4);
|
||||
memcpy(m_packet_buffer->vaddr().as_ptr(), (const u8*)(start_of_packet + 4), length - 4);
|
||||
// let the card know that we've read this data
|
||||
m_rx_buffer_offset = ((m_rx_buffer_offset + length + 4 + 3) & ~3) % RX_BUFFER_SIZE;
|
||||
out16(REG_CAPR, m_rx_buffer_offset - 0x10);
|
||||
m_rx_buffer_offset %= RX_BUFFER_SIZE;
|
||||
|
||||
did_receive((const u8*)m_packet_buffer, length - 4);
|
||||
did_receive(m_packet_buffer->vaddr().as_ptr(), length - 4);
|
||||
}
|
||||
|
||||
void RTL8139NetworkAdapter::out8(u16 address, u8 data)
|
||||
|
|
|
@ -67,11 +67,11 @@ private:
|
|||
|
||||
IOAddress m_io_base;
|
||||
u8 m_interrupt_line { 0 };
|
||||
u32 m_rx_buffer_addr { 0 };
|
||||
OwnPtr<Region> m_rx_buffer;
|
||||
u16 m_rx_buffer_offset { 0 };
|
||||
u32 m_tx_buffer_addr[RTL8139_TX_BUFFER_COUNT];
|
||||
Vector<OwnPtr<Region>> m_tx_buffers;
|
||||
u8 m_tx_next_buffer { 0 };
|
||||
u32 m_packet_buffer { 0 };
|
||||
OwnPtr<Region> m_packet_buffer;
|
||||
bool m_link_up { false };
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue