Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fdc3a71dc | ||
|
|
b835d76311 | ||
|
|
b7725812ac | ||
|
|
e31c15606b | ||
|
|
a755f24369 | ||
|
|
59fd910355 | ||
|
|
654427d4d0 | ||
|
|
82979296d2 | ||
|
|
6325c3044c | ||
|
|
d3783fcc52 | ||
|
|
e9d19add7d | ||
|
|
b54cdeb284 | ||
|
|
0740758b25 | ||
|
|
f9259c0383 |
No files matched your search
@@ -107,6 +107,11 @@ Stream::State AudioRenderer::GetStreamState() const {
|
||||
return stream->GetState();
|
||||
}
|
||||
|
||||
static constexpr u32 VersionFromRevision(u32_le rev) {
|
||||
// "REV7" -> 7
|
||||
return ((rev >> 24) & 0xff) - 0x30;
|
||||
}
|
||||
|
||||
std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
|
||||
// Copy UpdateDataHeader struct
|
||||
UpdateDataHeader config{};
|
||||
@@ -166,6 +171,11 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_
|
||||
// Copy output header
|
||||
UpdateDataHeader response_data{worker_params};
|
||||
std::vector<u8> output_params(response_data.total_size);
|
||||
const auto audren_revision = VersionFromRevision(config.revision);
|
||||
if (audren_revision >= 5) {
|
||||
response_data.frame_count = 0x10;
|
||||
response_data.total_size += 0x10;
|
||||
}
|
||||
std::memcpy(output_params.data(), &response_data, sizeof(UpdateDataHeader));
|
||||
|
||||
// Copy output memory pool entries
|
||||
|
||||
@@ -194,21 +194,24 @@ struct UpdateDataHeader {
|
||||
mixes_size = 0x0;
|
||||
sinks_size = config.sink_count * 0x20;
|
||||
performance_manager_size = 0x10;
|
||||
frame_count = 0;
|
||||
total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size + voices_size +
|
||||
effects_size + sinks_size + performance_manager_size;
|
||||
}
|
||||
|
||||
u32_le revision;
|
||||
u32_le behavior_size;
|
||||
u32_le memory_pools_size;
|
||||
u32_le voices_size;
|
||||
u32_le voice_resource_size;
|
||||
u32_le effects_size;
|
||||
u32_le mixes_size;
|
||||
u32_le sinks_size;
|
||||
u32_le performance_manager_size;
|
||||
INSERT_PADDING_WORDS(6);
|
||||
u32_le total_size;
|
||||
u32_le revision{};
|
||||
u32_le behavior_size{};
|
||||
u32_le memory_pools_size{};
|
||||
u32_le voices_size{};
|
||||
u32_le voice_resource_size{};
|
||||
u32_le effects_size{};
|
||||
u32_le mixes_size{};
|
||||
u32_le sinks_size{};
|
||||
u32_le performance_manager_size{};
|
||||
INSERT_PADDING_WORDS(1);
|
||||
u32_le frame_count{};
|
||||
INSERT_PADDING_WORDS(4);
|
||||
u32_le total_size{};
|
||||
};
|
||||
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size");
|
||||
|
||||
|
||||
+6
-10
@@ -28,18 +28,14 @@ __declspec(noinline, noreturn)
|
||||
}
|
||||
|
||||
#define ASSERT(_a_) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \
|
||||
} \
|
||||
while (0)
|
||||
if (!(_a_)) { \
|
||||
LOG_CRITICAL(Debug, "Assertion Failed!"); \
|
||||
}
|
||||
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
|
||||
} \
|
||||
while (0)
|
||||
if (!(_a_)) { \
|
||||
LOG_CRITICAL(Debug, "Assertion Failed! " __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!")
|
||||
#define UNREACHABLE_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
|
||||
protected:
|
||||
void Get(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
ProfileBase profile_base{};
|
||||
ProfileData data{};
|
||||
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
|
||||
@@ -89,7 +89,7 @@ protected:
|
||||
}
|
||||
|
||||
void GetBase(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
ProfileBase profile_base{};
|
||||
if (profile_manager.GetProfileBase(user_id, profile_base)) {
|
||||
IPC::ResponseBuilder rb{ctx, 16};
|
||||
@@ -263,7 +263,7 @@ private:
|
||||
};
|
||||
|
||||
void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called");
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(static_cast<u32>(profile_manager->GetUserCount()));
|
||||
@@ -272,7 +272,7 @@ void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
Common::UUID user_id = rp.PopRaw<Common::UUID>();
|
||||
LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
@@ -280,21 +280,21 @@ void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called");
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
ctx.WriteBuffer(profile_manager->GetAllUsers());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called");
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
ctx.WriteBuffer(profile_manager->GetOpenUsers());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_ACC, "called");
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<Common::UUID>(profile_manager->GetLastOpenedUser());
|
||||
|
||||
@@ -169,8 +169,10 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
|
||||
|
||||
void Controller_NPad::OnInit() {
|
||||
auto& kernel = system.Kernel();
|
||||
styleset_changed_event = Kernel::WritableEvent::CreateEventPair(
|
||||
kernel, Kernel::ResetType::Automatic, "npad:NpadStyleSetChanged");
|
||||
for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
|
||||
styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
|
||||
kernel, Kernel::ResetType::Automatic, fmt::format("npad:NpadStyleSetChanged_{}", i));
|
||||
}
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
return;
|
||||
@@ -453,7 +455,7 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
|
||||
had_controller_update = true;
|
||||
}
|
||||
if (had_controller_update) {
|
||||
styleset_changed_event.writable->Signal();
|
||||
styleset_changed_events[i].writable->Signal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,7 +470,6 @@ std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
|
||||
}
|
||||
|
||||
void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
|
||||
styleset_changed_event.writable->Signal();
|
||||
hold_type = joy_hold_type;
|
||||
}
|
||||
|
||||
@@ -479,7 +480,10 @@ Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
|
||||
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
|
||||
const std::size_t npad_index = NPadIdToIndex(npad_id);
|
||||
ASSERT(npad_index < shared_memory_entries.size());
|
||||
shared_memory_entries[npad_index].pad_assignment = assignment_mode;
|
||||
if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
|
||||
styleset_changed_events[npad_index].writable->Signal();
|
||||
shared_memory_entries[npad_index].pad_assignment = assignment_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
@@ -498,11 +502,13 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
last_processed_vibration = vibrations.back();
|
||||
}
|
||||
|
||||
Kernel::SharedPtr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent() const {
|
||||
Kernel::SharedPtr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(
|
||||
u32 npad_id) const {
|
||||
// TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
|
||||
// be signalled at least once, and signaled after a new controller is connected?
|
||||
styleset_changed_event.writable->Signal();
|
||||
return styleset_changed_event.readable;
|
||||
const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
|
||||
styleset_event.writable->Signal();
|
||||
return styleset_event.readable;
|
||||
}
|
||||
|
||||
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
void VibrateController(const std::vector<u32>& controller_ids,
|
||||
const std::vector<Vibration>& vibrations);
|
||||
|
||||
Kernel::SharedPtr<Kernel::ReadableEvent> GetStyleSetChangedEvent() const;
|
||||
Kernel::SharedPtr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
|
||||
Vibration GetLastVibration() const;
|
||||
|
||||
void AddNewController(NPadControllerType controller);
|
||||
@@ -315,7 +315,8 @@ private:
|
||||
sticks;
|
||||
std::vector<u32> supported_npad_id_types{};
|
||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||
Kernel::EventPair styleset_changed_event;
|
||||
// Each controller should have their own styleset changed event
|
||||
std::array<Kernel::EventPair, 10> styleset_changed_events;
|
||||
Vibration last_processed_vibration{};
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
bool can_controllers_vibrate{true};
|
||||
|
||||
@@ -480,7 +480,7 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.GetStyleSetChangedEvent());
|
||||
.GetStyleSetChangedEvent(npad_id));
|
||||
}
|
||||
|
||||
void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
@@ -38,8 +39,9 @@ public:
|
||||
* @param output A buffer where the output data will be written to.
|
||||
* @returns The result code of the ioctl.
|
||||
*/
|
||||
virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) = 0;
|
||||
virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) = 0;
|
||||
|
||||
protected:
|
||||
Core::System& system;
|
||||
|
||||
@@ -17,8 +17,9 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_de
|
||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||
nvdisp_disp0 ::~nvdisp_disp0() = default;
|
||||
|
||||
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@ public:
|
||||
explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||
~nvdisp_disp0() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
/// Performs a screen flip, drawing the buffer pointed to by the handle.
|
||||
void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride,
|
||||
|
||||
@@ -26,8 +26,9 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_
|
||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||
nvhost_as_gpu::~nvhost_as_gpu() = default;
|
||||
|
||||
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@ public:
|
||||
explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||
~nvhost_as_gpu() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
|
||||
@@ -19,8 +19,9 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface)
|
||||
: nvdevice(system), events_interface{events_interface} {}
|
||||
nvhost_ctrl::~nvhost_ctrl() = default;
|
||||
|
||||
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ public:
|
||||
explicit nvhost_ctrl(Core::System& system, EventInterface& events_interface);
|
||||
~nvhost_ctrl() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
|
||||
@@ -15,14 +15,15 @@ namespace Service::Nvidia::Devices {
|
||||
nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {}
|
||||
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
|
||||
|
||||
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input,
|
||||
const std::vector<u8>& input2, std::vector<u8>& output,
|
||||
std::vector<u8>& output2, IoctlCtrl& ctrl, IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||
case IoctlCommand::IocGetCharacteristicsCommand:
|
||||
return GetCharacteristics(input, output);
|
||||
return GetCharacteristics(input, output, output2, version);
|
||||
case IoctlCommand::IocGetTPCMasksCommand:
|
||||
return GetTPCMasks(input, output);
|
||||
case IoctlCommand::IocGetActiveSlotMaskCommand:
|
||||
@@ -44,7 +45,8 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
|
||||
std::vector<u8>& output2, IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
IoctlCharacteristics params{};
|
||||
std::memcpy(¶ms, input.data(), input.size());
|
||||
@@ -85,7 +87,13 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto
|
||||
params.gc.gr_compbit_store_base_hw = 0x0;
|
||||
params.gpu_characteristics_buf_size = 0xA0;
|
||||
params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
|
||||
std::memcpy(output.data(), ¶ms, output.size());
|
||||
|
||||
if (version == IoctlVersion::Version3) {
|
||||
std::memcpy(output.data(), input.data(), output.size());
|
||||
std::memcpy(output2.data(), ¶ms.gc, output2.size());
|
||||
} else {
|
||||
std::memcpy(output.data(), ¶ms, output.size());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ public:
|
||||
explicit nvhost_ctrl_gpu(Core::System& system);
|
||||
~nvhost_ctrl_gpu() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
@@ -162,7 +163,8 @@ private:
|
||||
};
|
||||
static_assert(sizeof(IoctlGetGpuTime) == 8, "IoctlGetGpuTime is incorrect size");
|
||||
|
||||
u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
|
||||
std::vector<u8>& output2, IoctlVersion version);
|
||||
u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
|
||||
@@ -17,8 +17,9 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
|
||||
: nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
|
||||
nvhost_gpu::~nvhost_gpu() = default;
|
||||
|
||||
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
@@ -50,7 +51,7 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
|
||||
return SubmitGPFIFO(input, output);
|
||||
}
|
||||
if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) {
|
||||
return KickoffPB(input, output);
|
||||
return KickoffPB(input, output, input2, version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +174,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
|
||||
const std::vector<u8>& input2, IoctlVersion version) {
|
||||
if (input.size() < sizeof(IoctlSubmitGpfifo)) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
@@ -183,9 +185,13 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
|
||||
params.num_entries, params.flags.raw);
|
||||
|
||||
Tegra::CommandList entries(params.num_entries);
|
||||
Memory::ReadBlock(params.address, entries.data(),
|
||||
params.num_entries * sizeof(Tegra::CommandListHeader));
|
||||
|
||||
if (version == IoctlVersion::Version2) {
|
||||
std::memcpy(entries.data(), input2.data(),
|
||||
params.num_entries * sizeof(Tegra::CommandListHeader));
|
||||
} else {
|
||||
Memory::ReadBlock(params.address, entries.data(),
|
||||
params.num_entries * sizeof(Tegra::CommandListHeader));
|
||||
}
|
||||
UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
|
||||
UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ public:
|
||||
explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
|
||||
~nvhost_gpu() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
@@ -183,7 +184,8 @@ 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 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output,
|
||||
const std::vector<u8>& input2, IoctlVersion version);
|
||||
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
|
||||
nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {}
|
||||
nvhost_nvdec::~nvhost_nvdec() = default;
|
||||
|
||||
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ public:
|
||||
explicit nvhost_nvdec(Core::System& system);
|
||||
~nvhost_nvdec() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
|
||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
|
||||
nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {}
|
||||
nvhost_nvjpg::~nvhost_nvjpg() = default;
|
||||
|
||||
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ public:
|
||||
explicit nvhost_nvjpg(Core::System& system);
|
||||
~nvhost_nvjpg() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
|
||||
@@ -13,8 +13,9 @@ namespace Service::Nvidia::Devices {
|
||||
nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system) {}
|
||||
nvhost_vic::~nvhost_vic() = default;
|
||||
|
||||
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
|
||||
command.raw, input.size(), output.size());
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ public:
|
||||
explicit nvhost_vic(Core::System& system);
|
||||
~nvhost_vic() override;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
|
||||
@@ -28,8 +28,9 @@ VAddr nvmap::GetObjectAddress(u32 handle) const {
|
||||
return object->addr;
|
||||
}
|
||||
|
||||
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||
case IoctlCommand::Create:
|
||||
return IocCreate(input, output);
|
||||
|
||||
@@ -22,8 +22,9 @@ public:
|
||||
/// Returns the allocated address of an nvmap object given its handle.
|
||||
VAddr GetObjectAddress(u32 handle) const;
|
||||
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) override;
|
||||
u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) override;
|
||||
|
||||
/// Represents an nvmap object.
|
||||
struct Object {
|
||||
|
||||
@@ -33,42 +33,77 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push<u32>(0);
|
||||
}
|
||||
|
||||
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
|
||||
void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
u32 fd = rp.Pop<u32>();
|
||||
u32 command = rp.Pop<u32>();
|
||||
|
||||
std::vector<u8> output(ctx.GetWriteBufferSize());
|
||||
/// Ioctl 3 has 2 outputs, first in the input params, second is the result
|
||||
std::vector<u8> output(ctx.GetWriteBufferSize(0));
|
||||
std::vector<u8> output2;
|
||||
if (version == IoctlVersion::Version3) {
|
||||
output2.resize((ctx.GetWriteBufferSize(1)));
|
||||
}
|
||||
|
||||
/// Ioctl2 has 2 inputs. It's used to pass data directly instead of providing a pointer.
|
||||
/// KickOfPB uses this
|
||||
auto input = ctx.ReadBuffer(0);
|
||||
|
||||
std::vector<u8> input2;
|
||||
if (version == IoctlVersion::Version2) {
|
||||
input2 = ctx.ReadBuffer(1);
|
||||
}
|
||||
|
||||
IoctlCtrl ctrl{};
|
||||
|
||||
u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output, ctrl);
|
||||
u32 result = nvdrv->Ioctl(fd, command, input, input2, output, output2, ctrl, version);
|
||||
|
||||
if (ctrl.must_delay) {
|
||||
ctrl.fresh_call = false;
|
||||
ctx.SleepClientThread(
|
||||
"NVServices::DelayedResponse", ctrl.timeout,
|
||||
[=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||
Kernel::ThreadWakeupReason reason) {
|
||||
IoctlCtrl ctrl2{ctrl};
|
||||
std::vector<u8> output2 = output;
|
||||
u32 result = nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output2, ctrl2);
|
||||
ctx.WriteBuffer(output2);
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(result);
|
||||
},
|
||||
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||
ctx.SleepClientThread("NVServices::DelayedResponse", ctrl.timeout,
|
||||
[=](Kernel::SharedPtr<Kernel::Thread> thread,
|
||||
Kernel::HLERequestContext& ctx,
|
||||
Kernel::ThreadWakeupReason reason) {
|
||||
IoctlCtrl ctrl2{ctrl};
|
||||
std::vector<u8> tmp_output = output;
|
||||
std::vector<u8> tmp_output2 = output2;
|
||||
u32 result = nvdrv->Ioctl(fd, command, input, input2, tmp_output,
|
||||
tmp_output2, ctrl2, version);
|
||||
ctx.WriteBuffer(tmp_output, 0);
|
||||
if (version == IoctlVersion::Version3) {
|
||||
ctx.WriteBuffer(tmp_output2, 1);
|
||||
}
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(result);
|
||||
},
|
||||
nvdrv->GetEventWriteable(ctrl.event_id));
|
||||
} else {
|
||||
ctx.WriteBuffer(output);
|
||||
if (version == IoctlVersion::Version3) {
|
||||
ctx.WriteBuffer(output2, 1);
|
||||
}
|
||||
}
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
IoctlBase(ctx, IoctlVersion::Version1);
|
||||
}
|
||||
|
||||
void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
IoctlBase(ctx, IoctlVersion::Version2);
|
||||
}
|
||||
|
||||
void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
IoctlBase(ctx, IoctlVersion::Version3);
|
||||
}
|
||||
|
||||
void NVDRV::Close(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NVDRV, "called");
|
||||
|
||||
@@ -154,8 +189,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
|
||||
{8, &NVDRV::SetClientPID, "SetClientPID"},
|
||||
{9, &NVDRV::DumpGraphicsMemoryInfo, "DumpGraphicsMemoryInfo"},
|
||||
{10, nullptr, "InitializeDevtools"},
|
||||
{11, &NVDRV::Ioctl, "Ioctl2"},
|
||||
{12, nullptr, "Ioctl3"},
|
||||
{11, &NVDRV::Ioctl2, "Ioctl2"},
|
||||
{12, &NVDRV::Ioctl3, "Ioctl3"},
|
||||
{13, &NVDRV::FinishInitialize, "FinishInitialize"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
@@ -24,6 +24,8 @@ public:
|
||||
private:
|
||||
void Open(Kernel::HLERequestContext& ctx);
|
||||
void Ioctl(Kernel::HLERequestContext& ctx);
|
||||
void Ioctl2(Kernel::HLERequestContext& ctx);
|
||||
void Ioctl3(Kernel::HLERequestContext& ctx);
|
||||
void Close(Kernel::HLERequestContext& ctx);
|
||||
void Initialize(Kernel::HLERequestContext& ctx);
|
||||
void QueryEvent(Kernel::HLERequestContext& ctx);
|
||||
@@ -31,6 +33,7 @@ private:
|
||||
void FinishInitialize(Kernel::HLERequestContext& ctx);
|
||||
void GetStatus(Kernel::HLERequestContext& ctx);
|
||||
void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx);
|
||||
void IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version);
|
||||
|
||||
std::shared_ptr<Module> nvdrv;
|
||||
|
||||
|
||||
@@ -34,6 +34,12 @@ enum class EventState {
|
||||
Busy = 3,
|
||||
};
|
||||
|
||||
enum class IoctlVersion : u32 {
|
||||
Version1,
|
||||
Version2,
|
||||
Version3,
|
||||
};
|
||||
|
||||
struct IoctlCtrl {
|
||||
// First call done to the servioce for services that call itself again after a call.
|
||||
bool fresh_call{true};
|
||||
|
||||
@@ -71,13 +71,14 @@ u32 Module::Open(const std::string& device_name) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl) {
|
||||
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version) {
|
||||
auto itr = open_files.find(fd);
|
||||
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
|
||||
|
||||
auto& device = itr->second;
|
||||
return device->ioctl({command}, input, output, ctrl);
|
||||
return device->ioctl({command}, input, input2, output, output2, ctrl, version);
|
||||
}
|
||||
|
||||
ResultCode Module::Close(u32 fd) {
|
||||
|
||||
@@ -106,8 +106,9 @@ public:
|
||||
/// Opens a device node and returns a file descriptor to it.
|
||||
u32 Open(const std::string& device_name);
|
||||
/// Sends an ioctl command to the specified file descriptor.
|
||||
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output,
|
||||
IoctlCtrl& ctrl);
|
||||
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2,
|
||||
std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl,
|
||||
IoctlVersion version);
|
||||
/// Closes a device file descriptor and returns operation success.
|
||||
ResultCode Close(u32 fd);
|
||||
|
||||
|
||||
Reference in new issue
Block a user