Stylechanges to binder, and implemented gpu address space

This commit is contained in:
plutooo 2018-02-26 05:27:55 +01:00 committed by fincs
parent cd753b1b58
commit 04751087ca
10 changed files with 167 additions and 95 deletions

View File

@ -69,10 +69,12 @@ extern "C" {
#include "switch/display/binder.h" #include "switch/display/binder.h"
#include "switch/display/parcel.h" #include "switch/display/parcel.h"
#include "switch/display/buffer_producer.h" #include "switch/display/buffer_producer.h"
#include "switch/display/ioctl.h"
#include "switch/display/nvioctl.h"
#include "switch/display/nvgfx.h" #include "switch/display/nvgfx.h"
#include "switch/nvidia/ioctl.h"
#include "switch/nvidia/nvmap.h"
#include "switch/nvidia/address_space.h"
#include "switch/audio/driver.h" #include "switch/audio/driver.h"
#include "switch/runtime/env.h" #include "switch/runtime/env.h"

View File

@ -6,24 +6,25 @@
typedef struct { typedef struct {
bool created; bool created;
bool initialized; bool initialized;
Handle sessionHandle; Handle session_handle;
s32 id; s32 id;
Handle nativeHandle; Handle native_handle;
size_t ipcBufferSize; size_t ipc_buffer_size;
bool hasTransactAuto; bool has_transact_auto;
} Binder; } Binder;
// binderExitSession will not close the sessionHandle since it's user-specified via binderCreateSession and may be used elsewhere. // Note: binderClose will not close the session_handle provided to binderCreate.
void binderCreateSession(Binder *session, Handle sessionHandle, s32 ID); void binderCreate(Binder* b, Handle session_handle, s32 id);
Result binderInitSession(Binder *session, u32 unk0); void binderClose(Binder* b);
void binderExitSession(Binder *session);
Result binderInitSession(Binder* b, u32 unk0);
Result binderTransactParcel( Result binderTransactParcel(
Binder *session, u32 code, Binder* b, u32 code,
void* parcel_data, size_t parcel_data_size, void* parcel_data, size_t parcel_data_size,
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags); u32 flags);
Result binderAdjustRefcount(Binder *session, s32 addval, s32 type); Result binderAdjustRefcount(Binder* b, s32 addval, s32 type);
Result binderGetNativeHandle(Binder *session, u32 unk0, Handle *handle_out); Result binderGetNativeHandle(Binder* b, u32 unk0, Handle *handle_out);

View File

@ -14,7 +14,7 @@ typedef struct {
u32 pos; u32 pos;
} Parcel; } Parcel;
void parcelInitialize(Parcel *ctx); void parcelCreate(Parcel *ctx);
Result parcelTransact(Binder *session, u32 code, Parcel *in_parcel, Parcel *reply_parcel); Result parcelTransact(Binder *session, u32 code, Parcel *in_parcel, Parcel *reply_parcel);
void* parcelWriteData(Parcel *ctx, void* data, size_t data_size); void* parcelWriteData(Parcel *ctx, void* data, size_t data_size);

View File

@ -0,0 +1,22 @@
#pragma once
typedef struct {
u32 fd;
} NvAddressSpace;
typedef enum {
NvPageSize_4K = 0x1000,
NvPageSize_64K = 0x10000
} NvPageSize;
typedef u64 iova_t;
Result nvasCreate(NvAddressSpace* a);
Result nvasClose(NvAddressSpace* a);
Result nvasReserveAlign(NvAddressSpace* a, NvPageSize align, u32 pages, NvPageSize page_sz, iova_t* iova_out);
Result nvasReserveAtFixedAddr(NvAddressSpace* a, iova_t addr, u32 pages, NvPageSize page_sz);
Result nvasReserveFull(NvAddressSpace* a);
Result nvasMapBuffer(NvAddressSpace* a, Nvmap* buffer, NvmapKind kind, iova_t* iova_out);

View File

@ -5,94 +5,99 @@
#include "kernel/detect.h" #include "kernel/detect.h"
#include "display/binder.h" #include "display/binder.h"
void binderCreateSession(Binder *session, Handle sessionHandle, s32 id) void binderCreate(Binder* b, Handle session_handle, s32 id)
{ {
memset(session, 0, sizeof(Binder)); memset(b, 0, sizeof(Binder));
session->created = 1; b->created = true;
session->sessionHandle = sessionHandle; b->session_handle = session_handle;
session->id = id; b->id = id;
session->nativeHandle = INVALID_HANDLE; b->native_handle = INVALID_HANDLE;
session->hasTransactAuto = 0; b->has_transact_auto = false;
} }
Result binderInitSession(Binder *session, u32 unk0) Result binderInitSession(Binder* b, u32 unk0)
{ {
Result rc = 0; Result rc = 0;
if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (!b->created)
if (session->initialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = binderAdjustRefcount(session, 1, 0); if (b->initialized)
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
rc = binderAdjustRefcount(b, 1, 0);
if (R_FAILED(rc)) if (R_FAILED(rc))
return rc; return rc;
rc = binderAdjustRefcount(session, 1, 1); rc = binderAdjustRefcount(b, 1, 1);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
binderAdjustRefcount(session, -1, 0); binderAdjustRefcount(b, -1, 0);
return rc; return rc;
} }
rc = binderGetNativeHandle(session, unk0, &session->nativeHandle); rc = binderGetNativeHandle(b, unk0, &b->native_handle);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
binderAdjustRefcount(session, -1, 1); binderAdjustRefcount(b, -1, 1);
binderAdjustRefcount(session, -1, 0); binderAdjustRefcount(b, -1, 0);
return rc; return rc;
} }
// When the output nativeHandle is 0 the Binder ID is probably invalid. // When the output native_handle is 0 the Binder ID is probably invalid.
if (session->nativeHandle == 0) { if (b->native_handle == 0) {
binderAdjustRefcount(session, -1, 1); binderAdjustRefcount(b, -1, 1);
binderAdjustRefcount(session, -1, 0); binderAdjustRefcount(b, -1, 0);
return MAKERESULT(Module_Libnx, LibnxError_BadInput); return MAKERESULT(Module_Libnx, LibnxError_BadInput);
} }
session->initialized = 1; b->initialized = true;
rc = ipcQueryPointerBufferSize(session->sessionHandle, &session->ipcBufferSize); rc = ipcQueryPointerBufferSize(b->session_handle, &b->ipc_buffer_size);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
binderExitSession(session); binderClose(b);
return rc; return rc;
} }
// Use TransactParcelAuto when available. // Use TransactParcelAuto when available.
if (kernelAbove300()) if (kernelAbove300())
session->hasTransactAuto = 1; b->has_transact_auto = true;
return rc; return rc;
} }
void binderExitSession(Binder *session) void binderExitSession(Binder* b)
{ {
if (!session->created) return; if (!b->created)
return;
if (session->initialized) { if (b->initialized) {
binderAdjustRefcount(session, -1, 1); binderAdjustRefcount(b, -1, 1);
binderAdjustRefcount(session, -1, 0); binderAdjustRefcount(b, -1, 0);
if (session->nativeHandle != INVALID_HANDLE) { if (b->native_handle != INVALID_HANDLE) {
svcCloseHandle(session->nativeHandle); svcCloseHandle(b->native_handle);
session->nativeHandle = INVALID_HANDLE; b->native_handle = INVALID_HANDLE;
} }
} }
session->sessionHandle = INVALID_HANDLE; b->session_handle = INVALID_HANDLE;
session->id = 0; b->id = 0;
session->created = 0; b->created = false;
session->initialized = 0; b->initialized = false;
} }
static Result _binderTransactParcel( static Result _binderTransactParcel(
Binder *session, u32 code, Binder* b, u32 code,
void* parcel_data, size_t parcel_data_size, void* parcel_data, size_t parcel_data_size,
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags) u32 flags)
{ {
if (!session->created || !session->initialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (!b->created || !b->initialized)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -111,11 +116,11 @@ static Result _binderTransactParcel(
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 0; raw->cmd_id = 0;
raw->session_id = session->id; raw->session_id = b->id;
raw->code = code; raw->code = code;
raw->flags = flags; raw->flags = flags;
Result rc = ipcDispatch(session->sessionHandle); Result rc = ipcDispatch(b->session_handle);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
@ -133,12 +138,13 @@ static Result _binderTransactParcel(
} }
static Result _binderTransactParcelAuto( static Result _binderTransactParcelAuto(
Binder *session, u32 code, Binder* b, u32 code,
void* parcel_data, size_t parcel_data_size, void* parcel_data, size_t parcel_data_size,
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags) u32 flags)
{ {
if (!session->created || !session->initialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (!b->created || !b->initialized)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -151,17 +157,17 @@ static Result _binderTransactParcelAuto(
u32 flags; u32 flags;
} *raw; } *raw;
ipcAddSendSmart(&c, session->ipcBufferSize, parcel_data, parcel_data_size, 0); ipcAddSendSmart(&c, b->ipc_buffer_size, parcel_data, parcel_data_size, 0);
ipcAddRecvSmart(&c, session->ipcBufferSize, parcel_reply, parcel_reply_size, 0); ipcAddRecvSmart(&c, b->ipc_buffer_size, parcel_reply, parcel_reply_size, 0);
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 3; raw->cmd_id = 3;
raw->session_id = session->id; raw->session_id = b->id;
raw->code = code; raw->code = code;
raw->flags = flags; raw->flags = flags;
Result rc = ipcDispatch(session->sessionHandle); Result rc = ipcDispatch(b->session_handle);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
@ -179,24 +185,25 @@ static Result _binderTransactParcelAuto(
} }
Result binderTransactParcel( Result binderTransactParcel(
Binder *session, u32 code, Binder* b, u32 code,
void* parcel_data, size_t parcel_data_size, void* parcel_data, size_t parcel_data_size,
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags) u32 flags)
{ {
Result rc = 0; Result rc = 0;
if (session->hasTransactAuto) if (b->has_transact_auto)
rc = _binderTransactParcelAuto(session, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); rc = _binderTransactParcelAuto(b, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags);
else else
rc = _binderTransactParcel(session, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); rc = _binderTransactParcel(b, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags);
return rc; return rc;
} }
Result binderAdjustRefcount(Binder *session, s32 addval, s32 type) Result binderAdjustRefcount(Binder* b, s32 addval, s32 type)
{ {
if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (!b->created)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -212,11 +219,11 @@ Result binderAdjustRefcount(Binder *session, s32 addval, s32 type)
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 1; raw->cmd_id = 1;
raw->session_id = session->id; raw->session_id = b->id;
raw->addval = addval; raw->addval = addval;
raw->type = type; raw->type = type;
Result rc = ipcDispatch(session->sessionHandle); Result rc = ipcDispatch(b->session_handle);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
@ -233,9 +240,10 @@ Result binderAdjustRefcount(Binder *session, s32 addval, s32 type)
return rc; return rc;
} }
Result binderGetNativeHandle(Binder *session, u32 inval, Handle *handle_out) Result binderGetNativeHandle(Binder* b, u32 inval, Handle *handle_out)
{ {
if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (!b->created)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -251,10 +259,10 @@ Result binderGetNativeHandle(Binder *session, u32 inval, Handle *handle_out)
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 2; raw->cmd_id = 2;
raw->session_id = session->id; raw->session_id = b->id;
raw->inval = inval; raw->inval = inval;
Result rc = ipcDispatch(session->sessionHandle); Result rc = ipcDispatch(b->session_handle);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;

View File

@ -50,8 +50,8 @@ Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf)
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, bufferIdx); parcelWriteInt32(&parcel, bufferIdx);
@ -91,8 +91,8 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage,
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
@ -135,8 +135,8 @@ Result bqDetachBuffer(s32 slot)
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, slot); parcelWriteInt32(&parcel, slot);
@ -158,8 +158,8 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf); parcelWriteInt32(&parcel, buf);
@ -187,8 +187,8 @@ Result bqQuery(s32 what, s32* value)
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, what); parcelWriteInt32(&parcel, what);
@ -214,8 +214,8 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
@ -246,8 +246,8 @@ Result bqDisconnect(s32 api)
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, api); parcelWriteInt32(&parcel, api);
@ -270,8 +270,8 @@ Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input)
if (g_bqBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelCreate(&parcel);
parcelInitialize(&parcel_reply); parcelCreate(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf); parcelWriteInt32(&parcel, buf);

View File

@ -235,7 +235,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
if (R_SUCCEEDED(rc)) rc = _gfxGetNativeWindowID(g_gfxNativeWindow, g_gfxNativeWindow_Size, &g_gfxNativeWindow_ID); if (R_SUCCEEDED(rc)) rc = _gfxGetNativeWindowID(g_gfxNativeWindow, g_gfxNativeWindow_Size, &g_gfxNativeWindow_ID);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
binderCreateSession(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxNativeWindow_ID); binderCreate(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxNativeWindow_ID);
rc = binderInitSession(&g_gfxBinderSession, 0x0f); rc = binderInitSession(&g_gfxBinderSession, 0x0f);
} }
@ -291,7 +291,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
nvgfxExit(); nvgfxExit();
bqExit(); bqExit();
binderExitSession(&g_gfxBinderSession); binderClose(&g_gfxBinderSession);
nvExit(); nvExit();
viCloseLayer(&g_gfxLayer); viCloseLayer(&g_gfxLayer);
@ -361,7 +361,7 @@ void gfxExit(void)
nvgfxExit(); nvgfxExit();
bqExit(); bqExit();
binderExitSession(&g_gfxBinderSession); binderClose(&g_gfxBinderSession);
nvExit(); nvExit();

View File

@ -11,7 +11,7 @@ typedef struct {
u32 objects_off; u32 objects_off;
} ParcelHeader; } ParcelHeader;
void parcelInitialize(Parcel *ctx) void parcelCreate(Parcel *ctx)
{ {
memset(ctx, 0, sizeof(Parcel)); memset(ctx, 0, sizeof(Parcel));
ctx->capacity = sizeof(ctx->payload); ctx->capacity = sizeof(ctx->payload);

View File

@ -0,0 +1,38 @@
#include <switch.h>
Result nvasCreate(NvAddressSpace* a)
{
Result rc = nvOpen(&a->fd, "/dev/nvhost-as-gpu");
if (R_SUCCEEDED(rc))
{
rc = nvioctlNvhostAsGpu_InitializeEx(a->fd, 1, 0x100);
if (R_FAILED(rc))
nvasClose(a);
}
return rc;
}
Result nvasClose(NvAddressSpace* a)
{
nvClose(a->fd);
a->fd = -1;
}
Result nvasReserveAlign(NvAddressSpace* a, NvPageSize align, u32 pages, NvPageSize page_sz, iova_t* iova_out) {
return nvioctlNvhostAsGpu_AllocSpace(a->fd, pages, page_sz, 0, align, iova_out);
}
Result nvasReserveAtFixedAddr(NvAddressSpace* a, iova_t addr, u32 pages, NvPageSize page_sz) {
return nvioctlNvhostAsGpu_AllocSpace(a->fd, pages, page_sz, 1, addr, NULL);
}
Result nvasReserveFull(NvAddressSpace* a) {
return nvasReserveAlign(a, NvPageSize_64K, 0x10000, NvPageSize_64K, NULL);
}
Result nvasMapBuffer(NvAddressSpace* a, Nvmap* buffer, NvmapKind kind, iova_t* iova_out) {
return nvioctlNvhostAsGpu_MapBufferEx(a->fd, 0, kind, buffer->fd, 0, 0, buffer->size, 0, iova_out);
}

View File

@ -15,7 +15,7 @@ Result nvioctlNvhostAsGpu_BindChannel(u32 fd, u32 channel_fd) {
return nvIoctl(fd, _NV_IOW(0x41, 0x01, data), &data); return nvIoctl(fd, _NV_IOW(0x41, 0x01, data), &data);
} }
Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align, u64 *offset) { Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align_or_offset, u64 *offset) {
Result rc = 0; Result rc = 0;
struct { struct {
@ -33,12 +33,13 @@ Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags
data.pages = pages; data.pages = pages;
data.page_size = page_size; data.page_size = page_size;
data.flags = flags; data.flags = flags;
data.align = align; data.align = align_or_offset;
rc = nvIoctl(fd, _NV_IOWR(0x41, 0x02, data), &data); rc = nvIoctl(fd, _NV_IOWR(0x41, 0x02, data), &data);
if (R_FAILED(rc)) return rc; if (R_FAILED(rc)) return rc;
*offset = data.offset; if (offset != NULL)
*offset = data.offset;
return rc; return rc;
} }