ryujinx/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs
Thomas Guillemard 9426ef3f06 Rewrite nvservices (#800)
* Start rewriting nvservices internals

TODO:

- nvgpu device interface
- nvhost generic device interface

* Some clean up and fixes

- Make sure to remove the fd of a closed channel.
- NvFileDevice now doesn't implement Disposable as it was never used.
- Rename NvHostCtrlGetConfigurationArgument to GetConfigurationArguments
to follow calling convention.
- Make sure to check every ioctls magic.

* Finalize migration for ioctl standard variant

TODO: ioctl2 migration

* Implement SubmitGpfifoEx and fix nvdec

* Implement Ioctl3

* Implement some ioctl3 required by recent games

* Remove unused code and outdated comments

* Return valid event handles with QueryEvent

Also add an exception for unimplemented event ids.

This commit doesn't implement accurately the events, this only define
different events for different event ids.

* Rename all occurance of FileDevice to DeviceFile

* Restub SetClientPid to not cause regressions

* Address comments

* Remove GlobalStateTable

* Address comments

* Align variables in ioctl3

* Some missing alignments

* GetVaRegionsArguments realign

* Make Owner public in NvDeviceFile

* Address LDj3SNuD's comments
2019-11-03 09:47:56 +11:00

240 lines
8.9 KiB
C#

using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
using System;
using System.Diagnostics;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
{
class NvHostCtrlGpuDeviceFile : NvDeviceFile
{
private static Stopwatch _pTimer = new Stopwatch();
private static double _ticksToNs = (1.0 / Stopwatch.Frequency) * 1_000_000_000;
private KEvent _errorEvent;
private KEvent _unknownEvent;
public NvHostCtrlGpuDeviceFile(ServiceCtx context) : base(context)
{
_errorEvent = new KEvent(context.Device.System);
_unknownEvent = new KEvent(context.Device.System);
}
static NvHostCtrlGpuDeviceFile()
{
_pTimer.Start();
}
public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments)
{
NvInternalResult result = NvInternalResult.NotImplemented;
if (command.Type == NvIoctl.NvGpuMagic)
{
switch (command.Number)
{
case 0x01:
result = CallIoctlMethod<ZcullGetCtxSizeArguments>(ZcullGetCtxSize, arguments);
break;
case 0x02:
result = CallIoctlMethod<ZcullGetInfoArguments>(ZcullGetInfo, arguments);
break;
case 0x03:
result = CallIoctlMethod<ZbcSetTableArguments>(ZbcSetTable, arguments);
break;
case 0x05:
result = CallIoctlMethod<GetCharacteristicsArguments>(GetCharacteristics, arguments);
break;
case 0x06:
result = CallIoctlMethod<GetTpcMasksArguments>(GetTpcMasks, arguments);
break;
case 0x14:
result = CallIoctlMethod<GetActiveSlotMaskArguments>(GetActiveSlotMask, arguments);
break;
case 0x1c:
result = CallIoctlMethod<GetGpuTimeArguments>(GetGpuTime, arguments);
break;
}
}
return result;
}
public override NvInternalResult Ioctl3(NvIoctl command, Span<byte> arguments, Span<byte> inlineOutBuffer)
{
NvInternalResult result = NvInternalResult.NotImplemented;
if (command.Type == NvIoctl.NvGpuMagic)
{
switch (command.Number)
{
case 0x05:
result = CallIoctlMethod<GetCharacteristicsArguments, GpuCharacteristics>(GetCharacteristics, arguments, inlineOutBuffer);
break;
case 0x06:
result = CallIoctlMethod<GetTpcMasksArguments, int>(GetTpcMasks, arguments, inlineOutBuffer);
break;
}
}
return result;
}
public override NvInternalResult QueryEvent(out int eventHandle, uint eventId)
{
// TODO: accurately represent and implement those events.
KEvent targetEvent = null;
switch (eventId)
{
case 0x1:
targetEvent = _errorEvent;
break;
case 0x2:
targetEvent = _unknownEvent;
break;
}
if (targetEvent != null)
{
if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
else
{
eventHandle = 0;
return NvInternalResult.InvalidInput;
}
return NvInternalResult.Success;
}
public override void Close() { }
private NvInternalResult ZcullGetCtxSize(ref ZcullGetCtxSizeArguments arguments)
{
arguments.Size = 1;
return NvInternalResult.Success;
}
private NvInternalResult ZcullGetInfo(ref ZcullGetInfoArguments arguments)
{
arguments.WidthAlignPixels = 0x20;
arguments.HeightAlignPixels = 0x20;
arguments.PixelSquaresByAliquots = 0x400;
arguments.AliquotTotal = 0x800;
arguments.RegionByteMultiplier = 0x20;
arguments.RegionHeaderSize = 0x20;
arguments.SubregionHeaderSize = 0xc0;
arguments.SubregionWidthAlignPixels = 0x20;
arguments.SubregionHeightAlignPixels = 0x40;
arguments.SubregionCount = 0x10;
return NvInternalResult.Success;
}
private NvInternalResult ZbcSetTable(ref ZbcSetTableArguments arguments)
{
Logger.PrintStub(LogClass.ServiceNv);
return NvInternalResult.Success;
}
private NvInternalResult GetCharacteristics(ref GetCharacteristicsArguments arguments)
{
return GetCharacteristics(ref arguments, ref arguments.Characteristics);
}
private NvInternalResult GetCharacteristics(ref GetCharacteristicsArguments arguments, ref GpuCharacteristics characteristics)
{
arguments.Header.BufferSize = 0xa0;
characteristics.Arch = 0x120;
characteristics.Impl = 0xb;
characteristics.Rev = 0xa1;
characteristics.NumGpc = 0x1;
characteristics.L2CacheSize = 0x40000;
characteristics.OnBoardVideoMemorySize = 0x0;
characteristics.NumTpcPerGpc = 0x2;
characteristics.BusType = 0x20;
characteristics.BigPageSize = 0x20000;
characteristics.CompressionPageSize = 0x20000;
characteristics.PdeCoverageBitCount = 0x1b;
characteristics.AvailableBigPageSizes = 0x30000;
characteristics.GpcMask = 0x1;
characteristics.SmArchSmVersion = 0x503;
characteristics.SmArchSpaVersion = 0x503;
characteristics.SmArchWarpCount = 0x80;
characteristics.GpuVaBitCount = 0x28;
characteristics.Reserved = 0x0;
characteristics.Flags = 0x55;
characteristics.TwodClass = 0x902d;
characteristics.ThreedClass = 0xb197;
characteristics.ComputeClass = 0xb1c0;
characteristics.GpfifoClass = 0xb06f;
characteristics.InlineToMemoryClass = 0xa140;
characteristics.DmaCopyClass = 0xb0b5;
characteristics.MaxFbpsCount = 0x1;
characteristics.FbpEnMask = 0x0;
characteristics.MaxLtcPerFbp = 0x2;
characteristics.MaxLtsPerLtc = 0x1;
characteristics.MaxTexPerTpc = 0x0;
characteristics.MaxGpcCount = 0x1;
characteristics.RopL2EnMask0 = 0x21d70;
characteristics.RopL2EnMask1 = 0x0;
characteristics.ChipName = 0x6230326d67;
characteristics.GrCompbitStoreBaseHw = 0x0;
arguments.Characteristics = characteristics;
return NvInternalResult.Success;
}
private NvInternalResult GetTpcMasks(ref GetTpcMasksArguments arguments)
{
return GetTpcMasks(ref arguments, ref arguments.TpcMask);
}
private NvInternalResult GetTpcMasks(ref GetTpcMasksArguments arguments, ref int tpcMask)
{
if (arguments.MaskBufferSize != 0)
{
tpcMask = 3;
arguments.TpcMask = tpcMask;
}
return NvInternalResult.Success;
}
private NvInternalResult GetActiveSlotMask(ref GetActiveSlotMaskArguments arguments)
{
Logger.PrintStub(LogClass.ServiceNv);
arguments.Slot = 0x07;
arguments.Mask = 0x01;
return NvInternalResult.Success;
}
private NvInternalResult GetGpuTime(ref GetGpuTimeArguments arguments)
{
arguments.Timestamp = GetPTimerNanoSeconds();
return NvInternalResult.Success;
}
private static ulong GetPTimerNanoSeconds()
{
double ticks = _pTimer.ElapsedTicks;
return (ulong)(ticks * _ticksToNs) & 0xff_ffff_ffff_ffff;
}
}
}