GraphicsAdapter.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Atomic.h>
  7. #include <AK/Checked.h>
  8. #include <AK/Try.h>
  9. #include <Kernel/Bus/PCI/API.h>
  10. #include <Kernel/Bus/PCI/IDs.h>
  11. #include <Kernel/Debug.h>
  12. #include <Kernel/Graphics/Bochs/Definitions.h>
  13. #include <Kernel/Graphics/Bochs/DisplayConnector.h>
  14. #include <Kernel/Graphics/Bochs/GraphicsAdapter.h>
  15. #include <Kernel/Graphics/Bochs/QEMUDisplayConnector.h>
  16. #include <Kernel/Graphics/Console/ContiguousFramebufferConsole.h>
  17. #include <Kernel/Graphics/GraphicsManagement.h>
  18. #include <Kernel/Memory/TypedMapping.h>
  19. #include <Kernel/Sections.h>
  20. namespace Kernel {
  21. UNMAP_AFTER_INIT NonnullLockRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initialize(PCI::DeviceIdentifier const& pci_device_identifier)
  22. {
  23. PCI::HardwareID id = pci_device_identifier.hardware_id();
  24. VERIFY((id.vendor_id == PCI::VendorID::QEMUOld && id.device_id == 0x1111) || (id.vendor_id == PCI::VendorID::VirtualBox && id.device_id == 0xbeef));
  25. auto adapter = adopt_lock_ref(*new BochsGraphicsAdapter(pci_device_identifier));
  26. MUST(adapter->initialize_adapter(pci_device_identifier));
  27. return adapter;
  28. }
  29. UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::DeviceIdentifier const& pci_device_identifier)
  30. : PCI::Device(pci_device_identifier.address())
  31. {
  32. }
  33. UNMAP_AFTER_INIT ErrorOr<void> BochsGraphicsAdapter::initialize_adapter(PCI::DeviceIdentifier const& pci_device_identifier)
  34. {
  35. // Note: If we use VirtualBox graphics adapter (which is based on Bochs one), we need to use IO ports
  36. // Note: Bochs (the real bochs graphics adapter in the Bochs emulator) uses revision ID of 0x0
  37. // and doesn't support memory-mapped IO registers.
  38. bool virtual_box_hardware = (pci_device_identifier.hardware_id().vendor_id == 0x80ee && pci_device_identifier.hardware_id().device_id == 0xbeef);
  39. auto bar0_space_size = PCI::get_BAR_space_size(pci_device_identifier.address(), 0);
  40. if (pci_device_identifier.revision_id().value() == 0x0 || virtual_box_hardware) {
  41. m_display_connector = BochsDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), bar0_space_size, virtual_box_hardware);
  42. } else {
  43. auto registers_mapping = TRY(Memory::map_typed_writable<BochsDisplayMMIORegisters volatile>(PhysicalAddress(PCI::get_BAR2(pci_device_identifier.address()) & 0xfffffff0)));
  44. VERIFY(registers_mapping.region);
  45. m_display_connector = QEMUDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), bar0_space_size, move(registers_mapping));
  46. }
  47. // Note: According to Gerd Hoffmann - "The linux driver simply does
  48. // the unblank unconditionally. With bochs-display this is not needed but
  49. // it also has no bad side effect".
  50. // FIXME: If the error is ENOTIMPL, ignore it for now until we implement
  51. // unblank support for VBoxDisplayConnector class too.
  52. auto result = m_display_connector->unblank();
  53. if (result.is_error() && result.error().code() != ENOTIMPL)
  54. return result;
  55. TRY(m_display_connector->set_safe_mode_setting());
  56. return {};
  57. }
  58. }