blob: 25c3d489dcb819d927a4487d7b069275befac160 [file]
// Copyright 2018 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 <endian.h>
#include <fuchsia/hardware/pciroot/c/banjo.h>
#include <inttypes.h>
#include <lib/ddk/debug.h>
#include <lib/pci/pciroot.h>
#include <lib/pci/pio.h>
#include <zircon/compiler.h>
#include <zircon/syscalls/resource.h>
#include <zircon/types.h>
#include <array>
#include <memory>
#include <acpica/acpi.h>
#include <ddktl/device.h>
#include "lib/ddk/driver.h"
#include "src/devices/board/lib/acpi/device.h"
#include "src/devices/board/lib/acpi/pci-internal.h"
#include "src/devices/lib/iommu/iommu.h"
zx_status_t AcpiPciroot::PcirootGetBti(uint32_t bdf, uint32_t index, zx::bti* bti) {
// x86 uses PCI BDFs as hardware identifiers, and ARM uses PCI root complexes. There will be at
// most one BTI per device.
if (index != 0) {
return ZX_ERR_OUT_OF_RANGE;
}
auto iommu = context_.iommu->IommuForPciDevice(bdf);
const zx_status_t status = zx::bti::create(*iommu, 0, bdf, bti);
if (status == ZX_OK) {
char name[ZX_MAX_NAME_LEN]{};
snprintf(name, std::size(name) - 1, "acpi bti %02x:%02x.%1x", (bdf >> 8) & 0xFF,
(bdf >> 3) & 0x1F, bdf & 0x7);
const zx_status_t name_status = bti->set_property(ZX_PROP_NAME, name, std::size(name));
if (name_status != ZX_OK) {
zxlogf(WARNING, "Couldn't set name for BTI '%s': %s", name,
zx_status_get_string(name_status));
}
}
return status;
}
zx_status_t AcpiPciroot::PcirootGetPciPlatformInfo(pci_platform_info_t* info) {
*info = context_.info;
info->irq_routing_list = context_.routing.data();
info->irq_routing_count = context_.routing.size();
info->acpi_bdfs_list = acpi_bdfs_.data();
info->acpi_bdfs_count = acpi_bdfs_.size();
// ACPI platforms do not describe PCI devices via the devicetree.
info->devicetree_bdfs_count = 0;
return ZX_OK;
}
zx_status_t AcpiPciroot::PcirootReadConfig8(const pci_bdf_t* address, uint16_t offset,
uint8_t* value) {
return pci_pio_read8(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::PcirootReadConfig16(const pci_bdf_t* address, uint16_t offset,
uint16_t* value) {
return pci_pio_read16(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::PcirootReadConfig32(const pci_bdf_t* address, uint16_t offset,
uint32_t* value) {
return pci_pio_read32(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::PcirootWriteConfig8(const pci_bdf_t* address, uint16_t offset,
uint8_t value) {
return pci_pio_write8(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::PcirootWriteConfig16(const pci_bdf_t* address, uint16_t offset,
uint16_t value) {
return pci_pio_write16(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::PcirootWriteConfig32(const pci_bdf_t* address, uint16_t offset,
uint32_t value) {
return pci_pio_write32(*address, static_cast<uint8_t>(offset), value);
}
zx_status_t AcpiPciroot::Create(PciRootHost* root_host, AcpiPciroot::Context ctx,
zx_device_t* parent, const char* name,
std::vector<pci_bdf_t> acpi_bdfs) {
auto pciroot = new AcpiPciroot(root_host, std::move(ctx), parent, name, std::move(acpi_bdfs));
return pciroot->DdkAdd(ddk::DeviceAddArgs(name)
.set_proto_id(ZX_PROTOCOL_PCIROOT)
.set_inspect_vmo(pciroot->inspect().DuplicateVmo()));
}