blob: b20458ee18f4f13f25264c3c7455610c18110731 [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_BLOCK_DRIVERS_AHCI_CONTROLLER_H_
#define SRC_DEVICES_BLOCK_DRIVERS_AHCI_CONTROLLER_H_
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/sync/cpp/completion.h>
#include <lib/zx/time.h>
#include <zircon/types.h>
#include <memory>
#include <mutex>
#include <fbl/condition_variable.h>
#include "ahci.h"
#include "bus.h"
#include "port.h"
namespace ahci {
class Controller : public fdf::DriverBase {
public:
static constexpr char kDriverName[] = "ahci";
Controller(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher dispatcher)
: fdf::DriverBase(kDriverName, std::move(start_args), std::move(dispatcher)) {}
~Controller() = default;
DISALLOW_COPY_ASSIGN_AND_MOVE(Controller);
zx::result<> Start() override;
void PrepareStop(fdf::PrepareStopCompleter completer) __TA_EXCLUDES(lock_) override;
virtual zx::result<std::unique_ptr<Bus>> CreateBus();
// Read or write a 32-bit AHCI controller reg. Endinaness is corrected.
uint32_t RegRead(size_t offset);
zx_status_t RegWrite(size_t offset, uint32_t val);
// Create irq and worker dispatchers.
zx_status_t LaunchIrqAndWorkerDispatchers();
// Release all resources.
void Shutdown() __TA_EXCLUDES(lock_);
zx_status_t HbaReset();
void AhciEnable();
zx_status_t SetDevInfo(uint32_t portnr, SataDeviceInfo* devinfo);
void Queue(uint32_t portnr, SataTransaction* txn);
void SignalWorker() { worker_event_completion_.Signal(); }
inspect::Inspector& inspector() { return inspector_; }
inspect::Node& inspect_node() { return inspect_node_; }
Bus* bus() { return bus_.get(); }
Port* port(uint32_t portnr) { return &ports_[portnr]; }
std::vector<std::unique_ptr<SataDevice>>& sata_devices() { return sata_devices_; }
// Called by children device of this controller for invoking AddChild() or instantiating
// compat::DeviceServer.
fidl::WireSyncClient<fuchsia_driver_framework::Node>& root_node() { return root_node_; }
std::string_view driver_name() const { return name(); }
const std::shared_ptr<fdf::Namespace>& driver_incoming() const { return incoming(); }
std::shared_ptr<fdf::OutgoingDirectory>& driver_outgoing() { return outgoing(); }
const std::optional<std::string>& driver_node_name() const { return node_name(); }
private:
void WorkerLoop();
void IrqLoop();
// Initialize controller and detect devices.
zx_status_t Init();
bool ShouldExit() __TA_EXCLUDES(lock_);
inspect::Inspector inspector_;
inspect::Node inspect_node_;
std::optional<inspect::ComponentInspector> exposed_inspector_;
std::mutex lock_;
bool shutdown_ __TA_GUARDED(lock_) = false;
// Dispatcher for handling interrupt requests.
fdf::Dispatcher irq_dispatcher_;
// Signaled when irq_dispatcher_ is shut down.
libsync::Completion irq_shutdown_completion_;
// Dispatcher for processing queued block requests.
fdf::Dispatcher worker_dispatcher_;
// True when worker_dispatcher_ is shut down.
std::atomic_bool worker_shutdown_;
// Signaled when there is work to be done in the worker loop.
libsync::Completion worker_event_completion_;
std::unique_ptr<Bus> bus_;
Port ports_[AHCI_MAX_PORTS];
std::vector<std::unique_ptr<SataDevice>> sata_devices_;
fidl::WireSyncClient<fuchsia_driver_framework::Node> parent_node_;
fidl::WireSyncClient<fuchsia_driver_framework::Node> root_node_;
fidl::WireSyncClient<fuchsia_driver_framework::NodeController> node_controller_;
};
} // namespace ahci
#endif // SRC_DEVICES_BLOCK_DRIVERS_AHCI_CONTROLLER_H_