DisplayConnector.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Arch/x86/IO.h>
  7. #include <Kernel/Debug.h>
  8. #include <Kernel/Devices/DeviceManagement.h>
  9. #include <Kernel/Graphics/Console/ContiguousFramebufferConsole.h>
  10. #include <Kernel/Graphics/GraphicsManagement.h>
  11. #include <Kernel/Graphics/VGA/DisplayConnector.h>
  12. namespace Kernel {
  13. NonnullRefPtr<GenericDisplayConnector> GenericDisplayConnector::must_create_with_preset_resolution(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
  14. {
  15. auto device_or_error = DeviceManagement::try_create_device<GenericDisplayConnector>(framebuffer_address, width, height, pitch);
  16. VERIFY(!device_or_error.is_error());
  17. auto connector = device_or_error.release_value();
  18. MUST(connector->create_attached_framebuffer_console());
  19. MUST(connector->initialize_edid_for_generic_monitor());
  20. return connector;
  21. }
  22. GenericDisplayConnector::GenericDisplayConnector(PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
  23. : DisplayConnector()
  24. , m_framebuffer_address(framebuffer_address)
  25. {
  26. m_current_mode_setting.horizontal_active = width;
  27. m_current_mode_setting.vertical_active = height;
  28. m_current_mode_setting.horizontal_stride = pitch;
  29. }
  30. ErrorOr<void> GenericDisplayConnector::create_attached_framebuffer_console()
  31. {
  32. auto width = m_current_mode_setting.horizontal_active;
  33. auto height = m_current_mode_setting.vertical_active;
  34. auto pitch = m_current_mode_setting.horizontal_stride;
  35. auto rounded_size = TRY(Memory::page_round_up(pitch * height));
  36. m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite));
  37. [[maybe_unused]] auto result = m_framebuffer_region->set_write_combine(true);
  38. m_framebuffer_data = m_framebuffer_region->vaddr().offset(m_framebuffer_address.offset_in_page()).as_ptr();
  39. m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(m_framebuffer_address, width, height, pitch);
  40. GraphicsManagement::the().set_console(*m_framebuffer_console);
  41. return {};
  42. }
  43. ErrorOr<size_t> GenericDisplayConnector::write_to_first_surface(u64 offset, UserOrKernelBuffer const& buffer, size_t length)
  44. {
  45. VERIFY(m_control_lock.is_locked());
  46. if (offset + length > m_framebuffer_region->size())
  47. return Error::from_errno(EOVERFLOW);
  48. TRY(buffer.read(m_framebuffer_data + offset, 0, length));
  49. return length;
  50. }
  51. void GenericDisplayConnector::enable_console()
  52. {
  53. VERIFY(m_control_lock.is_locked());
  54. VERIFY(m_framebuffer_console);
  55. m_framebuffer_console->enable();
  56. }
  57. void GenericDisplayConnector::disable_console()
  58. {
  59. VERIFY(m_control_lock.is_locked());
  60. VERIFY(m_framebuffer_console);
  61. m_framebuffer_console->disable();
  62. }
  63. ErrorOr<void> GenericDisplayConnector::flush_first_surface()
  64. {
  65. return Error::from_errno(ENOTSUP);
  66. }
  67. }