summaryrefslogtreecommitdiff
path: root/Kernel/Bus/VirtIO/Console.h
blob: 77d0b1c285e72bdf904821f2b878386108d6384c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2021, Kyle Pereira <hey@xylepereira.me>
 * Copyright (c) 2021, the SerenityOS developers.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <Kernel/Bus/VirtIO/ConsolePort.h>
#include <Kernel/Bus/VirtIO/Device.h>
#include <Kernel/Memory/RingBuffer.h>

namespace Kernel::VirtIO {
class Console
    : public VirtIO::Device
    , public RefCounted<Console> {
    friend VirtIO::ConsolePort;

public:
    static NonnullRefPtr<Console> must_create(PCI::Address address);
    virtual ~Console() override = default;

    virtual StringView purpose() const override { return class_name(); }

    unsigned device_id() const
    {
        return m_device_id;
    }

    virtual void initialize() override;

private:
    virtual StringView class_name() const override { return "VirtIOConsole"; }
    explicit Console(PCI::Address);
    enum class ControlEvent : u16 {
        DeviceReady = 0,
        DeviceAdd = 1,
        PortReady = 3,
        ConsolePort = 4,
        PortOpen = 6,
    };
    struct [[gnu::packed]] ControlMessage {
        u32 id;
        u16 event;
        u16 value;

        enum class Status : u16 {
            Success = 1,
            Failure = 0
        };

        enum class PortStatus : u16 {
            Open = 1,
            Close = 0
        };
    };

    constexpr static u16 CONTROL_RECEIVEQ = 2;
    constexpr static u16 CONTROL_TRANSMITQ = 3;
    constexpr static size_t CONTROL_MESSAGE_SIZE = sizeof(ControlMessage);
    constexpr static size_t CONTROL_BUFFER_SIZE = CONTROL_MESSAGE_SIZE * 32;

    virtual bool handle_device_config_change() override;
    virtual void handle_queue_update(u16 queue_index) override;

    Vector<RefPtr<ConsolePort>> m_ports;
    void setup_multiport();
    void process_control_message(ControlMessage message);
    void write_control_message(ControlMessage message);
    void send_open_control_message(unsigned port_number, bool open);

    unsigned m_device_id;

    OwnPtr<Memory::RingBuffer> m_control_transmit_buffer;
    OwnPtr<Memory::RingBuffer> m_control_receive_buffer;

    WaitQueue m_control_wait_queue;

    static unsigned next_device_id;
};
}