Implement Ioctl3
This commit is contained in:
parent
72db77fbe6
commit
4cec3190ed
2 changed files with 55 additions and 5 deletions
|
@ -458,10 +458,49 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command(12)] // 3.0.0+
|
[Command(12)] // 3.0.0+
|
||||||
// Ioctl2(s32 fd, u32 ioctl_cmd, buffer<bytes, 0x21> in_args) -> (u32 error_code, buffer<bytes, 0x22> out_args, buffer<bytes, 0x22> out_additional_buffer)
|
// Ioctl3(s32 fd, u32 ioctl_cmd, buffer<bytes, 0x21> in_args) -> (u32 error_code, buffer<bytes, 0x22> out_args, buffer<bytes, 0x22> inline_out_buffer)
|
||||||
public ResultCode Ioctl3(ServiceCtx context)
|
public ResultCode Ioctl3(ServiceCtx context)
|
||||||
{
|
{
|
||||||
throw new ServiceNotImplementedException(context);
|
NvResult errorCode = EnsureInitialized();
|
||||||
|
|
||||||
|
if (errorCode == NvResult.Success)
|
||||||
|
{
|
||||||
|
int fd = context.RequestData.ReadInt32();
|
||||||
|
NvIoctl ioctlCommand = context.RequestData.ReadStruct<NvIoctl>();
|
||||||
|
|
||||||
|
(long inlineOutBufferPosition, long inlineOutBufferSize) = context.Request.GetBufferType0x22(1);
|
||||||
|
|
||||||
|
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
|
||||||
|
|
||||||
|
Span<byte> inlineOutBuffer = new Span<byte>(context.Memory.ReadBytes(inlineOutBufferPosition, inlineOutBufferSize));
|
||||||
|
|
||||||
|
if (errorCode == NvResult.Success)
|
||||||
|
{
|
||||||
|
errorCode = GetFileDeviceFromFd(fd, out NvFileDevice fileDevice);
|
||||||
|
|
||||||
|
if (errorCode == NvResult.Success)
|
||||||
|
{
|
||||||
|
NvInternalResult internalResult = fileDevice.Ioctl3(ioctlCommand, arguments, inlineOutBuffer);
|
||||||
|
|
||||||
|
if (internalResult == NvInternalResult.NotImplemented)
|
||||||
|
{
|
||||||
|
throw new NvIoctlNotImplementedException(context, fileDevice, ioctlCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCode = ConvertInternalErrorCode(internalResult);
|
||||||
|
|
||||||
|
if (errorCode == NvResult.Success && (ioctlCommand.GetDirectionValue() & NvIoctl.Direction.Write) != 0)
|
||||||
|
{
|
||||||
|
context.Memory.WriteBytes(context.Request.GetBufferType0x22(0).Position, arguments.ToArray());
|
||||||
|
context.Memory.WriteBytes(inlineOutBufferPosition, inlineOutBuffer.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.ResponseData.Write((uint)errorCode);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command(13)] // 3.0.0+
|
[Command(13)] // 3.0.0+
|
||||||
|
|
|
@ -50,18 +50,22 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
|
||||||
|
|
||||||
protected delegate NvInternalResult IoctlProcessor<T>(ref T arguments);
|
protected delegate NvInternalResult IoctlProcessor<T>(ref T arguments);
|
||||||
protected delegate NvInternalResult IoctlProcessorSpan<T>(Span<T> arguments);
|
protected delegate NvInternalResult IoctlProcessorSpan<T>(Span<T> arguments);
|
||||||
protected delegate NvInternalResult IoctlProcessorInline<T, Y>(ref T arguments, Span<Y> inlineData);
|
protected delegate NvInternalResult IoctlProcessorInline<T, Y>(ref T arguments, ref Y inlineData);
|
||||||
|
protected delegate NvInternalResult IoctlProcessorInlineSpan<T, Y>(ref T arguments, Span<Y> inlineData);
|
||||||
|
|
||||||
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessor<T> callback, Span<byte> arguments) where T : struct
|
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessor<T> callback, Span<byte> arguments) where T : struct
|
||||||
{
|
{
|
||||||
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
|
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
|
||||||
|
|
||||||
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0]);
|
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static NvInternalResult CallIoctlMethod<T, Y>(IoctlProcessorInline<T, Y> callback, Span<byte> arguments, Span<byte> inlineInBuffer) where T : struct where Y : struct
|
protected static NvInternalResult CallIoctlMethod<T, Y>(IoctlProcessorInline<T, Y> callback, Span<byte> arguments, Span<byte> inlineBuffer) where T : struct where Y : struct
|
||||||
{
|
{
|
||||||
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
|
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
|
||||||
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0], MemoryMarshal.Cast<byte, Y>(inlineInBuffer));
|
Debug.Assert(inlineBuffer.Length == Unsafe.SizeOf<Y>());
|
||||||
|
|
||||||
|
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0], ref MemoryMarshal.Cast<byte, Y>(inlineBuffer)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessorSpan<T> callback, Span<byte> arguments) where T : struct
|
protected static NvInternalResult CallIoctlMethod<T>(IoctlProcessorSpan<T> callback, Span<byte> arguments) where T : struct
|
||||||
|
@ -69,6 +73,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
|
||||||
return callback(MemoryMarshal.Cast<byte, T>(arguments));
|
return callback(MemoryMarshal.Cast<byte, T>(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static NvInternalResult CallIoctlMethod<T, Y>(IoctlProcessorInlineSpan<T, Y> callback, Span<byte> arguments, Span<byte> inlineBuffer) where T : struct where Y : struct
|
||||||
|
{
|
||||||
|
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
|
||||||
|
|
||||||
|
return callback(ref MemoryMarshal.Cast<byte, T>(arguments)[0], MemoryMarshal.Cast<byte, Y>(inlineBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void Close();
|
public abstract void Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue