summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/ipc.h2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp4
-rw-r--r--src/core/hle/kernel/mutex.cpp1
-rw-r--r--src/core/hle/result.h46
-rw-r--r--src/core/hle/service/audio/audin_u.cpp6
-rw-r--r--src/core/hle/service/audio/audout_u.cpp8
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp3
-rw-r--r--src/core/hle/service/audio/audren_u.cpp25
-rw-r--r--src/core/hle/service/audio/codecctl.cpp26
-rw-r--r--src/core/hle/service/fatal/fatal.cpp4
-rw-r--r--src/core/hle/service/fatal/fatal.h4
-rw-r--r--src/core/hle/service/fatal/fatal_u.cpp5
-rw-r--r--src/core/hle/service/nfp/nfp.cpp48
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp33
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h17
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp11
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h10
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp35
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h14
-rw-r--r--src/core/hle/service/service.cpp2
20 files changed, 230 insertions, 74 deletions
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index ef6595550..c9257de77 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -32,6 +32,8 @@ enum class CommandType : u32 {
Close = 2,
Request = 4,
Control = 5,
+ RequestWithContext = 6,
+ ControlWithContext = 7,
Unspecified,
};
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 349bc11df..01904467e 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -110,7 +110,9 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
// Padding to align to 16 bytes
rp.AlignWithPadding();
- if (Session()->IsDomain() && (command_header->type == IPC::CommandType::Request || !incoming)) {
+ if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request ||
+ command_header->type == IPC::CommandType::RequestWithContext) ||
+ !incoming)) {
// If this is an incoming message, only CommandType "Request" has a domain header
// All outgoing domain messages have the domain header, if only incoming has it
if (incoming || domain_message_header) {
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 63733ad79..bc144f3de 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -104,7 +104,6 @@ ResultCode Mutex::Release(VAddr address) {
// There are no more threads waiting for the mutex, release it completely.
if (thread == nullptr) {
- ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
Memory::Write32(address, 0);
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 052f49979..e3eda4f54 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -42,41 +42,75 @@ enum class ErrorModule : u32 {
PM = 15,
NS = 16,
HTC = 18,
+ NCMContent = 20,
SM = 21,
RO = 22,
SDMMC = 24,
+ OVLN = 25,
SPL = 26,
ETHC = 100,
I2C = 101,
+ GPIO = 102,
+ UART = 103,
Settings = 105,
+ WLAN = 107,
+ XCD = 108,
NIFM = 110,
- Display = 114,
- NTC = 116,
+ Hwopus = 111,
+ Bluetooth = 113,
+ VI = 114,
+ NFP = 115,
+ Time = 116,
FGM = 117,
- PCIE = 120,
+ PCIe = 120,
Friends = 121,
+ BCAT = 122,
SSL = 123,
Account = 124,
+ News = 125,
Mii = 126,
+ NFC = 127,
AM = 128,
PlayReport = 129,
+ AHID = 130,
+ Qlaunch = 132,
PCV = 133,
OMM = 134,
+ BPC = 135,
+ PSM = 136,
NIM = 137,
PSC = 138,
+ TC = 139,
USB = 140,
+ NSD = 141,
+ PCTL = 142,
BTM = 143,
+ ETicket = 145,
+ NGC = 146,
ERPT = 147,
APM = 148,
+ ErrorUpload = 151,
+ Audio = 153,
NPNS = 154,
+ NPNSHTTPSTREAM = 155,
ARP = 157,
BOOT = 158,
- NFC = 161,
+ NFCMifare = 161,
UserlandAssert = 162,
+ Fatal = 163,
+ NIMShop = 164,
+ SPSM = 165,
+ BGTC = 167,
UserlandCrash = 168,
- HID = 203,
+ SREPO = 180,
+ HID = 202,
+ LDN = 203,
+ Irsensor = 205,
Capture = 206,
- TC = 651,
+ Manu = 208,
+ GRC = 212,
+ Migration = 216,
+ MigrationLdcServ = 217,
GeneralWebApplet = 800,
WifiWebAuthApplet = 809,
WhitelistedApplet = 810,
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index dca2bfb92..cbc49e55e 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -35,10 +35,8 @@ public:
AudInU::AudInU() : ServiceFramework("audin:u") {
static const FunctionInfo functions[] = {
- {0, nullptr, "ListAudioIns"},
- {1, nullptr, "OpenAudioIn"},
- {3, nullptr, "OpenAudioInAuto"},
- {4, nullptr, "ListAudioInsAuto"},
+ {0, nullptr, "ListAudioIns"}, {1, nullptr, "OpenAudioIn"}, {2, nullptr, "Unknown"},
+ {3, nullptr, "OpenAudioInAuto"}, {4, nullptr, "ListAudioInsAuto"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index fa3728672..402eaa306 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -196,10 +196,10 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
}
AudOutU::AudOutU() : ServiceFramework("audout:u") {
- static const FunctionInfo functions[] = {{0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"},
- {0x00000001, &AudOutU::OpenAudioOut, "OpenAudioOut"},
- {0x00000002, nullptr, "ListAudioOutsAuto"},
- {0x00000003, nullptr, "OpenAudioOutAuto"}};
+ static const FunctionInfo functions[] = {{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
+ {1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
+ {2, nullptr, "ListAudioOutsAuto"},
+ {3, nullptr, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index b2be10919..74909415c 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -20,6 +20,7 @@ public:
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
{6, nullptr, "ContainsFinalOutputRecorderBuffer"},
+ {7, nullptr, "Unknown"},
{8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
{9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
};
@@ -30,7 +31,7 @@ public:
AudRecU::AudRecU() : ServiceFramework("audrec:u") {
static const FunctionInfo functions[] = {
- {0x00000000, nullptr, "OpenFinalOutputRecorder"},
+ {0, nullptr, "OpenFinalOutputRecorder"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 0d6eb1d51..38bc65d95 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -156,19 +156,20 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
IAudioDevice() : ServiceFramework("IAudioDevice") {
static const FunctionInfo functions[] = {
- {0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
- {0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
- {0x2, nullptr, "GetAudioDeviceOutputVolume"},
- {0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
- {0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
- {0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
- {0x6, &IAudioDevice::ListAudioDeviceName,
+ {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
+ {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
+ {2, nullptr, "GetAudioDeviceOutputVolume"},
+ {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
+ {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
+ {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
+ {6, &IAudioDevice::ListAudioDeviceName,
"ListAudioDeviceNameAuto"}, // TODO(ogniK): Confirm if autos are identical to non auto
- {0x7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
- {0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
- {0xa, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
- {0xb, nullptr, "QueryAudioDeviceInputEvent"},
- {0xc, nullptr, "QueryAudioDeviceOutputEvent"}};
+ {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
+ {8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
+ {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
+ {11, nullptr, "QueryAudioDeviceInputEvent"},
+ {12, nullptr, "QueryAudioDeviceOutputEvent"},
+ };
RegisterHandlers(functions);
buffer_event =
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp
index ba0f1d228..212c8d448 100644
--- a/src/core/hle/service/audio/codecctl.cpp
+++ b/src/core/hle/service/audio/codecctl.cpp
@@ -11,19 +11,19 @@ namespace Service::Audio {
CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
static const FunctionInfo functions[] = {
- {0x00000000, nullptr, "InitializeCodecController"},
- {0x00000001, nullptr, "FinalizeCodecController"},
- {0x00000002, nullptr, "SleepCodecController"},
- {0x00000003, nullptr, "WakeCodecController"},
- {0x00000004, nullptr, "SetCodecVolume"},
- {0x00000005, nullptr, "GetCodecVolumeMax"},
- {0x00000006, nullptr, "GetCodecVolumeMin"},
- {0x00000007, nullptr, "SetCodecActiveTarget"},
- {0x00000008, nullptr, "Unknown"},
- {0x00000009, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
- {0x00000010, nullptr, "IsCodecHeadphoneMicJackInserted"},
- {0x00000011, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
- {0x00000012, nullptr, "IsCodecDeviceRequested"},
+ {0, nullptr, "InitializeCodecController"},
+ {1, nullptr, "FinalizeCodecController"},
+ {2, nullptr, "SleepCodecController"},
+ {3, nullptr, "WakeCodecController"},
+ {4, nullptr, "SetCodecVolume"},
+ {5, nullptr, "GetCodecVolumeMax"},
+ {6, nullptr, "GetCodecVolumeMin"},
+ {7, nullptr, "SetCodecActiveTarget"},
+ {8, nullptr, "GetCodecActiveTarget"},
+ {9, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
+ {10, nullptr, "IsCodecHeadphoneMicJackInserted"},
+ {11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
+ {12, nullptr, "IsCodecDeviceRequested"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index bb75e7314..2d4282209 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -13,7 +13,7 @@ namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
-void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) {
+void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 error_code = rp.Pop<u32>();
NGLOG_WARNING(Service_Fatal, "(STUBBED) called, error_code=0x{:X}", error_code);
@@ -21,7 +21,7 @@ void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
-void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) {
+void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Fatal, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h
index 2d8d08320..5bd111a14 100644
--- a/src/core/hle/service/fatal/fatal.h
+++ b/src/core/hle/service/fatal/fatal.h
@@ -14,8 +14,8 @@ public:
public:
Interface(std::shared_ptr<Module> module, const char* name);
- void FatalSimple(Kernel::HLERequestContext& ctx);
- void TransitionToFatalError(Kernel::HLERequestContext& ctx);
+ void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx);
+ void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
diff --git a/src/core/hle/service/fatal/fatal_u.cpp b/src/core/hle/service/fatal/fatal_u.cpp
index 26aa9f3b7..f0631329e 100644
--- a/src/core/hle/service/fatal/fatal_u.cpp
+++ b/src/core/hle/service/fatal/fatal_u.cpp
@@ -8,8 +8,9 @@ namespace Service::Fatal {
Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") {
static const FunctionInfo functions[] = {
- {1, &Fatal_U::FatalSimple, "FatalSimple"},
- {2, &Fatal_U::TransitionToFatalError, "TransitionToFatalError"},
+ {0, nullptr, "ThrowFatal"},
+ {1, &Fatal_U::ThrowFatalWithPolicy, "ThrowFatalWithPolicy"},
+ {2, &Fatal_U::ThrowFatalWithCpuContext, "ThrowFatalWithCpuContext"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index cc0247881..2af4465de 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -17,30 +17,30 @@ public:
IUser() : ServiceFramework("IUser") {
static const FunctionInfo functions[] = {
{0, &IUser::Initialize, "Initialize"},
- {1, nullptr, "Unknown1"},
- {2, nullptr, "Unknown2"},
- {3, nullptr, "Unknown3"},
- {4, nullptr, "Unknown4"},
- {5, nullptr, "Unknown5"},
- {6, nullptr, "Unknown6"},
- {7, nullptr, "Unknown7"},
- {8, nullptr, "Unknown8"},
- {9, nullptr, "Unknown9"},
- {10, nullptr, "Unknown10"},
- {11, nullptr, "Unknown11"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {14, nullptr, "Unknown14"},
- {15, nullptr, "Unknown15"},
- {16, nullptr, "Unknown16"},
- {17, nullptr, "Unknown17"},
- {18, nullptr, "Unknown18"},
- {19, nullptr, "Unknown19"},
- {20, nullptr, "Unknown20"},
- {21, nullptr, "Unknown21"},
- {22, nullptr, "Unknown22"},
- {23, nullptr, "Unknown23"},
- {24, nullptr, "Unknown24"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "ListDevices"},
+ {3, nullptr, "StartDetection"},
+ {4, nullptr, "StopDetection"},
+ {5, nullptr, "Mount"},
+ {6, nullptr, "Unmount"},
+ {7, nullptr, "OpenApplicationArea"},
+ {8, nullptr, "GetApplicationArea"},
+ {9, nullptr, "SetApplicationArea"},
+ {10, nullptr, "Flush"},
+ {11, nullptr, "Restore"},
+ {12, nullptr, "CreateApplicationArea"},
+ {13, nullptr, "GetTagInfo"},
+ {14, nullptr, "GetRegisterInfo"},
+ {15, nullptr, "GetCommonInfo"},
+ {16, nullptr, "GetModelInfo"},
+ {17, nullptr, "AttachActivateEvent"},
+ {18, nullptr, "AttachDeactivateEvent"},
+ {19, nullptr, "GetState"},
+ {20, nullptr, "GetDeviceState"},
+ {21, nullptr, "GetNpadId"},
+ {22, nullptr, "GetApplicationArea2"},
+ {23, nullptr, "AttachAvailabilityChangeEvent"},
+ {24, nullptr, "RecreateApplicationArea"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index cb4913b07..c1eea861d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -26,6 +26,8 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
return BindChannel(input, output);
case IoctlCommand::IocGetVaRegionsCommand:
return GetVARegions(input, output);
+ case IoctlCommand::IocUnmapBufferCommand:
+ return UnmapBuffer(input, output);
}
if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand)
@@ -125,6 +127,37 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size);
}
+ // Create a new mapping entry for this operation.
+ ASSERT_MSG(buffer_mappings.find(params.offset) == buffer_mappings.end(),
+ "Offset is already mapped");
+
+ BufferMapping mapping{};
+ mapping.nvmap_handle = params.nvmap_handle;
+ mapping.offset = params.offset;
+ mapping.size = object->size;
+
+ buffer_mappings[params.offset] = mapping;
+
+ std::memcpy(output.data(), &params, output.size());
+ return 0;
+}
+
+u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlUnmapBuffer params{};
+ std::memcpy(&params, input.data(), input.size());
+
+ NGLOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
+
+ auto& gpu = Core::System::GetInstance().GPU();
+
+ auto itr = buffer_mappings.find(params.offset);
+
+ ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping");
+
+ params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);
+
+ buffer_mappings.erase(itr->second.offset);
+
std::memcpy(output.data(), &params, output.size());
return 0;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index f2dd0c3b3..d4c4b4db3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <unordered_map>
#include <utility>
#include <vector>
#include "common/common_types.h"
@@ -30,6 +31,7 @@ private:
IocMapBufferExCommand = 0xC0284106,
IocBindChannelCommand = 0x40044101,
IocGetVaRegionsCommand = 0xC0404108,
+ IocUnmapBufferCommand = 0xC0084105,
};
struct IoctlInitalizeEx {
@@ -76,6 +78,11 @@ private:
};
static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size");
+ struct IoctlUnmapBuffer {
+ u64_le offset;
+ };
+ static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size");
+
struct IoctlBindChannel {
u32_le fd;
};
@@ -98,12 +105,22 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2,
"IoctlGetVaRegions is incorrect size");
+ struct BufferMapping {
+ u64 offset;
+ u64 size;
+ u32 nvmap_handle;
+ };
+
+ /// Map containing the nvmap object mappings in GPU memory.
+ std::unordered_map<u64, BufferMapping> buffer_mappings;
+
u32 channel{};
u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 25e3ccef6..03126aeee 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -32,6 +32,8 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
return AllocGPFIFOEx2(input, output);
case IoctlCommand::IocAllocObjCtxCommand:
return AllocateObjectContext(input, output);
+ case IoctlCommand::IocChannelGetWaitbaseCommand:
+ return GetWaitbase(input, output);
}
if (command.group == NVGPU_IOCTL_MAGIC) {
@@ -138,4 +140,13 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
return 0;
}
+u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlGetWaitbase params{};
+ std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
+ NGLOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
+ params.value = 0; // Seems to be hard coded at 0
+ std::memcpy(output.data(), &params, output.size());
+ return 0;
+}
+
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 703c36bbb..beb1c4970 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -33,6 +33,7 @@ private:
IocChannelSetPriorityCommand = 0x4004480D,
IocAllocGPFIFOEx2Command = 0xC020481A,
IocAllocObjCtxCommand = 0xC0104809,
+ IocChannelGetWaitbaseCommand = 0xC0080003,
};
enum class CtxObjects : u32_le {
@@ -117,7 +118,13 @@ private:
IoctlFence fence_out; // returned new fence object for others to wait on
};
static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence),
- "submit_gpfifo is incorrect size");
+ "IoctlSubmitGpfifo is incorrect size");
+
+ struct IoctlGetWaitbase {
+ u32 unknown; // seems to be ignored? Nintendo added this
+ u32 value;
+ };
+ static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size");
u32_le nvmap_fd{};
u64_le user_data{};
@@ -133,6 +140,7 @@ private:
u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
std::shared_ptr<nvmap> nvmap_dev;
};
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 8d883209f..d66fb3a9c 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -30,6 +30,8 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
return IocFromId(input, output);
case IoctlCommand::Param:
return IocParam(input, output);
+ case IoctlCommand::Free:
+ return IocFree(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -45,6 +47,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
object->id = next_id++;
object->size = params.size;
object->status = Object::Status::Created;
+ object->refcount = 1;
u32 handle = next_handle++;
handles[handle] = std::move(object);
@@ -101,6 +104,8 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
[&](const auto& entry) { return entry.second->id == params.id; });
ASSERT(itr != handles.end());
+ itr->second->refcount++;
+
// Return the existing handle instead of creating a new one.
params.handle = itr->first;
@@ -142,4 +147,34 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
return 0;
}
+u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
+ enum FreeFlags {
+ Freed = 0,
+ NotFreedYet = 1,
+ };
+
+ IocFreeParams params;
+ std::memcpy(&params, input.data(), sizeof(params));
+
+ NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
+
+ auto itr = handles.find(params.handle);
+ ASSERT(itr != handles.end());
+
+ itr->second->refcount--;
+
+ params.refcount = itr->second->refcount;
+ params.size = itr->second->size;
+
+ if (itr->second->refcount == 0)
+ params.flags = Freed;
+ else
+ params.flags = NotFreedYet;
+
+ handles.erase(params.handle);
+
+ std::memcpy(output.data(), &params, sizeof(params));
+ return 0;
+}
+
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 431eb3773..5a3044167 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -34,6 +34,7 @@ public:
u8 kind;
VAddr addr;
Status status;
+ u32 refcount;
};
std::shared_ptr<Object> GetObject(u32 handle) const {
@@ -59,7 +60,8 @@ private:
FromId = 0xC0080103,
Alloc = 0xC0200104,
Param = 0xC00C0109,
- GetId = 0xC008010E
+ GetId = 0xC008010E,
+ Free = 0xC0180105,
};
struct IocCreateParams {
@@ -102,11 +104,21 @@ private:
u32_le value;
};
+ struct IocFreeParams {
+ u32_le handle;
+ INSERT_PADDING_BYTES(4);
+ u64_le refcount;
+ u32_le size;
+ u32_le flags;
+ };
+ static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size");
+
u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index dc30702c6..5b91089cf 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -144,10 +144,12 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
rb.Push(RESULT_SUCCESS);
return ResultCode(ErrorModule::HIPC, ErrorDescription::RemoteProcessDead);
}
+ case IPC::CommandType::ControlWithContext:
case IPC::CommandType::Control: {
Core::System::GetInstance().ServiceManager().InvokeControlRequest(context);
break;
}
+ case IPC::CommandType::RequestWithContext:
case IPC::CommandType::Request: {
InvokeRequest(context);
break;