blob: f74d7ac3109ab6822d3a072d0986a564274344a3 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/hardware/pciroot/c/banjo.h>
#include <lib/zx/vmo.h>
#include <stdint.h>
#include <zircon/errors.h>
#include <zircon/syscalls/types.h>
#include <array>
#include <limits>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include "qemu-bus.h"
#include "qemu-pciroot.h"
#include "qemu-virt.h"
namespace board_qemu_arm64 {
zx_status_t QemuArm64Pciroot::Create(PciRootHost* root_host, QemuArm64Pciroot::Context ctx,
zx_device_t* parent, const char* name) {
auto pciroot = new QemuArm64Pciroot(root_host, std::move(ctx), parent, name);
return pciroot->DdkAdd(name);
}
zx_status_t QemuArm64Pciroot::PcirootGetBti(uint32_t bdf, uint32_t index, zx::bti* bti) {
return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t QemuArm64Pciroot::PcirootGetPciPlatformInfo(pci_platform_info_t* info) {
*info = context_.info;
return ZX_OK;
}
zx_status_t QemuArm64::PciInit() {
zx_status_t status = pci_root_host_.Mmio32().AddRegion(
{.base = PCIE_MMIO_BASE_PHYS, .size = PCIE_MMIO_SIZE}, RegionAllocator::AllowOverlap::No);
if (status != ZX_OK) {
zxlogf(ERROR, "Failed to add MMIO region { %#lx - %#lx } to PCI root allocator: %s",
PCIE_MMIO_BASE_PHYS, PCIE_MMIO_BASE_PHYS + PCIE_MMIO_SIZE, zx_status_get_string(status));
return status;
}
status = pci_root_host_.Mmio64().AddRegion(
{.base = PCIE_MMIO_HIGH_BASE_PHYS, .size = PCIE_MMIO_HIGH_SIZE},
RegionAllocator::AllowOverlap::No);
if (status != ZX_OK) {
zxlogf(ERROR, "Failed to add MMIO region { %#lx - %#lx } to PCI root allocator: %s",
PCIE_MMIO_HIGH_BASE_PHYS, PCIE_MMIO_HIGH_BASE_PHYS + PCIE_MMIO_HIGH_SIZE,
zx_status_get_string(status));
return status;
}
if ((status = pci_root_host_.Io().AddRegion({.base = PCIE_PIO_BASE_PHYS, .size = PCIE_PIO_SIZE},
RegionAllocator::AllowOverlap::No)) != ZX_OK) {
zxlogf(ERROR, "Failed to add IO region { %#lx - %#lx } to the PCI root allocator: %s",
PCIE_PIO_BASE_PHYS, PCIE_PIO_BASE_PHYS + PCIE_PIO_SIZE, zx_status_get_string(status));
return status;
}
McfgAllocation pci0_mcfg = {
.address = PCIE_ECAM_BASE_PHYS,
.pci_segment = 0,
.start_bus_number = 0,
.end_bus_number = (PCIE_ECAM_SIZE / ZX_PCI_ECAM_BYTE_PER_BUS) - 1,
};
pci_root_host_.mcfgs().push_back(pci0_mcfg);
return ZX_OK;
}
zx_status_t QemuArm64::PciAdd() {
McfgAllocation pci0_mcfg = {};
zx_status_t status = pci_root_host_.GetSegmentMcfgAllocation(0, &pci0_mcfg);
if (status != ZX_OK) {
zxlogf(ERROR, "Couldn't retrieve the MMCFG for segment group %u: %s", 0,
zx_status_get_string(status));
return status;
}
// There's no dynamic configuration for this platform, so just grabbing the same mcfg
// created in Init is adequate.
std::array<char, 8> name = {"pci0"};
QemuArm64Pciroot::Context ctx = {};
ctx.info.start_bus_num = pci0_mcfg.start_bus_number;
ctx.info.end_bus_num = pci0_mcfg.end_bus_number;
ctx.info.segment_group = pci0_mcfg.pci_segment;
memcpy(ctx.info.name, name.data(), name.size());
zxlogf(DEBUG, "%s ecam { %#lx - %#lx }\n", name.data(), PCIE_ECAM_BASE_PHYS,
PCIE_ECAM_BASE_PHYS + PCIE_ECAM_SIZE);
zx::vmo ecam_vmo = {};
// Please do not use get_root_resource() in new code. See fxbug.dev/31358.
status = zx::vmo::create_physical(*zx::unowned_resource(get_root_resource()), PCIE_ECAM_BASE_PHYS,
PCIE_ECAM_SIZE, &ecam_vmo);
if (status != ZX_OK) {
return status;
}
ctx.info.ecam_vmo = ecam_vmo.release();
status = QemuArm64Pciroot::Create(&pci_root_host_, ctx, parent_, name.data());
if (status != ZX_OK) {
return status;
}
return ZX_OK;
}
} // namespace board_qemu_arm64