// Copyright 2016 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 MSD_INTEL_DEVICE_H
#define MSD_INTEL_DEVICE_H

#include <list>
#include <mutex>
#include <thread>

#include "device_request.h"
#include "engine_command_streamer.h"
#include "global_context.h"
#include "gpu_progress.h"
#include "gtt.h"
#include "interrupt_manager.h"
#include "magma_util/macros.h"
#include "magma_util/register_io.h"
#include "magma_util/thread.h"
#include "msd.h"
#include "msd_intel_connection.h"
#include "msd_intel_pci_device.h"
#include "platform_semaphore.h"
#include "platform_trace.h"
#include "sequencer.h"

class MsdIntelDevice : public msd_device_t,
                       public EngineCommandStreamer::Owner,
                       public Gtt::Owner,
                       public InterruptManager::Owner,
                       public MsdIntelConnection::Owner {
public:
    using DeviceRequest = DeviceRequest<MsdIntelDevice>;

    // Creates a device for the given |device_handle| and returns ownership.
    // If |start_device_thread| is false, then StartDeviceThread should be called
    // to enable device request processing.
    static std::unique_ptr<MsdIntelDevice> Create(void* device_handle, bool start_device_thread);

    virtual ~MsdIntelDevice();

    // This takes ownership of the connection so that ownership can be
    // transferred across the MSD ABI by the caller
    std::unique_ptr<MsdIntelConnection> Open(msd_client_id_t client_id);

    uint32_t device_id() { return device_id_; }
    uint32_t revision() { return revision_; }
    uint32_t subslice_total() { return subslice_total_; }
    uint32_t eu_total() { return eu_total_; }

    static MsdIntelDevice* cast(msd_device_t* dev)
    {
        DASSERT(dev);
        DASSERT(dev->magic_ == kMagic);
        return static_cast<MsdIntelDevice*>(dev);
    }

    bool Init(void* device_handle);

    struct DumpState {
        struct RenderCommandStreamer {
            uint32_t sequence_number;
            uint64_t active_head_pointer;
            std::vector<MappedBatch*> inflight_batches;
        } render_cs;

        bool fault_present;
        uint8_t fault_engine;
        uint8_t fault_src;
        uint8_t fault_type;
        uint64_t fault_gpu_address;
        bool global;
    };

    void Dump(DumpState* dump_state);
    void DumpToString(std::string& dump_string);
    void DumpStatusToLog();

private:
    MsdIntelDevice();

#define CHECK_THREAD_IS_CURRENT(x)                                                                 \
    if (x)                                                                                         \
    DASSERT(magma::ThreadIdCheck::IsCurrent(*x))

#define CHECK_THREAD_NOT_CURRENT(x)                                                                \
    if (x)                                                                                         \
    DASSERT(!magma::ThreadIdCheck::IsCurrent(*x))

    // EngineCommandStreamer::Owner
    magma::RegisterIo* register_io() override
    {
        CHECK_THREAD_IS_CURRENT(device_thread_id_);
        DASSERT(register_io_);
        return register_io_.get();
    }

    // InterruptManager::Owner
    magma::RegisterIo* register_io_for_interrupt() override
    {
        DASSERT(register_io_);
        return register_io_.get();
    }
    magma::PlatformPciDevice* platform_device() override
    {
        DASSERT(platform_device_);
        return platform_device_.get();
    }

    // EngineCommandStreamer::Owner
    Sequencer* sequencer() override
    {
        CHECK_THREAD_IS_CURRENT(device_thread_id_);
        DASSERT(sequencer_);
        return sequencer_.get();
    }

    // EngineCommandStreamer::Owner
    HardwareStatusPage* hardware_status_page(EngineCommandStreamerId id) override;

    void batch_submitted(uint32_t sequence_number) override
    {
        DASSERT(progress_);
        progress_->Submitted(sequence_number, std::chrono::steady_clock::now());
    }

    // MsdIntelConnection::Owner
    magma::Status SubmitBatch(std::unique_ptr<MappedBatch> batch) override;
    void DestroyContext(std::shared_ptr<ClientContext> client_context) override;
    magma::PlatformBusMapper* GetBusMapper() override { return bus_mapper_.get(); }

    void StartDeviceThread();

    void Destroy();

    bool BaseInit(void* device_handle);
    bool RenderEngineInit(bool exec_init_batch);
    bool RenderEngineReset();

    bool InitContextForRender(MsdIntelContext* context);

    void ProcessCompletedCommandBuffers();
    void HangCheckTimeout();

    magma::Status ProcessBatch(std::unique_ptr<MappedBatch> batch);
    magma::Status ProcessDestroyContext(std::shared_ptr<ClientContext> client_context);
    magma::Status ProcessReleaseBuffer(std::shared_ptr<AddressSpace> address_space,
                                       std::shared_ptr<MsdIntelBuffer> buffer);
    magma::Status ProcessInterrupts(uint64_t interrupt_time_ns, uint32_t master_interrupt_control,
                                    uint32_t render_interrupt_status);
    magma::Status ProcessDumpStatusToLog();

    void EnqueueDeviceRequest(std::unique_ptr<DeviceRequest> request, bool enqueue_front = false);

    bool WaitIdle();

    uint32_t GetCurrentFrequency();
    void RequestMaxFreq();

    static void DumpFault(DumpState* dump_out, uint32_t fault);
    static void DumpFaultAddress(DumpState* dump_out, magma::RegisterIo* register_io);
    void FormatDump(DumpState& dump_state, std::string& dump_string);

    int DeviceThreadLoop();
    void FrequencyMonitorDeviceThreadLoop();
    static void InterruptCallback(void* data, uint32_t master_interrupt_control);

    void QuerySliceInfo(uint32_t* subslice_total_out, uint32_t* eu_total_out);

    std::shared_ptr<GlobalContext> global_context() { return global_context_; }

    RenderEngineCommandStreamer* render_engine_cs() { return render_engine_cs_.get(); }

    std::shared_ptr<AddressSpace> gtt() { return gtt_; }

    std::shared_ptr<magma::PlatformBuffer> scratch_buffer() { return scratch_buffer_; }

    static const uint32_t kMagic = 0x64657669; //"devi"

    uint32_t device_id_{};
    uint32_t revision_{};
    uint32_t subslice_total_{};
    uint32_t eu_total_{};

    std::thread device_thread_;
    std::thread freq_monitor_device_thread_;
    std::unique_ptr<magma::PlatformThreadId> device_thread_id_;
    std::atomic_bool device_thread_quit_flag_{false};
    std::unique_ptr<GpuProgress> progress_;

    std::unique_ptr<MsdIntelPciDevice> platform_device_;
    std::unique_ptr<magma::RegisterIo> register_io_;
    std::shared_ptr<Gtt> gtt_;
    std::unique_ptr<RenderEngineCommandStreamer> render_engine_cs_;
    std::shared_ptr<GlobalContext> global_context_;
    std::unique_ptr<Sequencer> sequencer_;
    std::shared_ptr<magma::PlatformBuffer> scratch_buffer_;
    std::unique_ptr<InterruptManager> interrupt_manager_;
    std::unique_ptr<magma::PlatformBusMapper> bus_mapper_;

    class BatchRequest;
    class DestroyContextRequest;
    class ReleaseBufferRequest;
    class InterruptRequest;
    class DumpRequest;

    // Thread-shared data members
    std::unique_ptr<magma::PlatformSemaphore> device_request_semaphore_;
    std::mutex device_request_mutex_;
    std::list<std::unique_ptr<DeviceRequest>> device_request_list_;

    struct FreqMonitorContext {
        std::unique_ptr<magma::PlatformSemaphore> semaphore{magma::PlatformSemaphore::Create()};
        std::atomic_bool tracing_enabled{false};
    };
    std::shared_ptr<FreqMonitorContext> freq_monitor_context_;
    std::unique_ptr<magma::PlatformTraceObserver> trace_observer_;

    friend class TestMsdIntelDevice;
    friend class TestCommandBuffer;
    friend class TestExec;
};

#endif // MSD_INTEL_DEVICE_H
