mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-08 23:42:53 +03:00
7718842829
Simplify core methods in the VirtIO bus handling code by ensuring proper error propagation. This makes initialization of queues, handling changes in device configuration, and other core patterns more readable as well. It also allows us to remove the obnoxious pattern of checking for boolean "success" and if we get false answer then returning an actual errno code.
100 lines
2.7 KiB
C++
100 lines
2.7 KiB
C++
/*
|
|
* Copyright (c) 2021, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <Kernel/Bus/PCI/Access.h>
|
|
#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>
|
|
|
|
namespace Kernel::VirtIO {
|
|
|
|
void detect();
|
|
|
|
class Device {
|
|
public:
|
|
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(NonnullOwnPtr<TransportEntity>);
|
|
|
|
void mask_status_bits(u8 status_mask);
|
|
void set_status_bit(u8);
|
|
ErrorOr<void> setup_queues(u16 requested_queue_count = 0);
|
|
void finish_init();
|
|
|
|
Queue& get_queue(u16 queue_index)
|
|
{
|
|
VERIFY(queue_index < m_queue_count);
|
|
return *m_queues[queue_index];
|
|
}
|
|
|
|
Queue const& get_queue(u16 queue_index) const
|
|
{
|
|
VERIFY(queue_index < m_queue_count);
|
|
return *m_queues[queue_index];
|
|
}
|
|
|
|
template<typename F>
|
|
ErrorOr<void> negotiate_features(F f)
|
|
{
|
|
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);
|
|
}
|
|
|
|
static bool is_feature_set(u64 feature_set, u64 test_feature)
|
|
{
|
|
// features can have more than one bit
|
|
return (feature_set & test_feature) == test_feature;
|
|
}
|
|
bool is_feature_accepted(u64 feature) const
|
|
{
|
|
VERIFY(m_did_accept_features);
|
|
return is_feature_set(m_accepted_features, feature);
|
|
}
|
|
|
|
void supply_chain_and_notify(u16 queue_index, QueueChain& chain);
|
|
|
|
virtual ErrorOr<void> handle_device_config_change() = 0;
|
|
virtual void handle_queue_update(u16 queue_index) = 0;
|
|
|
|
TransportEntity& transport_entity() { return *m_transport_entity; }
|
|
|
|
private:
|
|
ErrorOr<void> accept_device_features(u64 device_features, u64 accepted_features);
|
|
|
|
ErrorOr<void> setup_queue(u16 queue_index);
|
|
ErrorOr<void> activate_queue(u16 queue_index);
|
|
void notify_queue(u16 queue_index);
|
|
|
|
Vector<NonnullOwnPtr<Queue>> m_queues;
|
|
|
|
StringView const m_class_name;
|
|
|
|
u16 m_queue_count { 0 };
|
|
u8 m_status { 0 };
|
|
u64 m_accepted_features { 0 };
|
|
bool m_did_accept_features { false };
|
|
bool m_did_setup_queues { false };
|
|
|
|
NonnullOwnPtr<TransportEntity> const m_transport_entity;
|
|
};
|
|
}
|