diff options
author | Conrad Pankoff <deoxxa@fknsrs.biz> | 2019-08-18 12:29:58 +1000 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-18 07:40:02 +0200 |
commit | 3932dfbb04b7263d9d2ce6fac8d193fca81bff68 (patch) | |
tree | 9b4e82fec670220ca2d516daad20c9a03c9c1a87 | |
parent | 5e46122a821344e0c3377e5d7d7ea0ebd6bfd267 (diff) | |
download | serenity-3932dfbb04b7263d9d2ce6fac8d193fca81bff68.zip |
Kernel: Implement generic framebuffer ioctls in BXVGA
This also hides some functions that were previously public, since that
same functionality is now exposed via ioctl functions.
-rw-r--r-- | Kernel/Devices/BXVGADevice.cpp | 59 | ||||
-rw-r--r-- | Kernel/Devices/BXVGADevice.h | 13 |
2 files changed, 46 insertions, 26 deletions
diff --git a/Kernel/Devices/BXVGADevice.cpp b/Kernel/Devices/BXVGADevice.cpp index 6aa7f18e71..b971a31dfc 100644 --- a/Kernel/Devices/BXVGADevice.cpp +++ b/Kernel/Devices/BXVGADevice.cpp @@ -5,6 +5,7 @@ #include <Kernel/VM/AnonymousVMObject.h> #include <Kernel/VM/MemoryManager.h> #include <LibC/errno_numbers.h> +#include <LibC/sys/ioctl_numbers.h> #define VBE_DISPI_IOPORT_INDEX 0x01CE #define VBE_DISPI_IOPORT_DATA 0x01CF @@ -23,13 +24,6 @@ #define VBE_DISPI_ENABLED 0x01 #define VBE_DISPI_LFB_ENABLED 0x40 -#define BXVGA_DEV_IOCTL_SET_Y_OFFSET 1982 -#define BXVGA_DEV_IOCTL_SET_RESOLUTION 1985 -struct BXVGAResolution { - int width; - int height; -}; - static BXVGADevice* s_the; BXVGADevice& BXVGADevice::the() @@ -52,6 +46,7 @@ void BXVGADevice::set_register(u16 index, u16 data) void BXVGADevice::set_resolution(int width, int height) { + m_framebuffer_pitch = width * sizeof(u32); m_framebuffer_width = width; m_framebuffer_height = height; @@ -65,10 +60,11 @@ void BXVGADevice::set_resolution(int width, int height) set_register(VBE_DISPI_INDEX_BANK, 0); } -void BXVGADevice::set_y_offset(int offset) +void BXVGADevice::set_y_offset(int y_offset) { - ASSERT(offset <= m_framebuffer_height); - set_register(VBE_DISPI_INDEX_Y_OFFSET, (u16)offset); + ASSERT(y_offset == 0 || y_offset == m_framebuffer_height); + m_y_offset = y_offset; + set_register(VBE_DISPI_INDEX_Y_OFFSET, (u16)y_offset); } u32 BXVGADevice::find_framebuffer_address() @@ -90,7 +86,7 @@ KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, Virtual { ASSERT(offset == 0); ASSERT(size == framebuffer_size_in_bytes()); - auto vmo = AnonymousVMObject::create_for_physical_range(framebuffer_address(), framebuffer_size_in_bytes()); + auto vmo = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); auto* region = process.allocate_region_with_vmo( preferred_vaddr, framebuffer_size_in_bytes(), @@ -100,7 +96,7 @@ KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, Virtual prot); kprintf("BXVGA: %s(%u) created Region{%p} with size %u for framebuffer P%x with vaddr L%x\n", process.name().characters(), process.pid(), - region, region->size(), framebuffer_address().as_ptr(), region->vaddr().get()); + region, region->size(), m_framebuffer_address.as_ptr(), region->vaddr().get()); ASSERT(region); return region; } @@ -108,16 +104,43 @@ KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, Virtual int BXVGADevice::ioctl(FileDescription&, unsigned request, unsigned arg) { switch (request) { - case BXVGA_DEV_IOCTL_SET_Y_OFFSET: - if (arg > (unsigned)m_framebuffer_height * 2) + case FB_IOCTL_GET_SIZE_IN_BYTES: { + auto* out = (size_t*)arg; + if (!current->process().validate_write_typed(out)) + return -EFAULT; + *out = framebuffer_size_in_bytes(); + return 0; + } + case FB_IOCTL_GET_BUFFER: { + auto* index = (int*)arg; + if (!current->process().validate_write_typed(index)) + return -EFAULT; + *index = m_y_offset == 0 ? 0 : 1; + return 0; + } + case FB_IOCTL_SET_BUFFER: { + if (arg != 0 && arg != 1) return -EINVAL; - set_y_offset((int)arg); + set_y_offset(arg == 0 ? 0 : m_framebuffer_height); return 0; - case BXVGA_DEV_IOCTL_SET_RESOLUTION: { - auto* resolution = (const BXVGAResolution*)arg; - if (!current->process().validate_read_typed(resolution)) + } + case FB_IOCTL_GET_RESOLUTION: { + auto* resolution = (FBResolution*)arg; + if (!current->process().validate_write_typed(resolution)) + return -EFAULT; + resolution->pitch = m_framebuffer_pitch; + resolution->width = m_framebuffer_width; + resolution->height = m_framebuffer_height; + return 0; + } + case FB_IOCTL_SET_RESOLUTION: { + auto* resolution = (FBResolution*)arg; + if (!current->process().validate_read_typed(resolution) || !current->process().validate_write_typed(resolution)) return -EFAULT; set_resolution(resolution->width, resolution->height); + resolution->pitch = m_framebuffer_pitch; + resolution->width = m_framebuffer_width; + resolution->height = m_framebuffer_height; return 0; } default: diff --git a/Kernel/Devices/BXVGADevice.h b/Kernel/Devices/BXVGADevice.h index 6a3c040789..30a5c7a03c 100644 --- a/Kernel/Devices/BXVGADevice.h +++ b/Kernel/Devices/BXVGADevice.h @@ -12,17 +12,9 @@ public: BXVGADevice(); - PhysicalAddress framebuffer_address() const { return m_framebuffer_address; } - void set_resolution(int width, int height); - void set_y_offset(int); - virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t, int prot) override; - size_t framebuffer_size_in_bytes() const { return m_framebuffer_width * m_framebuffer_height * sizeof(u32) * 2; } - int framebuffer_width() const { return m_framebuffer_width; } - int framebuffer_height() const { return m_framebuffer_height; } - private: virtual const char* class_name() const override { return "BXVGA"; } virtual bool can_read(FileDescription&) const override; @@ -32,8 +24,13 @@ private: void set_register(u16 index, u16 value); u32 find_framebuffer_address(); + size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height * 2; } + void set_resolution(int width, int height); + void set_y_offset(int); PhysicalAddress m_framebuffer_address; + int m_framebuffer_pitch { 0 }; int m_framebuffer_width { 0 }; int m_framebuffer_height { 0 }; + int m_y_offset { 0 }; }; |