using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Memory; using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices { abstract class NvDeviceFile { public readonly ServiceCtx Context; public readonly long Owner; public string Path; public NvDeviceFile(ServiceCtx context, long owner) { Context = context; Owner = owner; } public virtual NvInternalResult QueryEvent(out int eventHandle, uint eventId) { eventHandle = 0; return NvInternalResult.NotImplemented; } public virtual NvInternalResult MapSharedMemory(int sharedMemoryHandle, uint argument) { // Close shared memory immediately as we don't use it. Context.Device.System.KernelContext.Syscall.CloseHandle(sharedMemoryHandle); return NvInternalResult.NotImplemented; } public virtual NvInternalResult Ioctl(NvIoctl command, Span arguments) { return NvInternalResult.NotImplemented; } public virtual NvInternalResult Ioctl2(NvIoctl command, Span arguments, Span inlineInBuffer) { return NvInternalResult.NotImplemented; } public virtual NvInternalResult Ioctl3(NvIoctl command, Span arguments, Span inlineOutBuffer) { return NvInternalResult.NotImplemented; } protected delegate NvInternalResult IoctlProcessor(ref T arguments); protected delegate NvInternalResult IoctlProcessorSpan(Span arguments); protected delegate NvInternalResult IoctlProcessorInline(ref T arguments, ref T1 inlineData); protected delegate NvInternalResult IoctlProcessorInlineSpan(ref T arguments, Span inlineData); private static NvInternalResult PrintResult(MethodInfo info, NvInternalResult result) { Logger.Debug?.Print(LogClass.ServiceNv, $"{info.Name} returned result {result}"); return result; } protected static NvInternalResult CallIoctlMethod(IoctlProcessor callback, Span arguments) where T : struct { Debug.Assert(arguments.Length == Unsafe.SizeOf()); return PrintResult(callback.Method, callback(ref MemoryMarshal.Cast(arguments)[0])); } protected static NvInternalResult CallIoctlMethod(IoctlProcessorInline callback, Span arguments, Span inlineBuffer) where T : struct where T1 : struct { Debug.Assert(arguments.Length == Unsafe.SizeOf()); Debug.Assert(inlineBuffer.Length == Unsafe.SizeOf()); return PrintResult(callback.Method, callback(ref MemoryMarshal.Cast(arguments)[0], ref MemoryMarshal.Cast(inlineBuffer)[0])); } protected static NvInternalResult CallIoctlMethod(IoctlProcessorSpan callback, Span arguments) where T : struct { return PrintResult(callback.Method, callback(MemoryMarshal.Cast(arguments))); } protected static NvInternalResult CallIoctlMethod(IoctlProcessorInlineSpan callback, Span arguments, Span inlineBuffer) where T : struct where T1 : struct { Debug.Assert(arguments.Length == Unsafe.SizeOf()); return PrintResult(callback.Method, callback(ref MemoryMarshal.Cast(arguments)[0], MemoryMarshal.Cast(inlineBuffer))); } public abstract void Close(); } }