ladybird/Kernel/Net/NetworkingManagement.cpp
Liav A c876412b1b Kernel: Remove the NE2000 PCI network adapter driver
Nobody tests this network card as the person who added it, Jean-Baptiste
Boric (known as boricj) is not an active contributor in the project now.
After a discussion with him on the Discord server, we agreed it's for
the best to remove the driver, as for two reasons:
- The original author (boricj) agreed to do this, stating that he will
  not be able to test the driver anymore after his Athlon XP machine is
  no longer supported after the removal of the i686 port.
- It was agreed that the NE2000 network card family is far from the
  ideal hardware we would want to support, similarly to the RTL8139 that
  got removed recently for almost the same reason.
2023-01-08 21:51:59 +01:00

144 lines
5.1 KiB
C++

/*
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Singleton.h>
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/CommandLine.h>
#include <Kernel/KString.h>
#include <Kernel/Memory/AnonymousVMObject.h>
#include <Kernel/Multiboot.h>
#include <Kernel/Net/Intel/E1000ENetworkAdapter.h>
#include <Kernel/Net/Intel/E1000NetworkAdapter.h>
#include <Kernel/Net/LoopbackAdapter.h>
#include <Kernel/Net/NetworkingManagement.h>
#include <Kernel/Net/Realtek/RTL8168NetworkAdapter.h>
#include <Kernel/Sections.h>
namespace Kernel {
static Singleton<NetworkingManagement> s_the;
NetworkingManagement& NetworkingManagement::the()
{
return *s_the;
}
bool NetworkingManagement::is_initialized()
{
return s_the.is_initialized();
}
UNMAP_AFTER_INIT NetworkingManagement::NetworkingManagement()
{
}
NonnullLockRefPtr<NetworkAdapter> NetworkingManagement::loopback_adapter() const
{
return *m_loopback_adapter;
}
void NetworkingManagement::for_each(Function<void(NetworkAdapter&)> callback)
{
m_adapters.for_each([&](auto& adapter) {
callback(adapter);
});
}
ErrorOr<void> NetworkingManagement::try_for_each(Function<ErrorOr<void>(NetworkAdapter&)> callback)
{
return m_adapters.with([&](auto& adapters) -> ErrorOr<void> {
for (auto& adapter : adapters)
TRY(callback(adapter));
return {};
});
}
LockRefPtr<NetworkAdapter> NetworkingManagement::from_ipv4_address(IPv4Address const& address) const
{
if (address[0] == 0 && address[1] == 0 && address[2] == 0 && address[3] == 0)
return m_loopback_adapter;
if (address[0] == 127)
return m_loopback_adapter;
return m_adapters.with([&](auto& adapters) -> LockRefPtr<NetworkAdapter> {
for (auto& adapter : adapters) {
if (adapter.ipv4_address() == address || adapter.ipv4_broadcast() == address)
return adapter;
}
return nullptr;
});
}
LockRefPtr<NetworkAdapter> NetworkingManagement::lookup_by_name(StringView name) const
{
return m_adapters.with([&](auto& adapters) -> LockRefPtr<NetworkAdapter> {
for (auto& adapter : adapters) {
if (adapter.name() == name)
return adapter;
}
return nullptr;
});
}
ErrorOr<NonnullOwnPtr<KString>> NetworkingManagement::generate_interface_name_from_pci_address(PCI::DeviceIdentifier const& device_identifier)
{
VERIFY(device_identifier.class_code().value() == 0x2);
// Note: This stands for e - "Ethernet", p - "Port" as for PCI bus, "s" for slot as for PCI slot
auto name = TRY(KString::formatted("ep{}s{}", device_identifier.address().bus(), device_identifier.address().device()));
VERIFY(!NetworkingManagement::the().lookup_by_name(name->view()));
return name;
}
struct PCINetworkDriverInitializer {
ErrorOr<bool> (*probe)(PCI::DeviceIdentifier const&) = nullptr;
ErrorOr<NonnullLockRefPtr<NetworkAdapter>> (*create)(PCI::DeviceIdentifier const&) = nullptr;
};
static constexpr PCINetworkDriverInitializer s_initializers[] = {
{ RTL8168NetworkAdapter::probe, RTL8168NetworkAdapter::create },
{ E1000NetworkAdapter::probe, E1000NetworkAdapter::create },
{ E1000ENetworkAdapter::probe, E1000ENetworkAdapter::create },
};
UNMAP_AFTER_INIT ErrorOr<NonnullLockRefPtr<NetworkAdapter>> NetworkingManagement::determine_network_device(PCI::DeviceIdentifier const& device_identifier) const
{
for (auto& initializer : s_initializers) {
auto initializer_probe_found_driver_match_or_error = initializer.probe(device_identifier);
if (initializer_probe_found_driver_match_or_error.is_error()) {
dmesgln("Networking: Failed to probe device {}, due to {}", device_identifier.address(), initializer_probe_found_driver_match_or_error.error());
continue;
}
auto initializer_probe_found_driver_match = initializer_probe_found_driver_match_or_error.release_value();
if (initializer_probe_found_driver_match) {
auto adapter = TRY(initializer.create(device_identifier));
TRY(adapter->initialize({}));
return adapter;
}
}
return Error::from_string_literal("Unsupported network adapter");
}
bool NetworkingManagement::initialize()
{
if (!kernel_command_line().is_physical_networking_disabled() && !PCI::Access::is_disabled()) {
MUST(PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
// Note: PCI class 2 is the class of Network devices
if (device_identifier.class_code().value() != 0x02)
return;
auto result = determine_network_device(device_identifier);
if (result.is_error()) {
dmesgln("Failed to initialize network adapter ({} {}): {}", device_identifier.address(), device_identifier.hardware_id(), result.error());
return;
}
m_adapters.with([&](auto& adapters) { adapters.append(result.release_value()); });
}));
}
auto loopback = LoopbackAdapter::try_create();
VERIFY(loopback);
m_adapters.with([&](auto& adapters) { adapters.append(*loopback); });
m_loopback_adapter = loopback;
return true;
}
}