Kernel: Add very simple BGA driver
Only thing this is currently helpful is qemu when booting with -kernel flag as that does not provide framebuffer info in multiboot headers
This commit is contained in:
@@ -41,6 +41,7 @@ set(KERNEL_SOURCES
|
||||
kernel/FS/USTARModule.cpp
|
||||
kernel/FS/VirtualFileSystem.cpp
|
||||
kernel/GDT.cpp
|
||||
kernel/Graphics/BGA.cpp
|
||||
kernel/IDT.cpp
|
||||
kernel/Input/InputDevice.cpp
|
||||
kernel/Input/PS2/Controller.cpp
|
||||
|
||||
@@ -6,15 +6,22 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class BGAController;
|
||||
|
||||
class FramebufferDevice : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(BAN::RefPtr<BGAController>);
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
||||
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
|
||||
~FramebufferDevice();
|
||||
|
||||
uint32_t width() const { return m_width; }
|
||||
uint32_t height() const { return m_height; }
|
||||
uint8_t bpp() const { return m_bpp; }
|
||||
|
||||
BAN::ErrorOr<void> set_bga_controller(BAN::RefPtr<BGAController>);
|
||||
|
||||
uint32_t get_pixel(uint32_t x, uint32_t y) const;
|
||||
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
|
||||
@@ -50,14 +57,16 @@ namespace Kernel
|
||||
private:
|
||||
const BAN::String m_name;
|
||||
|
||||
vaddr_t m_video_memory_vaddr { 0 };
|
||||
const paddr_t m_video_memory_paddr;
|
||||
const uint32_t m_width;
|
||||
const uint32_t m_height;
|
||||
const uint32_t m_pitch;
|
||||
const uint8_t m_bpp;
|
||||
vaddr_t m_video_memory_vaddr { 0 };
|
||||
paddr_t m_video_memory_paddr { 0 };
|
||||
|
||||
uint32_t m_width { 0 };
|
||||
uint32_t m_height { 0 };
|
||||
uint32_t m_pitch { 0 };
|
||||
uint8_t m_bpp { 0 };
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_video_buffer;
|
||||
BAN::RefPtr<BGAController> m_bga_controller;
|
||||
|
||||
friend class FramebufferMemoryRegion;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/PCI.h>
|
||||
|
||||
#include <sys/framebuffer.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class BGAController : public BAN::RefCounted<BGAController>
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<BGAController>> create(PCI::Device&);
|
||||
|
||||
fb_fix_info get_fb_fix_info() const;
|
||||
fb_var_info get_fb_var_info() const;
|
||||
BAN::ErrorOr<void> set_fb_var_info(const fb_var_info&);
|
||||
|
||||
private:
|
||||
BGAController(PCI::Device&);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
void write_reg(uint16_t reg, uint16_t value);
|
||||
uint16_t read_reg(uint16_t reg);
|
||||
|
||||
private:
|
||||
mutable RecursiveSpinLock m_lock;
|
||||
PCI::Device& m_pci_device;
|
||||
BAN::UniqPtr<PCI::BarRegion> m_lfb_bar;
|
||||
|
||||
fb_fix_info m_fix_info {};
|
||||
fb_var_info m_var_info {};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -53,6 +53,8 @@ namespace Kernel
|
||||
|
||||
virtual bool master_has_closed() const { return false; }
|
||||
|
||||
virtual bool is_vtty() const { return false; }
|
||||
|
||||
protected:
|
||||
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Kernel
|
||||
|
||||
void clear() override;
|
||||
|
||||
bool is_vtty() const override { return true; }
|
||||
BAN::ErrorOr<void> set_terminal_driver(BAN::RefPtr<TerminalDriver>);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <kernel/Device/DeviceNumbers.h>
|
||||
#include <kernel/Device/FramebufferDevice.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Graphics/BGA.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Terminal/FramebufferTerminal.h>
|
||||
|
||||
@@ -26,19 +27,14 @@ namespace Kernel
|
||||
return s_boot_framebuffer;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create_from_boot_framebuffer()
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp)
|
||||
{
|
||||
ASSERT(g_boot_info.framebuffer.type == FramebufferInfo::Type::RGB);
|
||||
if (g_boot_info.framebuffer.bpp != 24 && g_boot_info.framebuffer.bpp != 32)
|
||||
if (bpp != 24 && bpp != 32)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
auto* device_ptr = new FramebufferDevice(
|
||||
0660, 0, 900,
|
||||
makedev(DeviceNumber::Framebuffer, get_framebuffer_device_index()),
|
||||
g_boot_info.framebuffer.address,
|
||||
g_boot_info.framebuffer.width,
|
||||
g_boot_info.framebuffer.height,
|
||||
g_boot_info.framebuffer.pitch,
|
||||
g_boot_info.framebuffer.bpp
|
||||
paddr, width, height, pitch, bpp
|
||||
);
|
||||
if (device_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
@@ -49,6 +45,33 @@ namespace Kernel
|
||||
return device;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create(BAN::RefPtr<BGAController> bga_controller)
|
||||
{
|
||||
const auto fix_info = bga_controller->get_fb_fix_info();
|
||||
const auto var_info = bga_controller->get_fb_var_info();
|
||||
auto controller = TRY(create(
|
||||
fix_info.mem_start,
|
||||
var_info.xres,
|
||||
var_info.yres,
|
||||
fix_info.pitch,
|
||||
var_info.bpp
|
||||
));
|
||||
controller->m_bga_controller = bga_controller;
|
||||
return controller;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create_from_boot_framebuffer()
|
||||
{
|
||||
s_boot_framebuffer = TRY(create(
|
||||
g_boot_info.framebuffer.address,
|
||||
g_boot_info.framebuffer.width,
|
||||
g_boot_info.framebuffer.height,
|
||||
g_boot_info.framebuffer.pitch,
|
||||
g_boot_info.framebuffer.bpp
|
||||
));
|
||||
return s_boot_framebuffer;
|
||||
}
|
||||
|
||||
FramebufferDevice::FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp)
|
||||
: CharacterDevice(mode, uid, gid)
|
||||
, m_name(MUST(BAN::String::formatted("fb{}", minor(rdev))))
|
||||
@@ -65,16 +88,20 @@ namespace Kernel
|
||||
{
|
||||
if (m_video_memory_vaddr == 0)
|
||||
return;
|
||||
size_t video_memory_pages = range_page_count(m_video_memory_paddr, m_height * m_pitch);
|
||||
const size_t video_memory_bytes = m_bga_controller ? m_bga_controller->get_fb_fix_info().mem_size : m_height * m_pitch;
|
||||
const size_t video_memory_pages = range_page_count(m_video_memory_paddr, video_memory_bytes);
|
||||
PageTable::kernel().unmap_range(m_video_memory_vaddr, video_memory_pages * PAGE_SIZE);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> FramebufferDevice::initialize()
|
||||
{
|
||||
size_t video_memory_pages = range_page_count(m_video_memory_paddr, m_height * m_pitch);
|
||||
const size_t video_memory_bytes = m_bga_controller ? m_bga_controller->get_fb_fix_info().mem_size : m_height * m_pitch;
|
||||
const size_t video_memory_pages = range_page_count(m_video_memory_paddr, video_memory_bytes);
|
||||
|
||||
m_video_memory_vaddr = PageTable::kernel().reserve_free_contiguous_pages(video_memory_pages, KERNEL_OFFSET);
|
||||
if (m_video_memory_vaddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
||||
PageTable::kernel().map_range_at(
|
||||
m_video_memory_paddr & PAGE_ADDR_MASK,
|
||||
m_video_memory_vaddr,
|
||||
@@ -86,7 +113,7 @@ namespace Kernel
|
||||
m_video_buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||
PageTable::kernel(),
|
||||
{ KERNEL_OFFSET, UINTPTR_MAX },
|
||||
BAN::Math::div_round_up<size_t>(m_width * m_height * (BANAN_FB_BPP / 8), PAGE_SIZE) * PAGE_SIZE,
|
||||
video_memory_pages * PAGE_SIZE,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
false
|
||||
));
|
||||
@@ -94,6 +121,37 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> FramebufferDevice::set_bga_controller(BAN::RefPtr<BGAController> bga_controller)
|
||||
{
|
||||
ASSERT(!m_bga_controller);
|
||||
|
||||
if (auto var_info = bga_controller->get_fb_var_info(); var_info.bpp != 32)
|
||||
{
|
||||
var_info.bpp = 32;
|
||||
TRY(bga_controller->set_fb_var_info(var_info));
|
||||
}
|
||||
|
||||
const auto fix_info = bga_controller->get_fb_fix_info();
|
||||
const auto var_info = bga_controller->get_fb_var_info();
|
||||
|
||||
ASSERT(m_video_memory_vaddr);
|
||||
PageTable::kernel().unmap_range(m_video_memory_vaddr, m_height * m_pitch);
|
||||
|
||||
m_video_memory_vaddr = 0;
|
||||
m_video_memory_paddr = fix_info.mem_start;
|
||||
|
||||
m_width = var_info.xres;
|
||||
m_height = var_info.yres;
|
||||
m_pitch = fix_info.pitch;
|
||||
m_bpp = var_info.bpp;
|
||||
|
||||
m_bga_controller = bga_controller;
|
||||
|
||||
TRY(initialize());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> FramebufferDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||
{
|
||||
// Reading from negative offset will fill buffer with framebuffer info
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
#include <kernel/Device/FramebufferDevice.h>
|
||||
#include <kernel/Graphics/BGA.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Terminal/FramebufferTerminal.h>
|
||||
#include <kernel/Terminal/VirtualTTY.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
enum BGA_IO_PORT : uint16_t
|
||||
{
|
||||
BGA_IO_PORT_INDEX = 0x1CE,
|
||||
BGA_IO_PORT_DATA = 0x1CF,
|
||||
};
|
||||
|
||||
enum BGA_REG : uint16_t
|
||||
{
|
||||
BGA_REG_ID = 0,
|
||||
BGA_REG_XRES = 1,
|
||||
BGA_REG_YRES = 2,
|
||||
BGA_REG_BPP = 3,
|
||||
BGA_REG_ENABLE = 4,
|
||||
BGA_REG_BANK = 5,
|
||||
BGA_REG_XRES_VIRT = 6,
|
||||
BGA_REG_YRES_VIRT = 7,
|
||||
BGA_REG_XOFF = 8,
|
||||
BGA_REG_YOFF = 9,
|
||||
};
|
||||
|
||||
enum BGA_ID : uint16_t
|
||||
{
|
||||
BGA_ID_0 = 0xB0C0,
|
||||
BGA_ID_1 = 0xB0C1,
|
||||
BGA_ID_2 = 0xB0C2,
|
||||
BGA_ID_3 = 0xB0C3,
|
||||
BGA_ID_4 = 0xB0C4,
|
||||
BGA_ID_5 = 0xB0C5,
|
||||
};
|
||||
|
||||
enum BGA_ENABLE : uint16_t
|
||||
{
|
||||
BGA_ENABLE_ENABLE = 0x01,
|
||||
BGA_ENABLE_LFB_ENABLE = 0x40,
|
||||
BGA_ENABLE_NOCLEARMEM = 0x80,
|
||||
};
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<BGAController>> BGAController::create(PCI::Device& pci_device)
|
||||
{
|
||||
auto* bga_controller_ptr = new BGAController(pci_device);
|
||||
if (bga_controller_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto bga_controller = BAN::RefPtr<BGAController>::adopt(bga_controller_ptr);
|
||||
TRY(bga_controller->initialize());
|
||||
return bga_controller;
|
||||
}
|
||||
|
||||
BGAController::BGAController(PCI::Device& pci_device)
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> BGAController::initialize()
|
||||
{
|
||||
auto boot_framebuffer = FramebufferDevice::boot_framebuffer();
|
||||
|
||||
m_lfb_bar = TRY(m_pci_device.allocate_bar_region(0));
|
||||
if (m_lfb_bar->type() != PCI::BarType::MEM)
|
||||
{
|
||||
dwarnln("BGA LFB is not memory bar");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
m_fix_info = {
|
||||
.xpanstep = 1,
|
||||
.ypanstep = 1,
|
||||
.pitch = 0,
|
||||
.mem_start = static_cast<uint64_t>(m_lfb_bar->paddr()),
|
||||
.mem_size = static_cast<uint32_t>(m_lfb_bar->size()),
|
||||
};
|
||||
|
||||
const auto ready_to_use_flags = BGA_ENABLE_LFB_ENABLE | BGA_ENABLE_ENABLE;
|
||||
if ((read_reg(BGA_REG_ENABLE) & ready_to_use_flags) == ready_to_use_flags)
|
||||
{
|
||||
m_var_info = {
|
||||
.xres = read_reg(BGA_REG_XRES),
|
||||
.yres = read_reg(BGA_REG_YRES),
|
||||
.xres_virt = read_reg(BGA_REG_XRES_VIRT),
|
||||
.yres_virt = read_reg(BGA_REG_XRES_VIRT),
|
||||
.xoff = read_reg(BGA_REG_XOFF),
|
||||
.yoff = read_reg(BGA_REG_YOFF),
|
||||
.bpp = read_reg(BGA_REG_BPP),
|
||||
};
|
||||
|
||||
m_fix_info.pitch = m_var_info.xres_virt * m_var_info.bpp / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t xres = boot_framebuffer ? boot_framebuffer->width() : 1280;
|
||||
const uint32_t yres = boot_framebuffer ? boot_framebuffer->height() : 800;
|
||||
const uint32_t bpp = boot_framebuffer ? boot_framebuffer->bpp() : 32;
|
||||
|
||||
TRY(set_fb_var_info({
|
||||
.xres = xres,
|
||||
.yres = yres,
|
||||
.xres_virt = xres,
|
||||
.yres_virt = yres * 2,
|
||||
.xoff = 0,
|
||||
.yoff = 0,
|
||||
.bpp = bpp,
|
||||
}));
|
||||
}
|
||||
|
||||
if (boot_framebuffer)
|
||||
{
|
||||
// FIXME: check that this is actually the boot framebuffer
|
||||
TRY(boot_framebuffer->set_bga_controller(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto framebuffer_device = TRY(FramebufferDevice::create(this));
|
||||
auto fb_terminal_driver = TRY(FramebufferTerminalDriver::create(framebuffer_device));
|
||||
|
||||
// FIXME: query vtty instead of checking the current tty
|
||||
if (auto tty = TTY::current(); tty && tty->is_vtty())
|
||||
TRY(static_cast<VirtualTTY*>(tty.ptr())->set_terminal_driver(fb_terminal_driver));
|
||||
else
|
||||
TRY(VirtualTTY::create(fb_terminal_driver));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> BGAController::set_fb_var_info(const fb_var_info& var_info)
|
||||
{
|
||||
const auto validate_u16 = [](auto value) -> BAN::ErrorOr<void> {
|
||||
if (value > BAN::numeric_limits<uint16_t>::max())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return {};
|
||||
};
|
||||
TRY(validate_u16(var_info.xres));
|
||||
TRY(validate_u16(var_info.xres));
|
||||
TRY(validate_u16(var_info.xres_virt));
|
||||
TRY(validate_u16(var_info.yres_virt));
|
||||
TRY(validate_u16(var_info.xoff));
|
||||
TRY(validate_u16(var_info.yoff));
|
||||
TRY(validate_u16(var_info.bpp));
|
||||
|
||||
if (var_info.xres + var_info.xoff > var_info.xres_virt)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (var_info.yres + var_info.yoff > var_info.yres_virt)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (static_cast<uint64_t>(var_info.xres_virt) * var_info.yres_virt * var_info.bpp / 8 > m_lfb_bar->size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
const bool needs_reconf =
|
||||
(m_var_info.xres != var_info.xres) ||
|
||||
(m_var_info.yres != var_info.yres) ||
|
||||
(m_var_info.xres_virt != var_info.xres_virt) ||
|
||||
(m_var_info.yres_virt != var_info.yres_virt) ||
|
||||
(m_var_info.bpp != var_info.bpp);
|
||||
|
||||
if (!needs_reconf)
|
||||
{
|
||||
write_reg(BGA_REG_XOFF, var_info.xoff);
|
||||
write_reg(BGA_REG_YOFF, var_info.yoff);
|
||||
m_var_info.xoff = var_info.xoff;
|
||||
m_var_info.yoff = var_info.yoff;
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto old_enable = read_reg(BGA_REG_ENABLE);
|
||||
write_reg(BGA_REG_ENABLE, 0);
|
||||
|
||||
write_reg(BGA_REG_BPP, var_info.bpp);
|
||||
write_reg(BGA_REG_XRES, var_info.xres);
|
||||
write_reg(BGA_REG_YRES, var_info.yres);
|
||||
write_reg(BGA_REG_XRES_VIRT, var_info.xres_virt);
|
||||
write_reg(BGA_REG_YRES_VIRT, var_info.yres_virt);
|
||||
|
||||
const bool valid_config =
|
||||
read_reg(BGA_REG_BPP) == var_info.bpp &&
|
||||
read_reg(BGA_REG_XRES) == var_info.xres &&
|
||||
read_reg(BGA_REG_YRES) == var_info.yres &&
|
||||
read_reg(BGA_REG_XRES_VIRT) == var_info.xres_virt;
|
||||
|
||||
if (!valid_config)
|
||||
{
|
||||
write_reg(BGA_REG_BPP, m_var_info.bpp);
|
||||
write_reg(BGA_REG_XRES, m_var_info.xres);
|
||||
write_reg(BGA_REG_YRES, m_var_info.yres);
|
||||
write_reg(BGA_REG_XRES_VIRT, m_var_info.xres_virt);
|
||||
write_reg(BGA_REG_YRES_VIRT, m_var_info.yres_virt);
|
||||
|
||||
write_reg(BGA_REG_ENABLE, BGA_ENABLE_NOCLEARMEM | old_enable);
|
||||
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
write_reg(BGA_REG_ENABLE, BGA_ENABLE_LFB_ENABLE | BGA_ENABLE_ENABLE);
|
||||
|
||||
// NOTE: At least qemu only sets virtual yres on enable and it will be
|
||||
// maximum that fits within vram. Our initial bounds check should
|
||||
// make sure this always succeeds
|
||||
ASSERT(read_reg(BGA_REG_YRES_VIRT) >= var_info.yres_virt);
|
||||
|
||||
write_reg(BGA_REG_XOFF, var_info.xoff);
|
||||
write_reg(BGA_REG_YOFF, var_info.yoff);
|
||||
|
||||
m_var_info = var_info;
|
||||
m_fix_info.pitch = m_var_info.xres_virt * m_var_info.bpp / 8;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void BGAController::write_reg(uint16_t reg, uint16_t value)
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
IO::outw(BGA_IO_PORT_INDEX, reg);
|
||||
IO::outw(BGA_IO_PORT_DATA, value);
|
||||
}
|
||||
|
||||
uint16_t BGAController::read_reg(uint16_t reg)
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
IO::outw(BGA_IO_PORT_INDEX, reg);
|
||||
return IO::inw(BGA_IO_PORT_DATA);
|
||||
}
|
||||
|
||||
fb_fix_info BGAController::get_fb_fix_info() const
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
return m_fix_info;
|
||||
}
|
||||
|
||||
fb_var_info BGAController::get_fb_var_info() const
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
return m_var_info;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <kernel/ACPI/ACPI.h>
|
||||
#include <kernel/APIC.h>
|
||||
#include <kernel/Audio/Controller.h>
|
||||
#include <kernel/Graphics/BGA.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
@@ -258,6 +259,13 @@ namespace Kernel::PCI
|
||||
for_each_device(
|
||||
[&](PCI::Device& pci_device)
|
||||
{
|
||||
if (pci_device.vendor_id() == 0x1234 && pci_device.device_id() == 0x1111)
|
||||
{
|
||||
if (auto ret = BGAController::create(pci_device); ret.is_error())
|
||||
dprintln("BGA: {}", ret.error());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pci_device.class_code())
|
||||
{
|
||||
case 0x01:
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace Kernel
|
||||
|
||||
BAN::RefPtr<TTY> TTY::current()
|
||||
{
|
||||
ASSERT(s_tty);
|
||||
return s_tty;
|
||||
}
|
||||
|
||||
|
||||
+48
-19
@@ -68,6 +68,8 @@ static bool should_disable_serial(BAN::StringView full_command_line)
|
||||
extern bool g_disable_debug;
|
||||
static ParsedCommandLine cmdline;
|
||||
|
||||
static bool s_has_early_console { false };
|
||||
|
||||
static void parse_command_line()
|
||||
{
|
||||
auto full_command_line = Kernel::g_boot_info.command_line.sv();
|
||||
@@ -160,7 +162,24 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
|
||||
if (auto ret = TerminalDriver::initialize_from_boot_info(); ret.is_error())
|
||||
dprintln("failed to initialize terminal driver: {}", ret.error());
|
||||
else
|
||||
dprintln("terminal driver initialized");
|
||||
{
|
||||
MUST(VirtualTTY::create(g_terminal_driver));
|
||||
dprintln("Virtual TTY initialized");
|
||||
}
|
||||
|
||||
if (Serial::has_devices())
|
||||
{
|
||||
Serial::initialize_devices();
|
||||
dprintln("Serial devices initialized");
|
||||
}
|
||||
|
||||
if (auto ret = DevFileSystem::get().root_inode()->find_inode(cmdline.console); !ret.is_error())
|
||||
{
|
||||
auto console = ret.release_value();
|
||||
ASSERT(console->is_tty());
|
||||
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
|
||||
s_has_early_console = true;
|
||||
}
|
||||
|
||||
if (!cmdline.disable_smp)
|
||||
InterruptController::get().initialize_multiprocessor();
|
||||
@@ -171,18 +190,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
|
||||
MUST(SharedMemoryObjectManager::initialize());
|
||||
dprintln("Shared memory object system initialized");
|
||||
|
||||
if (Serial::has_devices())
|
||||
{
|
||||
Serial::initialize_devices();
|
||||
dprintln("Serial devices initialized");
|
||||
}
|
||||
|
||||
if (g_terminal_driver)
|
||||
{
|
||||
auto vtty = MUST(VirtualTTY::create(g_terminal_driver));
|
||||
dprintln("Virtual TTY initialized");
|
||||
}
|
||||
|
||||
Random::initialize();
|
||||
dprintln("RNG initialized");
|
||||
|
||||
@@ -213,10 +220,6 @@ static void init2(void*)
|
||||
|
||||
ProcFileSystem::get().post_scheduler_initialize();
|
||||
|
||||
auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console));
|
||||
ASSERT(console->is_tty());
|
||||
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
|
||||
|
||||
// This only initializes PCIManager by enumerating available devices and choosing PCIe/legacy
|
||||
// ACPI might require PCI access during its namespace initialization
|
||||
PCI::PCIManager::initialize();
|
||||
@@ -256,6 +259,32 @@ static void init2(void*)
|
||||
PCI::PCIManager::get().initialize_devices(cmdline.disable_usb);
|
||||
dprintln("PCI devices initialized");
|
||||
|
||||
if (!s_has_early_console)
|
||||
{
|
||||
auto console_or_error = DevFileSystem::get().root_inode()->find_inode(cmdline.console);
|
||||
if (!console_or_error.is_error())
|
||||
{
|
||||
auto console = console_or_error.release_value();
|
||||
ASSERT(console->is_tty());
|
||||
static_cast<TTY*>(console.ptr())->set_as_current();
|
||||
}
|
||||
else
|
||||
{
|
||||
BAN::RefPtr<TTY> tty;
|
||||
DevFileSystem::get().for_each_inode([&](BAN::RefPtr<Inode> inode) -> BAN::Iteration {
|
||||
if (!inode->is_tty())
|
||||
return BAN::Iteration::Continue;
|
||||
tty = static_cast<TTY*>(inode.ptr());
|
||||
return BAN::Iteration::Break;
|
||||
});
|
||||
|
||||
ASSERT(tty);
|
||||
|
||||
dwarnln("Could not find /dev/{}, falling back to /dev/{}", cmdline.console, tty->name());
|
||||
tty->set_as_current();
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFileSystem::initialize(cmdline.root);
|
||||
dprintln("VFS initialized");
|
||||
|
||||
@@ -266,9 +295,9 @@ static void init2(void*)
|
||||
|
||||
Banos::initialize_initial_drivers();
|
||||
|
||||
auto console_path = MUST(BAN::String::formatted("/dev/{}", cmdline.console));
|
||||
auto console_path = MUST(BAN::String::formatted("/dev/{}", TTY::current()->name()));
|
||||
auto console_path_sv = console_path.sv();
|
||||
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, BAN::Span<BAN::StringView>(&console_path_sv, 1)));
|
||||
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, { &console_path_sv, 1 }));
|
||||
}
|
||||
|
||||
extern "C" void ap_main()
|
||||
|
||||
Reference in New Issue
Block a user