예제 #1
0
파일: ofw_pci.c 프로젝트: embedclub/freebsd
int
ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
                          struct resource *r)
{
    struct ofw_pci_softc *sc;
    struct bus_space_tag *tag;

    sc = device_get_softc(bus);
    switch (type) {
    case SYS_RES_IRQ:
        return (bus_generic_activate_resource(bus, child, type, rid,
                                              r));
    case SYS_RES_MEMORY:
        tag = sparc64_alloc_bus_tag(r, PCI_MEMORY_BUS_SPACE);
        if (tag == NULL)
            return (ENOMEM);
        rman_set_bustag(r, tag);
        rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
                           rman_get_start(r));
        break;
    case SYS_RES_IOPORT:
        rman_set_bustag(r, sc->sc_pci_iot);
        rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
                           rman_get_start(r));
        break;
    }
    return (rman_activate_resource(r));
}
예제 #2
0
static int
sbus_activate_resource(device_t bus, device_t child, int type, int rid,
                       struct resource *r)
{
    struct sbus_softc *sc;
    struct bus_space_tag *tag;
    int i;

    switch (type) {
    case SYS_RES_IRQ:
        return (bus_generic_activate_resource(bus, child, type, rid,
                                              r));
    case SYS_RES_MEMORY:
        sc = device_get_softc(bus);
        for (i = 0; i < sc->sc_nrange; i++) {
            if (rman_is_region_manager(r,
                                       &sc->sc_rd[i].rd_rman) != 0) {
                tag = sparc64_alloc_bus_tag(r, SBUS_BUS_SPACE);
                if (tag == NULL)
                    return (ENOMEM);
                rman_set_bustag(r, tag);
                rman_set_bushandle(r,
                                   sc->sc_rd[i].rd_bushandle +
                                   rman_get_start(r));
                return (rman_activate_resource(r));
            }
        }
    /* FALLTHROUGH */
    default:
        return (EINVAL);
    }
}
예제 #3
0
파일: ofw_pci.c 프로젝트: embedclub/freebsd
int
ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize,
                      u_long memsize)
{
    struct ofw_pci_softc *sc;
    struct ofw_pci_ranges *range;
    phandle_t node;
    uint32_t prop_array[2];
    u_int i, j, nrange;

    sc = device_get_softc(dev);
    node = ofw_bus_get_node(dev);
    sc->sc_node = node;
    sc->sc_pci_dmat = dmat;

    /* Initialize memory and I/O rmans. */
    sc->sc_pci_io_rman.rm_type = RMAN_ARRAY;
    sc->sc_pci_io_rman.rm_descr = "PCI I/O Ports";
    if (rman_init(&sc->sc_pci_io_rman) != 0 ||
            rman_manage_region(&sc->sc_pci_io_rman, 0, iosize) != 0) {
        device_printf(dev, "failed to set up I/O rman\n");
        return (ENXIO);
    }
    sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY;
    sc->sc_pci_mem_rman.rm_descr = "PCI Memory";
    if (rman_init(&sc->sc_pci_mem_rman) != 0 ||
            rman_manage_region(&sc->sc_pci_mem_rman, 0, memsize) != 0) {
        device_printf(dev, "failed to set up memory rman\n");
        return (ENXIO);
    }

    /*
     * Find the addresses of the various bus spaces.  The physical
     * start addresses of the ranges are the configuration, I/O and
     * memory handles.  There should not be multiple ones of one kind.
     */
    nrange = OF_getprop_alloc(node, "ranges", sizeof(*range),
                              (void **)&range);
    for (i = 0; i < nrange; i++) {
        j = OFW_PCI_RANGE_CS(&range[i]);
        if (sc->sc_pci_bh[j] != 0) {
            device_printf(dev, "duplicate range for space %d\n",
                          j);
            free(range, M_OFWPROP);
            return (EINVAL);
        }
        sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
    }
    free(range, M_OFWPROP);

    /*
     * Make sure that the expected ranges are actually present.
     * The OFW_PCI_CS_MEM64 one is not currently used.
     */
    if (sc->sc_pci_bh[OFW_PCI_CS_CONFIG] == 0) {
        device_printf(dev, "missing CONFIG range\n");
        return (ENXIO);
    }
    if (sc->sc_pci_bh[OFW_PCI_CS_IO] == 0) {
        device_printf(dev, "missing IO range\n");
        return (ENXIO);
    }
    if (sc->sc_pci_bh[OFW_PCI_CS_MEM32] == 0) {
        device_printf(dev, "missing MEM32 range\n");
        return (ENXIO);
    }

    /* Allocate our tags. */
    sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, PCI_IO_BUS_SPACE);
    if (sc->sc_pci_iot == NULL) {
        device_printf(dev, "could not allocate PCI I/O tag\n");
        return (ENXIO);
    }
    sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, PCI_CONFIG_BUS_SPACE);
    if (sc->sc_pci_cfgt == NULL) {
        device_printf(dev,
                      "could not allocate PCI configuration space tag\n");
        return (ENXIO);
    }

    /*
     * Get the bus range from the firmware.
     */
    i = OF_getprop(node, "bus-range", (void *)prop_array,
                   sizeof(prop_array));
    if (i == -1) {
        device_printf(dev, "could not get bus-range\n");
        return (ENXIO);
    }
    if (i != sizeof(prop_array)) {
        device_printf(dev, "broken bus-range (%d)", i);
        return (EINVAL);
    }
    sc->sc_pci_secbus = prop_array[0];
    sc->sc_pci_subbus = prop_array[1];
    if (bootverbose != 0)
        device_printf(dev, "bus range %u to %u; PCI bus %d\n",
                      sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus);

    ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));

    return (0);
}