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

#include "platform_logger.h"

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 = (void*)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(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(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;
}
