Implement Ioctl3

This commit is contained in:
Thog 2019-10-29 00:37:31 +01:00
parent 72db77fbe6
commit 4cec3190ed
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
2 changed files with 55 additions and 5 deletions

View file

@ -458,10 +458,49 @@ namespace Ryujinx.HLE.HOS.Services.Nv
}
[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)
{
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+

View file

@ -50,18 +50,22 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
protected delegate NvInternalResult IoctlProcessor<T>(ref 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
{
Debug.Assert(arguments.Length == Unsafe.SizeOf<T>());
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>());
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
@ -69,6 +73,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
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();
}
}