1 // Copyright 2018 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #include <dev/address_provider/ecam_region.h>
8 #include <dev/pci_common.h>
9 #include <vm/vm_aspace.h>
10 
~MappedEcamRegion()11 MappedEcamRegion::~MappedEcamRegion() {
12     if (vaddr_ != nullptr) {
13         VmAspace::kernel_aspace()->FreeRegion(reinterpret_cast<vaddr_t>(vaddr_));
14     }
15 }
16 
MapEcam()17 zx_status_t MappedEcamRegion::MapEcam() {
18     DEBUG_ASSERT(ecam_.bus_start <= ecam_.bus_end);
19 
20     // TODO(gkalsi): These asserts are helpful but they don't apply for the DWC
21     //               since the ECAM is broken up and mapped in different places.
22     //               We should find a way to enforce these only for MMIO ECAMs
23     // DEBUG_ASSERT((ecam_.size % PCIE_ECAM_BYTE_PER_BUS) == 0);
24     // DEBUG_ASSERT((ecam_.size / PCIE_ECAM_BYTE_PER_BUS) ==
25                  // (static_cast<size_t>(ecam_.bus_end) - ecam_.bus_start + 1u));
26 
27     if (vaddr_ != nullptr) {
28         return ZX_ERR_BAD_STATE;
29     }
30 
31     char name_buf[32];
32     snprintf(name_buf, sizeof(name_buf), "pcie_cfg_%02x_%02x",
33              ecam_.bus_start, ecam_.bus_end);
34 
35     return VmAspace::kernel_aspace()->AllocPhysical(
36         name_buf,
37         ecam_.size,
38         &vaddr_,
39         PAGE_SIZE_SHIFT,
40         ecam_.phys_base,
41         0 /* vmm flags */,
42         ARCH_MMU_FLAG_UNCACHED_DEVICE |
43             ARCH_MMU_FLAG_PERM_READ |
44             ARCH_MMU_FLAG_PERM_WRITE);
45 }
46