blob: 0992efd108d4e50b7a07291a09816098b0a21ca6 [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.
#ifndef SRC_DEVICES_BUS_TESTING_FAKE_PDEV_FAKE_PDEV_H_
#define SRC_DEVICES_BUS_TESTING_FAKE_PDEV_FAKE_PDEV_H_
#include <fuchsia/hardware/platform/device/cpp/banjo.h>
#include <lib/fake_ddk/fake_ddk.h>
#include <atomic>
#include <map>
#include <optional>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
namespace fake_pdev {
// This class is thread-safe.
class FakePDev : public ddk::PDevProtocol<FakePDev> {
public:
FakePDev() : proto_({&pdev_protocol_ops_, this}) {}
const pdev_protocol_t* proto() const { return &proto_; }
fake_ddk::FragmentEntry fragment() const;
struct MmioInfo {
zx::vmo vmo;
zx_off_t offset;
size_t size;
};
void set_mmio(uint32_t idx, MmioInfo mmio) {
fbl::AutoLock al(&lock_);
mmios_[idx] = std::move(mmio);
}
void set_bti(uint32_t idx, zx::bti bti) {
fbl::AutoLock al(&lock_);
btis_[idx] = std::move(bti);
}
void set_interrupt(uint32_t idx, zx::interrupt irq) {
fbl::AutoLock al(&lock_);
irqs_[idx] = std::move(irq);
}
void set_smc(uint32_t idx, zx::resource smc) {
fbl::AutoLock al(&lock_);
smcs_[idx] = std::move(smc);
}
// Creates a virtual interrupt and returns an unowned copy to it.
zx::unowned_interrupt CreateVirtualInterrupt(uint32_t idx);
// Generates a fake bti lazily if true.
void UseFakeBti(bool use_fake_bti = true) { use_fake_bti_ = use_fake_bti; }
// Generates a fake smc resource lazily if true.
void UseFakeSmc(bool use_fake_smc = true) { use_fake_smc_ = use_fake_smc; }
void set_device_info(std::optional<pdev_device_info_t> info) {
fbl::AutoLock al(&lock_);
device_info_ = info;
}
void set_board_info(std::optional<pdev_board_info_t> info) {
fbl::AutoLock al(&lock_);
board_info_ = info;
}
// PDev protocol implementation.
zx_status_t PDevGetMmio(uint32_t index, pdev_mmio_t* out_mmio);
zx_status_t PDevGetBti(uint32_t index, zx::bti* out_bti);
zx_status_t PDevGetSmc(uint32_t index, zx::resource* out_resource);
zx_status_t PDevGetInterrupt(uint32_t index, uint32_t flags, zx::interrupt* out_irq);
zx_status_t PDevGetDeviceInfo(pdev_device_info_t* out_info);
zx_status_t PDevGetBoardInfo(pdev_board_info_t* out_info);
private:
pdev_protocol_t proto_;
fbl::Mutex lock_;
std::map<uint32_t, MmioInfo> mmios_ __TA_GUARDED(lock_);
std::map<uint32_t, zx::interrupt> irqs_ __TA_GUARDED(lock_);
std::map<uint32_t, zx::bti> btis_ __TA_GUARDED(lock_);
std::map<uint32_t, zx::resource> smcs_ __TA_GUARDED(lock_);
std::atomic<bool> use_fake_bti_ = false;
std::atomic<bool> use_fake_smc_ = false;
std::optional<pdev_device_info_t> device_info_ __TA_GUARDED(lock_);
std::optional<pdev_board_info_t> board_info_ __TA_GUARDED(lock_);
};
} // namespace fake_pdev
#endif // SRC_DEVICES_BUS_TESTING_FAKE_PDEV_FAKE_PDEV_H_