Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/pci_host_generic_fdt.c
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
#include "pcib_if.h" | #include "pcib_if.h" | ||||
#define SPACE_CODE_SHIFT 24 | #define SPACE_CODE_SHIFT 24 | ||||
#define SPACE_CODE_MASK 0x3 | #define SPACE_CODE_MASK 0x3 | ||||
#define SPACE_CODE_IO_SPACE 0x1 | #define SPACE_CODE_IO_SPACE 0x1 | ||||
#define PROPS_CELL_SIZE 1 | #define PROPS_CELL_SIZE 1 | ||||
#define PCI_ADDR_CELL_SIZE 2 | #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; | |||||
uint8_t bus; | |||||
}; | |||||
/* Forward prototypes */ | /* Forward prototypes */ | ||||
static int generic_pcie_fdt_probe(device_t dev); | static int generic_pcie_fdt_probe(device_t dev); | ||||
static int parse_pci_mem_ranges(device_t, struct generic_pcie_core_softc *); | 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 | static int | ||||
generic_pcie_fdt_probe(device_t dev) | generic_pcie_fdt_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
Show All 13 Lines | |||||
pci_host_generic_setup_fdt(device_t dev) | pci_host_generic_setup_fdt(device_t dev) | ||||
{ | { | ||||
struct generic_pcie_fdt_softc *sc; | struct generic_pcie_fdt_softc *sc; | ||||
phandle_t node; | phandle_t node; | ||||
int error; | int error; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
STAILQ_INIT(&sc->pci_ofw_devlist); | |||||
/* Retrieve 'ranges' property from FDT */ | /* Retrieve 'ranges' property from FDT */ | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "parsing FDT for ECAM%d:\n", sc->base.ecam); | device_printf(dev, "parsing FDT for ECAM%d:\n", sc->base.ecam); | ||||
if (parse_pci_mem_ranges(dev, &sc->base)) | if (parse_pci_mem_ranges(dev, &sc->base)) | ||||
return (ENXIO); | return (ENXIO); | ||||
/* Attach OFW bus */ | |||||
if (generic_pcie_ofw_bus_attach(dev) != 0) | |||||
return (ENXIO); | |||||
node = ofw_bus_get_node(dev); | node = ofw_bus_get_node(dev); | ||||
if (sc->base.coherent == 0) { | if (sc->base.coherent == 0) { | ||||
sc->base.coherent = OF_hasprop(node, "dma-coherent"); | sc->base.coherent = OF_hasprop(node, "dma-coherent"); | ||||
} | } | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "Bus is%s cache-coherent\n", | device_printf(dev, "Bus is%s cache-coherent\n", | ||||
sc->base.coherent ? "" : " not"); | sc->base.coherent ? "" : " not"); | ||||
▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | generic_pcie_get_id(device_t pci, device_t child, enum pci_id_type type, | ||||
err = ofw_bus_msimap(node, pci_rid, NULL, &rid); | err = ofw_bus_msimap(node, pci_rid, NULL, &rid); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
*id = rid; | *id = rid; | ||||
return (0); | return (0); | ||||
} | } | ||||
static const struct ofw_bus_devinfo * | |||||
generic_pcie_ofw_get_devinfo(device_t bus, device_t child) | |||||
{ | |||||
struct generic_pcie_fdt_softc *sc; | |||||
struct pci_ofw_devinfo *di; | |||||
uint8_t slot, func, busno; | |||||
sc = device_get_softc(bus); | |||||
slot = pci_get_slot(child); | |||||
func = pci_get_function(child); | |||||
busno = pci_get_bus(child); | |||||
andrew: Won't this break if there are multiple instances of this driver? | |||||
Done Inline ActionsWhoops, you're right. The list should definitely be stored in the sc. kd: Whoops, you're right. The list should definitely be stored in the sc. | |||||
STAILQ_FOREACH(di, &sc->pci_ofw_devlist, pci_ofw_link) | |||||
if (slot == di->slot && func == di->func && busno == di->bus) | |||||
return (&di->di_dinfo); | |||||
return (NULL); | |||||
} | |||||
/* Helper functions */ | /* Helper functions */ | ||||
static int | |||||
generic_pcie_ofw_bus_attach(device_t dev) | |||||
{ | |||||
struct generic_pcie_fdt_softc *sc; | |||||
struct pci_ofw_devinfo *di; | |||||
phandle_t parent, node; | |||||
pcell_t reg[5]; | |||||
ssize_t len; | |||||
sc = device_get_softc(dev); | |||||
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 = OFW_PCI_PHYS_HI_FUNCTION(reg[0]); | |||||
di->slot = OFW_PCI_PHYS_HI_DEVICE(reg[0]); | |||||
Not Done Inline ActionsDo we have macros for these? OFW_PCI_PHYS_HI_* look like what we should use. andrew: Do we have macros for these? `OFW_PCI_PHYS_HI_*` look like what we should use. | |||||
di->bus = OFW_PCI_PHYS_HI_BUS(reg[0]); | |||||
STAILQ_INSERT_TAIL(&sc->pci_ofw_devlist, di, pci_ofw_link); | |||||
} | |||||
return (0); | |||||
} | |||||
static device_method_t generic_pcie_fdt_methods[] = { | static device_method_t generic_pcie_fdt_methods[] = { | ||||
DEVMETHOD(device_probe, generic_pcie_fdt_probe), | DEVMETHOD(device_probe, generic_pcie_fdt_probe), | ||||
DEVMETHOD(device_attach, pci_host_generic_attach), | DEVMETHOD(device_attach, pci_host_generic_attach), | ||||
DEVMETHOD(bus_alloc_resource, pci_host_generic_core_alloc_resource), | DEVMETHOD(bus_alloc_resource, pci_host_generic_core_alloc_resource), | ||||
DEVMETHOD(bus_release_resource, pci_host_generic_core_release_resource), | DEVMETHOD(bus_release_resource, pci_host_generic_core_release_resource), | ||||
/* pcib interface */ | /* pcib interface */ | ||||
DEVMETHOD(pcib_route_interrupt, generic_pcie_fdt_route_interrupt), | DEVMETHOD(pcib_route_interrupt, generic_pcie_fdt_route_interrupt), | ||||
DEVMETHOD(pcib_alloc_msi, generic_pcie_fdt_alloc_msi), | DEVMETHOD(pcib_alloc_msi, generic_pcie_fdt_alloc_msi), | ||||
DEVMETHOD(pcib_release_msi, generic_pcie_fdt_release_msi), | DEVMETHOD(pcib_release_msi, generic_pcie_fdt_release_msi), | ||||
DEVMETHOD(pcib_alloc_msix, generic_pcie_fdt_alloc_msix), | DEVMETHOD(pcib_alloc_msix, generic_pcie_fdt_alloc_msix), | ||||
DEVMETHOD(pcib_release_msix, generic_pcie_fdt_release_msix), | DEVMETHOD(pcib_release_msix, generic_pcie_fdt_release_msix), | ||||
DEVMETHOD(pcib_map_msi, generic_pcie_fdt_map_msi), | DEVMETHOD(pcib_map_msi, generic_pcie_fdt_map_msi), | ||||
DEVMETHOD(pcib_get_id, generic_pcie_get_id), | DEVMETHOD(pcib_get_id, generic_pcie_get_id), | ||||
DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), | 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 | DEVMETHOD_END | ||||
}; | }; | ||||
DEFINE_CLASS_1(pcib, generic_pcie_fdt_driver, generic_pcie_fdt_methods, | DEFINE_CLASS_1(pcib, generic_pcie_fdt_driver, generic_pcie_fdt_methods, | ||||
sizeof(struct generic_pcie_fdt_softc), generic_pcie_core_driver); | sizeof(struct generic_pcie_fdt_softc), generic_pcie_core_driver); | ||||
static devclass_t generic_pcie_fdt_devclass; | static devclass_t generic_pcie_fdt_devclass; | ||||
DRIVER_MODULE(pcib, simplebus, generic_pcie_fdt_driver, | DRIVER_MODULE(pcib, simplebus, generic_pcie_fdt_driver, | ||||
generic_pcie_fdt_devclass, 0, 0); | generic_pcie_fdt_devclass, 0, 0); | ||||
DRIVER_MODULE(pcib, ofwbus, generic_pcie_fdt_driver, generic_pcie_fdt_devclass, | DRIVER_MODULE(pcib, ofwbus, generic_pcie_fdt_driver, generic_pcie_fdt_devclass, | ||||
0, 0); | 0, 0); |
Won't this break if there are multiple instances of this driver?