nv: Added nvIoctl3, updated _nvGetSessionForRequest, and:

* Check hosver in nvIoctl2.
This commit is contained in:
yellows8 2022-02-26 12:51:06 -05:00
parent 3d9e1a9c7b
commit 04aa28c436
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 61 additions and 3 deletions

View File

@ -32,7 +32,8 @@ typedef enum {
Result nvOpen(u32 *fd, const char *devicepath); Result nvOpen(u32 *fd, const char *devicepath);
Result nvIoctl(u32 fd, u32 request, void* argp); Result nvIoctl(u32 fd, u32 request, void* argp);
Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size); Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size); ///< [3.0.0+]
Result nvIoctl3(u32 fd, u32 request, void* argp, void* outbuf, size_t outbuf_size); ///< [3.0.0+]
Result nvClose(u32 fd); Result nvClose(u32 fd);
Result nvQueryEvent(u32 fd, u32 event_id, Event *event_out); Result nvQueryEvent(u32 fd, u32 event_id, Event *event_out);

View File

@ -3,6 +3,7 @@
#include "service_guard.h" #include "service_guard.h"
#include "kernel/tmem.h" #include "kernel/tmem.h"
#include "services/applet.h" #include "services/applet.h"
#include "runtime/hosversion.h"
#include "services/nv.h" #include "services/nv.h"
#include "nvidia/ioctl.h" #include "nvidia/ioctl.h"
@ -112,11 +113,19 @@ Result nvOpen(u32 *fd, const char *devicepath) {
// Get the appropriate session for the specified request (same logic as official sw) // Get the appropriate session for the specified request (same logic as official sw)
static inline Service* _nvGetSessionForRequest(u32 request) { static inline Service* _nvGetSessionForRequest(u32 request) {
u32 tmp = request & 0xC000FFFF;
if ( if (
(request & 0xC000FFFF) == 0xC0004808 || // NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO tmp == 0xC0004402 || // NVGPU_DBG_GPU_IOCTL_REG_OPS
tmp == 0xC000471C || // NVGPU_GPU_IOCTL_GET_GPU_TIME
tmp == 0xC0004808 || // NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO
tmp == 0xC0000024 || // NVHOST_IOCTL_CHANNEL_SUBMIT_EX
tmp == 0xC0000025 || // NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER_EX
tmp == 0xC0000026 || // NVHOST_IOCTL_CHANNEL_UNMAP_CMD_BUFFER_EX
request == 0xC018481B || // NVGPU_IOCTL_CHANNEL_KICKOFF_PB request == 0xC018481B || // NVGPU_IOCTL_CHANNEL_KICKOFF_PB
request == 0xC004001C || // NVHOST_IOCTL_CTRL_EVENT_SIGNAL request == 0xC004001C || // NVHOST_IOCTL_CTRL_EVENT_SIGNAL
request == 0xC010001E // NVHOST_IOCTL_CTRL_EVENT_WAIT_ASYNC request == 0xC010001E || // NVHOST_IOCTL_CTRL_EVENT_WAIT_ASYNC
request == 0xC4C80203 || // NVDISP_FLIP
request == 0x400C060E // NVSCHED_CTRL_PUT_CONDUCTOR_FLIP_FENCE
) )
return &g_nvSrvClone; return &g_nvSrvClone;
return &g_nvSrv; return &g_nvSrv;
@ -163,6 +172,9 @@ Result nvIoctl(u32 fd, u32 request, void* argp) {
} }
Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size) { Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
size_t bufsize = _NV_IOC_SIZE(request); size_t bufsize = _NV_IOC_SIZE(request);
u32 dir = _NV_IOC_DIR(request); u32 dir = _NV_IOC_DIR(request);
@ -204,6 +216,51 @@ Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf
return rc; return rc;
} }
Result nvIoctl3(u32 fd, u32 request, void* argp, void* outbuf, size_t outbuf_size) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
size_t bufsize = _NV_IOC_SIZE(request);
u32 dir = _NV_IOC_DIR(request);
void *buf_send = NULL, *buf_recv = NULL;
size_t buf_send_size = 0, buf_recv_size = 0;
if (dir & _NV_IOC_WRITE) {
buf_send = argp;
buf_send_size = bufsize;
}
if (dir & _NV_IOC_READ) {
buf_recv = argp;
buf_recv_size = bufsize;
}
const struct {
u32 fd;
u32 request;
} in = { fd, request };
u32 error = 0;
Result rc = serviceDispatchInOut(_nvGetSessionForRequest(request), 12, in, error,
.buffer_attrs = {
SfBufferAttr_HipcAutoSelect | SfBufferAttr_In,
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
},
.buffers = {
{ buf_send, buf_send_size },
{ buf_recv, buf_recv_size },
{ outbuf, outbuf_size },
},
);
if (R_SUCCEEDED(rc))
rc = nvConvertError(error);
return rc;
}
Result nvClose(u32 fd) { Result nvClose(u32 fd) {
u32 error = 0; u32 error = 0;
Result rc = serviceDispatchInOut(&g_nvSrv, 2, fd, error); Result rc = serviceDispatchInOut(&g_nvSrv, 2, fd, error);