1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:47:35 +00:00

Kernel/VirtIO: Introduce the concept of transport options

The VirtIO specification defines many types of devices with different
purposes, and it also defines 3 possible transport mediums where devices
could be connected to the host machine.

We only care about the PCIe transport, but this commit puts the actual
foundations for supporting the lean MMIO transport too in the future.

To ensure things are kept abstracted but still functional, the VirtIO
transport code is responsible for what is deemed as related to an actual
transport type - allocation of interrupt handlers and tinkering with low
level transport-related registers, etc.
This commit is contained in:
Liav A 2023-06-10 14:46:47 +03:00 committed by Andrew Kaster
parent 68c3f9aa5a
commit d61c23569e
24 changed files with 732 additions and 429 deletions

View file

@ -5,6 +5,7 @@
*/
#include <Kernel/Bus/PCI/IDs.h>
#include <Kernel/Bus/VirtIO/Transport/PCIe/TransportLink.h>
#include <Kernel/Net/NetworkingManagement.h>
#include <Kernel/Net/VirtIO/VirtIONetworkAdapter.h>
@ -102,11 +103,12 @@ UNMAP_AFTER_INIT ErrorOr<bool> VirtIONetworkAdapter::probe(PCI::DeviceIdentifier
UNMAP_AFTER_INIT ErrorOr<NonnullRefPtr<NetworkAdapter>> VirtIONetworkAdapter::create(PCI::DeviceIdentifier const& pci_device_identifier)
{
auto interface_name = TRY(NetworkingManagement::generate_interface_name_from_pci_address(pci_device_identifier));
return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) VirtIONetworkAdapter(interface_name.representable_view(), pci_device_identifier)));
auto pci_transport_link = TRY(VirtIO::PCIeTransportLink::create(pci_device_identifier));
return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) VirtIONetworkAdapter(interface_name.representable_view(), move(pci_transport_link))));
}
UNMAP_AFTER_INIT VirtIONetworkAdapter::VirtIONetworkAdapter(StringView interface_name, PCI::DeviceIdentifier const& pci_device_identifier)
: VirtIO::Device(pci_device_identifier)
UNMAP_AFTER_INIT VirtIONetworkAdapter::VirtIONetworkAdapter(StringView interface_name, NonnullOwnPtr<VirtIO::TransportEntity> pci_transport_link)
: VirtIO::Device(move(pci_transport_link))
, NetworkAdapter(interface_name)
{
}
@ -123,7 +125,7 @@ UNMAP_AFTER_INIT ErrorOr<void> VirtIONetworkAdapter::initialize_virtio_resources
{
dbgln_if(VIRTIO_DEBUG, "VirtIONetworkAdapter: initialize_virtio_resources");
TRY(Device::initialize_virtio_resources());
m_device_config = TRY(get_config(VirtIO::ConfigurationType::Device));
m_device_config = TRY(transport_entity().get_config(VirtIO::ConfigurationType::Device));
bool success = negotiate_features([&](u64 supported_features) {
u64 negotiated = 0;
@ -169,28 +171,28 @@ UNMAP_AFTER_INIT ErrorOr<void> VirtIONetworkAdapter::initialize_virtio_resources
bool VirtIONetworkAdapter::handle_device_config_change()
{
dbgln_if(VIRTIO_DEBUG, "VirtIONetworkAdapter: handle_device_config_change");
read_config_atomic([&]() {
transport_entity().read_config_atomic([&]() {
if (is_feature_accepted(VIRTIO_NET_F_MAC)) {
set_mac_address(MACAddress(
config_read8(*m_device_config, 0x0),
config_read8(*m_device_config, 0x1),
config_read8(*m_device_config, 0x2),
config_read8(*m_device_config, 0x3),
config_read8(*m_device_config, 0x4),
config_read8(*m_device_config, 0x5)));
transport_entity().config_read8(*m_device_config, 0x0),
transport_entity().config_read8(*m_device_config, 0x1),
transport_entity().config_read8(*m_device_config, 0x2),
transport_entity().config_read8(*m_device_config, 0x3),
transport_entity().config_read8(*m_device_config, 0x4),
transport_entity().config_read8(*m_device_config, 0x5)));
}
if (is_feature_accepted(VIRTIO_NET_F_STATUS)) {
u16 status = config_read16(*m_device_config, offsetof(VirtIONetConfig, status));
u16 status = transport_entity().config_read16(*m_device_config, offsetof(VirtIONetConfig, status));
m_link_up = (status & VIRTIO_NET_S_LINK_UP) != 0;
}
if (is_feature_accepted(VIRTIO_NET_F_MTU)) {
u16 mtu = config_read16(*m_device_config, offsetof(VirtIONetConfig, mtu));
u16 mtu = transport_entity().config_read16(*m_device_config, offsetof(VirtIONetConfig, mtu));
set_mtu(mtu);
}
if (is_feature_accepted(VIRTIO_NET_F_SPEED_DUPLEX)) {
u32 speed = config_read32(*m_device_config, offsetof(VirtIONetConfig, speed));
u32 speed = transport_entity().config_read32(*m_device_config, offsetof(VirtIONetConfig, speed));
m_link_speed = speed;
u32 duplex = config_read32(*m_device_config, offsetof(VirtIONetConfig, duplex));
u32 duplex = transport_entity().config_read32(*m_device_config, offsetof(VirtIONetConfig, duplex));
m_link_duplex = duplex == 0x01;
}
});