mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-14 01:04:38 +03:00
Kernel: Implement a PCI Serial Device driver
This simple driver simply finds a device in a device definitions list and then sets up a SerialDevice instance based on the definition. The driver currently only supports "WCH CH382 2S" pci serial boards, as that is the only device available for me to test with, but most other pci serial devices should be as easily addable as adding a board_definitions entry.
This commit is contained in:
parent
62f69cc50f
commit
ba9b3dc656
Notes:
sideshowbarker
2024-07-18 17:57:01 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/ba9b3dc6565 Pull-request: https://github.com/SerenityOS/serenity/pull/7116 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/supercomputer7
@ -33,6 +33,7 @@ set(KERNEL_SOURCES
|
||||
Devices/FullDevice.cpp
|
||||
Devices/MemoryDevice.cpp
|
||||
Devices/NullDevice.cpp
|
||||
Devices/PCISerialDevice.cpp
|
||||
Devices/PCSpeaker.cpp
|
||||
Devices/RandomDevice.cpp
|
||||
Devices/SB16.cpp
|
||||
|
50
Kernel/Devices/PCISerialDevice.cpp
Normal file
50
Kernel/Devices/PCISerialDevice.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Devices/PCISerialDevice.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static SerialDevice* s_the = nullptr;
|
||||
|
||||
void PCISerialDevice::detect()
|
||||
{
|
||||
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
|
||||
if (address.is_null())
|
||||
return;
|
||||
|
||||
// HACK: There's currently no way to break out of PCI::enumerate, so we just early return if we already initialized the pci serial device
|
||||
if (is_available())
|
||||
return;
|
||||
|
||||
for (auto& board_definition : board_definitions) {
|
||||
if (board_definition.device_id != id)
|
||||
continue;
|
||||
|
||||
auto bar_base = PCI::get_BAR(address, board_definition.pci_bar) & ~1;
|
||||
// FIXME: We should support more than 1 PCI serial port (per card/multiple devices)
|
||||
s_the = new SerialDevice(IOAddress(bar_base + board_definition.first_offset), 64);
|
||||
if (board_definition.baud_rate != SerialDevice::Baud::Baud38400) // non-default baud
|
||||
s_the->set_baud(board_definition.baud_rate);
|
||||
|
||||
dmesgln("PCISerialDevice: Found {} @ {}", board_definition.name, address);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SerialDevice& PCISerialDevice::the()
|
||||
{
|
||||
VERIFY(s_the);
|
||||
return *s_the;
|
||||
}
|
||||
|
||||
bool PCISerialDevice::is_available()
|
||||
{
|
||||
return s_the;
|
||||
}
|
||||
|
||||
}
|
39
Kernel/Devices/PCISerialDevice.h
Normal file
39
Kernel/Devices/PCISerialDevice.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/Devices/CharacterDevice.h>
|
||||
#include <Kernel/Devices/SerialDevice.h>
|
||||
#include <Kernel/PCI/Device.h>
|
||||
#include <Kernel/PCI/IDs.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class PCISerialDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static void detect();
|
||||
static SerialDevice& the();
|
||||
static bool is_available();
|
||||
|
||||
private:
|
||||
struct BoardDefinition {
|
||||
PCI::ID device_id;
|
||||
StringView name;
|
||||
u32 port_count { 0 };
|
||||
u32 pci_bar { 0 };
|
||||
u32 first_offset { 0 };
|
||||
u32 port_size { 0 };
|
||||
SerialDevice::Baud baud_rate { SerialDevice::Baud::Baud38400 };
|
||||
};
|
||||
|
||||
static constexpr BoardDefinition board_definitions[1] = {
|
||||
{ { (u16)PCIVendorID::WCH, 0x3253 }, "WCH CH382 2S", 2, 0, 0xC0, 8, SerialDevice::Baud::Baud115200 }
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -111,6 +111,8 @@ public:
|
||||
virtual String device_name() const override;
|
||||
|
||||
private:
|
||||
friend class PCISerialDevice;
|
||||
|
||||
// ^CharacterDevice
|
||||
virtual const char* class_name() const override { return "SerialDevice"; }
|
||||
|
||||
|
@ -11,6 +11,7 @@ namespace Kernel {
|
||||
enum class PCIVendorID {
|
||||
VirtIO = 0x1af4,
|
||||
Intel = 0x8086,
|
||||
WCH = 0x1c00,
|
||||
};
|
||||
|
||||
enum class PCIDeviceID {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <Kernel/Devices/HID/HIDManagement.h>
|
||||
#include <Kernel/Devices/MemoryDevice.h>
|
||||
#include <Kernel/Devices/NullDevice.h>
|
||||
#include <Kernel/Devices/PCISerialDevice.h>
|
||||
#include <Kernel/Devices/RandomDevice.h>
|
||||
#include <Kernel/Devices/SB16.h>
|
||||
#include <Kernel/Devices/SerialDevice.h>
|
||||
@ -146,6 +147,7 @@ extern "C" UNMAP_AFTER_INIT [[noreturn]] void init()
|
||||
|
||||
// Initialize the PCI Bus as early as possible, for early boot (PCI based) serial logging
|
||||
PCI::initialize();
|
||||
PCISerialDevice::detect();
|
||||
|
||||
VFS::initialize();
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <AK/PrintfImplementation.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/ConsoleDevice.h>
|
||||
#include <Kernel/Devices/PCISerialDevice.h>
|
||||
#include <Kernel/Graphics/Console/Console.h>
|
||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||
#include <Kernel/IO.h>
|
||||
@ -34,6 +35,9 @@ int get_serial_debug()
|
||||
|
||||
static void serial_putch(char ch)
|
||||
{
|
||||
if (PCISerialDevice::is_available())
|
||||
return PCISerialDevice::the().put_char(ch);
|
||||
|
||||
static bool serial_ready = false;
|
||||
static bool was_cr = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user