Index: sys/dev/pci/pci_host_generic_fdt.c =================================================================== --- sys/dev/pci/pci_host_generic_fdt.c +++ sys/dev/pci/pci_host_generic_fdt.c @@ -71,10 +71,21 @@ #define PROPS_CELL_SIZE 1 #define PCI_ADDR_CELL_SIZE 2 +struct pci_ofw_devinfo { + STAILQ_ENTRY(pci_ofw_devinfo) pci_ofw_link; + struct ofw_bus_devinfo di_dinfo; + uint8_t slot; + uint8_t func; +}; +static STAILQ_HEAD(, pci_ofw_devinfo) pci_ofw_devlist; + /* Forward prototypes */ static int generic_pcie_fdt_probe(device_t dev); static int parse_pci_mem_ranges(device_t, struct generic_pcie_core_softc *); +static int generic_pcie_ofw_bus_attach(device_t); +static const struct ofw_bus_devinfo *generic_pcie_ofw_get_devinfo(device_t, + device_t); static int generic_pcie_fdt_probe(device_t dev) @@ -110,6 +121,10 @@ if (parse_pci_mem_ranges(dev, &sc->base)) return (ENXIO); + /* Attach OFW bus */ + if (generic_pcie_ofw_bus_attach(dev) != 0) + return (ENXIO); + node = ofw_bus_get_node(dev); if (sc->base.coherent == 0) { sc->base.coherent = OF_hasprop(node, "dma-coherent"); @@ -367,8 +382,57 @@ return (0); } +static const struct ofw_bus_devinfo * +generic_pcie_ofw_get_devinfo(device_t bus, device_t child) +{ + uint8_t slot, func; + struct pci_ofw_devinfo *di; + + slot = pci_get_slot(child); + func = pci_get_function(child); + + STAILQ_FOREACH(di, &pci_ofw_devlist, pci_ofw_link) + if (slot == di->slot && func == di->func) + return (&di->di_dinfo); + + return (NULL); +} + /* Helper functions */ +static int +generic_pcie_ofw_bus_attach(device_t dev) +{ + struct pci_ofw_devinfo *di; + phandle_t parent, node; + pcell_t reg[5]; + ssize_t len; + + STAILQ_INIT(&pci_ofw_devlist); + parent = ofw_bus_get_node(dev); + if (parent == 0) + return (0); + + /* Iterate through all bus subordinates */ + for (node = OF_child(parent); node > 0; node = OF_peer(node)) { + len = OF_getencprop(node, "reg", reg, sizeof(reg)); + if (len != 5 * sizeof(pcell_t)) + continue; + + /* Allocate and populate devinfo. */ + di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) { + free(di, M_DEVBUF); + continue; + } + di->func = (reg[0] >> 8) & 0xFF; + di->slot = reg[0] & 0xFF; + STAILQ_INSERT_TAIL(&pci_ofw_devlist, di, pci_ofw_link); + } + + return (0); +} + static device_method_t generic_pcie_fdt_methods[] = { DEVMETHOD(device_probe, generic_pcie_fdt_probe), DEVMETHOD(device_attach, pci_host_generic_attach), @@ -385,6 +449,13 @@ DEVMETHOD(pcib_get_id, generic_pcie_get_id), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), + DEVMETHOD(ofw_bus_get_devinfo, generic_pcie_ofw_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + DEVMETHOD_END };