mirror of
https://github.com/yuzu-emu/yuzu-mainline.git
synced 2024-12-26 03:55:34 +00:00
NVServices: Correct CtrlEventWaitSync to block the ipc until timeout.
This commit is contained in:
parent
7d1b974bca
commit
b6844bec60
|
@ -8,6 +8,7 @@
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -37,7 +38,8 @@ public:
|
||||||
* @param output A buffer where the output data will be written to.
|
* @param output A buffer where the output data will be written to.
|
||||||
* @returns The result code of the ioctl.
|
* @returns The result code of the ioctl.
|
||||||
*/
|
*/
|
||||||
virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) = 0;
|
virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
|
@ -17,7 +17,8 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_de
|
||||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||||
nvdisp_disp0 ::~nvdisp_disp0() = default;
|
nvdisp_disp0 ::~nvdisp_disp0() = default;
|
||||||
|
|
||||||
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ public:
|
||||||
explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||||
~nvdisp_disp0() override;
|
~nvdisp_disp0() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
/// Performs a screen flip, drawing the buffer pointed to by the handle.
|
/// 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,
|
void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride,
|
||||||
|
|
|
@ -26,7 +26,8 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_
|
||||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||||
nvhost_as_gpu::~nvhost_as_gpu() = default;
|
nvhost_as_gpu::~nvhost_as_gpu() = default;
|
||||||
|
|
||||||
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ public:
|
||||||
explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||||
~nvhost_as_gpu() override;
|
~nvhost_as_gpu() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -19,7 +19,8 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventsInterface& events_interface
|
||||||
: nvdevice(system), events_interface{events_interface} {}
|
: nvdevice(system), events_interface{events_interface} {}
|
||||||
nvhost_ctrl::~nvhost_ctrl() = default;
|
nvhost_ctrl::~nvhost_ctrl() = default;
|
||||||
|
|
||||||
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
@ -27,9 +28,9 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
|
||||||
case IoctlCommand::IocGetConfigCommand:
|
case IoctlCommand::IocGetConfigCommand:
|
||||||
return NvOsGetConfigU32(input, output);
|
return NvOsGetConfigU32(input, output);
|
||||||
case IoctlCommand::IocCtrlEventWaitCommand:
|
case IoctlCommand::IocCtrlEventWaitCommand:
|
||||||
return IocCtrlEventWait(input, output, false);
|
return IocCtrlEventWait(input, output, false, ctrl);
|
||||||
case IoctlCommand::IocCtrlEventWaitAsyncCommand:
|
case IoctlCommand::IocCtrlEventWaitAsyncCommand:
|
||||||
return IocCtrlEventWait(input, output, true);
|
return IocCtrlEventWait(input, output, true, ctrl);
|
||||||
case IoctlCommand::IocCtrlEventRegisterCommand:
|
case IoctlCommand::IocCtrlEventRegisterCommand:
|
||||||
return IocCtrlEventRegister(input, output);
|
return IocCtrlEventRegister(input, output);
|
||||||
case IoctlCommand::IocCtrlEventUnregisterCommand:
|
case IoctlCommand::IocCtrlEventUnregisterCommand:
|
||||||
|
@ -50,7 +51,7 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
|
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
bool is_async) {
|
bool is_async, IoctlCtrl& ctrl) {
|
||||||
IocCtrlEventWaitParams params{};
|
IocCtrlEventWaitParams params{};
|
||||||
std::memcpy(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, input.data(), sizeof(params));
|
||||||
LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}",
|
LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}",
|
||||||
|
@ -94,7 +95,11 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event_id = events_interface.GetFreeEvent();
|
if (ctrl.fresh_call) {
|
||||||
|
event_id = events_interface.GetFreeEvent();
|
||||||
|
} else {
|
||||||
|
event_id = ctrl.event_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventState status = events_interface.status[event_id];
|
EventState status = events_interface.status[event_id];
|
||||||
|
@ -110,6 +115,13 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
|
||||||
params.value |= event_id;
|
params.value |= event_id;
|
||||||
events_interface.events[event_id].writable->Clear();
|
events_interface.events[event_id].writable->Clear();
|
||||||
gpu.RegisterSyncptInterrupt(params.syncpt_id, params.threshold);
|
gpu.RegisterSyncptInterrupt(params.syncpt_id, params.threshold);
|
||||||
|
if (!is_async && ctrl.fresh_call) {
|
||||||
|
ctrl.must_delay = true;
|
||||||
|
ctrl.timeout = params.timeout;
|
||||||
|
ctrl.event_id = event_id;
|
||||||
|
gpu.Guard(false);
|
||||||
|
return NvResult::Timeout;
|
||||||
|
}
|
||||||
std::memcpy(output.data(), ¶ms, sizeof(params));
|
std::memcpy(output.data(), ¶ms, sizeof(params));
|
||||||
gpu.Guard(false);
|
gpu.Guard(false);
|
||||||
return NvResult::Timeout;
|
return NvResult::Timeout;
|
||||||
|
|
|
@ -17,7 +17,8 @@ public:
|
||||||
nvhost_ctrl(Core::System& system, EventsInterface& events_interface);
|
nvhost_ctrl(Core::System& system, EventsInterface& events_interface);
|
||||||
~nvhost_ctrl() override;
|
~nvhost_ctrl() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
@ -133,7 +134,8 @@ private:
|
||||||
|
|
||||||
u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
|
u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
|
||||||
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async);
|
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async,
|
||||||
|
IoctlCtrl& ctrl);
|
||||||
|
|
||||||
u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
|
u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ namespace Service::Nvidia::Devices {
|
||||||
nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system){};
|
nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system){};
|
||||||
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
|
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
|
||||||
|
|
||||||
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
nvhost_ctrl_gpu(Core::System& system);
|
nvhost_ctrl_gpu(Core::System& system);
|
||||||
~nvhost_ctrl_gpu() override;
|
~nvhost_ctrl_gpu() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -17,7 +17,8 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
|
||||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||||
nvhost_gpu::~nvhost_gpu() = default;
|
nvhost_gpu::~nvhost_gpu() = default;
|
||||||
|
|
||||||
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ public:
|
||||||
explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||||
~nvhost_gpu() override;
|
~nvhost_gpu() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices {
|
||||||
nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system){};
|
nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system){};
|
||||||
nvhost_nvdec::~nvhost_nvdec() = default;
|
nvhost_nvdec::~nvhost_nvdec() = default;
|
||||||
|
|
||||||
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
nvhost_nvdec(Core::System& system);
|
nvhost_nvdec(Core::System& system);
|
||||||
~nvhost_nvdec() override;
|
~nvhost_nvdec() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices {
|
||||||
nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system){};
|
nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system){};
|
||||||
nvhost_nvjpg::~nvhost_nvjpg() = default;
|
nvhost_nvjpg::~nvhost_nvjpg() = default;
|
||||||
|
|
||||||
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
nvhost_nvjpg(Core::System& system);
|
nvhost_nvjpg(Core::System& system);
|
||||||
~nvhost_nvjpg() override;
|
~nvhost_nvjpg() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Service::Nvidia::Devices {
|
||||||
nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system){};
|
nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system){};
|
||||||
nvhost_vic::~nvhost_vic() = default;
|
nvhost_vic::~nvhost_vic() = default;
|
||||||
|
|
||||||
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||||
command.raw, input.size(), output.size());
|
command.raw, input.size(), output.size());
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
nvhost_vic(Core::System& system);
|
nvhost_vic(Core::System& system);
|
||||||
~nvhost_vic() override;
|
~nvhost_vic() override;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
|
|
|
@ -28,7 +28,8 @@ VAddr nvmap::GetObjectAddress(u32 handle) const {
|
||||||
return object->addr;
|
return object->addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||||
case IoctlCommand::Create:
|
case IoctlCommand::Create:
|
||||||
return IocCreate(input, output);
|
return IocCreate(input, output);
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
/// Returns the allocated address of an nvmap object given its handle.
|
/// Returns the allocated address of an nvmap object given its handle.
|
||||||
VAddr GetObjectAddress(u32 handle) const;
|
VAddr GetObjectAddress(u32 handle) const;
|
||||||
|
|
||||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
/// Represents an nvmap object.
|
/// Represents an nvmap object.
|
||||||
struct Object {
|
struct Object {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/readable_event.h"
|
#include "core/hle/kernel/readable_event.h"
|
||||||
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/kernel/writable_event.h"
|
#include "core/hle/kernel/writable_event.h"
|
||||||
#include "core/hle/service/nvdrv/interface.h"
|
#include "core/hle/service/nvdrv/interface.h"
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
|
@ -41,11 +42,36 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
std::vector<u8> output(ctx.GetWriteBufferSize());
|
std::vector<u8> output(ctx.GetWriteBufferSize());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IoctlCtrl ctrl{};
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.Push(nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output));
|
|
||||||
|
|
||||||
ctx.WriteBuffer(output);
|
u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl);
|
||||||
|
|
||||||
|
if (!ctrl.must_delay) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.Push(result);
|
||||||
|
|
||||||
|
ctx.WriteBuffer(output);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctrl.fresh_call = false;
|
||||||
|
ctx.SleepClientThread(
|
||||||
|
"NVServices::DelayedResponse", ctrl.timeout,
|
||||||
|
[this, ctrl = ctrl](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||||
|
Kernel::ThreadWakeupReason reason) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
u32 fd = rp.Pop<u32>();
|
||||||
|
u32 command = rp.Pop<u32>();
|
||||||
|
std::vector<u8> output(ctx.GetWriteBufferSize());
|
||||||
|
IoctlCtrl ctrl2{ctrl};
|
||||||
|
u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl2);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.Push(result);
|
||||||
|
|
||||||
|
ctx.WriteBuffer(output);
|
||||||
|
},
|
||||||
|
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NVDRV::Close(Kernel::HLERequestContext& ctx) {
|
void NVDRV::Close(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
|
@ -34,4 +34,11 @@ enum class EventState {
|
||||||
Busy = 3,
|
Busy = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IoctlCtrl {
|
||||||
|
bool fresh_call{true};
|
||||||
|
bool must_delay{};
|
||||||
|
s64 timeout{};
|
||||||
|
s32 event_id{-1};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia
|
||||||
|
|
|
@ -71,12 +71,13 @@ u32 Module::Open(const std::string& device_name) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
auto itr = open_files.find(fd);
|
auto itr = open_files.find(fd);
|
||||||
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
|
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
|
||||||
|
|
||||||
auto& device = itr->second;
|
auto& device = itr->second;
|
||||||
return device->ioctl({command}, input, output);
|
return device->ioctl({command}, input, output, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode Module::Close(u32 fd) {
|
ResultCode Module::Close(u32 fd) {
|
||||||
|
@ -103,4 +104,8 @@ Kernel::SharedPtr<Kernel::ReadableEvent> Module::GetEvent(const u32 event_id) {
|
||||||
return events_interface.events[event_id].readable;
|
return events_interface.events[event_id].readable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Kernel::SharedPtr<Kernel::WritableEvent> Module::GetEventWriteable(const u32 event_id) {
|
||||||
|
return events_interface.events[event_id].writable;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia
|
||||||
|
|
|
@ -95,7 +95,8 @@ public:
|
||||||
/// Opens a device node and returns a file descriptor to it.
|
/// Opens a device node and returns a file descriptor to it.
|
||||||
u32 Open(const std::string& device_name);
|
u32 Open(const std::string& device_name);
|
||||||
/// Sends an ioctl command to the specified file descriptor.
|
/// Sends an ioctl command to the specified file descriptor.
|
||||||
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output);
|
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl);
|
||||||
/// Closes a device file descriptor and returns operation success.
|
/// Closes a device file descriptor and returns operation success.
|
||||||
ResultCode Close(u32 fd);
|
ResultCode Close(u32 fd);
|
||||||
|
|
||||||
|
@ -103,6 +104,8 @@ public:
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::ReadableEvent> GetEvent(const u32 event_id);
|
Kernel::SharedPtr<Kernel::ReadableEvent> GetEvent(const u32 event_id);
|
||||||
|
|
||||||
|
Kernel::SharedPtr<Kernel::WritableEvent> GetEventWriteable(const u32 event_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Id to use for the next open file descriptor.
|
/// Id to use for the next open file descriptor.
|
||||||
u32 next_fd = 1;
|
u32 next_fd = 1;
|
||||||
|
|
Loading…
Reference in a new issue