mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	Merge pull request #2873 from ogniK5377/new-ioctls
Initial implementation of Ioctl2 & Ioctl3
This commit is contained in:
		@@ -9,6 +9,7 @@
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/swap.h"
 | 
			
		||||
#include "core/hle/service/nvdrv/nvdata.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
@@ -38,8 +39,9 @@ public:
 | 
			
		||||
     * @param output A buffer where the output data will be written to.
 | 
			
		||||
     * @returns The result code of the ioctl.
 | 
			
		||||
     */
 | 
			
		||||
    virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                      IoctlCtrl& ctrl) = 0;
 | 
			
		||||
    virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                      std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                      IoctlVersion version) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,9 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_de
 | 
			
		||||
    : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
 | 
			
		||||
nvdisp_disp0 ::~nvdisp_disp0() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                        IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                        std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                        IoctlVersion version) {
 | 
			
		||||
    UNIMPLEMENTED_MSG("Unimplemented ioctl");
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,9 @@ public:
 | 
			
		||||
    explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
 | 
			
		||||
    ~nvdisp_disp0() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
    /// Performs a screen flip, drawing the buffer pointed to by the handle.
 | 
			
		||||
    void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride,
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,9 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_
 | 
			
		||||
    : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
 | 
			
		||||
nvhost_as_gpu::~nvhost_as_gpu() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                         IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                         std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                         IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,9 @@ public:
 | 
			
		||||
    explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
 | 
			
		||||
    ~nvhost_as_gpu() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,9 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface)
 | 
			
		||||
    : nvdevice(system), events_interface{events_interface} {}
 | 
			
		||||
nvhost_ctrl::~nvhost_ctrl() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                       IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                       std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                       IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,9 @@ public:
 | 
			
		||||
    explicit nvhost_ctrl(Core::System& system, EventInterface& events_interface);
 | 
			
		||||
    ~nvhost_ctrl() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,14 +15,15 @@ namespace Service::Nvidia::Devices {
 | 
			
		||||
nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {}
 | 
			
		||||
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                           IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input,
 | 
			
		||||
                           const std::vector<u8>& input2, std::vector<u8>& output,
 | 
			
		||||
                           std::vector<u8>& output2, IoctlCtrl& ctrl, IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
    switch (static_cast<IoctlCommand>(command.raw)) {
 | 
			
		||||
    case IoctlCommand::IocGetCharacteristicsCommand:
 | 
			
		||||
        return GetCharacteristics(input, output);
 | 
			
		||||
        return GetCharacteristics(input, output, output2, version);
 | 
			
		||||
    case IoctlCommand::IocGetTPCMasksCommand:
 | 
			
		||||
        return GetTPCMasks(input, output);
 | 
			
		||||
    case IoctlCommand::IocGetActiveSlotMaskCommand:
 | 
			
		||||
@@ -44,7 +45,8 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
			
		||||
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                                        std::vector<u8>& output2, IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
    IoctlCharacteristics params{};
 | 
			
		||||
    std::memcpy(¶ms, input.data(), input.size());
 | 
			
		||||
@@ -85,7 +87,13 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto
 | 
			
		||||
    params.gc.gr_compbit_store_base_hw = 0x0;
 | 
			
		||||
    params.gpu_characteristics_buf_size = 0xA0;
 | 
			
		||||
    params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
 | 
			
		||||
    std::memcpy(output.data(), ¶ms, output.size());
 | 
			
		||||
 | 
			
		||||
    if (version == IoctlVersion::Version3) {
 | 
			
		||||
        std::memcpy(output.data(), input.data(), output.size());
 | 
			
		||||
        std::memcpy(output2.data(), ¶ms.gc, output2.size());
 | 
			
		||||
    } else {
 | 
			
		||||
        std::memcpy(output.data(), ¶ms, output.size());
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,9 @@ public:
 | 
			
		||||
    explicit nvhost_ctrl_gpu(Core::System& system);
 | 
			
		||||
    ~nvhost_ctrl_gpu() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
@@ -162,7 +163,8 @@ private:
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(IoctlGetGpuTime) == 8, "IoctlGetGpuTime is incorrect size");
 | 
			
		||||
 | 
			
		||||
    u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                           std::vector<u8>& output2, IoctlVersion version);
 | 
			
		||||
    u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,9 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
 | 
			
		||||
    : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
 | 
			
		||||
nvhost_gpu::~nvhost_gpu() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                      IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                      std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                      IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
@@ -50,7 +51,7 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
 | 
			
		||||
            return SubmitGPFIFO(input, output);
 | 
			
		||||
        }
 | 
			
		||||
        if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) {
 | 
			
		||||
            return KickoffPB(input, output);
 | 
			
		||||
            return KickoffPB(input, output, input2, version);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -173,7 +174,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
			
		||||
u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                          const std::vector<u8>& input2, IoctlVersion version) {
 | 
			
		||||
    if (input.size() < sizeof(IoctlSubmitGpfifo)) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
    }
 | 
			
		||||
@@ -183,9 +185,13 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
 | 
			
		||||
              params.num_entries, params.flags.raw);
 | 
			
		||||
 | 
			
		||||
    Tegra::CommandList entries(params.num_entries);
 | 
			
		||||
    Memory::ReadBlock(params.address, entries.data(),
 | 
			
		||||
                      params.num_entries * sizeof(Tegra::CommandListHeader));
 | 
			
		||||
 | 
			
		||||
    if (version == IoctlVersion::Version2) {
 | 
			
		||||
        std::memcpy(entries.data(), input2.data(),
 | 
			
		||||
                    params.num_entries * sizeof(Tegra::CommandListHeader));
 | 
			
		||||
    } else {
 | 
			
		||||
        Memory::ReadBlock(params.address, entries.data(),
 | 
			
		||||
                          params.num_entries * sizeof(Tegra::CommandListHeader));
 | 
			
		||||
    }
 | 
			
		||||
    UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
 | 
			
		||||
    UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,9 @@ public:
 | 
			
		||||
    explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
 | 
			
		||||
    ~nvhost_gpu() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
@@ -183,7 +184,8 @@ private:
 | 
			
		||||
    u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                  const std::vector<u8>& input2, IoctlVersion version);
 | 
			
		||||
    u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
    u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
 | 
			
		||||
nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {}
 | 
			
		||||
nvhost_nvdec::~nvhost_nvdec() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                        IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                        std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                        IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,9 @@ public:
 | 
			
		||||
    explicit nvhost_nvdec(Core::System& system);
 | 
			
		||||
    ~nvhost_nvdec() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
 | 
			
		||||
nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {}
 | 
			
		||||
nvhost_nvjpg::~nvhost_nvjpg() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                        IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                        std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                        IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,9 @@ public:
 | 
			
		||||
    explicit nvhost_nvjpg(Core::System& system);
 | 
			
		||||
    ~nvhost_nvjpg() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
 | 
			
		||||
nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system) {}
 | 
			
		||||
nvhost_vic::~nvhost_vic() = default;
 | 
			
		||||
 | 
			
		||||
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                      IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                      std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                      IoctlVersion version) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
 | 
			
		||||
              command.raw, input.size(), output.size());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,9 @@ public:
 | 
			
		||||
    explicit nvhost_vic(Core::System& system);
 | 
			
		||||
    ~nvhost_vic() override;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,9 @@ VAddr nvmap::GetObjectAddress(u32 handle) const {
 | 
			
		||||
    return object->addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                 IoctlCtrl& ctrl) {
 | 
			
		||||
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                 std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                 IoctlVersion version) {
 | 
			
		||||
    switch (static_cast<IoctlCommand>(command.raw)) {
 | 
			
		||||
    case IoctlCommand::Create:
 | 
			
		||||
        return IocCreate(input, output);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,9 @@ public:
 | 
			
		||||
    /// Returns the allocated address of an nvmap object given its handle.
 | 
			
		||||
    VAddr GetObjectAddress(u32 handle) const;
 | 
			
		||||
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl) override;
 | 
			
		||||
    u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version) override;
 | 
			
		||||
 | 
			
		||||
    /// Represents an nvmap object.
 | 
			
		||||
    struct Object {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,42 +33,77 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    rb.Push<u32>(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
 | 
			
		||||
void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    u32 fd = rp.Pop<u32>();
 | 
			
		||||
    u32 command = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> output(ctx.GetWriteBufferSize());
 | 
			
		||||
    /// Ioctl 3 has 2 outputs, first in the input params, second is the result
 | 
			
		||||
    std::vector<u8> output(ctx.GetWriteBufferSize(0));
 | 
			
		||||
    std::vector<u8> output2;
 | 
			
		||||
    if (version == IoctlVersion::Version3) {
 | 
			
		||||
        output2.resize((ctx.GetWriteBufferSize(1)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Ioctl2 has 2 inputs. It's used to pass data directly instead of providing a pointer.
 | 
			
		||||
    /// KickOfPB uses this
 | 
			
		||||
    auto input = ctx.ReadBuffer(0);
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> input2;
 | 
			
		||||
    if (version == IoctlVersion::Version2) {
 | 
			
		||||
        input2 = ctx.ReadBuffer(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IoctlCtrl ctrl{};
 | 
			
		||||
 | 
			
		||||
    u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl);
 | 
			
		||||
    u32 result = nvdrv->Ioctl(fd, command, input, input2, output, output2, ctrl, version);
 | 
			
		||||
 | 
			
		||||
    if (ctrl.must_delay) {
 | 
			
		||||
        ctrl.fresh_call = false;
 | 
			
		||||
        ctx.SleepClientThread(
 | 
			
		||||
            "NVServices::DelayedResponse", ctrl.timeout,
 | 
			
		||||
            [=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
 | 
			
		||||
                Kernel::ThreadWakeupReason reason) {
 | 
			
		||||
                IoctlCtrl ctrl2{ctrl};
 | 
			
		||||
                std::vector<u8> output2 = output;
 | 
			
		||||
                u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output2, ctrl2);
 | 
			
		||||
                ctx.WriteBuffer(output2);
 | 
			
		||||
                IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
                rb.Push(RESULT_SUCCESS);
 | 
			
		||||
                rb.Push(result);
 | 
			
		||||
            },
 | 
			
		||||
            nvdrv->GetEventWriteable(ctrl.event_id));
 | 
			
		||||
        ctx.SleepClientThread("NVServices::DelayedResponse", ctrl.timeout,
 | 
			
		||||
                              [=](Kernel::SharedPtr<Kernel::Thread> thread,
 | 
			
		||||
                                  Kernel::HLERequestContext& ctx,
 | 
			
		||||
                                  Kernel::ThreadWakeupReason reason) {
 | 
			
		||||
                                  IoctlCtrl ctrl2{ctrl};
 | 
			
		||||
                                  std::vector<u8> tmp_output = output;
 | 
			
		||||
                                  std::vector<u8> tmp_output2 = output2;
 | 
			
		||||
                                  u32 result = nvdrv->Ioctl(fd, command, input, input2, tmp_output,
 | 
			
		||||
                                                            tmp_output2, ctrl2, version);
 | 
			
		||||
                                  ctx.WriteBuffer(tmp_output, 0);
 | 
			
		||||
                                  if (version == IoctlVersion::Version3) {
 | 
			
		||||
                                      ctx.WriteBuffer(tmp_output2, 1);
 | 
			
		||||
                                  }
 | 
			
		||||
                                  IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
                                  rb.Push(RESULT_SUCCESS);
 | 
			
		||||
                                  rb.Push(result);
 | 
			
		||||
                              },
 | 
			
		||||
                              nvdrv->GetEventWriteable(ctrl.event_id));
 | 
			
		||||
    } else {
 | 
			
		||||
        ctx.WriteBuffer(output);
 | 
			
		||||
        if (version == IoctlVersion::Version3) {
 | 
			
		||||
            ctx.WriteBuffer(output2, 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
    IoctlBase(ctx, IoctlVersion::Version1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
    IoctlBase(ctx, IoctlVersion::Version2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
    IoctlBase(ctx, IoctlVersion::Version3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVDRV::Close(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_NVDRV, "called");
 | 
			
		||||
 | 
			
		||||
@@ -154,8 +189,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
 | 
			
		||||
        {8, &NVDRV::SetClientPID, "SetClientPID"},
 | 
			
		||||
        {9, &NVDRV::DumpGraphicsMemoryInfo, "DumpGraphicsMemoryInfo"},
 | 
			
		||||
        {10, nullptr, "InitializeDevtools"},
 | 
			
		||||
        {11, &NVDRV::Ioctl, "Ioctl2"},
 | 
			
		||||
        {12, nullptr, "Ioctl3"},
 | 
			
		||||
        {11, &NVDRV::Ioctl2, "Ioctl2"},
 | 
			
		||||
        {12, &NVDRV::Ioctl3, "Ioctl3"},
 | 
			
		||||
        {13, &NVDRV::FinishInitialize, "FinishInitialize"},
 | 
			
		||||
    };
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    void Open(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void Ioctl(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void Ioctl2(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void Ioctl3(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void Close(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void Initialize(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void QueryEvent(Kernel::HLERequestContext& ctx);
 | 
			
		||||
@@ -31,6 +33,7 @@ private:
 | 
			
		||||
    void FinishInitialize(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetStatus(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version);
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<Module> nvdrv;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,12 @@ enum class EventState {
 | 
			
		||||
    Busy = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class IoctlVersion : u32 {
 | 
			
		||||
    Version1,
 | 
			
		||||
    Version2,
 | 
			
		||||
    Version3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct IoctlCtrl {
 | 
			
		||||
    // First call done to the servioce for services that call itself again after a call.
 | 
			
		||||
    bool fresh_call{true};
 | 
			
		||||
 
 | 
			
		||||
@@ -71,13 +71,14 @@ u32 Module::Open(const std::string& device_name) {
 | 
			
		||||
    return fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
                  IoctlCtrl& ctrl) {
 | 
			
		||||
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
                  std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
                  IoctlVersion version) {
 | 
			
		||||
    auto itr = open_files.find(fd);
 | 
			
		||||
    ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
 | 
			
		||||
 | 
			
		||||
    auto& device = itr->second;
 | 
			
		||||
    return device->ioctl({command}, input, output, ctrl);
 | 
			
		||||
    return device->ioctl({command}, input, input2, output, output2, ctrl, version);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Module::Close(u32 fd) {
 | 
			
		||||
 
 | 
			
		||||
@@ -106,8 +106,9 @@ public:
 | 
			
		||||
    /// Opens a device node and returns a file descriptor to it.
 | 
			
		||||
    u32 Open(const std::string& device_name);
 | 
			
		||||
    /// Sends an ioctl command to the specified file descriptor.
 | 
			
		||||
    u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
 | 
			
		||||
              IoctlCtrl& ctrl);
 | 
			
		||||
    u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2,
 | 
			
		||||
              std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
 | 
			
		||||
              IoctlVersion version);
 | 
			
		||||
    /// Closes a device file descriptor and returns operation success.
 | 
			
		||||
    ResultCode Close(u32 fd);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user