blob: 3fccc73141ebcab97aa47b5cbc7f0b579f4f6008 [file]
// 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/zx/result.h>
#include <zircon/types.h>
#include <mutex>
#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/board/lib/acpi/power-resource.h"
#include "src/devices/lib/iommu/iommu.h"
namespace async {
class Executor;
}
namespace acpi_host_test {
class AcpiHostTest;
}
namespace acpi {
// Class that manages ACPI device discovery and publishing.
class Manager {
public:
// Construct a new manager.
// |acpi| should be a pointer to the ACPI implementation to use. The caller keeps ownership and
// must ensure it outlives the manager.
// |iommu| should be a pointer to the IOMMU manager implementation. The caller keeps ownership and
// must ensure it outlives the manager.
// |acpi_root| is a pointer to the device that will be the parent of all other ACPI devices. It
// should be owned by the DDK, and must outlive the manager.
explicit Manager(Acpi* acpi, iommu::IommuManagerInterface* iommu, zx_device_t* acpi_root)
: acpi_(acpi), iommu_manager_(iommu), acpi_root_(acpi_root) {}
virtual ~Manager() = default;
// 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, async_dispatcher_t* device_dispatcher);
// For devices: get the next unique BTI ID.
uint32_t GetNextBtiId() { return next_bti_++; }
// Get next unique ID for the enumerated composite.
uint32_t GetNextCompositeId(std::string composite);
// Used by a device to inform the manager about the existence of a power resource.
const PowerResource* AddPowerResource(ACPI_HANDLE power_resource_handle);
// Used by a device to declare that it requires a list of power resources to be on.
// The list of power resources should be sorted by ascending resource_order.
zx_status_t ReferencePowerResources(const std::vector<ACPI_HANDLE>& power_resource_handles);
// Used by a device to declare that it no longer requires a list of power resources to be on.
// The list of power resources should be sorted by ascending resource_order.
zx_status_t DereferencePowerResources(const std::vector<ACPI_HANDLE>& power_resource_handles);
// For internal and unit test use only.
DeviceBuilder* LookupDevice(ACPI_HANDLE handle);
Acpi* acpi() { return acpi_; }
zx_device_t* acpi_root() { return acpi_root_; }
iommu::IommuManagerInterface* iommu_manager() { return iommu_manager_; }
private:
friend acpi_host_test::AcpiHostTest;
// 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::IommuManagerInterface* iommu_manager_;
zx_device_t* acpi_root_;
std::unordered_map<ACPI_HANDLE, DeviceBuilder> devices_;
std::unordered_map<ACPI_HANDLE, zx_device_t*> zx_devices_;
// Contains a map of acpi name and the id for the next composite with the same name.
// The id is incremented each time a composite added for the acpi name.
std::unordered_map<std::string, uint32_t> composite_list_;
std::mutex power_resource_lock_;
std::unordered_map<ACPI_HANDLE, PowerResource> power_resources_
__TA_GUARDED(power_resource_lock_);
std::vector<ACPI_HANDLE> device_publish_order_;
std::unordered_map<BusType, uint32_t> next_bus_ids_;
bool published_pci_bus_ = false;
uint32_t device_id_ = 1;
uint32_t next_bti_ = 0;
uint32_t next_i2c_global_id_ = 0;
uint32_t next_spi_global_id_ = 0;
};
} // namespace acpi
#endif // SRC_DEVICES_BOARD_LIB_ACPI_MANAGER_H_