summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp35
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h14
2 files changed, 48 insertions, 1 deletions
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