/* * Copyright (c) 2020, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include namespace Kernel::Memory { template struct TypedMapping { T const* ptr() const { return reinterpret_cast(region->vaddr().offset(offset).as_ptr()); } T* ptr() { return reinterpret_cast(region->vaddr().offset(offset).as_ptr()); } VirtualAddress base_address() const { return region->vaddr().offset(offset); } T const* operator->() const { return ptr(); } T* operator->() { return ptr(); } T const& operator*() const { return *ptr(); } T& operator*() { return *ptr(); } OwnPtr region; PhysicalAddress paddr; size_t offset { 0 }; size_t length { 0 }; }; template static ErrorOr>> adopt_new_nonnull_own_typed_mapping(PhysicalAddress paddr, size_t length, Region::Access access = Region::Access::Read) { auto mapping_length = TRY(page_round_up(paddr.offset_in_page() + length)); auto region = TRY(MM.allocate_mmio_kernel_region(paddr.page_base(), mapping_length, {}, access)); auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Memory::TypedMapping())); table->region = move(region); table->offset = paddr.offset_in_page(); table->paddr = paddr; table->length = length; return table; } template static ErrorOr> map_typed(PhysicalAddress paddr, size_t length, Region::Access access = Region::Access::Read) { TypedMapping table; auto mapping_length = TRY(page_round_up(paddr.offset_in_page() + length)); table.region = TRY(MM.allocate_mmio_kernel_region(paddr.page_base(), mapping_length, {}, access)); table.offset = paddr.offset_in_page(); table.paddr = paddr; table.length = length; return table; } template static ErrorOr> map_typed(PhysicalAddress paddr) { return map_typed(paddr, sizeof(T)); } template static ErrorOr> map_typed_writable(PhysicalAddress paddr) { return map_typed(paddr, sizeof(T), Region::Access::Read | Region::Access::Write); } }