blob: 5c80f9413675b72f4ec1a154878b2b6fa87e0d75 [file] [log] [blame]
// Copyright 2019 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_BOARD_DRIVERS_X86_X86_H_
#define SRC_DEVICES_BOARD_DRIVERS_X86_X86_H_
#include <fidl/fuchsia.acpi.tables/cpp/wire.h>
#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/fidl/cpp/channel.h>
#include <threads.h>
#include <memory>
#include <ddktl/device.h>
#include <fbl/macros.h>
#include <fbl/vector.h>
#include "src/devices/board/lib/acpi/acpi.h"
#include "src/devices/board/lib/acpi/manager.h"
#include "src/devices/lib/iommu/iommu-x86.h"
namespace x86 {
class SysSuspender : public fidl::WireServer<fuchsia_hardware_platform_bus::SysSuspend> {
public:
explicit SysSuspender(zx_device_t* device) : device_(device) {}
void Callback(CallbackRequestView request, CallbackCompleter::Sync& completer) override;
private:
zx_device_t* device_;
};
class X86;
using DeviceType =
ddk::Device<X86, ddk::Messageable<fuchsia_acpi_tables::Tables>::Mixin, ddk::Initializable>;
// This is the main class for the X86 platform bus driver.
class X86 : public DeviceType {
public:
explicit X86(zx_device_t* parent, fdf::ClientEnd<fuchsia_hardware_platform_bus::PlatformBus> pbus,
std::unique_ptr<acpi::Acpi> acpi)
: DeviceType(parent), pbus_(std::move(pbus)), acpi_(std::move(acpi)), suspender_(parent) {}
~X86();
static zx_status_t Create(void* ctx, zx_device_t* parent, std::unique_ptr<X86>* out);
static zx_status_t CreateAndBind(void* ctx, zx_device_t* parent);
static bool RunUnitTests(void* ctx, zx_device_t* parent, zx_handle_t channel);
// Device protocol implementation.
void DdkRelease();
void DdkInit(ddk::InitTxn txn);
// ACPI tables protocol FIDL interface implementation.
void ListTableEntries(ListTableEntriesCompleter::Sync& completer) override;
void ReadNamedTable(ReadNamedTableRequestView request,
ReadNamedTableCompleter::Sync& completer) override;
// Performs ACPICA initialization.
zx_status_t EarlyAcpiInit();
zx_status_t EarlyInit();
// Add the list of ACPI entries present in the system to |entries|.
//
// Requires that ACPI has been initialised.
zx_status_t GetAcpiTableEntries(fbl::Vector<fuchsia_acpi_tables::wire::TableInfo>* entries);
acpi::Acpi* acpi() { return acpi_.get(); }
private:
X86(const X86&) = delete;
X86(X86&&) = delete;
X86& operator=(const X86&) = delete;
X86& operator=(X86&&) = delete;
zx_status_t SysmemInit();
zx_status_t GoldfishControlInit();
// Register this instance with devmgr.
zx_status_t Bind();
// Asynchronously complete initialisation.
zx_status_t DoInit();
IommuManager iommu_manager_{
[](fx_log_severity_t severity, const char* file, int line, const char* msg, va_list args) {
zxlogvf_etc(severity, nullptr, file, line, msg, args);
}};
// TODO(https://fxbug.dev/42059490): migrate to fdf::SyncClient when it is available.
fdf::WireSyncClient<fuchsia_hardware_platform_bus::PlatformBus> pbus_;
std::unique_ptr<acpi::Manager> acpi_manager_;
std::unique_ptr<acpi::Acpi> acpi_;
// Whether the global ACPICA initialization has been performed or not
bool acpica_initialized_ = false;
SysSuspender suspender_;
async::Loop suspender_loop_{&kAsyncLoopConfigNeverAttachToThread};
};
} // namespace x86
#endif // SRC_DEVICES_BOARD_DRIVERS_X86_X86_H_