blob: 567cd8ba8d11aae718dcb4dd5ece8d7382eb850b [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.
#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 "rgxdevice.h"
#include "srvcore.h"
}
namespace
{
static uint64_t registers_physical_address_s = 0u;
static void* registers_cpu_address_s = nullptr;
} // namespace
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>();
}
MsdImgDevice::~MsdImgDevice()
{
registers_physical_address_s = 0u;
registers_cpu_address_s = nullptr;
if (device_node_)
{
PVRSRVDeviceDestroy(device_node_);
}
}
bool
MsdImgDevice::Init()
{
#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);
}
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);
}
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;
}