blob: b08a2db1793b7eb49ebef83b13cdb17f2fa232fd [file] [log] [blame]
// Copyright 2024 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 LIB_DRIVER_FAKE_MMIO_REG_CPP_FAKE_MMIO_REG_H_
#define LIB_DRIVER_FAKE_MMIO_REG_CPP_FAKE_MMIO_REG_H_
#include <lib/fit/function.h>
#include <lib/mmio-ptr/fake.h>
#include <lib/mmio/mmio.h>
#include <vector>
namespace fake_mmio {
// Fakes a single MMIO register. This class is intended to be used with a fdf::MmioBuffer;
// operations on an instance of that class will be directed to the fake if the fake-mmio-reg library
// is a dependency of the test.
class FakeMmioReg {
public:
// Reads from the faked register. Returns the value set by the next expectation, or the default
// value. The default is initially zero and can be set by calling ReadReturns() or Write(). This
// method is expected to be called (indirectly) by the code under test.
FakeMmioReg() {
read_ = []() { return 0; };
write_ = [](uint64_t value) {};
}
// Ses the read callback function. The function is invoked every time the faked register is read.
void SetReadCallback(fit::function<uint64_t()> read) { read_ = std::move(read); }
// Sets the write callback function. The function is invoked every time the faked register is
// written.
void SetWriteCallback(fit::function<void(uint64_t)> write) { write_ = std::move(write); }
// Reads the faked register by calling the read callback and returning its value.
uint64_t Read() { return read_(); }
// Writes to the faked register. This method is expected to be called (indirectly) by the code
// under test.
void Write(uint64_t value) { write_(value); }
private:
// Callback functions for read and write operations.
fit::function<void(uint64_t value)> write_;
fit::function<uint64_t()> read_;
};
// Represents a region of fake MMIO registers. Each register is backed by a FakeMmioReg instance.
//
// Example:
// fake_mmio::FakeMmioRegRegion fake_registers(register_size, number_of_registers);
// fdf::MmioBuffer mmio_buffer(fake_registers.GetMmioBuffer());
// fake_registers[0].SetReadCallback(read_fn);
// fake_registers[0].SetWriteCallback(write_fn);
// SomeDriver dut(mmio_buffer);
//
// dut.DoSomeWork(); // backed by mmio_buffer.
class FakeMmioRegRegion {
public:
// Constructs a FakeMmioRegRegion backed by the given array. reg_size is the size of each
// register in bytes, and reg_count is the total number of registers.
FakeMmioRegRegion(size_t reg_size, size_t reg_count)
: reg_size_(reg_size), reg_count_(reg_count) {
ZX_ASSERT(reg_size_ > 0);
regs_.resize(reg_count_);
}
// Accesses the FakeMmioReg at the given offset. Note that this is the byte offset of the region
// of MMIO registers, not the index. The accessed FakeMmioReg will be at the index calculated by
// |offset| / |reg_size_|
const FakeMmioReg& operator[](size_t offset) const {
ZX_ASSERT(offset / reg_size_ < reg_count_);
return regs_[offset / reg_size_];
}
// Accesses the FakeMmioReg at the given offset. Note that this is the byte offset of the region
// of MMIO registers, not the index. The accessed FakeMmioReg will be at the index calculated by
// |offset| / |reg_size_|
FakeMmioReg& operator[](size_t offset) {
ZX_ASSERT(offset / reg_size_ < reg_count_);
return regs_[offset / reg_size_];
}
// Constructs and returns a MmioBuffer object with a size that matches the FakeMmioReg.
fdf::MmioBuffer GetMmioBuffer();
private:
static uint8_t Read8(const void* ctx, const mmio_buffer_t& mmio, zx_off_t offs);
static uint16_t Read16(const void* ctx, const mmio_buffer_t& mmio, zx_off_t offs);
static uint32_t Read32(const void* ctx, const mmio_buffer_t& mmio, zx_off_t offs);
static uint64_t Read64(const void* ctx, const mmio_buffer_t& mmio, zx_off_t offs);
static void Write8(const void* ctx, const mmio_buffer_t& mmio, uint8_t val, zx_off_t offs);
static void Write16(const void* ctx, const mmio_buffer_t& mmio, uint16_t val, zx_off_t offs);
static void Write32(const void* ctx, const mmio_buffer_t& mmio, uint32_t val, zx_off_t offs);
static void Write64(const void* ctx, const mmio_buffer_t& mmio, uint64_t val, zx_off_t offs);
std::vector<FakeMmioReg> regs_;
const size_t reg_size_;
const size_t reg_count_;
};
} // namespace fake_mmio
#endif // LIB_DRIVER_FAKE_MMIO_REG_CPP_FAKE_MMIO_REG_H_