diff options
author | Liav A <liavalb@gmail.com> | 2022-12-17 21:15:31 +0200 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-01-07 11:51:13 -0700 |
commit | 72b144e9e92605d48c83d6ad568add588ab0d32e (patch) | |
tree | 1670a24058161fe88edd73c7c8bc6710e961af0c /Kernel/Graphics | |
parent | 7625f7db739d7ce4e0b398e1f3d555960304366d (diff) | |
download | serenity-72b144e9e92605d48c83d6ad568add588ab0d32e.zip |
Kernel/Graphics: Introduce a new mechanism to initialize a PCI device
Instead of using a clunky switch-case paradigm, we now have all drivers
being declaring two methods for their adapter class - create and probe.
These methods are linked in each PCIGraphicsDriverInitializer structure,
in a new s_initializers static list of them.
Then, when we probe for a PCI device, we use each probe method and if
there's a match, then the corresponding create method is called.
As a result of this change, it's much more easy to add more drivers and
the initialization code is more readable.
Diffstat (limited to 'Kernel/Graphics')
-rw-r--r-- | Kernel/Graphics/Bochs/GraphicsAdapter.cpp | 18 | ||||
-rw-r--r-- | Kernel/Graphics/Bochs/GraphicsAdapter.h | 5 | ||||
-rw-r--r-- | Kernel/Graphics/GraphicsManagement.cpp | 58 | ||||
-rw-r--r-- | Kernel/Graphics/GraphicsManagement.h | 2 | ||||
-rw-r--r-- | Kernel/Graphics/Intel/NativeDisplayConnector.cpp | 14 | ||||
-rw-r--r-- | Kernel/Graphics/Intel/NativeDisplayConnector.h | 2 | ||||
-rw-r--r-- | Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp | 16 | ||||
-rw-r--r-- | Kernel/Graphics/Intel/NativeGraphicsAdapter.h | 3 | ||||
-rw-r--r-- | Kernel/Graphics/VMWare/GraphicsAdapter.cpp | 16 | ||||
-rw-r--r-- | Kernel/Graphics/VMWare/GraphicsAdapter.h | 3 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp | 16 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h | 3 |
12 files changed, 85 insertions, 71 deletions
diff --git a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp index 09a23f42f4..2494c6f448 100644 --- a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp +++ b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp @@ -22,17 +22,25 @@ namespace Kernel { -UNMAP_AFTER_INIT NonnullLockRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initialize(PCI::DeviceIdentifier const& pci_device_identifier) +UNMAP_AFTER_INIT ErrorOr<bool> BochsGraphicsAdapter::probe(PCI::DeviceIdentifier const& pci_device_identifier) { PCI::HardwareID id = pci_device_identifier.hardware_id(); - VERIFY((id.vendor_id == PCI::VendorID::QEMUOld && id.device_id == 0x1111) || (id.vendor_id == PCI::VendorID::VirtualBox && id.device_id == 0xbeef)); - auto adapter = adopt_lock_ref(*new BochsGraphicsAdapter(pci_device_identifier)); + if (id.vendor_id == PCI::VendorID::QEMUOld && id.device_id == 0x1111) + return true; + if (id.vendor_id == PCI::VendorID::VirtualBox && id.device_id == 0xbeef) + return true; + return false; +} + +UNMAP_AFTER_INIT ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> BochsGraphicsAdapter::create(PCI::DeviceIdentifier const& pci_device_identifier) +{ + auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) BochsGraphicsAdapter(pci_device_identifier.address()))); MUST(adapter->initialize_adapter(pci_device_identifier)); return adapter; } -UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::DeviceIdentifier const& pci_device_identifier) - : PCI::Device(pci_device_identifier.address()) +UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::Address const& address) + : PCI::Device(address) { } diff --git a/Kernel/Graphics/Bochs/GraphicsAdapter.h b/Kernel/Graphics/Bochs/GraphicsAdapter.h index 5fca7601a1..b865c40553 100644 --- a/Kernel/Graphics/Bochs/GraphicsAdapter.h +++ b/Kernel/Graphics/Bochs/GraphicsAdapter.h @@ -24,14 +24,15 @@ class BochsGraphicsAdapter final : public GenericGraphicsAdapter friend class GraphicsManagement; public: - static NonnullLockRefPtr<BochsGraphicsAdapter> initialize(PCI::DeviceIdentifier const&); + static ErrorOr<bool> probe(PCI::DeviceIdentifier const&); + static ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> create(PCI::DeviceIdentifier const&); virtual ~BochsGraphicsAdapter() = default; virtual StringView device_name() const override { return "BochsGraphicsAdapter"sv; } private: ErrorOr<void> initialize_adapter(PCI::DeviceIdentifier const&); - explicit BochsGraphicsAdapter(PCI::DeviceIdentifier const&); + explicit BochsGraphicsAdapter(PCI::Address const&); LockRefPtr<DisplayConnector> m_display_connector; }; diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp index a65e69d58f..3fc595d4e2 100644 --- a/Kernel/Graphics/GraphicsManagement.cpp +++ b/Kernel/Graphics/GraphicsManagement.cpp @@ -120,40 +120,35 @@ static inline bool is_display_controller_pci_device(PCI::DeviceIdentifier const& return device_identifier.class_code().value() == 0x3; } -UNMAP_AFTER_INIT bool GraphicsManagement::determine_and_initialize_graphics_device(PCI::DeviceIdentifier const& device_identifier) +struct PCIGraphicsDriverInitializer { + ErrorOr<bool> (*probe)(PCI::DeviceIdentifier const&) = nullptr; + ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> (*create)(PCI::DeviceIdentifier const&) = nullptr; +}; + +static constexpr PCIGraphicsDriverInitializer s_initializers[] = { + { IntelNativeGraphicsAdapter::probe, IntelNativeGraphicsAdapter::create }, + { BochsGraphicsAdapter::probe, BochsGraphicsAdapter::create }, + { VirtIOGraphicsAdapter::probe, VirtIOGraphicsAdapter::create }, + { VMWareGraphicsAdapter::probe, VMWareGraphicsAdapter::create }, +}; + +UNMAP_AFTER_INIT ErrorOr<void> GraphicsManagement::determine_and_initialize_graphics_device(PCI::DeviceIdentifier const& device_identifier) { VERIFY(is_vga_compatible_pci_device(device_identifier) || is_display_controller_pci_device(device_identifier)); - LockRefPtr<GenericGraphicsAdapter> adapter; - - if (!adapter) { - switch (device_identifier.hardware_id().vendor_id) { - case PCI::VendorID::QEMUOld: - if (device_identifier.hardware_id().device_id == 0x1111) - adapter = BochsGraphicsAdapter::initialize(device_identifier); - break; - case PCI::VendorID::VirtualBox: - if (device_identifier.hardware_id().device_id == 0xbeef) - adapter = BochsGraphicsAdapter::initialize(device_identifier); - break; - case PCI::VendorID::Intel: - adapter = IntelNativeGraphicsAdapter::initialize(device_identifier); - break; - case PCI::VendorID::VirtIO: - dmesgln("Graphics: Using VirtIO console"); - adapter = VirtIOGraphicsAdapter::initialize(device_identifier); - break; - case PCI::VendorID::VMWare: - adapter = VMWareGraphicsAdapter::try_initialize(device_identifier); - break; - default: - break; + for (auto& initializer : s_initializers) { + auto initializer_probe_found_driver_match_or_error = initializer.probe(device_identifier); + if (initializer_probe_found_driver_match_or_error.is_error()) { + dmesgln("Graphics: Failed to probe device {}, due to {}", device_identifier.address(), initializer_probe_found_driver_match_or_error.error()); + continue; + } + auto initializer_probe_found_driver_match = initializer_probe_found_driver_match_or_error.release_value(); + if (initializer_probe_found_driver_match) { + auto adapter = TRY(initializer.create(device_identifier)); + TRY(m_graphics_devices.try_append(*adapter)); + return {}; } } - - if (!adapter) - return false; - m_graphics_devices.append(*adapter); - return true; + return {}; } UNMAP_AFTER_INIT void GraphicsManagement::initialize_preset_resolution_generic_display_connector() @@ -239,7 +234,8 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize() // framebuffer console will take the control instead. if (!is_vga_compatible_pci_device(device_identifier) && !is_display_controller_pci_device(device_identifier)) return; - determine_and_initialize_graphics_device(device_identifier); + if (auto result = determine_and_initialize_graphics_device(device_identifier); result.is_error()) + dbgln("Failed to initialize device {}, due to {}", device_identifier.address(), result.error()); })); // Note: If we failed to find any graphics device to be used natively, but the diff --git a/Kernel/Graphics/GraphicsManagement.h b/Kernel/Graphics/GraphicsManagement.h index ec771c6528..ee30adf3ce 100644 --- a/Kernel/Graphics/GraphicsManagement.h +++ b/Kernel/Graphics/GraphicsManagement.h @@ -50,7 +50,7 @@ public: private: void enable_vga_text_mode_console_cursor(); - bool determine_and_initialize_graphics_device(PCI::DeviceIdentifier const&); + ErrorOr<void> determine_and_initialize_graphics_device(PCI::DeviceIdentifier const&); void initialize_preset_resolution_generic_display_connector(); diff --git a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp index 4ce94adf0c..260839d436 100644 --- a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp +++ b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp @@ -175,20 +175,18 @@ Optional<IntelGraphics::PLLSettings> IntelNativeDisplayConnector::create_pll_set return {}; } -NonnullLockRefPtr<IntelNativeDisplayConnector> IntelNativeDisplayConnector::must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length) +ErrorOr<NonnullLockRefPtr<IntelNativeDisplayConnector>> IntelNativeDisplayConnector::try_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length) { - auto registers_region = MUST(MM.allocate_kernel_region(PhysicalAddress(registers_region_address), registers_region_length, "Intel Native Graphics Registers"sv, Memory::Region::Access::ReadWrite)); - auto device_or_error = DeviceManagement::try_create_device<IntelNativeDisplayConnector>(framebuffer_address, framebuffer_resource_size, move(registers_region)); - VERIFY(!device_or_error.is_error()); - auto connector = device_or_error.release_value(); - MUST(connector->initialize_gmbus_settings_and_read_edid()); + auto registers_region = TRY(MM.allocate_kernel_region(PhysicalAddress(registers_region_address), registers_region_length, "Intel Native Graphics Registers"sv, Memory::Region::Access::ReadWrite)); + auto connector = TRY(DeviceManagement::try_create_device<IntelNativeDisplayConnector>(framebuffer_address, framebuffer_resource_size, move(registers_region))); + TRY(connector->initialize_gmbus_settings_and_read_edid()); // Note: This is very important to set the resolution to something safe so we // can create a framebuffer console with valid resolution. { SpinlockLocker control_lock(connector->m_control_lock); - MUST(connector->set_safe_mode_setting()); + TRY(connector->set_safe_mode_setting()); } - MUST(connector->create_attached_framebuffer_console()); + TRY(connector->create_attached_framebuffer_console()); return connector; } diff --git a/Kernel/Graphics/Intel/NativeDisplayConnector.h b/Kernel/Graphics/Intel/NativeDisplayConnector.h index 0cd60a4358..d8649d08f6 100644 --- a/Kernel/Graphics/Intel/NativeDisplayConnector.h +++ b/Kernel/Graphics/Intel/NativeDisplayConnector.h @@ -81,7 +81,7 @@ class IntelNativeDisplayConnector final friend class DeviceManagement; public: - static NonnullLockRefPtr<IntelNativeDisplayConnector> must_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length); + static ErrorOr<NonnullLockRefPtr<IntelNativeDisplayConnector>> try_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length); private: // ^DisplayConnector diff --git a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp index f410fceb75..6e583a0d58 100644 --- a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp +++ b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp @@ -26,13 +26,15 @@ static bool is_supported_model(u16 device_id) return false; } -LockRefPtr<IntelNativeGraphicsAdapter> IntelNativeGraphicsAdapter::initialize(PCI::DeviceIdentifier const& pci_device_identifier) +ErrorOr<bool> IntelNativeGraphicsAdapter::probe(PCI::DeviceIdentifier const& pci_device_identifier) { - VERIFY(pci_device_identifier.hardware_id().vendor_id == 0x8086); - if (!is_supported_model(pci_device_identifier.hardware_id().device_id)) - return {}; - auto adapter = adopt_lock_ref(*new IntelNativeGraphicsAdapter(pci_device_identifier.address())); - MUST(adapter->initialize_adapter()); + return is_supported_model(pci_device_identifier.hardware_id().device_id); +} + +ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> IntelNativeGraphicsAdapter::create(PCI::DeviceIdentifier const& pci_device_identifier) +{ + auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) IntelNativeGraphicsAdapter(pci_device_identifier.address()))); + TRY(adapter->initialize_adapter()); return adapter; } @@ -47,7 +49,7 @@ ErrorOr<void> IntelNativeGraphicsAdapter::initialize_adapter() dmesgln_pci(*this, "framebuffer @ {}", PhysicalAddress(PCI::get_BAR2(address))); PCI::enable_bus_mastering(address); - m_display_connector = IntelNativeDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR2(address) & 0xfffffff0), bar2_space_size, PhysicalAddress(PCI::get_BAR0(address) & 0xfffffff0), bar0_space_size); + m_display_connector = TRY(IntelNativeDisplayConnector::try_create(PhysicalAddress(PCI::get_BAR2(address) & 0xfffffff0), bar2_space_size, PhysicalAddress(PCI::get_BAR0(address) & 0xfffffff0), bar0_space_size)); return {}; } diff --git a/Kernel/Graphics/Intel/NativeGraphicsAdapter.h b/Kernel/Graphics/Intel/NativeGraphicsAdapter.h index b7c58dea8a..3cdb170bbc 100644 --- a/Kernel/Graphics/Intel/NativeGraphicsAdapter.h +++ b/Kernel/Graphics/Intel/NativeGraphicsAdapter.h @@ -20,7 +20,8 @@ class IntelNativeGraphicsAdapter final , public PCI::Device { public: - static LockRefPtr<IntelNativeGraphicsAdapter> initialize(PCI::DeviceIdentifier const&); + static ErrorOr<bool> probe(PCI::DeviceIdentifier const&); + static ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> create(PCI::DeviceIdentifier const&); virtual ~IntelNativeGraphicsAdapter() = default; diff --git a/Kernel/Graphics/VMWare/GraphicsAdapter.cpp b/Kernel/Graphics/VMWare/GraphicsAdapter.cpp index 839fe23df5..43f00f3222 100644 --- a/Kernel/Graphics/VMWare/GraphicsAdapter.cpp +++ b/Kernel/Graphics/VMWare/GraphicsAdapter.cpp @@ -20,16 +20,18 @@ namespace Kernel { -UNMAP_AFTER_INIT LockRefPtr<VMWareGraphicsAdapter> VMWareGraphicsAdapter::try_initialize(PCI::DeviceIdentifier const& pci_device_identifier) +ErrorOr<bool> VMWareGraphicsAdapter::probe(PCI::DeviceIdentifier const& pci_device_identifier) { PCI::HardwareID id = pci_device_identifier.hardware_id(); - VERIFY(id.vendor_id == PCI::VendorID::VMWare); // Note: We only support VMWare SVGA II adapter - if (id.device_id != 0x0405) - return {}; - auto registers_io_window = MUST(IOWindow::create_for_pci_device_bar(pci_device_identifier, PCI::HeaderType0BaseRegister::BAR0)); - auto adapter = MUST(adopt_nonnull_lock_ref_or_enomem(new (nothrow) VMWareGraphicsAdapter(pci_device_identifier, move(registers_io_window)))); - MUST(adapter->initialize_adapter()); + return id.vendor_id == PCI::VendorID::VMWare && id.device_id == 0x0405; +} + +ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> VMWareGraphicsAdapter::create(PCI::DeviceIdentifier const& pci_device_identifier) +{ + auto registers_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_device_identifier, PCI::HeaderType0BaseRegister::BAR0)); + auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) VMWareGraphicsAdapter(pci_device_identifier, move(registers_io_window)))); + TRY(adapter->initialize_adapter()); return adapter; } diff --git a/Kernel/Graphics/VMWare/GraphicsAdapter.h b/Kernel/Graphics/VMWare/GraphicsAdapter.h index fd159fb9fa..06c35efaa5 100644 --- a/Kernel/Graphics/VMWare/GraphicsAdapter.h +++ b/Kernel/Graphics/VMWare/GraphicsAdapter.h @@ -26,7 +26,8 @@ class VMWareGraphicsAdapter final friend class GraphicsManagement; public: - static LockRefPtr<VMWareGraphicsAdapter> try_initialize(PCI::DeviceIdentifier const&); + static ErrorOr<bool> probe(PCI::DeviceIdentifier const&); + static ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> create(PCI::DeviceIdentifier const&); virtual ~VMWareGraphicsAdapter() = default; virtual StringView device_name() const override { return "VMWareGraphicsAdapter"sv; } diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp index 5e8872011f..040db751d8 100644 --- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp @@ -22,19 +22,23 @@ namespace Kernel { #define DEVICE_EVENTS_CLEAR 0x4 #define DEVICE_NUM_SCANOUTS 0x8 -NonnullLockRefPtr<VirtIOGraphicsAdapter> VirtIOGraphicsAdapter::initialize(PCI::DeviceIdentifier const& device_identifier) +ErrorOr<bool> VirtIOGraphicsAdapter::probe(PCI::DeviceIdentifier const& device_identifier) +{ + return device_identifier.hardware_id().vendor_id == PCI::VendorID::VirtIO; +} + +ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> VirtIOGraphicsAdapter::create(PCI::DeviceIdentifier const& device_identifier) { - VERIFY(device_identifier.hardware_id().vendor_id == PCI::VendorID::VirtIO); // Setup memory transfer region - auto scratch_space_region = MUST(MM.allocate_contiguous_kernel_region( + auto scratch_space_region = TRY(MM.allocate_contiguous_kernel_region( 32 * PAGE_SIZE, "VirtGPU Scratch Space"sv, Memory::Region::Access::ReadWrite)); - auto active_context_ids = MUST(Bitmap::create(VREND_MAX_CTX, false)); - auto adapter = adopt_lock_ref(*new (nothrow) VirtIOGraphicsAdapter(device_identifier, move(active_context_ids), move(scratch_space_region))); + auto active_context_ids = TRY(Bitmap::create(VREND_MAX_CTX, false)); + auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) VirtIOGraphicsAdapter(device_identifier, move(active_context_ids), move(scratch_space_region)))); adapter->initialize(); - MUST(adapter->initialize_adapter()); + TRY(adapter->initialize_adapter()); return adapter; } diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h index bc6bf22b5e..ec01de1e76 100644 --- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h @@ -37,7 +37,8 @@ class VirtIOGraphicsAdapter final friend class VirtIOGPU3DDevice; public: - static NonnullLockRefPtr<VirtIOGraphicsAdapter> initialize(PCI::DeviceIdentifier const&); + static ErrorOr<bool> probe(PCI::DeviceIdentifier const&); + static ErrorOr<NonnullLockRefPtr<GenericGraphicsAdapter>> create(PCI::DeviceIdentifier const&); virtual void initialize() override; |