mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:57:45 +00:00
Kernel/Net: Support Intel 82574 adapter
We call it E1000E, because the layout for these cards is somewhat not the same like E1000 supported cards. Also, this card supports advanced features that are not supported on 8254x cards.
This commit is contained in:
parent
2e2201e8e1
commit
c6480a0426
8 changed files with 200 additions and 20 deletions
108
Kernel/Net/E1000ENetworkAdapter.cpp
Normal file
108
Kernel/Net/E1000ENetworkAdapter.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/MACAddress.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/Net/E1000ENetworkAdapter.h>
|
||||
#include <Kernel/PCI/IDs.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
#define REG_EEPROM 0x0014
|
||||
|
||||
static bool is_valid_device_id(u16 device_id)
|
||||
{
|
||||
switch (device_id) {
|
||||
case 0x10D3: // 82574
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT RefPtr<E1000ENetworkAdapter> E1000ENetworkAdapter::try_to_initialize(PCI::Address address)
|
||||
{
|
||||
auto id = PCI::get_id(address);
|
||||
if (id.vendor_id != (u16)PCIVendorID::Intel)
|
||||
return {};
|
||||
if (!is_valid_device_id(id.device_id))
|
||||
return {};
|
||||
u8 irq = PCI::get_interrupt_line(address);
|
||||
auto adapter = adopt_ref_if_nonnull(new E1000ENetworkAdapter(address, irq));
|
||||
if (!adapter)
|
||||
return {};
|
||||
if (adapter->initialize())
|
||||
return adapter;
|
||||
return {};
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT bool E1000ENetworkAdapter::initialize()
|
||||
{
|
||||
dmesgln("E1000e: Found @ {}", pci_address());
|
||||
|
||||
m_io_base = IOAddress(PCI::get_BAR2(pci_address()) & ~1);
|
||||
|
||||
enable_bus_mastering(pci_address());
|
||||
|
||||
size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), 0);
|
||||
m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(pci_address()))), page_round_up(mmio_base_size), "E1000e MMIO", Region::Access::Read | Region::Access::Write, Region::Cacheable::No);
|
||||
if (!m_mmio_region)
|
||||
return false;
|
||||
m_mmio_base = m_mmio_region->vaddr();
|
||||
m_use_mmio = true;
|
||||
m_interrupt_line = PCI::get_interrupt_line(pci_address());
|
||||
dmesgln("E1000e: port base: {}", m_io_base);
|
||||
dmesgln("E1000e: MMIO base: {}", PhysicalAddress(PCI::get_BAR0(pci_address()) & 0xfffffffc));
|
||||
dmesgln("E1000e: MMIO base size: {} bytes", mmio_base_size);
|
||||
dmesgln("E1000e: Interrupt line: {}", m_interrupt_line);
|
||||
detect_eeprom();
|
||||
dmesgln("E1000e: Has EEPROM? {}", m_has_eeprom);
|
||||
read_mac_address();
|
||||
const auto& mac = mac_address();
|
||||
dmesgln("E1000e: MAC address: {}", mac.to_string());
|
||||
|
||||
initialize_rx_descriptors();
|
||||
initialize_tx_descriptors();
|
||||
|
||||
setup_link();
|
||||
setup_interrupts();
|
||||
return true;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT E1000ENetworkAdapter::E1000ENetworkAdapter(PCI::Address address, u8 irq)
|
||||
: E1000NetworkAdapter(address, irq)
|
||||
{
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT E1000ENetworkAdapter::~E1000ENetworkAdapter()
|
||||
{
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void E1000ENetworkAdapter::detect_eeprom()
|
||||
{
|
||||
// FIXME: Try to find a way to detect if EEPROM exists instead of assuming it is
|
||||
m_has_eeprom = true;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT u32 E1000ENetworkAdapter::read_eeprom(u8 address)
|
||||
{
|
||||
VERIFY(m_has_eeprom);
|
||||
u16 data = 0;
|
||||
u32 tmp = 0;
|
||||
if (m_has_eeprom) {
|
||||
out32(REG_EEPROM, ((u32)address << 2) | 1);
|
||||
while (!((tmp = in32(REG_EEPROM)) & (1 << 1)))
|
||||
;
|
||||
} else {
|
||||
out32(REG_EEPROM, ((u32)address << 2) | 1);
|
||||
while (!((tmp = in32(REG_EEPROM)) & (1 << 1)))
|
||||
;
|
||||
}
|
||||
data = (tmp >> 16) & 0xffff;
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue