aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-07-15 00:04:46 -0300
committerGitHub <noreply@github.com>2018-07-15 00:04:46 -0300
commit21e590c3abe64a0cbe4e51ebcc9f4bb0f945fc00 (patch)
tree4ed9d303fb1c0a98d801f62fb3ca8b4b35d50ed0
parent98c6ceede564eda4aed528e51219a9b0d6bea1c4 (diff)
Add support for ioctl2, SetTimeout and KickoffPbWithAttr (#261)
* Add support for ioctl2, SetTimeout and KickoffPbWithAttr * Call UnloadProcess on NvHostChannelIoctl aswell
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/INvDrvServices.cs17
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannel.cs7
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannelName.cs7
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs116
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelSubmitGpfifo.cs2
5 files changed, 123 insertions, 26 deletions
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/OsHle/Services/Nv/INvDrvServices.cs
index 5c1748bd..4654d15f 100644
--- a/Ryujinx.HLE/OsHle/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nv/INvDrvServices.cs
@@ -23,11 +23,11 @@ namespace Ryujinx.HLE.OsHle.Services.Nv
private static Dictionary<string, IoctlProcessor> IoctlProcessors =
new Dictionary<string, IoctlProcessor>()
{
- { "/dev/nvhost-as-gpu", ProcessIoctlNvGpuAS },
- { "/dev/nvhost-ctrl", ProcessIoctlNvHostCtrl },
- { "/dev/nvhost-ctrl-gpu", ProcessIoctlNvGpuGpu },
- { "/dev/nvhost-gpu", ProcessIoctlNvHostChannel },
- { "/dev/nvmap", ProcessIoctlNvMap }
+ { "/dev/nvhost-as-gpu", ProcessIoctlNvGpuAS },
+ { "/dev/nvhost-ctrl", ProcessIoctlNvHostCtrl },
+ { "/dev/nvhost-ctrl-gpu", ProcessIoctlNvGpuGpu },
+ { "/dev/nvhost-gpu", ProcessIoctlNvHostGpu },
+ { "/dev/nvmap", ProcessIoctlNvMap }
};
public static GlobalStateTable Fds { get; private set; }
@@ -44,6 +44,7 @@ namespace Ryujinx.HLE.OsHle.Services.Nv
{ 3, Initialize },
{ 4, QueryEvent },
{ 8, SetClientPid },
+ { 11, Ioctl },
{ 13, FinishInitialize }
};
@@ -162,9 +163,9 @@ namespace Ryujinx.HLE.OsHle.Services.Nv
return ProcessIoctl(Context, Cmd, NvGpuGpuIoctl.ProcessIoctl);
}
- private static int ProcessIoctlNvHostChannel(ServiceCtx Context, int Cmd)
+ private static int ProcessIoctlNvHostGpu(ServiceCtx Context, int Cmd)
{
- return ProcessIoctl(Context, Cmd, NvHostChannelIoctl.ProcessIoctl);
+ return ProcessIoctl(Context, Cmd, NvHostChannelIoctl.ProcessIoctlGpu);
}
private static int ProcessIoctlNvMap(ServiceCtx Context, int Cmd)
@@ -207,6 +208,8 @@ namespace Ryujinx.HLE.OsHle.Services.Nv
NvGpuASIoctl.UnloadProcess(Process);
+ NvHostChannelIoctl.UnloadProcess(Process);
+
NvHostCtrlIoctl.UnloadProcess(Process);
NvMapIoctl.UnloadProcess(Process);
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannel.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannel.cs
new file mode 100644
index 00000000..486c3806
--- /dev/null
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannel.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
+{
+ class NvChannel
+ {
+ public int Timeout;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannelName.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannelName.cs
new file mode 100644
index 00000000..a46a6d98
--- /dev/null
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvChannelName.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
+{
+ enum NvChannelName
+ {
+ Gpu
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
index 8f3d3cd7..411a579a 100644
--- a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
@@ -3,23 +3,50 @@ using Ryujinx.HLE.Gpu.Memory;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Services.Nv.NvGpuAS;
using System;
+using System.Collections.Concurrent;
namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
{
class NvHostChannelIoctl
{
- public static int ProcessIoctl(ServiceCtx Context, int Cmd)
+ private class ChannelsPerProcess
+ {
+ public ConcurrentDictionary<NvChannelName, NvChannel> Channels { get; private set; }
+
+ public ChannelsPerProcess()
+ {
+ Channels = new ConcurrentDictionary<NvChannelName, NvChannel>();
+
+ Channels.TryAdd(NvChannelName.Gpu, new NvChannel());
+ }
+ }
+
+ private static ConcurrentDictionary<Process, ChannelsPerProcess> Channels;
+
+ static NvHostChannelIoctl()
+ {
+ Channels = new ConcurrentDictionary<Process, ChannelsPerProcess>();
+ }
+
+ public static int ProcessIoctlGpu(ServiceCtx Context, int Cmd)
+ {
+ return ProcessIoctl(Context, NvChannelName.Gpu, Cmd);
+ }
+
+ public static int ProcessIoctl(ServiceCtx Context, NvChannelName Channel, int Cmd)
{
switch (Cmd & 0xffff)
{
- case 0x4714: return SetUserData (Context);
- case 0x4801: return SetNvMap (Context);
- case 0x4808: return SubmitGpfifo (Context);
- case 0x4809: return AllocObjCtx (Context);
- case 0x480b: return ZcullBind (Context);
- case 0x480c: return SetErrorNotifier(Context);
- case 0x480d: return SetPriority (Context);
- case 0x481a: return AllocGpfifoEx2 (Context);
+ case 0x4714: return SetUserData (Context);
+ case 0x4801: return SetNvMap (Context);
+ case 0x4803: return SetTimeout (Context, Channel);
+ case 0x4808: return SubmitGpfifo (Context);
+ case 0x4809: return AllocObjCtx (Context);
+ case 0x480b: return ZcullBind (Context);
+ case 0x480c: return SetErrorNotifier (Context);
+ case 0x480d: return SetPriority (Context);
+ case 0x481a: return AllocGpfifoEx2 (Context);
+ case 0x481b: return KickoffPbWithAttr(Context);
}
throw new NotImplementedException(Cmd.ToString("x8"));
@@ -45,6 +72,15 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
return NvResult.Success;
}
+ private static int SetTimeout(ServiceCtx Context, NvChannelName Channel)
+ {
+ long InputPosition = Context.Request.GetBufferType0x21().Position;
+
+ GetChannel(Context, Channel).Timeout = Context.Memory.ReadInt32(InputPosition);
+
+ return NvResult.Success;
+ }
+
private static int SubmitGpfifo(ServiceCtx Context)
{
long InputPosition = Context.Request.GetBufferType0x21().Position;
@@ -58,15 +94,7 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
{
long Gpfifo = Context.Memory.ReadInt64(InputPosition + 0x18 + Index * 8);
- long VA = Gpfifo & 0xff_ffff_ffff;
-
- int Size = (int)(Gpfifo >> 40) & 0x7ffffc;
-
- byte[] Data = Vmm.ReadBytes(VA, Size);
-
- NvGpuPBEntry[] PushBuffer = NvGpuPushBuffer.Decode(Data);
-
- Context.Ns.Gpu.Fifo.PushBuffer(Vmm, PushBuffer);
+ PushGpfifo(Context, Vmm, Gpfifo);
}
Args.SyncptId = 0;
@@ -126,5 +154,57 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
return NvResult.Success;
}
+
+ private static int KickoffPbWithAttr(ServiceCtx Context)
+ {
+ long InputPosition = Context.Request.GetBufferType0x21().Position;
+ long OutputPosition = Context.Request.GetBufferType0x22().Position;
+
+ NvHostChannelSubmitGpfifo Args = AMemoryHelper.Read<NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition);
+
+ NvGpuVmm Vmm = NvGpuASIoctl.GetVmm(Context);
+
+ for (int Index = 0; Index < Args.NumEntries; Index++)
+ {
+ long Gpfifo = Context.Memory.ReadInt64(Args.Address + Index * 8);
+
+ PushGpfifo(Context, Vmm, Gpfifo);
+ }
+
+ Args.SyncptId = 0;
+ Args.SyncptValue = 0;
+
+ AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+
+ return NvResult.Success;
+ }
+
+ private static void PushGpfifo(ServiceCtx Context, NvGpuVmm Vmm, long Gpfifo)
+ {
+ long VA = Gpfifo & 0xff_ffff_ffff;
+
+ int Size = (int)(Gpfifo >> 40) & 0x7ffffc;
+
+ byte[] Data = Vmm.ReadBytes(VA, Size);
+
+ NvGpuPBEntry[] PushBuffer = NvGpuPushBuffer.Decode(Data);
+
+ Context.Ns.Gpu.Fifo.PushBuffer(Vmm, PushBuffer);
+ }
+
+ public static NvChannel GetChannel(ServiceCtx Context, NvChannelName Channel)
+ {
+ ChannelsPerProcess Cpp = Channels.GetOrAdd(Context.Process, (Key) =>
+ {
+ return new ChannelsPerProcess();
+ });
+
+ return Cpp.Channels[Channel];
+ }
+
+ public static void UnloadProcess(Process Process)
+ {
+ Channels.TryRemove(Process, out _);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelSubmitGpfifo.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelSubmitGpfifo.cs
index 9541f701..ee945839 100644
--- a/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelSubmitGpfifo.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvHostChannel/NvHostChannelSubmitGpfifo.cs
@@ -2,7 +2,7 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostChannel
{
struct NvHostChannelSubmitGpfifo
{
- public long Gpfifo;
+ public long Address;
public int NumEntries;
public int Flags;
public int SyncptId;