| // 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 <stdint.h> |
| #include <zircon/errors.h> |
| #include <zircon/syscalls/types.h> |
| |
| #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-virt.h" |
| |
| namespace board_qemu_arm64 { |
| |
| zx_status_t QemuArm64::PciInit() { |
| zx_status_t status; |
| |
| zx_pci_init_arg_t* arg1; |
| size_t arg_size = sizeof(*arg1) + sizeof(arg1->addr_windows[0]); // room for one addr window |
| fbl::AllocChecker ac; |
| std::unique_ptr<uint8_t[]> buf(new (&ac) uint8_t[arg_size]); |
| if (!ac.check()) { |
| return ZX_ERR_NO_MEMORY; |
| } |
| auto* arg = reinterpret_cast<zx_pci_init_arg_t*>(buf.get()); |
| |
| // Please do not use get_root_resource() in new code. See fxbug.dev/31358. |
| status = zx_pci_add_subtract_io_range(get_root_resource(), true /* mmio */, PCIE_MMIO_BASE_PHYS, |
| PCIE_MMIO_SIZE, true /* add */); |
| if (status != ZX_OK) { |
| return status; |
| } |
| // Please do not use get_root_resource() in new code. See fxbug.dev/31358. |
| status = zx_pci_add_subtract_io_range(get_root_resource(), false /* pio */, PCIE_PIO_BASE_PHYS, |
| PCIE_PIO_SIZE, true /* add */); |
| if (status != ZX_OK) { |
| return status; |
| } |
| |
| // initialize our swizzle table |
| zx_pci_irq_swizzle_lut_t* lut = &arg->dev_pin_to_global_irq; |
| for (unsigned dev_id = 0; dev_id < ZX_PCI_MAX_DEVICES_PER_BUS; dev_id++) { |
| for (unsigned func_id = 0; func_id < ZX_PCI_MAX_FUNCTIONS_PER_DEVICE; func_id++) { |
| for (unsigned pin = 0; pin < ZX_PCI_MAX_LEGACY_IRQ_PINS; pin++) { |
| (*lut)[dev_id][func_id][pin] = PCIE_INT_BASE + (pin + dev_id) % ZX_PCI_MAX_LEGACY_IRQ_PINS; |
| } |
| } |
| } |
| arg->num_irqs = 0; |
| arg->addr_window_count = 1; |
| arg->addr_windows[0].cfg_space_type = PCI_CFG_SPACE_TYPE_MMIO; |
| arg->addr_windows[0].has_ecam = true; |
| arg->addr_windows[0].base = PCIE_ECAM_BASE_PHYS; |
| arg->addr_windows[0].size = PCIE_ECAM_SIZE; |
| arg->addr_windows[0].bus_start = 0; |
| arg->addr_windows[0].bus_end = (PCIE_ECAM_SIZE / ZX_PCI_ECAM_BYTE_PER_BUS) - 1; |
| |
| // Please do not use get_root_resource() in new code. See fxbug.dev/31358. |
| status = zx_pci_init(get_root_resource(), arg, static_cast<uint32_t>(arg_size)); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: error %d in zx_pci_init", __func__, status); |
| return status; |
| } |
| |
| return ZX_OK; |
| } |
| |
| zx_status_t QemuArm64::PciAdd() { |
| constexpr pbus_bti_t kPciBtis[] = { |
| { |
| .iommu_index = 0, |
| .bti_id = 0, |
| }, |
| }; |
| |
| pbus_dev_t pci_dev = {}; |
| pci_dev.name = "pci"; |
| pci_dev.vid = PDEV_VID_GENERIC; |
| pci_dev.pid = PDEV_PID_GENERIC; |
| pci_dev.did = PDEV_DID_KPCI; |
| pci_dev.bti_list = kPciBtis; |
| pci_dev.bti_count = countof(kPciBtis); |
| |
| auto status = pbus_.DeviceAdd(&pci_dev); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: DeviceAdd failed %d", __func__, status); |
| return status; |
| } |
| |
| return ZX_OK; |
| } |
| |
| } // namespace board_qemu_arm64 |