From 04b711a1b2aa68e07d74015b32e23b359791c630 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Mon, 5 Feb 2018 01:40:25 -0800 Subject: [PATCH] /dev/nvhost-as-gpu --- .../service/nvdrv/devices/nvhost_as_gpu.cpp | 76 ++++++++++++++++++- .../hle/service/nvdrv/devices/nvhost_as_gpu.h | 67 ++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 9db08339a9..18bcaa2006 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -11,7 +11,81 @@ namespace Nvidia { namespace Devices { u32 nvhost_as_gpu::ioctl(u32 command, const std::vector& input, std::vector& output) { - UNIMPLEMENTED(); + LOG_DEBUG(Service_NVDRV, "Got Ioctl 0x%x, inputsz: 0x%x, outputsz: 0x%x", command, input.size(), + output.size()); + + switch (static_cast(command)) { + case IoctlCommand::IocInitalizeExCommand: + return InitalizeEx(input, output); + case IoctlCommand::IocAllocateSpaceCommand: + return AllocateSpace(input, output); + case IoctlCommand::IocMapBufferExCommand: + return MapBufferEx(input, output); + case IoctlCommand::IocBindChannelCommand: + return BindChannel(input, output); + case IoctlCommand::IocGetVaRegionsCommand: + return GetVARegions(input, output); + } + return 0; +} + +u32 nvhost_as_gpu::InitalizeEx(const std::vector& input, std::vector& output) { + initalize_ex params{}; + std::memcpy(¶ms, input.data(), input.size()); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x%x", params.big_page_size); + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_as_gpu::AllocateSpace(const std::vector& input, std::vector& output) { + alloc_space params{}; + std::memcpy(¶ms, input.data(), input.size()); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, pages=%x, page_size=%x, flags=%x", params.pages, + params.page_size, params.flags); + params.offset = 0xdeadbeef; // TODO(ogniK): Actually allocate space and give a real offset + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_as_gpu::MapBufferEx(const std::vector& input, std::vector& output) { + map_buffer_ex params{}; + std::memcpy(¶ms, input.data(), input.size()); + + LOG_WARNING(Service_NVDRV, + "(STUBBED) called, flags=%x, nvmap_handle=%x, buffer_offset=%lx, mapping_size=%lx, " + "offset=%lx", + params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size, + params.offset); + params.offset = 0x0; // TODO(ogniK): Actually map and give a real offset + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_as_gpu::BindChannel(const std::vector& input, std::vector& output) { + bind_channel params{}; + std::memcpy(¶ms, input.data(), input.size()); + LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.fd); + channel = params.fd; + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_as_gpu::GetVARegions(const std::vector& input, std::vector& output) { + get_va_regions params{}; + std::memcpy(¶ms, input.data(), input.size()); + LOG_WARNING(Service, "(STUBBED) called, buf_addr=%lx, buf_size=%x", params.buf_addr, + params.buf_size); + + params.buf_size = 0x30; + params.regions[0].offset = 0x04000000; + params.regions[0].page_size = 0x1000; + params.regions[0].pages = 0x3fbfff; + + params.regions[1].offset = 0x04000000; + params.regions[1].page_size = 0x10000; + params.regions[1].pages = 0x1bffff; + // TODO(ogniK): This probably can stay stubbed but should add support way way later + std::memcpy(output.data(), ¶ms, output.size()); return 0; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 01f8861c8f..f82d328166 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -6,6 +6,7 @@ #include #include "common/common_types.h" +#include "common/swap.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" namespace Service { @@ -18,6 +19,72 @@ public: ~nvhost_as_gpu() override = default; u32 ioctl(u32 command, const std::vector& input, std::vector& output) override; + +private: + enum class IoctlCommand : u32 { + IocInitalizeExCommand = 0x40284109, + IocAllocateSpaceCommand = 0xC0184102, + IocMapBufferExCommand = 0xC0284106, + IocBindChannelCommand = 0x40044101, + IocGetVaRegionsCommand = 0xC0404108, + }; + + struct initalize_ex { + u32_le big_page_size; // depends on GPU's available_big_page_sizes; 0=default + s32_le as_fd; // ignored; passes 0 + u32_le flags; // passes 0 + u32_le reserved; // ignored; passes 0 + u64_le unk0; + u64_le unk1; + u64_le unk2; + }; + + struct alloc_space { + u32_le pages; + u32_le page_size; + u32_le flags; + u32_le pad; + union { + u64_le offset; + u64_le align; + }; + }; + + struct map_buffer_ex { + u32_le flags; // bit0: fixed_offset, bit2: cacheable + u32_le kind; // -1 is default + u32_le nvmap_handle; + u32_le page_size; // 0 means don't care + u64_le buffer_offset; + u64_le mapping_size; + u64_le offset; + }; + + struct bind_channel { + u32_le fd; + }; + + struct va_region { + u64_le offset; + u32_le page_size; + u32_le pad; + u64_le pages; + }; + + struct get_va_regions { + u64_le buf_addr; // (contained output user ptr on linux, ignored) + u32_le buf_size; // forced to 2*sizeof(struct va_region) + u32_le reserved; + va_region regions[2]; + }; + + u32 channel{}; + + u32 InitalizeEx(const std::vector& input, std::vector& output); + u32 AllocateSpace(const std::vector& input, std::vector& output); + u32 MapBufferEx(const std::vector& input, std::vector& output); + u32 BindChannel(const std::vector& input, std::vector& output); + u32 GetVARegions(const std::vector& input, std::vector& output); }; } // namespace Devices