forked from suyu/suyu
nvservices: Reintroducee IoctlCtrl
Fixes regression caused by #4907 which caused games like Breath of the Wild 1.0.0 not to boot.
This commit is contained in:
parent
d04abd39eb
commit
ab25d1fe9a
24 changed files with 212 additions and 89 deletions
|
@ -31,8 +31,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 NvResult Ioctl1(Ioctl command, const std::vector<u8>& input,
|
virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) = 0;
|
IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an ioctl2 request.
|
* Handles an ioctl2 request.
|
||||||
|
@ -43,7 +43,8 @@ public:
|
||||||
* @returns The result code of the ioctl.
|
* @returns The result code of the ioctl.
|
||||||
*/
|
*/
|
||||||
virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) = 0;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an ioctl3 request.
|
* Handles an ioctl3 request.
|
||||||
|
@ -54,7 +55,7 @@ public:
|
||||||
* @returns The result code of the ioctl.
|
* @returns The result code of the ioctl.
|
||||||
*/
|
*/
|
||||||
virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) = 0;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
|
@ -18,20 +18,21 @@ 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;
|
||||||
|
|
||||||
NvResult nvdisp_disp0::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
NvResult nvdisp_disp0::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) {
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvdisp_disp0::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvdisp_disp0::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvdisp_disp0::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvdisp_disp0::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,13 @@ 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;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_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,
|
||||||
|
|
|
@ -21,8 +21,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;
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_as_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) {
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'A':
|
case 'A':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -55,13 +55,14 @@ NvResult nvhost_as_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_as_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_as_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'A':
|
case 'A':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
|
|
@ -30,11 +30,13 @@ 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;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class BufferMap final {
|
class BufferMap final {
|
||||||
|
|
|
@ -20,7 +20,8 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface,
|
||||||
: nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {}
|
: nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {}
|
||||||
nvhost_ctrl::~nvhost_ctrl() = default;
|
nvhost_ctrl::~nvhost_ctrl() = default;
|
||||||
|
|
||||||
NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -29,9 +30,9 @@ NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::v
|
||||||
case 0x1c:
|
case 0x1c:
|
||||||
return IocCtrlClearEventWait(input, output);
|
return IocCtrlClearEventWait(input, output);
|
||||||
case 0x1d:
|
case 0x1d:
|
||||||
return IocCtrlEventWait(input, output, false);
|
return IocCtrlEventWait(input, output, false, ctrl);
|
||||||
case 0x1e:
|
case 0x1e:
|
||||||
return IocCtrlEventWait(input, output, true);
|
return IocCtrlEventWait(input, output, true, ctrl);
|
||||||
case 0x1f:
|
case 0x1f:
|
||||||
return IocCtrlEventRegister(input, output);
|
return IocCtrlEventRegister(input, output);
|
||||||
case 0x20:
|
case 0x20:
|
||||||
|
@ -47,13 +48,14 @@ NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::v
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_ctrl::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_ctrl::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +69,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult 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={}",
|
||||||
|
@ -139,7 +141,10 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
|
||||||
params.value |= event_id;
|
params.value |= event_id;
|
||||||
event.event.writable->Clear();
|
event.event.writable->Clear();
|
||||||
gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
|
gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
|
||||||
if (!is_async) {
|
if (!is_async && ctrl.fresh_call) {
|
||||||
|
ctrl.must_delay = true;
|
||||||
|
ctrl.timeout = params.timeout;
|
||||||
|
ctrl.event_id = event_id;
|
||||||
return NvResult::Timeout;
|
return NvResult::Timeout;
|
||||||
}
|
}
|
||||||
std::memcpy(output.data(), ¶ms, sizeof(params));
|
std::memcpy(output.data(), ¶ms, sizeof(params));
|
||||||
|
|
|
@ -18,11 +18,13 @@ public:
|
||||||
SyncpointManager& syncpoint_manager);
|
SyncpointManager& syncpoint_manager);
|
||||||
~nvhost_ctrl() override;
|
~nvhost_ctrl() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct IocSyncptReadParams {
|
struct IocSyncptReadParams {
|
||||||
|
@ -121,7 +123,8 @@ private:
|
||||||
static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size");
|
static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size");
|
||||||
|
|
||||||
NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
|
NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async);
|
NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async,
|
||||||
|
IoctlCtrl& ctrl);
|
||||||
NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
|
NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
|
NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);
|
NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
|
|
@ -16,7 +16,7 @@ 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;
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_ctrl_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output) {
|
std::vector<u8>& output, IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'G':
|
case 'G':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -48,13 +48,15 @@ NvResult nvhost_ctrl_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_ctrl_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_ctrl_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output, std::vector<u8>& inline_output) {
|
std::vector<u8>& output, std::vector<u8>& inline_output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'G':
|
case 'G':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -162,7 +164,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::
|
||||||
params.gpu_characteristics_buf_size = 0xA0;
|
params.gpu_characteristics_buf_size = 0xA0;
|
||||||
params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
|
params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
|
||||||
|
|
||||||
std::memcpy(output.data(), input.data(), output.size());
|
std::memcpy(output.data(), ¶ms, output.size());
|
||||||
std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size());
|
std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size());
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ public:
|
||||||
explicit nvhost_ctrl_gpu(Core::System& system);
|
explicit nvhost_ctrl_gpu(Core::System& system);
|
||||||
~nvhost_ctrl_gpu() override;
|
~nvhost_ctrl_gpu() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct IoctlGpuCharacteristics {
|
struct IoctlGpuCharacteristics {
|
||||||
|
|
|
@ -23,7 +23,8 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev,
|
||||||
|
|
||||||
nvhost_gpu::~nvhost_gpu() = default;
|
nvhost_gpu::~nvhost_gpu() = default;
|
||||||
|
|
||||||
NvResult nvhost_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvhost_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -75,7 +76,8 @@ NvResult nvhost_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::ve
|
||||||
};
|
};
|
||||||
|
|
||||||
NvResult nvhost_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'H':
|
case 'H':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -89,7 +91,7 @@ NvResult nvhost_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,13 @@ public:
|
||||||
SyncpointManager& syncpoint_manager);
|
SyncpointManager& syncpoint_manager);
|
||||||
~nvhost_gpu() override;
|
~nvhost_gpu() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class CtxObjects : u32_le {
|
enum class CtxObjects : u32_le {
|
||||||
|
|
|
@ -15,8 +15,8 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_de
|
||||||
: nvhost_nvdec_common(system, std::move(nvmap_dev)) {}
|
: nvhost_nvdec_common(system, std::move(nvmap_dev)) {}
|
||||||
nvhost_nvdec::~nvhost_nvdec() = default;
|
nvhost_nvdec::~nvhost_nvdec() = default;
|
||||||
|
|
||||||
NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) {
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -58,13 +58,14 @@ NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_nvdec::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_nvdec::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_nvdec::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_nvdec::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,13 @@ public:
|
||||||
explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||||
~nvhost_nvdec() override;
|
~nvhost_nvdec() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -25,8 +25,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 NvResult Ioctl1(Ioctl command, const std::vector<u8>& input,
|
virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) = 0;
|
IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an ioctl2 request.
|
* Handles an ioctl2 request.
|
||||||
|
@ -37,7 +37,8 @@ public:
|
||||||
* @returns The result code of the ioctl.
|
* @returns The result code of the ioctl.
|
||||||
*/
|
*/
|
||||||
virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) = 0;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an ioctl3 request.
|
* Handles an ioctl3 request.
|
||||||
|
@ -48,7 +49,7 @@ public:
|
||||||
* @returns The result code of the ioctl.
|
* @returns The result code of the ioctl.
|
||||||
*/
|
*/
|
||||||
virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) = 0;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class BufferMap final {
|
class BufferMap final {
|
||||||
|
|
|
@ -13,8 +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;
|
||||||
|
|
||||||
NvResult nvhost_nvjpg::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_nvjpg::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& output) {
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 'H':
|
case 'H':
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -33,13 +33,14 @@ NvResult nvhost_nvjpg::Ioctl1(Ioctl command, const std::vector<u8>& input,
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_nvjpg::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_nvjpg::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_nvjpg::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_nvjpg::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ public:
|
||||||
explicit nvhost_nvjpg(Core::System& system);
|
explicit nvhost_nvjpg(Core::System& system);
|
||||||
~nvhost_nvjpg() override;
|
~nvhost_nvjpg() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct IoctlSetNvmapFD {
|
struct IoctlSetNvmapFD {
|
||||||
|
|
|
@ -15,7 +15,8 @@ nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
|
||||||
|
|
||||||
nvhost_vic::~nvhost_vic() = default;
|
nvhost_vic::~nvhost_vic() = default;
|
||||||
|
|
||||||
NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -50,13 +51,14 @@ NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::ve
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_vic::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_vic::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_vic::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvhost_vic::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,12 @@ public:
|
||||||
explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||||
~nvhost_vic();
|
~nvhost_vic();
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
};
|
};
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -19,7 +19,8 @@ nvmap::nvmap(Core::System& system) : nvdevice(system) {
|
||||||
|
|
||||||
nvmap::~nvmap() = default;
|
nvmap::~nvmap() = default;
|
||||||
|
|
||||||
NvResult nvmap::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvmap::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
switch (command.group) {
|
switch (command.group) {
|
||||||
case 0x1:
|
case 0x1:
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
|
@ -48,13 +49,14 @@ NvResult nvmap::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvmap::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult nvmap::Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvmap::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult nvmap::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) {
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,13 @@ public:
|
||||||
explicit nvmap(Core::System& system);
|
explicit nvmap(Core::System& system);
|
||||||
~nvmap() override;
|
~nvmap() override;
|
||||||
|
|
||||||
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
|
NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) override;
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) override;
|
||||||
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||||
std::vector<u8>& inline_output) override;
|
std::vector<u8>& inline_output, IoctlCtrl& ctrl) override;
|
||||||
|
|
||||||
/// 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;
|
||||||
|
|
|
@ -61,11 +61,33 @@ void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) {
|
||||||
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
||||||
const auto input_buffer = ctx.ReadBuffer(0);
|
const auto input_buffer = ctx.ReadBuffer(0);
|
||||||
|
|
||||||
const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer);
|
IoctlCtrl ctrl{};
|
||||||
|
|
||||||
|
const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer, ctrl);
|
||||||
|
if (ctrl.must_delay) {
|
||||||
|
ctrl.fresh_call = false;
|
||||||
|
ctx.SleepClientThread(
|
||||||
|
"NVServices::DelayedResponse", ctrl.timeout,
|
||||||
|
[=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_,
|
||||||
|
Kernel::ThreadWakeupReason reason) {
|
||||||
|
IoctlCtrl ctrl2{ctrl};
|
||||||
|
std::vector<u8> tmp_output = output_buffer;
|
||||||
|
const auto nv_result2 = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output, ctrl2);
|
||||||
|
|
||||||
|
if (command.is_out != 0) {
|
||||||
|
ctx.WriteBuffer(tmp_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx_, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushEnum(nv_result2);
|
||||||
|
},
|
||||||
|
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||||
|
} else {
|
||||||
if (command.is_out != 0) {
|
if (command.is_out != 0) {
|
||||||
ctx.WriteBuffer(output_buffer);
|
ctx.WriteBuffer(output_buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
@ -88,8 +110,35 @@ void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) {
|
||||||
const auto input_inlined_buffer = ctx.ReadBuffer(1);
|
const auto input_inlined_buffer = ctx.ReadBuffer(1);
|
||||||
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
||||||
|
|
||||||
|
IoctlCtrl ctrl{};
|
||||||
|
|
||||||
const auto nv_result =
|
const auto nv_result =
|
||||||
nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer);
|
nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer, ctrl);
|
||||||
|
if (ctrl.must_delay) {
|
||||||
|
ctrl.fresh_call = false;
|
||||||
|
ctx.SleepClientThread(
|
||||||
|
"NVServices::DelayedResponse", ctrl.timeout,
|
||||||
|
[=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_,
|
||||||
|
Kernel::ThreadWakeupReason reason) {
|
||||||
|
IoctlCtrl ctrl2{ctrl};
|
||||||
|
std::vector<u8> tmp_output = output_buffer;
|
||||||
|
const auto nv_result2 = nvdrv->Ioctl2(fd, command, input_buffer,
|
||||||
|
input_inlined_buffer, tmp_output, ctrl2);
|
||||||
|
|
||||||
|
if (command.is_out != 0) {
|
||||||
|
ctx.WriteBuffer(tmp_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx_, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushEnum(nv_result2);
|
||||||
|
},
|
||||||
|
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||||
|
} else {
|
||||||
|
if (command.is_out != 0) {
|
||||||
|
ctx.WriteBuffer(output_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (command.is_out != 0) {
|
if (command.is_out != 0) {
|
||||||
ctx.WriteBuffer(output_buffer);
|
ctx.WriteBuffer(output_buffer);
|
||||||
|
@ -116,13 +165,37 @@ void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) {
|
||||||
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
|
||||||
std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1));
|
std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1));
|
||||||
|
|
||||||
|
IoctlCtrl ctrl{};
|
||||||
const auto nv_result =
|
const auto nv_result =
|
||||||
nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline);
|
nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline, ctrl);
|
||||||
|
if (ctrl.must_delay) {
|
||||||
|
ctrl.fresh_call = false;
|
||||||
|
ctx.SleepClientThread(
|
||||||
|
"NVServices::DelayedResponse", ctrl.timeout,
|
||||||
|
[=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_,
|
||||||
|
Kernel::ThreadWakeupReason reason) {
|
||||||
|
IoctlCtrl ctrl2{ctrl};
|
||||||
|
std::vector<u8> tmp_output = output_buffer;
|
||||||
|
std::vector<u8> tmp_output2 = output_buffer;
|
||||||
|
const auto nv_result2 =
|
||||||
|
nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output2, ctrl2);
|
||||||
|
|
||||||
|
if (command.is_out != 0) {
|
||||||
|
ctx.WriteBuffer(tmp_output, 0);
|
||||||
|
ctx.WriteBuffer(tmp_output2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx_, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushEnum(nv_result2);
|
||||||
|
},
|
||||||
|
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||||
|
} else {
|
||||||
if (command.is_out != 0) {
|
if (command.is_out != 0) {
|
||||||
ctx.WriteBuffer(output_buffer, 0);
|
ctx.WriteBuffer(output_buffer, 0);
|
||||||
ctx.WriteBuffer(output_buffer_inline, 1);
|
ctx.WriteBuffer(output_buffer_inline, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
|
@ -97,4 +97,15 @@ union Ioctl {
|
||||||
BitField<31, 1, u32> is_out;
|
BitField<31, 1, u32> is_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IoctlCtrl {
|
||||||
|
// First call done to the servioce for services that call itself again after a call.
|
||||||
|
bool fresh_call{true};
|
||||||
|
// Tells the Ioctl Wrapper that it must delay the IPC response and send the thread to sleep
|
||||||
|
bool must_delay{};
|
||||||
|
// Timeout for the delay
|
||||||
|
s64 timeout{};
|
||||||
|
// NV Event Id
|
||||||
|
s32 event_id{-1};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia
|
||||||
|
|
|
@ -91,7 +91,7 @@ DeviceFD Module::Open(const std::string& device_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output) {
|
std::vector<u8>& output, IoctlCtrl& ctrl) {
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
||||||
return NvResult::InvalidState;
|
return NvResult::InvalidState;
|
||||||
|
@ -104,11 +104,12 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
return itr->second->Ioctl1(command, input, output);
|
return itr->second->Ioctl1(command, input, output, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output) {
|
const std::vector<u8>& inline_input, std::vector<u8>& output,
|
||||||
|
IoctlCtrl& ctrl) {
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
||||||
return NvResult::InvalidState;
|
return NvResult::InvalidState;
|
||||||
|
@ -121,11 +122,11 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
return itr->second->Ioctl2(command, input, inline_input, output);
|
return itr->second->Ioctl2(command, input, inline_input, output, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output, std::vector<u8>& inline_output) {
|
std::vector<u8>& output, std::vector<u8>& inline_output, IoctlCtrl& ctrl) {
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
|
||||||
return NvResult::InvalidState;
|
return NvResult::InvalidState;
|
||||||
|
@ -138,7 +139,7 @@ NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
return itr->second->Ioctl3(command, input, output, inline_output);
|
return itr->second->Ioctl3(command, input, output, inline_output, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult Module::Close(DeviceFD fd) {
|
NvResult Module::Close(DeviceFD fd) {
|
||||||
|
|
|
@ -119,13 +119,13 @@ public:
|
||||||
|
|
||||||
/// Sends an ioctl command to the specified file descriptor.
|
/// Sends an ioctl command to the specified file descriptor.
|
||||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output);
|
std::vector<u8>& output, IoctlCtrl& ctrl);
|
||||||
|
|
||||||
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
const std::vector<u8>& inline_input, std::vector<u8>& output);
|
const std::vector<u8>& inline_input, std::vector<u8>& output, IoctlCtrl& ctrl);
|
||||||
|
|
||||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
std::vector<u8>& output, std::vector<u8>& inline_output);
|
std::vector<u8>& output, std::vector<u8>& inline_output, IoctlCtrl& ctrl);
|
||||||
|
|
||||||
/// Closes a device file descriptor and returns operation success.
|
/// Closes a device file descriptor and returns operation success.
|
||||||
NvResult Close(DeviceFD fd);
|
NvResult Close(DeviceFD fd);
|
||||||
|
|
Loading…
Reference in a new issue