From d129905a665ce329089338b4e468da84b3dab5d6 Mon Sep 17 00:00:00 2001 From: David <25727384+ogniK5377@users.noreply.github.com> Date: Mon, 5 Feb 2018 18:19:31 -0800 Subject: Extra nvdrv support (#162) * FinishInitalize needed for 3.0.1+ games * nvdrv:s and nvdrv:t both use NVDRV * Most settings return 0 on hardware, disabled NV_MEMORY_PROFILER for now. NVN_THROUGH_OPENGL & NVRM_GPU_PREVENT_USE are a few interesting settings to look at. Carefully choosing settings can help with drawing graphics later on * Initial /dev/nvhost-gpu support * ZCullBind * Stubbed SetErrorNotifier * Fixed SetErrorNotifier log, Added SetChannelPriority * Allocate GPFIFO Ex2, Allocate Obj Ctx, Submit GPFIFO * oops * Fixed up naming/structs/enums. Used vector instead of array for "gpfifo_entry" * Added missing fixes * /dev/nvhost-ctrl-gpu * unneeded struct * Forgot u32 in enum class * Automatic descriptor swapping for ioctls, fixed nvgpu_gpu_get_tpc_masks_args being incorrect size * nvdrv#QueryEvent * Renamed logs for nvdrv * Refactor ioctl so nv_result isn't needed * /dev/nvhost-as-gpu * Fixed Log service naming, CtxObjects now u32, renamed all structs, added static_asserts to structs, used INSERT_PADDING_WORDS instead of u32s * nvdevices now uses "Ioctl" union, * IoctlGpfifoEntry now uses bit field * final changes --- src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 139 ++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/core/hle/service/nvdrv/devices/nvhost_gpu.h (limited to 'src/core/hle/service/nvdrv/devices/nvhost_gpu.h') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h new file mode 100644 index 000000000..4fe2c9ad5 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -0,0 +1,139 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" + +namespace Service { +namespace Nvidia { +namespace Devices { +constexpr u32 NVGPU_IOCTL_MAGIC('H'); +constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); + +class nvhost_gpu final : public nvdevice { +public: + nvhost_gpu() = default; + ~nvhost_gpu() override = default; + + u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; + +private: + enum class IoctlCommand : u32_le { + IocSetNVMAPfdCommand = 0x40044801, + IocSetClientDataCommand = 0x40084714, + IocGetClientDataCommand = 0x80084715, + IocZCullBind = 0xc010480b, + IocSetErrorNotifierCommand = 0xC018480C, + IocChannelSetPriorityCommand = 0x4004480D, + IocAllocGPFIFOEx2Command = 0xC020481A, + IocAllocObjCtxCommand = 0xC0104809, + }; + + enum class CtxObjects : u32_le { + Ctx2D = 0x902D, + Ctx3D = 0xB197, + CtxCompute = 0xB1C0, + CtxKepler = 0xA140, + CtxDMA = 0xB0B5, + CtxChannelGPFIFO = 0xB06F, + }; + + struct IoctlSetNvmapFD { + u32_le nvmap_fd; + }; + static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); + + struct IoctlClientData { + u64_le data; + }; + static_assert(sizeof(IoctlClientData) == 8, "IoctlClientData is incorrect size"); + + struct IoctlZCullBind { + u64_le gpu_va; + u32_le mode; // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf + INSERT_PADDING_WORDS(1); + }; + static_assert(sizeof(IoctlZCullBind) == 16, "IoctlZCullBind is incorrect size"); + + struct IoctlSetErrorNotifier { + u64_le offset; + u64_le size; + u32_le mem; // nvmap object handle + INSERT_PADDING_WORDS(1); + }; + static_assert(sizeof(IoctlSetErrorNotifier) == 24, "IoctlSetErrorNotifier is incorrect size"); + + struct IoctlFence { + u32_le id; + u32_le value; + }; + static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size"); + + struct IoctlAllocGpfifoEx2 { + u32_le num_entries; // in + u32_le flags; // in + u32_le unk0; // in (1 works) + IoctlFence fence_out; // out + u32_le unk1; // in + u32_le unk2; // in + u32_le unk3; // in + }; + static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); + + struct IoctlAllocObjCtx { + u32_le class_num; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, + // 0xB06F=channel_gpfifo + u32_le flags; + u64_le obj_id; // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported + }; + static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size"); + + struct IoctlGpfifoEntry { + u32_le entry0; // gpu_va_lo + union { + u32_le entry1; // gpu_va_hi | (unk_0x02 << 0x08) | (size << 0x0A) | (unk_0x01 << 0x1F) + BitField<0, 8, u32_le> gpu_va_hi; + BitField<8, 2, u32_le> unk1; + BitField<10, 21, u32_le> sz; + BitField<31, 1, u32_le> unk2; + }; + + VAddr Address() const { + return (static_cast(gpu_va_hi) << 32) | entry0; + } + }; + static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size"); + + struct IoctlSubmitGpfifo { + u64_le gpfifo; // (ignored) pointer to gpfifo fence structs + u32_le num_entries; // number of fence objects being submitted + u32_le flags; + IoctlFence fence_out; // returned new fence object for others to wait on + }; + static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence), + "submit_gpfifo is incorrect size"); + + u32_le nvmap_fd{}; + u64_le user_data{}; + IoctlZCullBind zcull_params{}; + u32_le channel_priority{}; + + u32 SetNVMAPfd(const std::vector& input, std::vector& output); + u32 SetClientData(const std::vector& input, std::vector& output); + u32 GetClientData(const std::vector& input, std::vector& output); + u32 ZCullBind(const std::vector& input, std::vector& output); + u32 SetErrorNotifier(const std::vector& input, std::vector& output); + u32 SetChannelPriority(const std::vector& input, std::vector& output); + u32 AllocGPFIFOEx2(const std::vector& input, std::vector& output); + u32 AllocateObjectContext(const std::vector& input, std::vector& output); + u32 SubmitGPFIFO(const std::vector& input, std::vector& output); +}; + +} // namespace Devices +} // namespace Nvidia +} // namespace Service -- cgit v1.2.3