| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVICES_BOARD_LIB_ACPI_MANAGER_H_ |
| #define SRC_DEVICES_BOARD_LIB_ACPI_MANAGER_H_ |
| |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async/cpp/executor.h> |
| #include <lib/zx/status.h> |
| |
| #include <string> |
| #include <unordered_map> |
| |
| #include "src/devices/board/lib/acpi/acpi.h" |
| #include "src/devices/board/lib/acpi/bus-type.h" |
| #include "src/devices/board/lib/acpi/device-builder.h" |
| #include "src/devices/lib/iommu/iommu.h" |
| |
| namespace acpi { |
| |
| // Class that manages ACPI device discovery and publishing. |
| class Manager { |
| public: |
| explicit Manager(Acpi* acpi, iommu::IommuManagerBase* iommu, zx_device_t* acpi_root) |
| : acpi_(acpi), |
| iommu_manager_(iommu), |
| acpi_root_(acpi_root), |
| loop_(&kAsyncLoopConfigNeverAttachToThread), |
| executor_(loop_.dispatcher()) {} |
| |
| ~Manager() { loop_.Shutdown(); } |
| |
| // Walk the ACPI tree, keeping track of each device that's found. |
| acpi::status<> DiscoverDevices(); |
| // Infer information about devices based on their relationships. |
| acpi::status<> ConfigureDiscoveredDevices(); |
| // Publish devices to driver manager. |
| acpi::status<> PublishDevices(zx_device_t* platform_bus); |
| |
| // For devices: get the next unique BTI ID. |
| uint32_t GetNextBtiId() { return next_bti_++; } |
| |
| // For internal and unit test use only. |
| DeviceBuilder* LookupDevice(ACPI_HANDLE handle); |
| zx_status_t StartFidlLoop() { return loop_.StartThread("acpi-fidl-thread"); } |
| |
| Acpi* acpi() { return acpi_; } |
| zx_device_t* acpi_root() { return acpi_root_; } |
| iommu::IommuManagerBase* iommu_manager() { return iommu_manager_; } |
| |
| async_dispatcher_t* fidl_dispatcher() { return loop_.dispatcher(); } |
| async::Executor& executor() { return executor_; } |
| |
| private: |
| // Returns true if the device is not present, and it and its children should be ignored. |
| // Returns false if the device is present and its children can be enumerated. |
| acpi::status<bool> DiscoverDevice(ACPI_HANDLE handle); |
| |
| // Call pci_init for the given device. |
| acpi::status<> PublishPciBus(zx_device_t* platform_bus, DeviceBuilder* device); |
| |
| Acpi* acpi_; |
| iommu::IommuManagerBase* iommu_manager_; |
| zx_device_t* acpi_root_; |
| std::unordered_map<ACPI_HANDLE, DeviceBuilder> devices_; |
| std::unordered_map<ACPI_HANDLE, zx_device_t*> zx_devices_; |
| std::vector<ACPI_HANDLE> device_publish_order_; |
| std::unordered_map<BusType, uint32_t> next_bus_ids_; |
| fidl::Arena<> allocator_; |
| bool published_pci_bus_ = false; |
| async::Loop loop_; |
| async::Executor executor_; |
| uint32_t device_id_ = 1; |
| uint32_t next_bti_ = 0; |
| }; |
| |
| } // namespace acpi |
| |
| #endif // SRC_DEVICES_BOARD_LIB_ACPI_MANAGER_H_ |