blob: 201562e8e0625828a38f9cf7d1e3e70f80b925d7 [file] [log] [blame]
// 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.
#include "src/devices/bus/testing/fake-pdev/fake-pdev.h"
#include <lib/device-protocol/pdev-fidl.h>
#include <lib/fake-bti/bti.h>
#include <lib/fake-resource/resource.h>
namespace fake_pdev {
void FakePDevFidl::GetMmioById(GetMmioByIdRequestView request,
GetMmioByIdCompleter::Sync& completer) {
auto mmio = config_.mmios.find(request->index);
if (mmio == config_.mmios.end()) {
completer.ReplyError(ZX_ERR_NOT_FOUND);
return;
}
fidl::Arena arena;
auto builder = fuchsia_hardware_platform_device::wire::Mmio::Builder(arena);
if (auto* mmio_info = std::get_if<MmioInfo>(&mmio->second); mmio_info) {
builder.offset(mmio_info->offset).size(mmio_info->size);
zx::vmo dup;
mmio_info->vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup);
builder.vmo(std::move(dup));
} else {
auto& mmio_buffer = std::get<fdf::MmioBuffer>(mmio->second);
builder.offset(reinterpret_cast<size_t>(&mmio_buffer));
}
completer.ReplySuccess(builder.Build());
}
void FakePDevFidl::GetMmioByName(GetMmioByNameRequestView request,
GetMmioByNameCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}
void FakePDevFidl::GetInterruptById(GetInterruptByIdRequestView request,
GetInterruptByIdCompleter::Sync& completer) {
auto itr = config_.irqs.find(request->index);
if (itr == config_.irqs.end()) {
if (!config_.use_fake_irq) {
completer.ReplyError(ZX_ERR_NOT_FOUND);
return;
}
zx::interrupt irq;
if (zx_status_t status = zx::interrupt::create(zx::resource(), 0, ZX_INTERRUPT_VIRTUAL, &irq);
status != ZX_OK) {
completer.ReplyError(status);
return;
}
return completer.ReplySuccess(std::move(irq));
}
zx::interrupt irq;
itr->second.duplicate(ZX_RIGHT_SAME_RIGHTS, &irq);
completer.ReplySuccess(std::move(irq));
}
void FakePDevFidl::GetInterruptByName(GetInterruptByNameRequestView request,
GetInterruptByNameCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}
void FakePDevFidl::GetBtiById(GetBtiByIdRequestView request, GetBtiByIdCompleter::Sync& completer) {
zx::bti bti;
auto itr = config_.btis.find(request->index);
if (itr == config_.btis.end()) {
if (!config_.use_fake_bti) {
completer.ReplyError(ZX_ERR_NOT_FOUND);
return;
}
zx_status_t status = fake_bti_create(bti.reset_and_get_address());
if (status != ZX_OK) {
completer.ReplyError(status);
return;
}
} else {
itr->second.duplicate(ZX_RIGHT_SAME_RIGHTS, &bti);
}
completer.ReplySuccess(std::move(bti));
}
void FakePDevFidl::GetBtiByName(GetBtiByNameRequestView request,
GetBtiByNameCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}
void FakePDevFidl::GetSmcById(GetSmcByIdRequestView request, GetSmcByIdCompleter::Sync& completer) {
zx::resource smc;
auto itr = config_.smcs.find(request->index);
if (itr == config_.smcs.end()) {
if (!config_.use_fake_smc) {
completer.ReplyError(ZX_ERR_NOT_FOUND);
return;
}
zx_status_t status = fake_root_resource_create(smc.reset_and_get_address());
if (status != ZX_OK) {
completer.ReplyError(status);
return;
}
} else {
itr->second.duplicate(ZX_RIGHT_SAME_RIGHTS, &smc);
}
completer.ReplySuccess(std::move(smc));
}
void FakePDevFidl::GetSmcByName(GetSmcByNameRequestView request,
GetSmcByNameCompleter::Sync& completer) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}
void FakePDevFidl::GetNodeDeviceInfo(GetNodeDeviceInfoCompleter::Sync& completer) {
if (!config_.device_info.has_value()) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
return;
}
pdev_device_info_t& info = config_.device_info.value();
fidl::Arena arena;
completer.ReplySuccess(fuchsia_hardware_platform_device::wire::NodeDeviceInfo::Builder(arena)
.vid(info.vid)
.pid(info.pid)
.did(info.did)
.mmio_count(info.mmio_count)
.irq_count(info.irq_count)
.bti_count(info.bti_count)
.smc_count(info.smc_count)
.metadata_count(info.metadata_count)
.name(info.name)
.Build());
}
void FakePDevFidl::GetBoardInfo(GetBoardInfoCompleter::Sync& completer) {
if (!config_.board_info.has_value()) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
return;
}
pdev_board_info_t& info = config_.board_info.value();
fidl::Arena arena;
completer.ReplySuccess(fuchsia_hardware_platform_device::wire::BoardInfo::Builder(arena)
.vid(info.vid)
.pid(info.pid)
.board_name(info.board_name)
.board_revision(info.board_revision)
.Build());
}
void FakePDevFidl::GetPowerConfiguration(GetPowerConfigurationCompleter::Sync& completer) {
static fidl::Arena arena;
fidl::VectorView<fuchsia_hardware_power::wire::PowerElementConfiguration> value;
value.Allocate(arena, config_.power_elements.size());
for (size_t i = 0; i < config_.power_elements.size(); i++) {
value[i] = fidl::ToWire(arena, config_.power_elements[i]);
}
completer.ReplySuccess(value);
}
void FakePDevFidl::handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_platform_device::Device> metadata,
fidl::UnknownMethodCompleter::Sync& completer) {}
} // namespace fake_pdev
zx_status_t ddk::PDevMakeMmioBufferWeak(const pdev_mmio_t& pdev_mmio,
std::optional<MmioBuffer>* mmio, uint32_t cache_policy) {
if (pdev_mmio.vmo != ZX_HANDLE_INVALID) {
zx::result<MmioBuffer> result =
MmioBuffer::Create(pdev_mmio.offset, pdev_mmio.size, zx::vmo(pdev_mmio.vmo), cache_policy);
if (result.is_ok()) {
mmio->emplace(std::move(result.value()));
}
return result.status_value();
}
auto* mmio_buffer = reinterpret_cast<MmioBuffer*>(pdev_mmio.offset);
mmio->emplace(std::move(*mmio_buffer));
return ZX_OK;
}