summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/CMakeLists.txt8
-rw-r--r--Kernel/Devices/BXVGADevice.cpp290
-rw-r--r--Kernel/Devices/BXVGADevice.h64
-rw-r--r--Kernel/Graphics/Bochs.h27
-rw-r--r--Kernel/Graphics/BochsFramebufferDevice.cpp114
-rw-r--r--Kernel/Graphics/BochsFramebufferDevice.h41
-rw-r--r--Kernel/Graphics/BochsGraphicsAdapter.cpp126
-rw-r--r--Kernel/Graphics/BochsGraphicsAdapter.h49
-rw-r--r--Kernel/Graphics/FramebufferDevice.cpp (renamed from Kernel/Devices/MBVGADevice.cpp)64
-rw-r--r--Kernel/Graphics/FramebufferDevice.h (renamed from Kernel/Devices/MBVGADevice.h)29
-rw-r--r--Kernel/Graphics/GraphicsDevice.h33
-rw-r--r--Kernel/Graphics/GraphicsManagement.cpp68
-rw-r--r--Kernel/Graphics/GraphicsManagement.h38
-rw-r--r--Kernel/Graphics/RawFramebufferDevice.cpp20
-rw-r--r--Kernel/Graphics/RawFramebufferDevice.h31
-rw-r--r--Kernel/Graphics/VGACompatibleAdapter.cpp31
-rw-r--r--Kernel/Graphics/VGACompatibleAdapter.h38
-rw-r--r--Kernel/init.cpp31
18 files changed, 673 insertions, 429 deletions
diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt
index 103ba80609..e0e6be75d8 100644
--- a/Kernel/CMakeLists.txt
+++ b/Kernel/CMakeLists.txt
@@ -27,12 +27,10 @@ set(KERNEL_SOURCES
CoreDump.cpp
DMI.cpp
Devices/AsyncDeviceRequest.cpp
- Devices/BXVGADevice.cpp
Devices/BlockDevice.cpp
Devices/CharacterDevice.cpp
Devices/Device.cpp
Devices/FullDevice.cpp
- Devices/MBVGADevice.cpp
Devices/MemoryDevice.cpp
Devices/NullDevice.cpp
Devices/PCSpeaker.cpp
@@ -52,6 +50,12 @@ set(KERNEL_SOURCES
Devices/HID/PS2KeyboardDevice.cpp
Devices/HID/PS2MouseDevice.cpp
Devices/HID/VMWareMouseDevice.cpp
+ Graphics/BochsFramebufferDevice.cpp
+ Graphics/BochsGraphicsAdapter.cpp
+ Graphics/FramebufferDevice.cpp
+ Graphics/GraphicsManagement.cpp
+ Graphics/RawFramebufferDevice.cpp
+ Graphics/VGACompatibleAdapter.cpp
Storage/Partition/DiskPartition.cpp
Storage/Partition/DiskPartitionMetadata.cpp
Storage/Partition/EBRPartitionTable.cpp
diff --git a/Kernel/Devices/BXVGADevice.cpp b/Kernel/Devices/BXVGADevice.cpp
deleted file mode 100644
index 06be3bb785..0000000000
--- a/Kernel/Devices/BXVGADevice.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <AK/Checked.h>
-#include <AK/Format.h>
-#include <AK/Singleton.h>
-#include <Kernel/Debug.h>
-#include <Kernel/Devices/BXVGADevice.h>
-#include <Kernel/IO.h>
-#include <Kernel/PCI/Access.h>
-#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>
-
-namespace Kernel {
-
-#define MAX_RESOLUTION_WIDTH 4096
-#define MAX_RESOLUTION_HEIGHT 2160
-
-#define VBE_DISPI_IOPORT_INDEX 0x01CE
-#define VBE_DISPI_IOPORT_DATA 0x01CF
-
-#define VBE_DISPI_INDEX_ID 0x0
-#define VBE_DISPI_INDEX_XRES 0x1
-#define VBE_DISPI_INDEX_YRES 0x2
-#define VBE_DISPI_INDEX_BPP 0x3
-#define VBE_DISPI_INDEX_ENABLE 0x4
-#define VBE_DISPI_INDEX_BANK 0x5
-#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
-#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
-#define VBE_DISPI_INDEX_X_OFFSET 0x8
-#define VBE_DISPI_INDEX_Y_OFFSET 0x9
-#define VBE_DISPI_DISABLED 0x00
-#define VBE_DISPI_ENABLED 0x01
-#define VBE_DISPI_LFB_ENABLED 0x40
-
-static AK::Singleton<BXVGADevice> s_the;
-
-UNMAP_AFTER_INIT void BXVGADevice::initialize()
-{
- s_the.ensure_instance();
-}
-
-BXVGADevice& BXVGADevice::the()
-{
- return *s_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();
-}
-
-void BXVGADevice::set_safe_resolution()
-{
- m_framebuffer_width = 1024;
- m_framebuffer_height = 768;
- m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
- set_resolution(m_framebuffer_width, m_framebuffer_height);
-}
-
-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()
-{
- set_resolution_registers(m_framebuffer_width, m_framebuffer_height);
- VERIFY(validate_setup_resolution(m_framebuffer_width, m_framebuffer_height));
-}
-
-void BXVGADevice::set_resolution_registers(size_t width, size_t height)
-{
- dbgln_if(BXVGA_DEBUG, "BXVGADevice resolution registers set to - {}x{}", width, height);
- set_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
- set_register(VBE_DISPI_INDEX_XRES, (u16)width);
- set_register(VBE_DISPI_INDEX_YRES, (u16)height);
- set_register(VBE_DISPI_INDEX_VIRT_WIDTH, (u16)width);
- set_register(VBE_DISPI_INDEX_VIRT_HEIGHT, (u16)height * 2);
- set_register(VBE_DISPI_INDEX_BPP, 32);
- set_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
- set_register(VBE_DISPI_INDEX_BANK, 0);
-}
-
-bool BXVGADevice::test_resolution(size_t width, size_t height)
-{
- dbgln_if(BXVGA_DEBUG, "BXVGADevice resolution test - {}x{}", width, height);
- set_resolution_registers(width, height);
- bool resolution_changed = validate_setup_resolution(width, height);
- revert_resolution();
- return resolution_changed;
-}
-bool BXVGADevice::set_resolution(size_t width, size_t height)
-{
- if (Checked<size_t>::multiplication_would_overflow(width, height, sizeof(u32)))
- return false;
-
- if (!test_resolution(width, height))
- return false;
-
- set_resolution_registers(width, height);
- dbgln("BXVGADevice resolution set to {}x{} (pitch={})", width, height, m_framebuffer_pitch);
-
- m_framebuffer_width = width;
- m_framebuffer_height = height;
- m_framebuffer_pitch = width * sizeof(u32);
- return true;
-}
-
-bool BXVGADevice::validate_setup_resolution(size_t width, size_t height)
-{
- if ((u16)width != get_register(VBE_DISPI_INDEX_XRES) || (u16)height != get_register(VBE_DISPI_INDEX_YRES)) {
- return false;
- }
- return true;
-}
-
-void BXVGADevice::set_y_offset(size_t y_offset)
-{
- VERIFY(y_offset == 0 || y_offset == m_framebuffer_height);
- m_y_offset = y_offset;
- set_register(VBE_DISPI_INDEX_Y_OFFSET, (u16)y_offset);
-}
-
-UNMAP_AFTER_INIT u32 BXVGADevice::find_framebuffer_address()
-{
- // 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 framebuffer_address = 0;
- PCI::enumerate([&framebuffer_address](const PCI::Address& address, PCI::ID id) {
- if (id == bochs_vga_id || id == virtualbox_vga_id) {
- framebuffer_address = PCI::get_BAR0(address) & 0xfffffff0;
- dbgln("BXVGA: framebuffer @ {}", PhysicalAddress(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);
- if (!shared)
- return ENODEV;
- if (offset != 0)
- return ENXIO;
- if (range.size() != page_round_up(framebuffer_size_in_bytes()))
- return EOVERFLOW;
-
- auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes());
- if (!vmobject)
- return ENOMEM;
- return process.space().allocate_region_with_vmobject(
- range,
- vmobject.release_nonnull(),
- 0,
- "BXVGA Framebuffer",
- prot,
- shared);
-}
-
-String BXVGADevice::device_name() const
-{
- return String::formatted("fb{}", minor());
-}
-
-int BXVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
-{
- REQUIRE_PROMISE(video);
- switch (request) {
- case FB_IOCTL_GET_SIZE_IN_BYTES: {
- auto* out = (size_t*)arg;
- size_t value = framebuffer_size_in_bytes();
- if (!copy_to_user(out, &value))
- return -EFAULT;
- return 0;
- }
- case FB_IOCTL_GET_BUFFER: {
- auto* index = (int*)arg;
- int value = m_y_offset == 0 ? 0 : 1;
- if (!copy_to_user(index, &value))
- return -EFAULT;
- return 0;
- }
- case FB_IOCTL_SET_BUFFER: {
- if (arg != 0 && arg != 1)
- return -EINVAL;
- set_y_offset(arg == 0 ? 0 : m_framebuffer_height);
- return 0;
- }
- case FB_IOCTL_GET_RESOLUTION: {
- auto* user_resolution = (FBResolution*)arg;
- FBResolution resolution;
- resolution.pitch = m_framebuffer_pitch;
- resolution.width = m_framebuffer_width;
- resolution.height = m_framebuffer_height;
- if (!copy_to_user(user_resolution, &resolution))
- return -EFAULT;
- return 0;
- }
- case FB_IOCTL_SET_RESOLUTION: {
- auto* user_resolution = (FBResolution*)arg;
- FBResolution resolution;
- if (!copy_from_user(&resolution, user_resolution))
- return -EFAULT;
- if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT)
- return -EINVAL;
- if (!set_resolution(resolution.width, resolution.height)) {
- dbgln_if(BXVGA_DEBUG, "Reverting resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
- resolution.pitch = m_framebuffer_pitch;
- resolution.width = m_framebuffer_width;
- resolution.height = m_framebuffer_height;
- if (!copy_to_user(user_resolution, &resolution))
- return -EFAULT;
- return -EINVAL;
- }
- dbgln_if(BXVGA_DEBUG, "New resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
- resolution.pitch = m_framebuffer_pitch;
- resolution.width = m_framebuffer_width;
- resolution.height = m_framebuffer_height;
- if (!copy_to_user(user_resolution, &resolution))
- return -EFAULT;
- return 0;
- }
- default:
- return -EINVAL;
- };
-}
-
-}
diff --git a/Kernel/Devices/BXVGADevice.h b/Kernel/Devices/BXVGADevice.h
deleted file mode 100644
index b1692dc9f7..0000000000
--- a/Kernel/Devices/BXVGADevice.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-#include <AK/String.h>
-#include <AK/Types.h>
-#include <Kernel/Devices/BlockDevice.h>
-#include <Kernel/PhysicalAddress.h>
-
-namespace Kernel {
-
-class BXVGADevice final : public BlockDevice {
- AK_MAKE_ETERNAL
-public:
- static void initialize();
- static BXVGADevice& the();
-
- BXVGADevice();
-
- virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
- virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override;
-
- // ^Device
- virtual mode_t required_mode() const override { return 0660; }
- virtual String device_name() const override;
-
-private:
- virtual const char* class_name() const override { return "BXVGA"; }
- virtual bool can_read(const FileDescription&, size_t) const override { return true; }
- virtual bool can_write(const FileDescription&, size_t) const override { return true; }
- virtual void start_request(AsyncBlockDeviceRequest& request) override { request.complete(AsyncDeviceRequest::Failure); }
- 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);
- u16 get_register(u16 index);
- bool validate_setup_resolution(size_t width, size_t height);
- u32 find_framebuffer_address();
- void revert_resolution();
- bool test_resolution(size_t width, size_t height);
- size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height * 2; }
- bool set_resolution(size_t width, size_t height);
- void set_resolution_registers(size_t width, size_t height);
- 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 };
- size_t m_y_offset { 0 };
-};
-
-}
diff --git a/Kernel/Graphics/Bochs.h b/Kernel/Graphics/Bochs.h
new file mode 100644
index 0000000000..19b9d08a4b
--- /dev/null
+++ b/Kernel/Graphics/Bochs.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#define MAX_RESOLUTION_WIDTH 4096
+#define MAX_RESOLUTION_HEIGHT 2160
+
+#define VBE_DISPI_IOPORT_INDEX 0x01CE
+#define VBE_DISPI_IOPORT_DATA 0x01CF
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_LFB_ENABLED 0x40
diff --git a/Kernel/Graphics/BochsFramebufferDevice.cpp b/Kernel/Graphics/BochsFramebufferDevice.cpp
new file mode 100644
index 0000000000..15af62d532
--- /dev/null
+++ b/Kernel/Graphics/BochsFramebufferDevice.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Checked.h>
+#include <AK/Singleton.h>
+#include <Kernel/Debug.h>
+#include <Kernel/Graphics/Bochs.h>
+#include <Kernel/Graphics/BochsFramebufferDevice.h>
+#include <Kernel/IO.h>
+#include <Kernel/PCI/Access.h>
+#include <Kernel/Process.h>
+#include <LibC/errno_numbers.h>
+#include <LibC/sys/ioctl_numbers.h>
+
+namespace Kernel {
+
+UNMAP_AFTER_INIT NonnullRefPtr<BochsFramebufferDevice> BochsFramebufferDevice::create(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height)
+{
+ return adopt_ref(*new BochsFramebufferDevice(adapter, framebuffer_address, pitch, width, height));
+}
+
+UNMAP_AFTER_INIT BochsFramebufferDevice::BochsFramebufferDevice(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height)
+ : FramebufferDevice(framebuffer_address, pitch, width, height)
+ , m_bochs_adapter(adapter)
+{
+ m_bochs_adapter->set_safe_resolution();
+ m_framebuffer_width = 1024;
+ m_framebuffer_height = 768;
+ m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
+}
+
+void BochsFramebufferDevice::set_y_offset(size_t y_offset)
+{
+ VERIFY(y_offset == 0 || y_offset == m_framebuffer_height);
+ m_y_offset = y_offset;
+ m_bochs_adapter->set_y_offset(y_offset);
+}
+
+int BochsFramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
+{
+ REQUIRE_PROMISE(video);
+ switch (request) {
+ case FB_IOCTL_GET_SIZE_IN_BYTES: {
+ auto* out = (size_t*)arg;
+ size_t value = framebuffer_size_in_bytes();
+ if (!copy_to_user(out, &value))
+ return -EFAULT;
+ return 0;
+ }
+ case FB_IOCTL_GET_BUFFER: {
+ auto* index = (int*)arg;
+ int value = m_y_offset == 0 ? 0 : 1;
+ if (!copy_to_user(index, &value))
+ return -EFAULT;
+ return 0;
+ }
+ case FB_IOCTL_SET_BUFFER: {
+ if (arg != 0 && arg != 1)
+ return -EINVAL;
+ set_y_offset(arg == 0 ? 0 : m_framebuffer_height);
+ return 0;
+ }
+ case FB_IOCTL_GET_RESOLUTION: {
+ auto* user_resolution = (FBResolution*)arg;
+ FBResolution resolution;
+ resolution.pitch = m_framebuffer_pitch;
+ resolution.width = m_framebuffer_width;
+ resolution.height = m_framebuffer_height;
+ if (!copy_to_user(user_resolution, &resolution))
+ return -EFAULT;
+ return 0;
+ }
+ case FB_IOCTL_SET_RESOLUTION: {
+ auto* user_resolution = (FBResolution*)arg;
+ FBResolution resolution;
+ if (!copy_from_user(&resolution, user_resolution))
+ return -EFAULT;
+ if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT)
+ return -EINVAL;
+
+ if (!m_bochs_adapter->set_resolution(resolution.width, resolution.height)) {
+ m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
+ dbgln_if(BXVGA_DEBUG, "Reverting resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
+ // Note: We try to revert everything back, and if it doesn't work, just assert.
+ if (!m_bochs_adapter->set_resolution(m_framebuffer_width, m_framebuffer_height)) {
+ VERIFY_NOT_REACHED();
+ }
+ resolution.pitch = m_framebuffer_pitch;
+ resolution.width = m_framebuffer_width;
+ resolution.height = m_framebuffer_height;
+ if (!copy_to_user(user_resolution, &resolution))
+ return -EFAULT;
+ return -EINVAL;
+ }
+ m_framebuffer_width = resolution.width;
+ m_framebuffer_height = resolution.height;
+ m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
+
+ dbgln_if(BXVGA_DEBUG, "New resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
+ resolution.pitch = m_framebuffer_pitch;
+ resolution.width = m_framebuffer_width;
+ resolution.height = m_framebuffer_height;
+ if (!copy_to_user(user_resolution, &resolution))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ };
+}
+}
diff --git a/Kernel/Graphics/BochsFramebufferDevice.h b/Kernel/Graphics/BochsFramebufferDevice.h
new file mode 100644
index 0000000000..5133c3320f
--- /dev/null
+++ b/Kernel/Graphics/BochsFramebufferDevice.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <Kernel/Graphics/BochsGraphicsAdapter.h>
+#include <Kernel/Graphics/FramebufferDevice.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+class BochsFramebufferDevice final : public FramebufferDevice {
+ AK_MAKE_ETERNAL
+ friend class BochsGraphicsAdapter;
+
+public:
+ static NonnullRefPtr<BochsFramebufferDevice> create(const BochsGraphicsAdapter&, PhysicalAddress, size_t, size_t, size_t);
+
+ virtual size_t framebuffer_size_in_bytes() const override { return m_framebuffer_pitch * m_framebuffer_height * 2; }
+
+ virtual ~BochsFramebufferDevice() = default;
+
+private:
+ virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
+
+ BochsFramebufferDevice(const BochsGraphicsAdapter&, PhysicalAddress, size_t, size_t, size_t);
+ virtual const char* class_name() const override { return "BXVGA"; }
+
+ void set_y_offset(size_t);
+
+ size_t m_y_offset { 0 };
+
+ NonnullRefPtr<BochsGraphicsAdapter> m_bochs_adapter;
+};
+
+}
diff --git a/Kernel/Graphics/BochsGraphicsAdapter.cpp b/Kernel/Graphics/BochsGraphicsAdapter.cpp
new file mode 100644
index 0000000000..d6f42b1662
--- /dev/null
+++ b/Kernel/Graphics/BochsGraphicsAdapter.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Atomic.h>
+#include <AK/Checked.h>
+#include <AK/Singleton.h>
+#include <Kernel/Debug.h>
+#include <Kernel/Graphics/Bochs.h>
+#include <Kernel/Graphics/BochsFramebufferDevice.h>
+#include <Kernel/Graphics/BochsGraphicsAdapter.h>
+#include <Kernel/IO.h>
+#include <Kernel/PCI/Access.h>
+#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>
+
+namespace Kernel {
+
+struct [[gnu::packed]] DISPIInterface {
+ u16 index_id;
+ u16 xres;
+ u16 yres;
+ u16 bpp;
+ u16 enable;
+ u16 bank;
+ u16 virt_width;
+ u16 virt_height;
+ u16 x_offset;
+ u16 y_offset;
+};
+
+struct [[gnu::packed]] BochsDisplayMMIORegisters {
+ u8 edid_data[0x400];
+ u16 vga_ioports[0x10];
+ u8 reserved[0xE0];
+ DISPIInterface bochs_regs;
+};
+
+UNMAP_AFTER_INIT NonnullRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initialize(PCI::Address address)
+{
+ return adopt_ref(*new BochsGraphicsAdapter(address));
+}
+
+UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::Address pci_address)
+ : PCI::DeviceController(pci_address)
+ , m_mmio_registers(PCI::get_BAR2(pci_address) & 0xfffffff0)
+{
+ set_safe_resolution();
+}
+
+UNMAP_AFTER_INIT void BochsGraphicsAdapter::initialize_framebuffer_devices()
+{
+ // FIXME: Find a better way to determine default resolution...
+ m_framebuffer = BochsFramebufferDevice::create(*this, PhysicalAddress(PCI::get_BAR0(pci_address()) & 0xfffffff0), 1024 * 4, 1024, 768);
+}
+
+GraphicsDevice::Type BochsGraphicsAdapter::type() const
+{
+ if (PCI::get_class(pci_address()) == 0x3 && PCI::get_subclass(pci_address()) == 0x0)
+ return Type::VGACompatible;
+ return Type::Bochs;
+}
+
+void BochsGraphicsAdapter::set_safe_resolution()
+{
+ set_resolution(1024, 768);
+}
+
+void BochsGraphicsAdapter::set_resolution_registers(size_t width, size_t height)
+{
+ dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter resolution registers set to - {}x{}", width, height);
+ auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers);
+ registers->bochs_regs.enable = VBE_DISPI_DISABLED;
+ full_memory_barrier();
+ registers->bochs_regs.xres = width;
+ registers->bochs_regs.yres = height;
+ registers->bochs_regs.virt_width = width;
+ registers->bochs_regs.virt_height = height * 2;
+ registers->bochs_regs.bpp = 32;
+ full_memory_barrier();
+ registers->bochs_regs.enable = VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED;
+ full_memory_barrier();
+ registers->bochs_regs.bank = 0;
+}
+
+bool BochsGraphicsAdapter::try_to_set_resolution(size_t width, size_t height)
+{
+ dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter resolution test - {}x{}", width, height);
+ set_resolution_registers(width, height);
+ return validate_setup_resolution(width, height);
+}
+
+bool BochsGraphicsAdapter::set_resolution(size_t width, size_t height)
+{
+ if (Checked<size_t>::multiplication_would_overflow(width, height, sizeof(u32)))
+ return false;
+
+ if (!try_to_set_resolution(width, height))
+ return false;
+
+ dbgln("BochsGraphicsAdapter: resolution set to {}x{}", width, height);
+ return true;
+}
+
+bool BochsGraphicsAdapter::validate_setup_resolution(size_t width, size_t height)
+{
+ auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers);
+ if ((u16)width != registers->bochs_regs.xres || (u16)height != registers->bochs_regs.yres) {
+ return false;
+ }
+ return true;
+}
+
+void BochsGraphicsAdapter::set_y_offset(size_t y_offset)
+{
+ auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers);
+ registers->bochs_regs.y_offset = y_offset;
+}
+
+}
diff --git a/Kernel/Graphics/BochsGraphicsAdapter.h b/Kernel/Graphics/BochsGraphicsAdapter.h
new file mode 100644
index 0000000000..e2c2b1cdd5
--- /dev/null
+++ b/Kernel/Graphics/BochsGraphicsAdapter.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <Kernel/Graphics/GraphicsDevice.h>
+#include <Kernel/PCI/DeviceController.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+class BochsFramebufferDevice;
+class GraphicsManagement;
+class BochsGraphicsAdapter final : public GraphicsDevice
+ , public PCI::DeviceController {
+ AK_MAKE_ETERNAL
+ friend class BochsFramebufferDevice;
+ friend class GraphicsManagement;
+
+public:
+ static NonnullRefPtr<BochsGraphicsAdapter> initialize(PCI::Address);
+ virtual ~BochsGraphicsAdapter() = default;
+
+private:
+ // ^GraphicsDevice
+ virtual void initialize_framebuffer_devices() override;
+ virtual Type type() const override;
+
+ explicit BochsGraphicsAdapter(PCI::Address);
+
+ void set_safe_resolution();
+
+ bool validate_setup_resolution(size_t width, size_t height);
+ u32 find_framebuffer_address();
+ bool try_to_set_resolution(size_t width, size_t height);
+ bool set_resolution(size_t width, size_t height);
+ void set_resolution_registers(size_t width, size_t height);
+ void set_y_offset(size_t);
+
+ PhysicalAddress m_mmio_registers;
+ RefPtr<BochsFramebufferDevice> m_framebuffer;
+};
+
+}
diff --git a/Kernel/Devices/MBVGADevice.cpp b/Kernel/Graphics/FramebufferDevice.cpp
index bfefe387d8..c6d45774cf 100644
--- a/Kernel/Devices/MBVGADevice.cpp
+++ b/Kernel/Graphics/FramebufferDevice.cpp
@@ -1,37 +1,24 @@
/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include <Kernel/Devices/MBVGADevice.h>
+#include <AK/Checked.h>
+#include <AK/Singleton.h>
+#include <Kernel/Debug.h>
+#include <Kernel/Graphics/FramebufferDevice.h>
+#include <Kernel/Graphics/GraphicsManagement.h>
#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>
namespace Kernel {
-static MBVGADevice* s_the;
-
-MBVGADevice& MBVGADevice::the()
-{
- return *s_the;
-}
-
-UNMAP_AFTER_INIT MBVGADevice::MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height)
- : BlockDevice(29, 0)
- , m_framebuffer_address(addr)
- , m_framebuffer_pitch(pitch)
- , m_framebuffer_width(width)
- , m_framebuffer_height(height)
-{
- dbgln("MBVGADevice address={}, pitch={}, width={}, height={}", addr, pitch, width, height);
- s_the = this;
-}
-
-KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared)
+KResultOr<Region*> FramebufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared)
{
REQUIRE_PROMISE(video);
if (!shared)
@@ -48,12 +35,32 @@ KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, const R
range,
vmobject.release_nonnull(),
0,
- "MBVGA Framebuffer",
+ "Framebuffer",
prot,
shared);
}
-int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
+String FramebufferDevice::device_name() const
+{
+ return String::formatted("fb{}", minor());
+}
+
+UNMAP_AFTER_INIT FramebufferDevice::FramebufferDevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height)
+ : BlockDevice(29, GraphicsManagement::the().current_minor_number())
+ , m_framebuffer_address(addr)
+ , m_framebuffer_pitch(pitch)
+ , m_framebuffer_width(width)
+ , m_framebuffer_height(height)
+{
+ dbgln("Framebuffer {}: address={}, pitch={}, width={}, height={}", minor(), addr, pitch, width, height);
+}
+
+bool FramebufferDevice::set_resolution(size_t, size_t, size_t)
+{
+ VERIFY_NOT_REACHED();
+}
+
+int FramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
{
REQUIRE_PROMISE(video);
switch (request) {
@@ -65,11 +72,7 @@ int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
return 0;
}
case FB_IOCTL_GET_BUFFER: {
- auto* index = (int*)arg;
- int value = 0;
- if (!copy_to_user(index, &value))
- return -EFAULT;
- return 0;
+ return -ENOTIMPL;
}
case FB_IOCTL_GET_RESOLUTION: {
auto* user_resolution = (FBResolution*)arg;
@@ -96,9 +99,4 @@ int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
};
}
-String MBVGADevice::device_name() const
-{
- return String::formatted("fb{}", minor());
-}
-
}
diff --git a/Kernel/Devices/MBVGADevice.h b/Kernel/Graphics/FramebufferDevice.h
index db473c5443..104fc5739d 100644
--- a/Kernel/Devices/MBVGADevice.h
+++ b/Kernel/Graphics/FramebufferDevice.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -9,17 +9,14 @@
#include <AK/String.h>
#include <AK/Types.h>
#include <Kernel/Devices/BlockDevice.h>
+#include <Kernel/Graphics/GraphicsDevice.h>
#include <Kernel/PhysicalAddress.h>
namespace Kernel {
-class MBVGADevice final : public BlockDevice {
+class FramebufferDevice : public BlockDevice {
AK_MAKE_ETERNAL
public:
- static MBVGADevice& the();
-
- MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height);
-
virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override;
@@ -27,16 +24,22 @@ public:
virtual mode_t required_mode() const override { return 0660; }
virtual String device_name() const override;
-private:
- virtual const char* class_name() const override { return "MBVGA"; }
- virtual bool can_read(const FileDescription&, size_t) const override { return true; }
- virtual bool can_write(const FileDescription&, size_t) const override { return true; }
+ virtual size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height; }
+
+ virtual ~FramebufferDevice() {};
+
+protected:
+ virtual bool set_resolution(size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
+
+ FramebufferDevice(PhysicalAddress, size_t, size_t, size_t);
+
+ virtual bool can_read(const FileDescription&, size_t) const override final { return true; }
+ virtual bool can_write(const FileDescription&, size_t) const override final { return true; }
+ virtual void start_request(AsyncBlockDeviceRequest& request) override final { request.complete(AsyncDeviceRequest::Failure); }
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; }
- virtual void start_request(AsyncBlockDeviceRequest& request) override { request.complete(AsyncDeviceRequest::Failure); }
-
- size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height; }
+protected:
PhysicalAddress m_framebuffer_address;
size_t m_framebuffer_pitch { 0 };
size_t m_framebuffer_width { 0 };
diff --git a/Kernel/Graphics/GraphicsDevice.h b/Kernel/Graphics/GraphicsDevice.h
new file mode 100644
index 0000000000..f4d3ae7e29
--- /dev/null
+++ b/Kernel/Graphics/GraphicsDevice.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <Kernel/Devices/BlockDevice.h>
+#include <Kernel/Graphics/FramebufferDevice.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+class FramebufferDevice;
+class GraphicsDevice : public RefCounted<GraphicsDevice> {
+public:
+ enum class Type {
+ VGACompatible,
+ Bochs,
+ SVGA,
+ Raw
+ };
+ virtual ~GraphicsDevice() = default;
+ virtual void initialize_framebuffer_devices() = 0;
+ virtual Type type() const = 0;
+
+protected:
+ GraphicsDevice() = default;
+};
+
+}
diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp
new file mode 100644
index 0000000000..4fbef68629
--- /dev/null
+++ b/Kernel/Graphics/GraphicsManagement.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Checked.h>
+#include <AK/Singleton.h>
+#include <Kernel/CommandLine.h>
+#include <Kernel/Debug.h>
+#include <Kernel/Graphics/BochsGraphicsAdapter.h>
+#include <Kernel/Graphics/GraphicsManagement.h>
+#include <Kernel/Graphics/VGACompatibleAdapter.h>
+#include <Kernel/Multiboot.h>
+
+namespace Kernel {
+
+static AK::Singleton<GraphicsManagement> s_the;
+
+GraphicsManagement& GraphicsManagement::the()
+{
+ return *s_the;
+}
+
+bool GraphicsManagement::is_initialized()
+{
+ return s_the.is_initialized();
+}
+
+UNMAP_AFTER_INIT GraphicsManagement::GraphicsManagement()
+ : m_textmode_enabled(kernel_command_line().is_text_mode())
+{
+}
+
+UNMAP_AFTER_INIT RefPtr<GraphicsDevice> GraphicsManagement::determine_graphics_device(PCI::Address address, PCI::ID id) const
+{
+ if ((id.vendor_id == 0x1234 && id.device_id == 0x1111) || (id.vendor_id == 0x80ee && id.device_id == 0xbeef)) {
+ return BochsGraphicsAdapter::initialize(address);
+ }
+ if (PCI::get_class(address) == 0x3 && PCI::get_subclass(address) == 0x0) {
+ VERIFY(multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB || multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT);
+ return VGACompatibleAdapter::initialize_with_preset_resolution(address,
+ PhysicalAddress((u32)(multiboot_info_ptr->framebuffer_addr)),
+ multiboot_info_ptr->framebuffer_pitch,
+ multiboot_info_ptr->framebuffer_width,
+ multiboot_info_ptr->framebuffer_height);
+ }
+ return {};
+}
+
+UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
+{
+ if (kernel_command_line().is_text_mode()) {
+ dbgln("Text mode enabled");
+ return false;
+ }
+
+ PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
+ auto adapter = determine_graphics_device(address, id);
+ if (!adapter)
+ return;
+ adapter->initialize_framebuffer_devices();
+ m_graphics_devices.append(adapter.release_nonnull());
+ });
+ return true;
+}
+
+}
diff --git a/Kernel/Graphics/GraphicsManagement.h b/Kernel/Graphics/GraphicsManagement.h
new file mode 100644
index 0000000000..bcf0cded39
--- /dev/null
+++ b/Kernel/Graphics/GraphicsManagement.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullRefPtr.h>
+#include <AK/NonnullRefPtrVector.h>
+#include <AK/Types.h>
+#include <Kernel/Graphics/GraphicsDevice.h>
+#include <Kernel/PCI/Definitions.h>
+
+namespace Kernel {
+
+class GraphicsManagement {
+ AK_MAKE_ETERNAL;
+
+public:
+ static GraphicsManagement& the();
+ static bool is_initialized();
+ bool initialize();
+
+ unsigned current_minor_number() { return m_current_minor_number++; };
+ GraphicsManagement();
+
+ bool is_text_mode_enabled() const { return m_textmode_enabled; }
+
+private:
+ RefPtr<GraphicsDevice> determine_graphics_device(PCI::Address address, PCI::ID id) const;
+
+ NonnullRefPtrVector<GraphicsDevice> m_graphics_devices;
+ unsigned m_current_minor_number { 0 };
+ bool m_textmode_enabled;
+};
+
+}
diff --git a/Kernel/Graphics/RawFramebufferDevice.cpp b/Kernel/Graphics/RawFramebufferDevice.cpp
new file mode 100644
index 0000000000..f36a5cfa27
--- /dev/null
+++ b/Kernel/Graphics/RawFramebufferDevice.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Graphics/RawFramebufferDevice.h>
+
+namespace Kernel {
+
+UNMAP_AFTER_INIT NonnullRefPtr<RawFramebufferDevice> RawFramebufferDevice::create(const GraphicsDevice&, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height)
+{
+ return adopt_ref(*new RawFramebufferDevice(framebuffer_address, pitch, width, height));
+}
+UNMAP_AFTER_INIT RawFramebufferDevice::RawFramebufferDevice(PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height)
+ : FramebufferDevice(framebuffer_address, pitch, width, height)
+{
+}
+
+}
diff --git a/Kernel/Graphics/RawFramebufferDevice.h b/Kernel/Graphics/RawFramebufferDevice.h
new file mode 100644
index 0000000000..10ddf44ea8
--- /dev/null
+++ b/Kernel/Graphics/RawFramebufferDevice.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <Kernel/Graphics/FramebufferDevice.h>
+#include <Kernel/Graphics/GraphicsDevice.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+class RawFramebufferDevice : public FramebufferDevice {
+ AK_MAKE_ETERNAL
+ friend class GraphicsDevice;
+
+public:
+ static NonnullRefPtr<RawFramebufferDevice> create(const GraphicsDevice&, PhysicalAddress, size_t pitch, size_t width, size_t height);
+
+ virtual ~RawFramebufferDevice() {};
+
+private:
+ RawFramebufferDevice(PhysicalAddress, size_t pitch, size_t width, size_t height);
+ virtual const char* class_name() const override { return "RawFramebuffer"; }
+};
+
+}
diff --git a/Kernel/Graphics/VGACompatibleAdapter.cpp b/Kernel/Graphics/VGACompatibleAdapter.cpp
new file mode 100644
index 0000000000..80b2e8b0d4
--- /dev/null
+++ b/Kernel/Graphics/VGACompatibleAdapter.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Graphics/VGACompatibleAdapter.h>
+
+namespace Kernel {
+
+UNMAP_AFTER_INIT NonnullRefPtr<VGACompatibleAdapter> VGACompatibleAdapter::initialize_with_preset_resolution(PCI::Address address, PhysicalAddress m_framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
+{
+ return adopt_ref(*new VGACompatibleAdapter(address, m_framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch));
+}
+
+UNMAP_AFTER_INIT void VGACompatibleAdapter::initialize_framebuffer_devices()
+{
+}
+
+UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address)
+ : PCI::DeviceController(address)
+{
+}
+
+UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
+ : PCI::DeviceController(address)
+{
+ m_framebuffer = RawFramebufferDevice::create(*this, framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
+}
+
+}
diff --git a/Kernel/Graphics/VGACompatibleAdapter.h b/Kernel/Graphics/VGACompatibleAdapter.h
new file mode 100644
index 0000000000..75ed5ee946
--- /dev/null
+++ b/Kernel/Graphics/VGACompatibleAdapter.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <Kernel/Graphics/GraphicsDevice.h>
+#include <Kernel/Graphics/RawFramebufferDevice.h>
+#include <Kernel/PCI/DeviceController.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+class VGACompatibleAdapter final : public GraphicsDevice
+ , public PCI::DeviceController {
+ AK_MAKE_ETERNAL
+public:
+ static NonnullRefPtr<VGACompatibleAdapter> initialize_with_preset_resolution(PCI::Address, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
+
+protected:
+ explicit VGACompatibleAdapter(PCI::Address);
+
+private:
+ VGACompatibleAdapter(PCI::Address, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
+
+ // ^GraphicsDevice
+ virtual void initialize_framebuffer_devices() override;
+ virtual Type type() const override { return Type::VGACompatible; }
+
+protected:
+ RefPtr<RawFramebufferDevice> m_framebuffer;
+};
+
+}
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 1918aa1dc8..e497688b56 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -12,10 +12,8 @@
#include <Kernel/CMOS.h>
#include <Kernel/CommandLine.h>
#include <Kernel/DMI.h>
-#include <Kernel/Devices/BXVGADevice.h>
#include <Kernel/Devices/FullDevice.h>
#include <Kernel/Devices/HID/HIDManagement.h>
-#include <Kernel/Devices/MBVGADevice.h>
#include <Kernel/Devices/MemoryDevice.h>
#include <Kernel/Devices/NullDevice.h>
#include <Kernel/Devices/RandomDevice.h>
@@ -26,6 +24,7 @@
#include <Kernel/Devices/ZeroDevice.h>
#include <Kernel/FileSystem/Ext2FileSystem.h>
#include <Kernel/FileSystem/VirtualFileSystem.h>
+#include <Kernel/Graphics/GraphicsManagement.h>
#include <Kernel/Heap/SlabAllocator.h>
#include <Kernel/Heap/kmalloc.h>
#include <Kernel/Interrupts/APIC.h>
@@ -233,30 +232,8 @@ void init_stage2(void*)
PCI::initialize();
auto boot_profiling = kernel_command_line().is_boot_profiling_enabled();
- auto is_text_mode = kernel_command_line().is_text_mode();
- if (is_text_mode) {
- dbgln("Text mode enabled");
- } else {
- bool bxvga_found = false;
- PCI::enumerate([&](const PCI::Address&, PCI::ID id) {
- if ((id.vendor_id == 0x1234 && id.device_id == 0x1111) || (id.vendor_id == 0x80ee && id.device_id == 0xbeef))
- bxvga_found = true;
- });
-
- if (bxvga_found) {
- BXVGADevice::initialize();
- } else {
- if (multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB || multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT) {
- new MBVGADevice(
- PhysicalAddress((u32)(multiboot_info_ptr->framebuffer_addr)),
- multiboot_info_ptr->framebuffer_pitch,
- multiboot_info_ptr->framebuffer_width,
- multiboot_info_ptr->framebuffer_height);
- } else {
- BXVGADevice::initialize();
- }
- }
- }
+
+ GraphicsManagement::the().initialize();
USB::UHCIController::detect();
@@ -297,7 +274,7 @@ void init_stage2(void*)
int error;
// FIXME: It would be nicer to set the mode from userspace.
- tty0->set_graphical(!is_text_mode);
+ tty0->set_graphical(!GraphicsManagement::the().is_text_mode_enabled());
RefPtr<Thread> thread;
auto userspace_init = kernel_command_line().userspace_init();
auto init_args = kernel_command_line().userspace_init_args();