blob: 2b6833c290ce66fc8e1f00a4a4869fafa222f709 [file] [log] [blame]
// Copyright 2022 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_ACPI_MULTIPLY_ACPI_MULTIPLY_H_
#define SRC_ACPI_MULTIPLY_ACPI_MULTIPLY_H_
#include <fidl/fuchsia.driver.framework/cpp/markers.h>
#include <fidl/fuchsia.driver.framework/cpp/wire_types.h>
#include <fidl/fuchsia.hardware.acpi/cpp/markers.h>
#include <fidl/sample.acpi.multiply/cpp/wire.h>
#include <lib/async/cpp/irq.h>
#include <lib/driver2/logger.h>
#include <lib/driver2/namespace.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
#include <lib/zx/interrupt.h>
#include <list>
namespace acpi_multiply {
// Sample driver for a virtual "multiplier" device described using ACPI.
class AcpiMultiplyDriver : public fidl::WireServer<sample_acpi_multiply::Device> {
public:
AcpiMultiplyDriver(async_dispatcher_t* dispatcher,
fidl::WireSharedClient<fuchsia_driver_framework::Node> node,
driver::Namespace ns, driver::Logger logger)
: dispatcher_(dispatcher),
node_(std::move(node)),
outgoing_(component::OutgoingDirectory::Create(dispatcher)),
ns_(std::move(ns)),
logger_(std::move(logger)) {}
virtual ~AcpiMultiplyDriver() = default;
static constexpr const char* Name() { return "acpi-multiply"; }
static zx::status<std::unique_ptr<AcpiMultiplyDriver>> Start(
fuchsia_driver_framework::wire::DriverStartArgs& start_args,
fdf::UnownedDispatcher dispatcher,
fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
driver::Logger logger);
// sample.acpi.multiply/Device:
void Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer);
private:
struct Operation {
// Operands to the multiply.
uint32_t a;
uint32_t b;
// Completer.
MultiplyCompleter::Async completer;
};
zx::status<> Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir);
void HandleIrq(async_dispatcher_t* dispatcher, async::IrqBase* irq, zx_status_t status,
const zx_packet_interrupt_t* interrupt);
void DoMultiply(Operation operation) __TA_REQUIRES(completer_lock_);
async_dispatcher_t* const dispatcher_;
std::optional<fdf::MmioBuffer> mmio_;
zx::interrupt irq_;
async::IrqMethod<AcpiMultiplyDriver, &AcpiMultiplyDriver::HandleIrq> irq_method_{this};
fidl::WireSyncClient<fuchsia_hardware_acpi::Device> acpi_;
// TODO(fxbug.dev/99975): This will no longer be necessary once interrupts can be handled without
// spawning a separate dispatcher thread.
std::mutex completer_lock_;
std::optional<MultiplyCompleter::Async> cur_completer_ __TA_GUARDED(completer_lock_);
std::list<Operation> operation_queue_ __TA_GUARDED(completer_lock_);
fidl::WireSharedClient<fuchsia_driver_framework::Node> node_;
component::OutgoingDirectory outgoing_;
driver::Namespace ns_;
driver::Logger logger_;
// Used by the self-test.
fidl::WireClient<sample_acpi_multiply::Device> client_;
};
} // namespace acpi_multiply
#endif /* SRC_ACPI_MULTIPLY_ACPI_MULTIPLY_H_ */