forked from Bananymous/banan-os
Kernel: Implement mmaping for framebuffer device
This commit is contained in:
parent
4275d2ce48
commit
cc572af390
|
@ -21,6 +21,8 @@ namespace Kernel
|
|||
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
||||
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
||||
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||
|
||||
|
@ -44,6 +46,8 @@ namespace Kernel
|
|||
const uint8_t m_bpp;
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_video_buffer;
|
||||
|
||||
friend class FramebufferMemoryRegion;
|
||||
};
|
||||
|
||||
}
|
|
@ -3,6 +3,9 @@
|
|||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
|
||||
#include <sys/framebuffer.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -190,4 +193,86 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
class FramebufferMemoryRegion : public MemoryRegion
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<FramebufferMemoryRegion>> create(PageTable& page_table, size_t size, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||
{
|
||||
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, framebuffer);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||
|
||||
TRY(region->initialize(address_range));
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
~FramebufferMemoryRegion()
|
||||
{
|
||||
m_framebuffer->sync_pixels_full();
|
||||
}
|
||||
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
||||
{
|
||||
if (flags != MS_SYNC)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
if (vaddr < m_vaddr)
|
||||
vaddr = m_vaddr;
|
||||
if (vaddr + size > m_vaddr + m_size)
|
||||
size = (vaddr - m_vaddr) + m_size;
|
||||
|
||||
m_framebuffer->sync_pixels_linear(
|
||||
(vaddr - m_vaddr) / bytes_per_pixel_internal,
|
||||
BAN::Math::div_round_up<uint32_t>((vaddr % bytes_per_pixel_internal) + size, bytes_per_pixel_internal)
|
||||
);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override
|
||||
{
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Returns error if no memory was available
|
||||
// Returns true if page was succesfully allocated
|
||||
// Returns false if page was already allocated
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr) override
|
||||
{
|
||||
vaddr &= PAGE_ADDR_MASK;
|
||||
if (m_page_table.physical_address_of(vaddr))
|
||||
return false;
|
||||
|
||||
paddr_t paddr = PageTable::kernel().physical_address_of(m_framebuffer->m_video_buffer->vaddr() + (vaddr - m_vaddr));
|
||||
m_page_table.map_page_at(paddr, vaddr, m_flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FramebufferMemoryRegion(PageTable& page_table, size_t size, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||
: MemoryRegion(page_table, size, region_type, page_flags)
|
||||
, m_framebuffer(framebuffer)
|
||||
{ }
|
||||
|
||||
private:
|
||||
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FramebufferDevice::mmap_region(PageTable& page_table, off_t offset, size_t len, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags)
|
||||
{
|
||||
if (offset != 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (len > m_video_buffer->size())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (region_type != MemoryRegion::Type::SHARED)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, this));
|
||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue