blob: 3b5f67b42cbf47ae45cb20a9f883cf5b6f7048ba [file] [log] [blame]
// 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.
library fuchsia.hardware.pciroot;
using zx;
type PciBdf = struct {
bus_id uint8;
device_id uint8;
function_id uint8;
};
const DEVICES_PER_BUS uint8 = 32;
const FUNCTIONS_PER_DEVICE uint8 = 8;
const PINS_PER_FUNCTION uint8 = 4;
/// Used to indicate within a routing entry that there is no parent bridge/port
/// device, it is connected directly at the root.
const PCI_IRQ_ROUTING_NO_PARENT uint8 = 0xFF;
/// An entry corresponds to all functions for the given device.
const PCI_IRQ_ROUTING_ALL_FUNCTIONS uint8 = 0xF;
/// A protocol representation of a routing entry.
/// It is intentionally very similar to an ACPI _PRT entry to reduce the complexity of
/// the data structure that needs to be passed over the 'wire'. Endpoints
/// directly connected to a root complex will have port device and function_ids
/// of PCI_IRQ_ROUTING_NO_PARENT. For other endpoints hanging off root ports or
/// bridges their upstream port address will be contained in these fields.
type PciIrqRoutingEntry = struct {
port_device_id uint8;
port_function_id uint8;
device_id uint8;
pins array<uint8, PINS_PER_FUNCTION>;
};
/// This represents one of the vectors wired up for PCI legacy interrupts. How
/// the bus driver uses them depends on the irq routing table provided to them.
/// The vector is supplied because interrupt objects cannot be inspected with
/// zx_get_object_info.
type PciLegacyIrq = resource struct {
interrupt zx.Handle:INTERRUPT;
vector uint32;
};
/// This structure is the primary means of passing PCI platform information from
/// the platform bus implementation to the PCI bus driver. If an ecam is found
/// for this segment group then a handle to a VMO for it will be provided via
/// |ecam_vmo|. The VMO's start address will correspond to the base address of
/// the bus number specified by |start_bus_num|.
type PciPlatformInfo = resource struct {
name string:8;
start_bus_num uint8;
end_bus_num uint8;
segment_group uint16;
ecam_vmo zx.Handle:VMO;
legacy_irqs vector<PciLegacyIrq>:MAX;
irq_routing vector<PciIrqRoutingEntry>:MAX;
/// A vector of PciBdfs that are known to ACPI.
/// For each BDF in this list, the composite device published by the PCI bus
/// driver will bind to an ACPI device with ACPI_BUS_TYPE == PCI and a
/// matching PCI_BIND_TOPO.
acpi_bdfs vector<PciBdf>:MAX;
};
type PciAddressSpace = strict enum : uint8 {
NONE = 0;
MEMORY = 1;
IO = 2;
};
@transport("Banjo")
@banjo_layout("ddk-protocol")
closed protocol Pciroot {
/// Legacy methods
strict GetBti(struct {
bdf uint32;
index uint32;
}) -> (resource struct {
s zx.Status;
bti zx.Handle:BTI;
});
/// Get the platform information structure from the pciroot protocol to be used for bus init.
strict GetPciPlatformInfo() -> (resource struct {
s zx.Status;
info PciPlatformInfo;
});
/// Contemporary methods:
/// Returns true if the bus driver should proxy all device config access to pciroot. This is
/// necessary in cases of IO config on x86, or for controllers that require configuration to
/// map in device config headers.
strict DriverShouldProxyConfig() -> (struct {
use_proxy bool;
});
/// Read 8 bytes from config space for device at bdf address |address|:we, offset |offset|.
strict ReadConfig8(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.Status;
value uint8;
});
/// Read 16 bytes from config space for device at bdf address |address|, offset |offset|.
strict ReadConfig16(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.Status;
value uint16;
});
/// Read 32 bytes from config space for device at bdf address |address|, offset |offset|.
strict ReadConfig32(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.Status;
value uint32;
});
/// Write 8 bytes to config space for device at bdf |address| offset |offset|.
strict WriteConfig8(struct {
address PciBdf;
offset uint16;
value uint8;
}) -> (struct {
s zx.Status;
});
/// Write 16 bytes to config space for device at bdf |address| offset |offset|.
strict WriteConfig16(struct {
address PciBdf;
offset uint16;
value uint16;
}) -> (struct {
s zx.Status;
});
/// Write 32 bytes to config space for device at bdf |address| offset |offset|.
strict WriteConfig32(struct {
address PciBdf;
offset uint16;
value uint32;
}) -> (struct {
s zx.Status;
});
/// Request address space reservations from platform bus to use for mapping bars / bridges
/// |in_base| is an optional requested start address which should otherwise be 0. |size| is the
/// size of the request in bytes. |low| dictates whether the allocation should be an address
/// below 4 GB or not.
///
/// On success, the base address is provided in |out_base| and the size is |size|.
///
/// An error will be returned if |size| cannot be fulfilled, |low| is set with |in_base|+|size|
/// being >=4GB, or if a requested |in_base| cannot be provided.
strict GetAddressSpace(struct {
in_base uint64;
size uint64;
type PciAddressSpace;
low bool;
}) -> (resource struct {
s zx.Status;
base uint64;
resource zx.Handle:RESOURCE;
token zx.Handle:EVENTPAIR;
});
/// Allocate |msi_count| MSIs and return a handle to the backing MsiAllocation.
strict AllocateMsi(struct {
msi_count uint32;
can_target_64bit bool;
}) -> (resource struct {
s zx.Status;
allocation zx.Handle:MSI;
});
};