mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:57: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:
parent
68c3f9aa5a
commit
d61c23569e
24 changed files with 732 additions and 429 deletions
|
@ -10,6 +10,8 @@
|
|||
#include <Kernel/Bus/PCI/Device.h>
|
||||
#include <Kernel/Bus/VirtIO/Definitions.h>
|
||||
#include <Kernel/Bus/VirtIO/Queue.h>
|
||||
#include <Kernel/Bus/VirtIO/Transport/Entity.h>
|
||||
#include <Kernel/Bus/VirtIO/Transport/InterruptHandler.h>
|
||||
#include <Kernel/Interrupts/IRQHandler.h>
|
||||
#include <Kernel/Library/IOWindow.h>
|
||||
#include <Kernel/Memory/MemoryManager.h>
|
||||
|
@ -18,61 +20,21 @@ namespace Kernel::VirtIO {
|
|||
|
||||
void detect();
|
||||
|
||||
class Device
|
||||
: public PCI::Device
|
||||
, public IRQHandler {
|
||||
class Device {
|
||||
public:
|
||||
virtual ~Device() override = default;
|
||||
virtual ~Device() = default;
|
||||
|
||||
virtual ErrorOr<void> initialize_virtio_resources();
|
||||
|
||||
bool handle_irq(Badge<TransportInterruptHandler>);
|
||||
|
||||
protected:
|
||||
virtual StringView class_name() const { return "VirtIO::Device"sv; }
|
||||
explicit Device(PCI::DeviceIdentifier const&);
|
||||
|
||||
ErrorOr<Configuration const*> get_config(ConfigurationType cfg_type, u32 index = 0) const
|
||||
{
|
||||
for (auto const& cfg : m_configs) {
|
||||
if (cfg.cfg_type != cfg_type)
|
||||
continue;
|
||||
if (index > 0) {
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
return &cfg;
|
||||
}
|
||||
return Error::from_errno(ENXIO);
|
||||
}
|
||||
explicit Device(NonnullOwnPtr<TransportEntity>);
|
||||
|
||||
template<typename F>
|
||||
void read_config_atomic(F f)
|
||||
{
|
||||
if (m_common_cfg) {
|
||||
u8 generation_before, generation_after;
|
||||
do {
|
||||
generation_before = config_read8(*m_common_cfg, 0x15);
|
||||
f();
|
||||
generation_after = config_read8(*m_common_cfg, 0x15);
|
||||
} while (generation_before != generation_after);
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
u8 config_read8(Configuration const&, u32);
|
||||
u16 config_read16(Configuration const&, u32);
|
||||
u32 config_read32(Configuration const&, u32);
|
||||
void config_write8(Configuration const&, u32, u8);
|
||||
void config_write16(Configuration const&, u32, u16);
|
||||
void config_write32(Configuration const&, u32, u32);
|
||||
void config_write64(Configuration const&, u32, u64);
|
||||
|
||||
auto mapping_for_bar(u8) -> IOWindow&;
|
||||
|
||||
u8 read_status_bits();
|
||||
void mask_status_bits(u8 status_mask);
|
||||
void set_status_bit(u8);
|
||||
u64 get_device_features();
|
||||
bool setup_queues(u16 requested_queue_count = 0);
|
||||
void finish_init();
|
||||
|
||||
|
@ -91,7 +53,7 @@ protected:
|
|||
template<typename F>
|
||||
bool negotiate_features(F f)
|
||||
{
|
||||
u64 device_features = get_device_features();
|
||||
u64 device_features = m_transport_entity->get_device_features();
|
||||
u64 accept_features = f(device_features);
|
||||
VERIFY(!(~device_features & accept_features));
|
||||
return accept_device_features(device_features, accept_features);
|
||||
|
@ -113,6 +75,8 @@ protected:
|
|||
virtual bool handle_device_config_change() = 0;
|
||||
virtual void handle_queue_update(u16 queue_index) = 0;
|
||||
|
||||
TransportEntity& transport_entity() { return *m_transport_entity; }
|
||||
|
||||
private:
|
||||
bool accept_device_features(u64 device_features, u64 accepted_features);
|
||||
|
||||
|
@ -120,29 +84,16 @@ private:
|
|||
bool activate_queue(u16 queue_index);
|
||||
void notify_queue(u16 queue_index);
|
||||
|
||||
void reset_device();
|
||||
|
||||
u8 isr_status();
|
||||
virtual bool handle_irq(RegisterState const&) override;
|
||||
|
||||
Vector<NonnullOwnPtr<Queue>> m_queues;
|
||||
Vector<Configuration> m_configs;
|
||||
Configuration const* m_common_cfg { nullptr }; // Cached due to high usage
|
||||
Configuration const* m_notify_cfg { nullptr }; // Cached due to high usage
|
||||
Configuration const* m_isr_cfg { nullptr }; // Cached due to high usage
|
||||
|
||||
IOWindow& base_io_window();
|
||||
Array<OwnPtr<IOWindow>, 6> m_register_bases;
|
||||
|
||||
StringView const m_class_name;
|
||||
|
||||
u16 m_queue_count { 0 };
|
||||
bool m_use_mmio { false };
|
||||
u8 m_status { 0 };
|
||||
u64 m_accepted_features { 0 };
|
||||
bool m_did_accept_features { false };
|
||||
bool m_did_setup_queues { false };
|
||||
u32 m_notify_multiplier { 0 };
|
||||
};
|
||||
|
||||
NonnullOwnPtr<TransportEntity> const m_transport_entity;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue