diff --git a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp index ba40777a..a60a53a8 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp @@ -6,7 +6,13 @@ #include "driver.h" #include "devices/nvdevice.h" -#define NVRESULT(x) [&response](NvResult err) { response.Push(err); return Result{}; }(x) +#define NVRESULT(x) [&response, this](NvResult err) { \ + if (err != NvResult::Success) \ + state.logger->Debug("IOCTL Failed: {}", err); \ + \ + response.Push(err); \ + return Result{}; \ + } (x) namespace skyline::service::nvdrv { INvDrvServices::INvDrvServices(const DeviceState &state, ServiceManager &manager, Driver &driver, const SessionPermissions &perms) : BaseService(state, manager), driver(driver), ctx(SessionContext{.perms = perms}) {} @@ -29,29 +35,34 @@ namespace skyline::service::nvdrv { return NVRESULT(NvResult::Success); } - Result INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - auto fd{request.Pop()}; - auto ioctl{request.Pop()}; - - auto inBuf{request.inputBuf.at(0)}; - auto outBuf{request.outputBuf.at(0)}; - + static NvResultValue> GetMainIoctlBuffer(IoctlDescriptor ioctl, span inBuf, span outBuf) { if (ioctl.in && inBuf.size() < ioctl.size) - return NVRESULT(NvResult::InvalidSize); + return NvResult::InvalidSize; if (ioctl.out && outBuf.size() < ioctl.size) - return NVRESULT(NvResult::InvalidSize); + return NvResult::InvalidSize; if (ioctl.in && ioctl.out) { if (outBuf.size() < inBuf.size()) - return NVRESULT(NvResult::InvalidSize); + return NvResult::InvalidSize; // Copy in buf to out buf for inout ioctls to avoid needing to pass around two buffers everywhere if (outBuf.data() != inBuf.data()) outBuf.copy_from(inBuf, ioctl.size); } - return NVRESULT(driver.Ioctl(fd, ioctl, ioctl.out ? outBuf : inBuf)); + return ioctl.out ? outBuf : inBuf; + } + + Result INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto fd{request.Pop()}; + auto ioctl{request.Pop()}; + + auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))}; + if (!buf) + return NVRESULT(buf); + else + return NVRESULT(driver.Ioctl(fd, ioctl, *buf)); } Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { @@ -85,6 +96,34 @@ namespace skyline::service::nvdrv { } } + Result INvDrvServices::Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto fd{request.Pop()}; + auto ioctl{request.Pop()}; + + // The inline buffer is technically not required + auto inlineBuf{request.inputBuf.size() > 1 ? request.inputBuf.at(1) : span{}}; + + auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))}; + if (!buf) + return NVRESULT(buf); + else + return NVRESULT(driver.Ioctl2(fd, ioctl, *buf, inlineBuf)); + } + + Result INvDrvServices::Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto fd{request.Pop()}; + auto ioctl{request.Pop()}; + + // The inline buffer is technically not required + auto inlineBuf{request.outputBuf.size() > 1 ? request.outputBuf.at(1) : span{}}; + + auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))}; + if (!buf) + return NVRESULT(buf); + else + return NVRESULT(driver.Ioctl3(fd, ioctl, *buf, inlineBuf)); + } + Result INvDrvServices::SetAruid(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { return NVRESULT(NvResult::Success); } diff --git a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.h b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.h index 7378874f..86a297c6 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.h +++ b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.h @@ -63,13 +63,13 @@ namespace skyline::service::nvdrv { * @brief Perform an IOCTL on the specified FD with an extra input buffer * @url https://switchbrew.org/wiki/NV_services#Ioctl2 */ - // Result Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + Result Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); /** * @brief Perform an IOCTL on the specified FD with an extra output buffer * @url https://switchbrew.org/wiki/NV_services#Ioctl3 */ - // Result Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + Result Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); /** * @brief Enables the graphics firmware memory margin @@ -84,7 +84,8 @@ namespace skyline::service::nvdrv { SFUNC(0x3, INvDrvServices, Initialize), SFUNC(0x4, INvDrvServices, QueryEvent), SFUNC(0x8, INvDrvServices, SetAruid), - + SFUNC(0xB, INvDrvServices, Ioctl2), + SFUNC(0xC, INvDrvServices, Ioctl3), SFUNC(0xD, INvDrvServices, SetGraphicsFirmwareMemoryMarginEnabled) ) }; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_def.h b/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_def.h index 1a69a7f9..4a031e7f 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_def.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_def.h @@ -3,6 +3,16 @@ #include "deserialisation.h" +#define INLINE_IOCTL_HANDLER_FUNC(type, name, cases) \ + PosixResult name::type(IoctlDescriptor cmd, span buffer, span inlineBuffer) { \ + using className = name; \ + switch (cmd.raw) { \ + cases; \ + default: \ + return PosixResult::InappropriateIoctlForDevice; \ + } \ + } + #define VARIABLE_IOCTL_HANDLER_FUNC(name, cases, variableCases) \ PosixResult name::Ioctl(IoctlDescriptor cmd, span buffer) { \ using className = name; \ @@ -28,11 +38,11 @@ } \ } -#define IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \ - case MetaIoctlDescriptor::Raw(): { \ - using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \ - auto args = DecodeArguments(buffer.subspan<0, size>()); \ - return std::apply(&className::name, std::tuple_cat(std::make_tuple(this), args)); \ +#define IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \ + case MetaIoctlDescriptor::Raw(): { \ + using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \ + auto args = DecodeArguments(buffer.subspan<0, size>()); \ + return std::apply(&className::name, std::tuple_cat(std::make_tuple(this), args)); \ } #define IOCTL_CASE_NOARGS_I(out, in, size, magic, function, name) \ @@ -47,6 +57,7 @@ #define IOCTL_CASE_NOARGS(...) IOCTL_CASE_NOARGS_I(__VA_ARGS__) #define IOCTL_CASE_RESULT(...) IOCTL_CASE_RESULT_I(__VA_ARGS__) + #define VARIABLE_IOCTL_CASE_ARGS_I(out, in, magic, function, name, ...) \ case MetaVariableIoctlDescriptor::Raw(): { \ using IoctlType = MetaVariableIoctlDescriptor; \ @@ -56,6 +67,16 @@ #define VARIABLE_IOCTL_CASE_ARGS(...) VARIABLE_IOCTL_CASE_ARGS_I(__VA_ARGS__) + +#define INLINE_IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \ + case MetaIoctlDescriptor::Raw(): { \ + using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \ + auto args = DecodeArguments(buffer.subspan<0, size>()); \ + return std::apply(&className::name, std::tuple_cat(std::make_tuple(this, inlineBuffer), args)); \ + } + +#define INLINE_IOCTL_CASE_ARGS(...) INLINE_IOCTL_CASE_ARGS_I(__VA_ARGS__) + #define IN false, true #define OUT true, false #define INOUT true, true diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_undef.h b/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_undef.h index 34af31c7..ca65bb3d 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_undef.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/deserialisation/macro_undef.h @@ -3,14 +3,21 @@ #undef IOCTL_HANDLER_FUNC #undef VARIABLE_IOCTL_HANDLER_FUNC +#undef INLINE_IOCTL_HANDLER_FUNC + #undef IOCTL_CASE_ARGS_I #undef IOCTL_CASE_NOARGS_I #undef IOCTL_CASE_RESULT_I #undef IOCTL_CASE_ARGS #undef IOCTL_CASE_NOARGS #undef IOCTL_CASE_RESULT + #undef VARIABLE_IOCTL_CASE_ARGS_I #undef VARIABLE_IOCTL_CASE_ARGS + +#undef INLINE_IOCTL_CASE_ARGS_I +#undef INLINE_IOCTL_CASE_ARGS + #undef IN #undef OUT #undef INOUT diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h index 3ba436b3..60e0c87e 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h @@ -40,9 +40,13 @@ namespace skyline::service::nvdrv::device { virtual PosixResult Ioctl(IoctlDescriptor cmd, span buffer) = 0; - virtual PosixResult Ioctl2(IoctlDescriptor cmd, span buffer, span inlineOutput) { return PosixResult::NotSupported; } + virtual PosixResult Ioctl2(IoctlDescriptor cmd, span buffer, span inlineOutput) { + return PosixResult::InappropriateIoctlForDevice; + } - virtual PosixResult Ioctl3(IoctlDescriptor cmd, span buffer, span inlineInput) { return PosixResult::NotSupported; } + virtual PosixResult Ioctl3(IoctlDescriptor cmd, span buffer, span inlineInput) { + return PosixResult::InappropriateIoctlForDevice; + } virtual std::shared_ptr QueryEvent(u32 eventId) { return nullptr; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.cpp index 01701f41..d8160a5f 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.cpp @@ -54,6 +54,8 @@ namespace skyline::service::nvdrv::device::nvhost { } PosixResult AsGpu::MapBufferEx(In flags, In kind, In handle, InOut pageSize, In bufferOffset, In mappingSize, InOut offset) { + state.logger->Debug("flags: ( fixed: {}, remap: {} ), kind: {}, handle: {}, pageSize: 0x{:X}, bufferOffset: 0x{:X}, mappingSize: 0x{:X}, offset: 0x{:X}", flags.fixed, flags.remap, kind, handle, pageSize, bufferOffset, mappingSize, offset); + if (flags.remap) { auto region{regionMap.lower_bound(offset)}; if (region == regionMap.end()) { @@ -95,8 +97,11 @@ namespace skyline::service::nvdrv::device::nvhost { if (offset == 0) { state.logger->Warn("Failed to map GPU address space region!"); return PosixResult::InvalidArgument; + } + state.logger->Debug("Mapped to 0x{:X}", offset); + regionMap[offset] = {cpuPtr, size, flags.fixed}; return PosixResult::Success; @@ -107,6 +112,10 @@ namespace skyline::service::nvdrv::device::nvhost { return PosixResult::Success; } + PosixResult AsGpu::GetVaRegions3(span inlineBufer, In bufAddr, InOut bufSize, Out> vaRegions) { + return GetVaRegions(bufAddr, bufSize, vaRegions); + } + PosixResult AsGpu::AllocAsEx(In bigPageSize, In asFd, In flags, In vaRangeStart, In vaRangeEnd, In vaRangeSplit) { // TODO: create the allocator here return PosixResult::Success; @@ -152,5 +161,10 @@ namespace skyline::service::nvdrv::device::nvhost { VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(AsGpuMagic), FUNC(0x14), Remap, ARGS(AutoSizeSpan)) })) + + INLINE_IOCTL_HANDLER_FUNC(Ioctl3, AsGpu, ({ + INLINE_IOCTL_CASE_ARGS(INOUT, SIZE(0x40), MAGIC(AsGpuMagic), FUNC(0x8), + GetVaRegions3, ARGS(In, InOut, Pad, Out>)) + })) #include } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h index 9dbad2af..ec109b08 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h @@ -85,6 +85,11 @@ namespace skyline::service::nvdrv::device::nvhost { */ PosixResult GetVaRegions(In bufAddr, InOut bufSize, Out> vaRegions); + /** + * @brief Ioctl3 variant of GetVaRegions + */ + PosixResult GetVaRegions3(span inlineBuffer, In bufAddr, InOut bufSize, Out> vaRegions); + /** * @brief Allocates this address space with the given parameters * @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX @@ -98,5 +103,7 @@ namespace skyline::service::nvdrv::device::nvhost { PosixResult Remap(span entries); PosixResult Ioctl(IoctlDescriptor cmd, span buffer) override; + + PosixResult Ioctl3(IoctlDescriptor cmd, span buffer, span inlineBuffer) override; }; } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.cpp index 58e3b57a..dbe5f2ab 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.cpp @@ -26,9 +26,22 @@ namespace skyline::service::nvdrv::device::nvhost { return PosixResult::Success; } - PosixResult CtrlGpu::GetTpcMasks(In bufSize, Out maskBuf) { - // TODO - maskBuf = 0x3; + PosixResult CtrlGpu::GetCharacteristics3(span inlineBuffer, InOut size, In userAddress, Out characteristics) { + inlineBuffer.as() = {}; + return GetCharacteristics(size, userAddress, characteristics); + } + + PosixResult CtrlGpu::GetTpcMasks(In bufSize, Out mask) { + if (bufSize) + mask = 0x3; + + return PosixResult::Success; + } + + PosixResult CtrlGpu::GetTpcMasks3(span inlineBuffer, In bufSize, Out mask) { + if (bufSize) + mask = inlineBuffer.as() = 0x3; + return PosixResult::Success; } @@ -60,7 +73,7 @@ namespace skyline::service::nvdrv::device::nvhost { IOCTL_CASE_ARGS(INOUT, SIZE(0xB0), MAGIC(CtrlGpuMagic), FUNC(0x5), GetCharacteristics, ARGS(InOut, In, Out)) IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(CtrlGpuMagic), FUNC(0x6), - GetTpcMasks, ARGS(In, Pad, Out)) + GetTpcMasks, ARGS(In, Pad, Out)) IOCTL_CASE_ARGS(OUT, SIZE(0x8), MAGIC(CtrlGpuMagic), FUNC(0x14), GetActiveSlotMask, ARGS(Out, Out)) })) diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.h index 03a9ca95..1183bb86 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.h @@ -93,11 +93,21 @@ namespace skyline::service::nvdrv::device::nvhost { */ PosixResult GetCharacteristics(InOut size, In userAddress, Out characteristics); + /** + * @brief Ioctl3 variant of GetTpcMasks + */ + PosixResult GetCharacteristics3(span inlineBuffer, InOut size, In userAddress, Out characteristics); + /** * @brief Returns the TPC mask value for each GPC * @url https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS */ - PosixResult GetTpcMasks(In bufSize, Out maskBuf); + PosixResult GetTpcMasks(In bufSize, Out mask); + + /** + * @brief Ioctl3 variant of GetTpcMasks + */ + PosixResult GetTpcMasks3(span inlineBuffer, In bufSize, Out mask); /** * @brief Returns the mask value for a ZBC slot diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.cpp index 26ea4492..c326c528 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.cpp @@ -23,7 +23,7 @@ namespace skyline::service::nvdrv::device::nvhost { } PosixResult GpuChannel::SubmitGpfifo(In userAddress, In numEntries, InOut flags, InOut fence, span gpEntries) { - if (numEntries != gpEntries.size()) + if (numEntries > gpEntries.size()) throw exception("GpEntry size mismatch!"); if (flags.fenceWait) { @@ -34,7 +34,7 @@ namespace skyline::service::nvdrv::device::nvhost { throw exception("Waiting on a fence through SubmitGpfifo is unimplemented"); } - state.soc->gm20b.gpfifo.Push(gpEntries); + state.soc->gm20b.gpfifo.Push(gpEntries.subspan(0, numEntries)); fence.id = channelSyncpoint; @@ -49,6 +49,10 @@ namespace skyline::service::nvdrv::device::nvhost { return PosixResult::Success; } + PosixResult GpuChannel::SubmitGpfifo2(span inlineBuffer, In userAddress, In numEntries, InOut flags, InOut fence) { + return SubmitGpfifo(userAddress, numEntries, flags, fence, inlineBuffer.cast()); + } + PosixResult GpuChannel::AllocObjCtx(In classId, In flags, Out objId) { return PosixResult::Success; } @@ -129,5 +133,10 @@ namespace skyline::service::nvdrv::device::nvhost { VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(GpuChannelMagic), FUNC(0x8), SubmitGpfifo, ARGS(In, In, InOut, InOut, AutoSizeSpan)) })) + + INLINE_IOCTL_HANDLER_FUNC(Ioctl2, GpuChannel, ({ + INLINE_IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(GpuChannelMagic), FUNC(0x1B), + SubmitGpfifo2, ARGS(In, In, InOut, InOut)) + })) #include } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.h index 1baf5d26..b9a807f3 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/gpu_channel.h @@ -57,6 +57,11 @@ namespace skyline::service::nvdrv::device::nvhost { */ PosixResult SubmitGpfifo(In userAddress, In numEntries, InOut flags, InOut fence, span gpEntries); + /** + * @brief Ioctl2 variant of SubmitGpfifo + */ + PosixResult SubmitGpfifo2(span inlineBuffer, In userAddress, In numEntries, InOut flags, InOut fence); + /** * @brief Allocates a graphic context object * @url https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX @@ -108,5 +113,7 @@ namespace skyline::service::nvdrv::device::nvhost { std::shared_ptr QueryEvent(u32 eventId) override; PosixResult Ioctl(IoctlDescriptor cmd, span buffer) override; + + PosixResult Ioctl2(IoctlDescriptor cmd, span buffer, span inlineBuffer) override; }; } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp index 0689089f..1eb36e05 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp @@ -13,6 +13,7 @@ namespace skyline::service::nvdrv::device { if (h) { (*h)->origSize = size; // Orig size is the unaligned size handle = (*h)->id; + state.logger->Debug("handle: {}, size: 0x{:X}", (*h)->id, size); } return h; @@ -47,6 +48,8 @@ namespace skyline::service::nvdrv::device { if (!h) [[unlikely]] return PosixResult::InvalidArgument; + state.logger->Debug("handle: {}, flags: ( mapUncached: {}, keepUncachedAfterFree: {} ), align: 0x{:X}, kind: {}, address: 0x{:X}", handle, flags.mapUncached, flags.keepUncachedAfterFree, align, kind, address); + return h->Alloc(flags, align, kind, address); } diff --git a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp index 3cdf8023..aa55d087 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp @@ -95,11 +95,34 @@ namespace skyline::service::nvdrv { } } + NvResult Driver::Ioctl(u32 fd, IoctlDescriptor cmd, span buffer) { + state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName()); + try { return ConvertResult(devices.at(fd)->Ioctl(cmd, buffer)); } catch (const std::out_of_range &) { - throw exception("GetDevice was called with invalid file descriptor: 0x{:X}", fd); + throw exception("Ioctl was called with invalid file descriptor: 0x{:X}", fd); + } + } + + NvResult Driver::Ioctl2(u32 fd, IoctlDescriptor cmd, span buffer, span inlineBuffer) { + state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName()); + + try { + return ConvertResult(devices.at(fd)->Ioctl2(cmd, buffer, inlineBuffer)); + } catch (const std::out_of_range &) { + throw exception("Ioctl2 was called with invalid file descriptor: 0x{:X}", fd); + } + } + + NvResult Driver::Ioctl3(u32 fd, IoctlDescriptor cmd, span buffer, span inlineBuffer) { + state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName()); + + try { + return ConvertResult(devices.at(fd)->Ioctl3(cmd, buffer, inlineBuffer)); + } catch (const std::out_of_range &) { + throw exception("Ioctl3 was called with invalid file descriptor: 0x{:X}", fd); } } @@ -112,6 +135,8 @@ namespace skyline::service::nvdrv { } std::shared_ptr Driver::QueryEvent(u32 fd, u32 eventId) { + state.logger->Debug("fd: {}, eventId: 0x{:X}, device: {}", fd, eventId, devices.at(fd)->GetName()); + try { return devices.at(fd)->QueryEvent(eventId); } catch (const std::exception &) { diff --git a/app/src/main/cpp/skyline/services/nvdrv/driver.h b/app/src/main/cpp/skyline/services/nvdrv/driver.h index 35284e40..2e827fc3 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/driver.h +++ b/app/src/main/cpp/skyline/services/nvdrv/driver.h @@ -32,6 +32,16 @@ namespace skyline::service::nvdrv { */ NvResult Ioctl(u32 fd, IoctlDescriptor cmd, span buffer); + /** + * @brief Calls an IOCTL on the device specified by `fd` using the given inline input buffer + */ + NvResult Ioctl2(u32 fd, IoctlDescriptor cmd, span buffer, span inlineBuffer); + + /** + * @brief Calls an IOCTL on the device specified by `fd` using the given inline output buffer + */ + NvResult Ioctl3(u32 fd, IoctlDescriptor cmd, span buffer, span inlineBuffer); + /** * @brief Queries a KEvent for the given `eventId` for the device specified by `fd` */ diff --git a/app/src/main/cpp/skyline/services/nvdrv/types.h b/app/src/main/cpp/skyline/services/nvdrv/types.h index 9cf4976b..abd75265 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/types.h +++ b/app/src/main/cpp/skyline/services/nvdrv/types.h @@ -90,4 +90,7 @@ namespace skyline::service::nvdrv { AccessDenied = 0x30010, IoctlFailed = 0x3000F }; + + template + using NvResultValue = ResultValue; }