mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
Kernel: Add base support for VirtConsole (VirtIO based consoles)
Based on pull #3236 by tomuta, this is still very much WIP but will eventually allow us to switch from the considerably slower method of knocking on port 0xe9 for each character Co-authored-by: Tom <tomut@yahoo.com> Co-authored-by: Sahan <sahan.h.fernando@gmail.com>
This commit is contained in:
parent
62303d46d1
commit
ea4c9efbb9
Notes:
sideshowbarker
2024-07-18 19:31:42 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/ea4c9efbb98 Pull-request: https://github.com/SerenityOS/serenity/pull/6340
4 changed files with 191 additions and 0 deletions
|
@ -42,6 +42,7 @@ set(KERNEL_SOURCES
|
|||
Devices/USB/UHCIController.cpp
|
||||
VirtIO/VirtIO.cpp
|
||||
VirtIO/VirtIOQueue.cpp
|
||||
VirtIO/VirtIOConsole.cpp
|
||||
Devices/VMWareBackdoor.cpp
|
||||
Devices/ZeroDevice.cpp
|
||||
Devices/HID/I8042Controller.cpp
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <Kernel/VirtIO/VirtIO.h>
|
||||
#include <Kernel/VirtIO/VirtIOConsole.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -35,6 +36,11 @@ void VirtIO::detect()
|
|||
return;
|
||||
if (id.vendor_id != VIRTIO_PCI_VENDOR_ID)
|
||||
return;
|
||||
switch (id.device_id) {
|
||||
case VIRTIO_CONSOLE_PCI_DEVICE_ID:
|
||||
[[maybe_unused]] auto& unused = adopt(*new VirtIOConsole(address)).leak_ref();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
118
Kernel/VirtIO/VirtIOConsole.cpp
Normal file
118
Kernel/VirtIO/VirtIOConsole.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <Kernel/VirtIO/VirtIOConsole.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
VirtIOConsole::VirtIOConsole(PCI::Address address)
|
||||
: CharacterDevice(229, 0)
|
||||
, VirtIODevice(address, "VirtIOConsole")
|
||||
{
|
||||
if (auto* cfg = get_device_config()) {
|
||||
bool success = negotiate_features([&](u64 supported_features) {
|
||||
u64 negotiated = 0;
|
||||
if (is_feature_set(supported_features, VIRTIO_CONSOLE_F_SIZE))
|
||||
dbgln("VirtIOConsole: Console size is not yet supported!");
|
||||
if (is_feature_set(supported_features, VIRTIO_CONSOLE_F_MULTIPORT))
|
||||
dbgln("VirtIOConsole: Multi port is not yet supported!");
|
||||
return negotiated;
|
||||
});
|
||||
if (success) {
|
||||
u32 max_nr_ports = 0;
|
||||
u16 cols = 0, rows = 0;
|
||||
read_config_atomic([&]() {
|
||||
if (is_feature_accepted(VIRTIO_CONSOLE_F_SIZE)) {
|
||||
cols = config_read16(cfg, 0x0);
|
||||
rows = config_read16(cfg, 0x2);
|
||||
}
|
||||
if (is_feature_accepted(VIRTIO_CONSOLE_F_MULTIPORT)) {
|
||||
max_nr_ports = config_read32(cfg, 0x4);
|
||||
}
|
||||
});
|
||||
dbgln("VirtIOConsole: cols: {}, rows: {}, max nr ports {}", cols, rows, max_nr_ports);
|
||||
set_requested_queue_count(2 + max_nr_ports * 2); // base receiveq/transmitq for port0 + 2 per every additional port
|
||||
success = finish_init();
|
||||
}
|
||||
if (success) {
|
||||
m_receive_queue = get_queue(RECEIVEQ);
|
||||
m_receive_queue->on_data_available = [&]() {
|
||||
dbgln("VirtIOConsole: receive_queue on_data_available");
|
||||
};
|
||||
m_send_queue = get_queue(TRANSMITQ);
|
||||
m_send_queue->on_data_available = [&]() {
|
||||
dbgln("VirtIOConsole: send_queue on_data_available");
|
||||
};
|
||||
dbgln("TODO: Populate receive queue with a receive buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtIOConsole::~VirtIOConsole()
|
||||
{
|
||||
}
|
||||
|
||||
void VirtIOConsole::handle_device_config_change()
|
||||
{
|
||||
dbgln("VirtIOConsole: Handle device config change");
|
||||
}
|
||||
|
||||
bool VirtIOConsole::can_read(const FileDescription&, size_t) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
KResultOr<size_t> VirtIOConsole::read(FileDescription&, u64, [[maybe_unused]] UserOrKernelBuffer& data, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool VirtIOConsole::can_write(const FileDescription&, size_t) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
KResultOr<size_t> VirtIOConsole::write(FileDescription&, u64, const UserOrKernelBuffer& data, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
dbgln("VirtIOConsole: Write with size {}, kernel: {}", size, data.is_kernel_buffer());
|
||||
|
||||
ssize_t nread = data.read_buffered<256>(size, [&](const u8* bytes, size_t bytes_count) {
|
||||
supply_buffer_and_notify(TRANSMITQ, bytes, bytes_count, BufferType::DeviceReadable);
|
||||
return (ssize_t)bytes_count;
|
||||
});
|
||||
|
||||
if (nread < 0)
|
||||
return Kernel::KResult((ErrnoCode)-nread);
|
||||
return (size_t)nread;
|
||||
}
|
||||
|
||||
}
|
66
Kernel/VirtIO/VirtIOConsole.h
Normal file
66
Kernel/VirtIO/VirtIOConsole.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/Devices/CharacterDevice.h>
|
||||
#include <Kernel/VirtIO/VirtIO.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
#define VIRTIO_CONSOLE_PCI_DEVICE_ID 0x1003
|
||||
|
||||
#define VIRTIO_CONSOLE_F_SIZE (1 << 0)
|
||||
#define VIRTIO_CONSOLE_F_MULTIPORT (1 << 1)
|
||||
#define VIRTIO_CONSOLE_F_EMERG_WRITE (1 << 2)
|
||||
|
||||
#define RECEIVEQ 0
|
||||
#define TRANSMITQ 1
|
||||
|
||||
class VirtIOConsole final : public CharacterDevice
|
||||
, public VirtIODevice {
|
||||
public:
|
||||
VirtIOConsole(PCI::Address);
|
||||
virtual ~VirtIOConsole() override;
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return m_class_name; }
|
||||
|
||||
virtual bool can_read(const FileDescription&, size_t) const override;
|
||||
virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override;
|
||||
virtual bool can_write(const FileDescription&, size_t) const override;
|
||||
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override;
|
||||
|
||||
virtual mode_t required_mode() const override { return 0666; }
|
||||
|
||||
virtual void handle_device_config_change() override;
|
||||
virtual String device_name() const override { return String::formatted("hvc{}", minor()); }
|
||||
|
||||
VirtIOQueue* m_receive_queue { nullptr };
|
||||
VirtIOQueue* m_send_queue { nullptr };
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in a new issue