mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:47:35 +00:00
Kernel: Support the bochs-display device
This device is a graphics display device that is not supporting VGA functionality. Therefore, it exposes a MMIO region to configure it, so we use that region to set the framebuffer resolution.
This commit is contained in:
parent
2dcafde330
commit
86be477da0
2 changed files with 54 additions and 5 deletions
|
@ -14,6 +14,7 @@
|
|||
#include <Kernel/Process.h>
|
||||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#include <Kernel/VM/TypedMapping.h>
|
||||
#include <LibC/errno_numbers.h>
|
||||
#include <LibC/sys/ioctl_numbers.h>
|
||||
|
||||
|
@ -53,9 +54,13 @@ BXVGADevice& BXVGADevice::the()
|
|||
|
||||
UNMAP_AFTER_INIT BXVGADevice::BXVGADevice()
|
||||
: BlockDevice(29, 0)
|
||||
|
||||
{
|
||||
m_framebuffer_address = PhysicalAddress(find_framebuffer_address());
|
||||
m_mmio_registers = find_mmio_region();
|
||||
m_vga_compatible = is_vga_compatible();
|
||||
|
||||
set_register(VBE_DISPI_INDEX_ID, 0xB0C0);
|
||||
dmesgln("BXVGA: ID {}", get_register(VBE_DISPI_INDEX_ID));
|
||||
set_safe_resolution();
|
||||
}
|
||||
|
||||
|
@ -69,14 +74,23 @@ void BXVGADevice::set_safe_resolution()
|
|||
|
||||
void BXVGADevice::set_register(u16 index, u16 data)
|
||||
{
|
||||
if (m_vga_compatible) {
|
||||
IO::out16(VBE_DISPI_IOPORT_INDEX, index);
|
||||
IO::out16(VBE_DISPI_IOPORT_DATA, data);
|
||||
return;
|
||||
}
|
||||
auto reg = map_typed_writable<u16>(m_mmio_registers.offset(index * 2));
|
||||
*(reg.ptr()) = data;
|
||||
}
|
||||
|
||||
u16 BXVGADevice::get_register(u16 index)
|
||||
{
|
||||
if (m_vga_compatible) {
|
||||
IO::out16(VBE_DISPI_IOPORT_INDEX, index);
|
||||
return IO::in16(VBE_DISPI_IOPORT_DATA);
|
||||
}
|
||||
auto reg = map_typed_writable<u16>(m_mmio_registers.offset(index * 2));
|
||||
return *(reg.ptr());
|
||||
}
|
||||
|
||||
void BXVGADevice::revert_resolution()
|
||||
|
@ -153,6 +167,36 @@ UNMAP_AFTER_INIT u32 BXVGADevice::find_framebuffer_address()
|
|||
return framebuffer_address;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT PhysicalAddress BXVGADevice::find_mmio_region()
|
||||
{
|
||||
// NOTE: The QEMU card has the same PCI ID as the Bochs one.
|
||||
static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 };
|
||||
static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef };
|
||||
u32 mmio_region = 0;
|
||||
PCI::enumerate([&mmio_region](const PCI::Address& address, PCI::ID id) {
|
||||
if (id == bochs_vga_id || id == virtualbox_vga_id) {
|
||||
mmio_region = PCI::get_BAR1(address) & 0xfffffff0;
|
||||
dmesgln("BXVGA: mmio region @ {}", PhysicalAddress(mmio_region));
|
||||
}
|
||||
});
|
||||
return PhysicalAddress(mmio_region);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT bool BXVGADevice::is_vga_compatible()
|
||||
{
|
||||
// NOTE: The QEMU card has the same PCI ID as the Bochs one.
|
||||
static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 };
|
||||
static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef };
|
||||
bool vga_compatible = true;
|
||||
PCI::enumerate([&vga_compatible](const PCI::Address& address, PCI::ID id) {
|
||||
if (id == bochs_vga_id || id == virtualbox_vga_id) {
|
||||
if (PCI::get_subclass(address) != 0)
|
||||
vga_compatible = false;
|
||||
}
|
||||
});
|
||||
return vga_compatible;
|
||||
}
|
||||
|
||||
KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared)
|
||||
{
|
||||
REQUIRE_PROMISE(video);
|
||||
|
|
|
@ -36,6 +36,9 @@ private:
|
|||
virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return EINVAL; }
|
||||
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return EINVAL; }
|
||||
|
||||
PhysicalAddress find_mmio_region();
|
||||
bool is_vga_compatible();
|
||||
|
||||
void set_safe_resolution();
|
||||
|
||||
void set_register(u16 index, u16 value);
|
||||
|
@ -50,6 +53,8 @@ private:
|
|||
void set_y_offset(size_t);
|
||||
|
||||
PhysicalAddress m_framebuffer_address;
|
||||
PhysicalAddress m_mmio_registers;
|
||||
bool m_vga_compatible { true };
|
||||
size_t m_framebuffer_pitch { 0 };
|
||||
size_t m_framebuffer_width { 0 };
|
||||
size_t m_framebuffer_height { 0 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue