BochsFramebufferDevice.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Checked.h>
  7. #include <AK/Singleton.h>
  8. #include <Kernel/Debug.h>
  9. #include <Kernel/Graphics/Bochs.h>
  10. #include <Kernel/Graphics/BochsFramebufferDevice.h>
  11. #include <Kernel/IO.h>
  12. #include <Kernel/PCI/Access.h>
  13. #include <Kernel/Process.h>
  14. #include <LibC/errno_numbers.h>
  15. #include <LibC/sys/ioctl_numbers.h>
  16. namespace Kernel {
  17. UNMAP_AFTER_INIT NonnullRefPtr<BochsFramebufferDevice> BochsFramebufferDevice::create(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
  18. {
  19. return adopt_ref(*new BochsFramebufferDevice(adapter, framebuffer_address, pitch, width, height));
  20. }
  21. UNMAP_AFTER_INIT BochsFramebufferDevice::BochsFramebufferDevice(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t width, size_t height, size_t pitch)
  22. : FramebufferDevice(framebuffer_address, width, height, pitch)
  23. , m_bochs_adapter(adapter)
  24. {
  25. m_bochs_adapter->set_safe_resolution();
  26. m_framebuffer_width = 1024;
  27. m_framebuffer_height = 768;
  28. m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
  29. }
  30. void BochsFramebufferDevice::set_y_offset(size_t y_offset)
  31. {
  32. VERIFY(y_offset == 0 || y_offset == m_framebuffer_height);
  33. m_y_offset = y_offset;
  34. m_bochs_adapter->set_y_offset(y_offset);
  35. }
  36. int BochsFramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg)
  37. {
  38. REQUIRE_PROMISE(video);
  39. switch (request) {
  40. case FB_IOCTL_GET_SIZE_IN_BYTES: {
  41. auto* out = (size_t*)arg;
  42. size_t value = framebuffer_size_in_bytes();
  43. if (!copy_to_user(out, &value))
  44. return -EFAULT;
  45. return 0;
  46. }
  47. case FB_IOCTL_GET_BUFFER: {
  48. auto* index = (int*)arg;
  49. int value = m_y_offset == 0 ? 0 : 1;
  50. if (!copy_to_user(index, &value))
  51. return -EFAULT;
  52. return 0;
  53. }
  54. case FB_IOCTL_SET_BUFFER: {
  55. if (arg != 0 && arg != 1)
  56. return -EINVAL;
  57. set_y_offset(arg == 0 ? 0 : m_framebuffer_height);
  58. return 0;
  59. }
  60. case FB_IOCTL_GET_RESOLUTION: {
  61. auto* user_resolution = (FBResolution*)arg;
  62. FBResolution resolution;
  63. resolution.pitch = m_framebuffer_pitch;
  64. resolution.width = m_framebuffer_width;
  65. resolution.height = m_framebuffer_height;
  66. if (!copy_to_user(user_resolution, &resolution))
  67. return -EFAULT;
  68. return 0;
  69. }
  70. case FB_IOCTL_SET_RESOLUTION: {
  71. auto* user_resolution = (FBResolution*)arg;
  72. FBResolution resolution;
  73. if (!copy_from_user(&resolution, user_resolution))
  74. return -EFAULT;
  75. if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT)
  76. return -EINVAL;
  77. if (!m_bochs_adapter->set_resolution(resolution.width, resolution.height)) {
  78. m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
  79. dbgln_if(BXVGA_DEBUG, "Reverting resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
  80. // Note: We try to revert everything back, and if it doesn't work, just assert.
  81. if (!m_bochs_adapter->set_resolution(m_framebuffer_width, m_framebuffer_height)) {
  82. VERIFY_NOT_REACHED();
  83. }
  84. resolution.pitch = m_framebuffer_pitch;
  85. resolution.width = m_framebuffer_width;
  86. resolution.height = m_framebuffer_height;
  87. if (!copy_to_user(user_resolution, &resolution))
  88. return -EFAULT;
  89. return -EINVAL;
  90. }
  91. m_framebuffer_width = resolution.width;
  92. m_framebuffer_height = resolution.height;
  93. m_framebuffer_pitch = m_framebuffer_width * sizeof(u32);
  94. dbgln_if(BXVGA_DEBUG, "New resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height);
  95. resolution.pitch = m_framebuffer_pitch;
  96. resolution.width = m_framebuffer_width;
  97. resolution.height = m_framebuffer_height;
  98. if (!copy_to_user(user_resolution, &resolution))
  99. return -EFAULT;
  100. return 0;
  101. }
  102. default:
  103. return -EINVAL;
  104. };
  105. }
  106. }