blob: 2999e89ed9274b1268e4b82cb3436a5e6b580ef4 [file] [log] [blame]
// Copyright 2018 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_BUS_DRIVERS_PLATFORM_PLATFORM_DEVICE_H_
#define SRC_DEVICES_BUS_DRIVERS_PLATFORM_PLATFORM_DEVICE_H_
#include <fidl/fuchsia.boot.metadata/cpp/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/natural_types.h>
#include <fidl/fuchsia.hardware.platform.device/cpp/wire.h>
#include <lib/driver/compat/cpp/device_server.h>
#include <lib/driver/metadata/cpp/metadata_server.h>
#include <lib/fpromise/promise.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/zx/bti.h>
#include "src/devices/bus/drivers/platform/platform-interrupt.h"
namespace platform_bus {
class PlatformBus;
// This class represents a platform device attached to the platform bus.
// Instances of this class are created by PlatformBus at boot time when the board driver
// calls the platform bus protocol method pbus_device_add().
class PlatformDevice : public fidl::WireServer<fuchsia_hardware_platform_device::Device> {
public:
// Creates a new PlatformDevice instance.
// *flags* contains zero or more PDEV_ADD_* flags from the platform bus protocol.
static zx::result<std::unique_ptr<PlatformDevice>> Create(
fuchsia_hardware_platform_bus::Node node, PlatformBus* bus,
inspect::ComponentInspector& inspector);
explicit PlatformDevice(PlatformBus* bus, inspect::Node inspect_node,
fuchsia_hardware_platform_bus::Node node);
const std::string& name() const { return name_; }
uint32_t vid() const { return vid_; }
uint32_t pid() const { return pid_; }
uint32_t did() const { return did_; }
uint32_t instance_id() const { return instance_id_; }
PlatformBus* bus() { return bus_; }
const PlatformBus* bus() const { return bus_; }
zx::result<> CreateNode();
zx::result<> Init();
struct Mmio {
zx_off_t offset;
uint64_t size;
zx_handle_t vmo;
};
struct DeviceInfo {
uint32_t vid;
uint32_t pid;
uint32_t did;
uint32_t mmio_count;
uint32_t irq_count;
uint32_t bti_count;
uint32_t smc_count;
uint32_t metadata_count;
uint32_t reserved[8];
std::string name;
};
struct BoardInfo {
uint32_t vid;
uint32_t pid;
uint32_t board_revision;
std::string board_name;
};
zx::result<Mmio> GetMmio(uint32_t index) const;
zx::result<zx::interrupt> GetInterrupt(uint32_t index, uint32_t flags);
zx::result<zx::bti> GetBti(uint32_t index) const;
zx::result<zx::resource> GetSmc(uint32_t index) const;
DeviceInfo GetDeviceInfo() const;
BoardInfo GetBoardInfo() const;
// Platform device protocol FIDL implementation.
void GetMmioById(GetMmioByIdRequestView request, GetMmioByIdCompleter::Sync& completer) override;
void GetMmioByName(GetMmioByNameRequestView request,
GetMmioByNameCompleter::Sync& completer) override;
void GetInterruptById(GetInterruptByIdRequestView request,
GetInterruptByIdCompleter::Sync& completer) override;
void GetInterruptByName(GetInterruptByNameRequestView request,
GetInterruptByNameCompleter::Sync& completer) override;
void GetBtiById(GetBtiByIdRequestView request, GetBtiByIdCompleter::Sync& completer) override;
void GetBtiByName(GetBtiByNameRequestView request,
GetBtiByNameCompleter::Sync& completer) override;
void GetSmcById(GetSmcByIdRequestView request, GetSmcByIdCompleter::Sync& completer) override;
void GetSmcByName(GetSmcByNameRequestView request,
GetSmcByNameCompleter::Sync& completer) override;
void GetPowerConfiguration(GetPowerConfigurationCompleter::Sync& completer) override;
void GetNodeDeviceInfo(GetNodeDeviceInfoCompleter::Sync& completer) override;
void GetBoardInfo(GetBoardInfoCompleter::Sync& completer) override;
void GetMetadata(GetMetadataRequestView request, GetMetadataCompleter::Sync& completer) override;
void handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_platform_device::Device> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override;
bool HasInterruptVector(uint32_t vector) const { return interrupt_vectors_.contains(vector); }
bool HasInterruptKoid(zx_koid_t koid) const { return interrupt_koids_.contains(koid); }
zx::event node_token() const {
if (node_token_.has_value()) {
zx::event duplicate;
ZX_ASSERT(node_token_->duplicate(ZX_RIGHT_SAME_RIGHTS, &duplicate) == ZX_OK);
return duplicate;
}
return zx::event();
}
private:
// Allows for `std::string_view`'s to be used when searching an unordered map that uses
// `std::string` as its key.
struct MetadataIdHash {
using hash_type = std::hash<std::string_view>;
using is_transparent = void;
std::size_t operator()(const char* str) const { return hash_type{}(str); }
std::size_t operator()(std::string_view str) const { return hash_type{}(str); }
std::size_t operator()(std::string const& str) const { return hash_type{}(str); }
};
fpromise::promise<inspect::Inspector> InspectNodeCallback() const;
PlatformBus* bus_;
std::string name_;
const uint32_t vid_;
const uint32_t pid_;
const uint32_t did_;
const uint32_t instance_id_;
fidl::Client<fuchsia_driver_framework::NodeController> node_controller_;
fuchsia_hardware_platform_bus::Node node_;
fdf::ServerBindingGroup<fuchsia_hardware_platform_bus::PlatformBus> bus_bindings_;
fidl::ServerBindingGroup<fuchsia_hardware_platform_device::Device> device_bindings_;
std::unordered_map<std::string, std::vector<uint8_t>, MetadataIdHash, std::equal_to<>> metadata_;
std::vector<std::unique_ptr<PlatformInterruptFragment>> fragments_;
// Contains the vectors used when creating interrupts. `interrupt_vectors_`
// must be above `inspector_`. This is to ensure that `interrupt_vectors_` is
// not destructed before `inspector_` is destructed. When `inspector_`
// destructs, it executes a callback that references `interrupt_vectors_`.
std::unordered_set<uint32_t> interrupt_vectors_;
std::unordered_set<zx_koid_t> interrupt_koids_;
// When the node is bound, a node_token_ representing the driver component which bound to the node
// is generated. This can be used to for introspection.
std::optional<zx::event> node_token_;
inspect::Node inspect_node_;
std::unique_ptr<compat::DeviceServer> device_server_;
std::unique_ptr<fdf_metadata::MetadataServer<fuchsia_boot_metadata::SerialNumberMetadata>>
serial_number_metadata_server_;
std::unique_ptr<fdf_metadata::MetadataServer<fuchsia_boot_metadata::PartitionMap>>
partition_map_metadata_server_;
std::unique_ptr<fdf_metadata::MetadataServer<fuchsia_boot_metadata::MacAddressMetadata>>
mac_address_metadata_server_;
};
} // namespace platform_bus
#endif // SRC_DEVICES_BUS_DRIVERS_PLATFORM_PLATFORM_DEVICE_H_