// 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.

#include "msd_img_device.h"

#include "fuchsia_sys_info.h"

#if defined(NO_HARDWARE)
#include "mock/mock_bus_mapper.h"
#include "mock/mock_mmio.h"
#endif

extern "C"
{
#include "process_stats.h"
#include "pvrsrv.h"
#include "pvrsrv_error.h"
#include "pvr_gputrace.h"
#include "rgxdevice.h"
#include "rgxinit.h"
#include "srvcore.h"
}

namespace
{
static uint64_t registers_physical_address_s = 0u;
static void* registers_cpu_address_s = nullptr;

static bool g_driver_initialized = false;
} // namespace

MsdImgDevice* MsdImgDevice::global_device_s_;


MsdImgDevice::MsdImgDevice(std::unique_ptr<magma::PlatformDevice> platform_device,
			   ImgSysDevice* sys_device)
	     : sys_device_(sys_device),
	       platform_device_(std::move(platform_device))
{
	magic_ = kMagic;
	sys_info_ = std::make_unique<FuchsiaSysInfo>();
	DASSERT(!global_device_s_);
	global_device_s_ = this;
}

MsdImgDevice::~MsdImgDevice()
{
	DASSERT(global_device_s_ == this);
	global_device_s_ = nullptr;
	registers_physical_address_s = 0u;
	registers_cpu_address_s = nullptr;
#if !defined(NO_HARDWARE)
	if (stats_user_)
	{
		SORgxGpuUtilStatsUnregister(stats_user_);
	}
#endif
#if defined(SUPPORT_GPUTRACE_EVENTS)
	if (trace_observer_)
	{
		trace_observer_.reset();
		PVRGpuTraceEnabledSet(IMG_FALSE);
	}
#endif
	if (device_node_)
	{
#if defined(SUPPORT_GPUTRACE_EVENTS)
		PVRGpuTraceDeInitDevice(device_node_);
#endif
		PVRSRVDeviceDestroy(device_node_);
	}
	if (g_driver_initialized)
	{
		PVRSRVDriverDeInit();
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
		PVRSRVStatsDestroy();
#endif
		g_driver_initialized = false;
	}
}

bool
MsdImgDevice::InitDriver()
{
	DASSERT(!g_driver_initialized);
	PVRSRV_ERROR pvrerr;
#if defined(PVRSRV_ENABLE_PROCESS_STATS)
	pvrerr = PVRSRVStatsInitialise();
	if (pvrerr != PVRSRV_OK)
	{
		return DRETF(false, "PVRSRVStatsInitialize failed: %d\n", pvrerr);
	}
#endif

	pvrerr = PVRSRVDriverInit();
	if (pvrerr != PVRSRV_OK)
	{
		return DRETF(false, "PVRSRVDriverInit failed: %d\n", pvrerr);
	}
	g_driver_initialized = true;
	return true;
}

bool
MsdImgDevice::Init()
{
	// Initialize here because it needs |global_device_s_| to be initialized to
	// set priorities on threads.
	if (!InitDriver())
	{
		return DRETF(false, "Failed to initialize driver");
	}
#if defined(NO_HARDWARE)
	bus_mapper_ = std::make_unique<MockBusMapper>();
	registers_physical_address_s = PAGE_SIZE;
	// The address doesn't matter (functions that read/write registers are
	// no-ops), but this needs to be non-zero to avoid hitting asserts.
	registers_cpu_address_s = reinterpret_cast<void*>(PAGE_SIZE);
	mmio_ = MockMmio::Create(PAGE_SIZE * 10);
#else
	bus_mapper_ = magma::PlatformBusMapper::Create(platform_device_->GetBusTransactionInitiator());
	if (!bus_mapper_)
	{
		return DRETF(false, "Failed to create bus transaction initiator");
	}
	mmio_ = platform_device_->CpuMapMmio(0u, magma::PlatformMmio::CACHE_POLICY_UNCACHED_DEVICE);
	if (!mmio_)
	{
		return DRETF(false, "Failed to get mmio");
	}
	registers_physical_address_s = mmio_->physical_address();
	registers_cpu_address_s = mmio_->addr();

#endif
	PVRSRV_ERROR srv_err;
	srv_err = PVRSRVDeviceCreate(this, 1u, &device_node_);
	if (srv_err != PVRSRV_OK)
	{
		return DRETF(false, "Failed to create device: %d", srv_err);
	}

	srv_err = PVRSRVDeviceInitialise(device_node_);
	if (srv_err != PVRSRV_OK)
	{
		return DRETF(false, "Failed to initialize device: %d", srv_err);
	}
#if !defined(NO_HARDWARE)
	srv_err = SORgxGpuUtilStatsRegister(&stats_user_);
	if (srv_err != PVRSRV_OK)
	{
		return DRETF(false, "Failed to initialize stats: %d", srv_err);
	}
#endif
#if defined(SUPPORT_GPUTRACE_EVENTS)
	srv_err = PVRGpuTraceInitDevice(device_node_);
	if (srv_err != 0)
	{
		return DRETF(false, "Failed to initialize GPU tracing: %d", srv_err);
	}
	trace_observer_ = magma::PlatformTraceObserver::Create();
	if (!trace_observer_)
	{
		return DRETF(false, "Failed to make trace observer");
	}
	trace_observer_->SetObserver([](bool enabled) {
		PVRGpuTraceEnabledSet(static_cast<IMG_BOOL>(enabled));
		// Don't enable UFO or Firmware activity notifications, since they seem
		// pretty chatty.
	});

#endif
	return true;
}

std::unique_ptr<magma::PlatformInterrupt>
MsdImgDevice::interrupt()
{
	return platform_device_->RegisterInterrupt(0);
}

void
MsdImgDevice::DumpStatus(uint32_t dump_state)
{
	PVRSRVDebugRequest(device_node_, DEBUG_REQUEST_VERBOSITY_HIGH, NULL, NULL);
#if !defined(NO_HARDWARE)
	PVRSRV_RGXDEV_INFO* psDevInfo = (PVRSRV_RGXDEV_INFO*)device_node_->pvDevice;
	RGXFWIF_GPU_UTIL_STATS stats;
	PVRSRV_ERROR eError = psDevInfo->pfnGetGpuUtilStats(device_node_, stats_user_, &stats);
	if (eError == PVRSRV_OK)
	{
		// ui64Timestamp is garbage.
		magma::log(magma::LOG_INFO,
			   "Times since last dump (microseconds):\n Active high: %lu, Active low: %lu, Blocked: %lu, Idle: "
			   "%lu, Total: %lu",
			   stats.ui64GpuStatActiveHigh, stats.ui64GpuStatActiveLow, stats.ui64GpuStatBlocked,
			   stats.ui64GpuStatIdle, stats.ui64GpuStatCumulative);
	}
	else
	{
		magma::log(magma::LOG_WARNING, "Unable to retrieve GPU utilization stats, error: %d", eError);
	}
#endif
}

zx_status_t
MsdImgDevice::PowerUp()
{
	return sys_device_->PowerUp();
}

zx_status_t
MsdImgDevice::PowerDown()
{
	return sys_device_->PowerDown();
}

// static
std::unique_ptr<MsdImgDevice>
MsdImgDevice::Create(msd_driver_t* drv, void* device)
{
	ImgSysDevice* sys_device = reinterpret_cast<ImgSysDevice*>(device);

	std::unique_ptr<magma::PlatformDevice> platform_device =
		magma::PlatformDevice::Create(sys_device->device());
	if (!platform_device)
	{
		return DRETP(nullptr, "Failed to create platform device");
	}

	auto msd_device = std::unique_ptr<MsdImgDevice>(
		new MsdImgDevice(std::move(platform_device), sys_device));
	if (!msd_device->Init())
	{
		return DRETP(nullptr, "Failed to create msd device");
	}
	return msd_device;
}

// static
void
MsdImgDevice::Destroy(MsdImgDevice* device)
{
	delete device;
}

// static
uint64_t
MsdImgDevice::GetRegistersPhysicalAddress()
{
	DASSERT(registers_physical_address_s);
	return registers_physical_address_s;
}

// static
void*
MsdImgDevice::GetRegistersCpuAddress()
{
	DASSERT(registers_cpu_address_s);
	return registers_cpu_address_s;
}
