Esempio n. 1
0
void
isa_init(device_t dev)
{
	device_t bridge;
	int i;

	/* The parent of the bus must be a PCI-ISA bridge. */
	bridge = device_get_parent(dev);
	isab_node = ofw_bus_get_node(bridge);
	isab_nrange = OF_getprop_alloc(isab_node, "ranges",
	    sizeof(*isab_ranges), (void **)&isab_ranges);
	if (isab_nrange <= 0)
		panic("isa_init: cannot get bridge range property");

	ofw_bus_setup_iinfo(isab_node, &isa_iinfo, sizeof(ofw_isa_intr_t));

	isa_setup_children(dev, isab_node);

	for (i = isab_nrange - 1; i >= 0; i--) {
		switch(ISAB_RANGE_SPACE(&isab_ranges[i])) {
		case ISAR_SPACE_IO:
			/* This is probably always 0. */
			isa_io_base = ISAB_RANGE_PHYS(&isab_ranges[i]);
			isa_io_limit = isab_ranges[i].size;
			break;
		case ISAR_SPACE_MEM:
			/* This is probably always 0. */
			isa_mem_base = ISAB_RANGE_PHYS(&isab_ranges[i]);
			isa_mem_limit = isab_ranges[i].size;
			break;
		}
	}
}
Esempio n. 2
0
void
ofw_pcib_gen_setup(device_t bridge)
{
	struct ofw_pcib_gen_softc *sc;

	sc = device_get_softc(bridge);
	sc->ops_pcib_sc.dev = bridge;
	sc->ops_node = ofw_bus_get_node(bridge);
	KASSERT(sc->ops_node != 0,
	    ("ofw_pcib_gen_setup: no ofw pci parent bus!"));

	ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
	    sizeof(ofw_pci_intr_t));
}
Esempio n. 3
0
static int
ofw_pcib_pci_attach(device_t dev)
{
	struct ofw_pcib_softc *sc;

	sc = device_get_softc(dev);
	sc->ops_pcib_sc.dev = dev;
	sc->ops_node = ofw_bus_get_node(dev);

	ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
	    sizeof(cell_t));

	pcib_attach_common(dev);

	device_add_child(dev, "pci", -1);

	return (bus_generic_attach(dev));
}
Esempio n. 4
0
static int
ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node)
{
	struct ebus_devinfo *edi;
	device_t cdev;

	ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));

	/*
	 * Now attach our children.
	 */
	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
		if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL)
			continue;
		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    edi->edi_obdinfo.obd_name);
			ebus_destroy_dinfo(edi);
			continue;
		}
		device_set_ivars(cdev, edi);
	}
	return (bus_generic_attach(dev));
}
Esempio n. 5
0
int
ofw_pci_init(device_t dev)
{
	struct		ofw_pci_softc *sc;
	phandle_t	node;
	u_int32_t	busrange[2];
	struct		ofw_pci_range *rp;
	int		error;

	node = ofw_bus_get_node(dev);
	sc = device_get_softc(dev);
	sc->sc_initialized = 1;

	if (OF_getprop(node, "reg", &sc->sc_pcir, sizeof(sc->sc_pcir)) == -1)
		return (ENXIO);

	if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
		busrange[0] = 0;

	sc->sc_dev = dev;
	sc->sc_node = node;
	sc->sc_bus = busrange[0];

	if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
		phandle_t c;
		int n, i;
		
		sc->sc_nrange = 0;
		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
			n = ofw_pci_nranges(c);
			if (n > 0)
				sc->sc_nrange += n;
		}
		if (sc->sc_nrange == 0)
			return (ENXIO);
		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
		    M_DEVBUF, M_WAITOK);
		i = 0;
		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
			n = ofw_pci_fill_ranges(c, &sc->sc_range[i]);
			if (n > 0)
				i += n;
		}
		KASSERT(i == sc->sc_nrange, ("range count mismatch"));
	} else {
		sc->sc_nrange = ofw_pci_nranges(node);
		if (sc->sc_nrange <= 0) {
			device_printf(dev, "could not get ranges\n");
			return (ENXIO);
		}
		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
		    M_DEVBUF, M_WAITOK);
		ofw_pci_fill_ranges(node, sc->sc_range);
	}
		
	sc->sc_io_rman.rm_type = RMAN_ARRAY;
	sc->sc_io_rman.rm_descr = "PCI I/O Ports";
	error = rman_init(&sc->sc_io_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "PCI Memory";
	error = rman_init(&sc->sc_mem_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}

	for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
	       rp->pci_hi != 0; rp++) {
		error = 0;

		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
			break;
		case OFW_PCI_PHYS_HI_SPACE_IO:
			error = rman_manage_region(&sc->sc_io_rman, rp->pci,
			    rp->pci + rp->size - 1);
			break;
		case OFW_PCI_PHYS_HI_SPACE_MEM32:
		case OFW_PCI_PHYS_HI_SPACE_MEM64:
			error = rman_manage_region(&sc->sc_mem_rman, rp->pci,
			    rp->pci + rp->size - 1);
			break;
		}

		if (error) {
			device_printf(dev, 
			    "rman_manage_region(%x, %#jx, %#jx) failed. "
			    "error = %d\n", rp->pci_hi &
			    OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
			    rp->pci + rp->size - 1, error);
			return (error);
		}
	}

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

	return (error);
}
Esempio n. 6
0
static int
ebus_attach(device_t dev)
{
	struct ebus_softc *sc;
	struct ebus_devinfo *edi;
	struct ebus_rinfo *eri;
	struct resource *res;
	device_t cdev;
	phandle_t node;
	int i, rnum, rid;

	sc = device_get_softc(dev);

	node = ofw_bus_get_node(dev);
	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(*sc->sc_range), (void **)&sc->sc_range);
	if (sc->sc_nrange == -1) {
		printf("ebus_attach: could not get ranges property\n");
		return (ENXIO);
	}

	sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF,
	    M_WAITOK | M_ZERO);

	/* For every range, there must be a matching resource. */
	for (rnum = 0; rnum < sc->sc_nrange; rnum++) {
		eri = &sc->sc_rinfo[rnum];
		eri->eri_rtype = ofw_isa_range_restype(&sc->sc_range[rnum]);
		rid = PCIR_BAR(rnum);
		res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
		    RF_ACTIVE);
		if (res == NULL) {
			printf("ebus_attach: failed to allocate range "
			    "resource!\n");
			goto fail;
		}
		eri->eri_res = res;
		eri->eri_rman.rm_type = RMAN_ARRAY;
		eri->eri_rman.rm_descr = "EBus range";
		if (rman_init(&eri->eri_rman) != 0) {
			printf("ebus_attach: failed to initialize rman!");
			goto fail;
		}
		if (rman_manage_region(&eri->eri_rman, rman_get_start(res),
		    rman_get_end(res)) != 0) {
			printf("ebus_attach: failed to register region!");
			rman_fini(&eri->eri_rman);
			goto fail;
		}
	}

	ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));

	/*
	 * Now attach our children.
	 */
	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
		if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL)
			continue;
		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    edi->edi_obdinfo.obd_name);
			ebus_destroy_dinfo(edi);
			continue;
		}
		device_set_ivars(cdev, edi);
	}
	return (bus_generic_attach(dev));

fail:
	for (i = rnum; i >= 0; i--) {
		eri = &sc->sc_rinfo[i];
		if (i < rnum)
			rman_fini(&eri->eri_rman);
		if (eri->eri_res != 0) {
			bus_release_resource(dev, eri->eri_rtype,
			    PCIR_BAR(rnum), eri->eri_res);
		}
	}
	free(sc->sc_rinfo, M_DEVBUF);
	free(sc->sc_range, M_OFWPROP);
	return (ENXIO);
}
Esempio n. 7
0
static int
grackle_attach(device_t dev)
{
	struct		grackle_softc *sc;
	phandle_t	node;
	u_int32_t	busrange[2];
	struct		grackle_range *rp, *io, *mem[2];
	int		nmem, i, error;

	node = ofw_bus_get_node(dev);
	sc = device_get_softc(dev);

	if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
		return (ENXIO);

	sc->sc_dev = dev;
	sc->sc_node = node;
	sc->sc_bus = busrange[0];

	/*
	 * The Grackle PCI config addr/data registers are actually in
	 * PCI space, but since they are needed to actually probe the
	 * PCI bus, use the fact that they are also available directly
	 * on the processor bus and map them
	 */
	sc->sc_addr = (vm_offset_t)pmap_mapdev(GRACKLE_ADDR, PAGE_SIZE);
	sc->sc_data = (vm_offset_t)pmap_mapdev(GRACKLE_DATA, PAGE_SIZE);

	bzero(sc->sc_range, sizeof(sc->sc_range));
	sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
	    sizeof(sc->sc_range));

	if (sc->sc_nrange == -1) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	sc->sc_range[6].pci_hi = 0;
	io = NULL;
	nmem = 0;

	for (rp = sc->sc_range; rp->pci_hi != 0; rp++) {
		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
			break;
		case OFW_PCI_PHYS_HI_SPACE_IO:
			io = rp;
			break;
		case OFW_PCI_PHYS_HI_SPACE_MEM32:
			mem[nmem] = rp;
			nmem++;
			break;
		case OFW_PCI_PHYS_HI_SPACE_MEM64:
			break;
		}
	}

	if (io == NULL) {
		device_printf(dev, "can't find io range\n");
		return (ENXIO);
	}
	sc->sc_io_rman.rm_type = RMAN_ARRAY;
	sc->sc_io_rman.rm_descr = "Grackle PCI I/O Ports";
	sc->sc_iostart = io->pci_iospace;
	if (rman_init(&sc->sc_io_rman) != 0 ||
	    rman_manage_region(&sc->sc_io_rman, io->pci_lo,
	    io->pci_lo + io->size_lo) != 0) {
		panic("grackle_attach: failed to set up I/O rman");
	}

	if (nmem == 0) {
		device_printf(dev, "can't find mem ranges\n");
		return (ENXIO);
	}
	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "Grackle PCI Memory";
	error = rman_init(&sc->sc_mem_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}
	for (i = 0; i < nmem; i++) {
		error = rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo,
		    mem[i]->pci_lo + mem[i]->size_lo);
		if (error) {
			device_printf(dev, 
			    "rman_manage_region() failed. error = %d\n", error);
			return (error);
		}
	}

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

	device_add_child(dev, "pci", device_get_unit(dev));
	return (bus_generic_attach(dev));
}
Esempio n. 8
0
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);
}