mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-15 03:27:49 +01:00
kern: add SvcCreateDeviceAddressSpace, SvcAttachDeviceAddressSpace
This commit is contained in:
parent
04f325cf5a
commit
cfddb75398
@ -53,6 +53,12 @@ namespace ams::kern::board::nintendo::nx {
|
||||
public:
|
||||
constexpr KDevicePageTable() : tables(), table_asids(), attached_device(), attached_value(), detached_value(), hs_attached_value(), hs_detached_value() { /* ... */ }
|
||||
|
||||
Result Initialize(u64 space_address, u64 space_size);
|
||||
void Finalize();
|
||||
|
||||
Result Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size);
|
||||
Result Detach(ams::svc::DeviceName device_name);
|
||||
public:
|
||||
static void Initialize();
|
||||
};
|
||||
|
||||
|
@ -23,10 +23,39 @@ namespace ams::kern {
|
||||
|
||||
class KDeviceAddressSpace final : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> {
|
||||
MESOSPHERE_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject);
|
||||
private:
|
||||
KLightLock lock;
|
||||
KDevicePageTable table;
|
||||
u64 space_address;
|
||||
u64 space_size;
|
||||
bool is_initialized;
|
||||
public:
|
||||
constexpr KDeviceAddressSpace() : lock(), table(), space_address(), space_size(), is_initialized() { /* ... */ }
|
||||
virtual ~KDeviceAddressSpace() { /* ... */ }
|
||||
|
||||
Result Initialize(u64 address, u64 size);
|
||||
virtual void Finalize() override;
|
||||
|
||||
virtual bool IsInitialized() const override { return this->is_initialized; }
|
||||
static void PostDestroy(uintptr_t arg) { /* ... */ }
|
||||
|
||||
Result Attach(ams::svc::DeviceName device_name);
|
||||
Result Detach(ams::svc::DeviceName device_name);
|
||||
|
||||
Result Map(size_t *out_mapped_size, KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) {
|
||||
return this->Map(out_mapped_size, page_table, process_address, size, device_address, device_perm, false, refresh_mappings);
|
||||
}
|
||||
|
||||
Result MapAligned(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm) {
|
||||
size_t dummy;
|
||||
return this->Map(std::addressof(dummy), page_table, process_address, size, device_address, device_perm, true, false);
|
||||
}
|
||||
|
||||
Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address);
|
||||
private:
|
||||
Result Map(size_t *out_mapped_size, KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool refresh_mappings);
|
||||
public:
|
||||
static void Initialize();
|
||||
|
||||
/* TODO: This is a placeholder definition. */
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||
constexpr size_t DeviceLargePageSize = (1ul << DevicePageBits);
|
||||
static_assert(DevicePageSize == PageSize);
|
||||
|
||||
constexpr size_t DeviceRegionSize = (1ul << 32);
|
||||
|
||||
constexpr size_t DeviceAsidRegisterOffsets[] = {
|
||||
[ams::svc::DeviceName_Afi] = MC_SMMU_AFI_ASID,
|
||||
[ams::svc::DeviceName_Avpc] = MC_SMMU_AVPC_ASID,
|
||||
@ -140,6 +142,57 @@ namespace ams::kern::board::nintendo::nx {
|
||||
return (static_cast<u64>(GetInteger(addr)) & ~PhysicalAddressMask) == 0;
|
||||
}
|
||||
|
||||
constexpr struct { u64 start; u64 end; } SmmuSupportedRanges[] = {
|
||||
[ams::svc::DeviceName_Afi] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Avpc] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Dc] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Dcb] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Hc] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Hda] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Isp2] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_MsencNvenc] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Nv] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Nv2] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Ppcs] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Sata] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Vi] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Vic] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_XusbHost] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_XusbDev] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Tsec] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Ppcs1] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Dc1] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Sdmmc1a] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Sdmmc2a] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Sdmmc3a] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Sdmmc4a] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Isp2b] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Gpu] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Gpub] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Ppcs2] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Nvdec] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Ape] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Se] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Nvjpg] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Hc1] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Se1] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Axiap] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Etr] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Tsecb] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Tsec1] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Tsecb1] = { 0x00000000ul, 0x3FFFFFFFFul },
|
||||
[ams::svc::DeviceName_Nvdec1] = { 0x00000000ul, 0x0FFFFFFFFul },
|
||||
};
|
||||
static_assert(util::size(SmmuSupportedRanges) == ams::svc::DeviceName_Count);
|
||||
|
||||
constexpr bool IsAttachable(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) {
|
||||
if (0 <= device_name && device_name < ams::svc::DeviceName_Count) {
|
||||
const auto &range = SmmuSupportedRanges[device_name];
|
||||
return range.start <= space_address && (space_address + space_size - 1) <= range.end;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Types. */
|
||||
class EntryBase {
|
||||
protected:
|
||||
@ -404,4 +457,130 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* TODO: Install interrupt handler. */
|
||||
}
|
||||
|
||||
/* Member functions. */
|
||||
|
||||
Result KDevicePageTable::Initialize(u64 space_address, u64 space_size) {
|
||||
/* Ensure space is valid. */
|
||||
R_UNLESS(((space_address + space_size - 1) & ~DeviceVirtualAddressMask) == 0, svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Determine extents. */
|
||||
const size_t start_index = space_address / DeviceRegionSize;
|
||||
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
|
||||
|
||||
/* Get the page table manager. */
|
||||
auto &ptm = Kernel::GetPageTableManager();
|
||||
|
||||
/* Clear the tables. */
|
||||
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->tables[i] = Null<KVirtualAddress>;
|
||||
}
|
||||
|
||||
/* Ensure that we clean up the tables on failure. */
|
||||
auto table_guard = SCOPE_GUARD {
|
||||
for (size_t i = start_index; i <= end_index; ++i) {
|
||||
if (this->tables[i] != Null<KVirtualAddress> && ptm.Close(this->tables[i], 1)) {
|
||||
ptm.Free(this->tables[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Allocate a table for all required indices. */
|
||||
for (size_t i = start_index; i <= end_index; ++i) {
|
||||
const KVirtualAddress table_vaddr = ptm.Allocate();
|
||||
R_UNLESS(table_vaddr != Null<KVirtualAddress>, svc::ResultOutOfMemory());
|
||||
|
||||
MESOSPHERE_ASSERT((static_cast<u64>(GetInteger(GetPageTablePhysicalAddress(table_vaddr))) & ~PhysicalAddressMask) == 0);
|
||||
|
||||
ptm.Open(table_vaddr, 1);
|
||||
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize);
|
||||
this->tables[i] = table_vaddr;
|
||||
}
|
||||
|
||||
/* Clear asids. */
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->table_asids[i] = g_reserved_asid;
|
||||
}
|
||||
|
||||
/* Reserve asids for the tables. */
|
||||
R_TRY(g_asid_manager.Reserve(std::addressof(this->table_asids[start_index]), end_index - start_index + 1));
|
||||
|
||||
/* Associate tables with asids. */
|
||||
for (size_t i = start_index; i <= end_index; ++i) {
|
||||
SetTable(this->table_asids[i], GetPageTablePhysicalAddress(this->tables[i]));
|
||||
}
|
||||
|
||||
/* Set member variables. */
|
||||
this->attached_device = 0;
|
||||
this->attached_value = (1u << 31) | this->table_asids[0];
|
||||
this->detached_value = (1u << 31) | g_reserved_asid;
|
||||
|
||||
this->hs_attached_value = (1u << 31);
|
||||
this->hs_detached_value = (1u << 31);
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->hs_attached_value |= (this->table_asids[i] << (i * BITSIZEOF(u8)));
|
||||
this->hs_detached_value |= (g_reserved_asid << (i * BITSIZEOF(u8)));
|
||||
}
|
||||
|
||||
/* We succeeded. */
|
||||
table_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void KDevicePageTable::Finalize() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
Result KDevicePageTable::Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) {
|
||||
/* Validate the device name. */
|
||||
R_UNLESS(0 <= device_name, svc::ResultNotFound());
|
||||
R_UNLESS(device_name < ams::svc::DeviceName_Count, svc::ResultNotFound());
|
||||
|
||||
/* Check that the device isn't already attached. */
|
||||
R_UNLESS((this->attached_device & (1ul << device_name)) == 0, svc::ResultBusy());
|
||||
|
||||
/* Validate that the space is allowed for the device. */
|
||||
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
|
||||
R_UNLESS(end_index == 0 || IsHsSupported(device_name), svc::ResultInvalidCombination());
|
||||
|
||||
/* Validate that the device can be attached. */
|
||||
R_UNLESS(IsAttachable(device_name, space_address, space_size), svc::ResultInvalidCombination());
|
||||
|
||||
/* Get the device asid register offset. */
|
||||
const int reg_offset = GetDeviceAsidRegisterOffset(device_name);
|
||||
R_UNLESS(reg_offset >= 0, svc::ResultNotFound());
|
||||
|
||||
/* Determine the old/new values. */
|
||||
const u32 old_val = IsHsSupported(device_name) ? this->hs_detached_value : this->detached_value;
|
||||
const u32 new_val = IsHsSupported(device_name) ? this->hs_attached_value : this->attached_value;
|
||||
|
||||
/* Attach the device. */
|
||||
{
|
||||
KScopedLightLock lk(g_lock);
|
||||
|
||||
/* Validate that the device is unclaimed. */
|
||||
R_UNLESS((ReadMcRegister(reg_offset) | (1u << 31)) == (old_val | (1u << 31)), svc::ResultBusy());
|
||||
|
||||
/* Claim the device. */
|
||||
WriteMcRegister(reg_offset, new_val);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Ensure that we claimed it successfully. */
|
||||
if (ReadMcRegister(reg_offset) != new_val) {
|
||||
WriteMcRegister(reg_offset, old_val);
|
||||
SmmuSynchronizationBarrier();
|
||||
return svc::ResultNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark the device as attached. */
|
||||
this->attached_device |= (1ul << device_name);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KDevicePageTable::Detach(ams::svc::DeviceName device_name) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,55 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
/* Static initializer. */
|
||||
void KDeviceAddressSpace::Initialize() {
|
||||
/* This just forwards to the device page table manager. */
|
||||
KDevicePageTable::Initialize();
|
||||
}
|
||||
|
||||
/* Member functions. */
|
||||
Result KDeviceAddressSpace::Initialize(u64 address, u64 size) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Initialize the device page table. */
|
||||
R_TRY(this->table.Initialize(address, size));
|
||||
|
||||
/* Set member variables. */
|
||||
this->space_address = address;
|
||||
this->space_size = size;
|
||||
this->is_initialized = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void KDeviceAddressSpace::Finalize() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Finalize the table. */
|
||||
this->table.Finalize();
|
||||
|
||||
/* Finalize base. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList>::Finalize();
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Attach(ams::svc::DeviceName device_name) {
|
||||
/* Lock the address space. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
|
||||
/* Attach. */
|
||||
return this->table.Attach(device_name, this->space_address, this->space_size);
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Detach(ams::svc::DeviceName device_name) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Map(size_t *out_mapped_size, KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool refresh_mappings) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,22 +21,61 @@ namespace ams::kern::svc {
|
||||
|
||||
namespace {
|
||||
|
||||
Result CreateDeviceAddressSpace(ams::svc::Handle *out, uint64_t das_address, uint64_t das_size) {
|
||||
/* Validate input. */
|
||||
R_UNLESS(util::IsAligned(das_address, PageSize), svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(util::IsAligned(das_size, PageSize), svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(das_size > 0, svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS((das_address < das_address + das_size), svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Create the device address space. */
|
||||
KScopedAutoObject das = KDeviceAddressSpace::Create();
|
||||
R_UNLESS(das.IsNotNull(), svc::ResultOutOfResource());
|
||||
|
||||
/* Initialize the device address space. */
|
||||
R_TRY(das->Initialize(das_address, das_size));
|
||||
|
||||
/* Register the device address space. */
|
||||
R_TRY(KDeviceAddressSpace::Register(das.GetPointerUnsafe()));
|
||||
|
||||
/* Add to the handle table. */
|
||||
R_TRY(GetCurrentProcess().GetHandleTable().Add(out, das.GetPointerUnsafe()));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result AttachDeviceAddressSpace(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
/* Get the device address space. */
|
||||
KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
|
||||
R_UNLESS(das.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Attach. */
|
||||
return das->Attach(device_name);
|
||||
}
|
||||
|
||||
Result DetachDeviceAddressSpace(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
/* Get the device address space. */
|
||||
KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
|
||||
R_UNLESS(das.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Detach. */
|
||||
return das->Detach(device_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ============================= 64 ABI ============================= */
|
||||
|
||||
Result CreateDeviceAddressSpace64(ams::svc::Handle *out_handle, uint64_t das_address, uint64_t das_size) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcCreateDeviceAddressSpace64 was called.");
|
||||
return CreateDeviceAddressSpace(out_handle, das_address, das_size);
|
||||
}
|
||||
|
||||
Result AttachDeviceAddressSpace64(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcAttachDeviceAddressSpace64 was called.");
|
||||
return AttachDeviceAddressSpace(device_name, das_handle);
|
||||
}
|
||||
|
||||
Result DetachDeviceAddressSpace64(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcDetachDeviceAddressSpace64 was called.");
|
||||
return DetachDeviceAddressSpace(device_name, das_handle);
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceByForce64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
|
||||
@ -58,15 +97,15 @@ namespace ams::kern::svc {
|
||||
/* ============================= 64From32 ABI ============================= */
|
||||
|
||||
Result CreateDeviceAddressSpace64From32(ams::svc::Handle *out_handle, uint64_t das_address, uint64_t das_size) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcCreateDeviceAddressSpace64From32 was called.");
|
||||
return CreateDeviceAddressSpace(out_handle, das_address, das_size);
|
||||
}
|
||||
|
||||
Result AttachDeviceAddressSpace64From32(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcAttachDeviceAddressSpace64From32 was called.");
|
||||
return AttachDeviceAddressSpace(device_name, das_handle);
|
||||
}
|
||||
|
||||
Result DetachDeviceAddressSpace64From32(ams::svc::DeviceName device_name, ams::svc::Handle das_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcDetachDeviceAddressSpace64From32 was called.");
|
||||
return DetachDeviceAddressSpace(device_name, das_handle);
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceByForce64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
|
||||
|
@ -43,20 +43,17 @@ namespace ams::kern::svc {
|
||||
auto &handle_table = process.GetHandleTable();
|
||||
|
||||
/* Create the interrupt event. */
|
||||
KInterruptEvent *event = KInterruptEvent::Create();
|
||||
R_UNLESS(event != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Ensure that we cleanup the event on exit, leaving the only reference as the one in the handle table. */
|
||||
ON_SCOPE_EXIT { event->Close(); };
|
||||
KScopedAutoObject event = KInterruptEvent::Create();
|
||||
R_UNLESS(event.IsNotNull(), svc::ResultOutOfResource());
|
||||
|
||||
/* Initialize the event. */
|
||||
R_TRY(event->Initialize(interrupt_id, type));
|
||||
|
||||
/* Register the event. */
|
||||
R_TRY(KInterruptEvent::Register(event));
|
||||
R_TRY(KInterruptEvent::Register(event.GetPointerUnsafe()));
|
||||
|
||||
/* Add the event to the handle table. */
|
||||
R_TRY(handle_table.Add(out, event));
|
||||
R_TRY(handle_table.Add(out, event.GetPointerUnsafe()));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user