/* * Copyright (c) 2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include namespace Kernel::VirtIO { void detect(); class Device { public: virtual ~Device() = default; virtual ErrorOr initialize_virtio_resources(); bool handle_irq(Badge); protected: virtual StringView class_name() const { return "VirtIO::Device"sv; } explicit Device(NonnullOwnPtr); void mask_status_bits(u8 status_mask); void set_status_bit(u8); ErrorOr 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 ErrorOr 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 handle_device_config_change() = 0; virtual void handle_queue_update(u16 queue_index) = 0; TransportEntity& transport_entity() { return *m_transport_entity; } private: ErrorOr accept_device_features(u64 device_features, u64 accepted_features); ErrorOr setup_queue(u16 queue_index); ErrorOr activate_queue(u16 queue_index); void notify_queue(u16 queue_index); Vector> 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 const m_transport_entity; }; }