void
mpcpcibrattach(struct device *parent, struct device *self, void *aux)
{
	struct pcibr_softc *sc = (struct pcibr_softc *)self;
	struct confargs *ca = aux;
	struct pcibr_config *lcp;
	struct pcibus_attach_args pba;
	int node;
	int of_node = 0;
	char compat[32];
	u_int32_t addr_offset;
	u_int32_t data_offset;
	int i;
	int len;
	int rangesize;
	u_int32_t range_store[32];

	if (ca->ca_node == 0) {
		printf("invalid node on mpcpcibr config\n");
		return;
	}
	len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
	compat[len] = '\0';
	if (len > 0)
		printf(" %s", compat);

	len=OF_getprop(ca->ca_node, "compatible", compat,
	    sizeof (compat));
	if (len <= 0 ) {
		len=OF_getprop(ca->ca_node, "name", compat,
			sizeof (compat));
		if (len <= 0) {
			printf(" compatible and name not found\n");
			return;
		}
		compat[len] = 0; 
		if (strcmp (compat, "bandit") != 0) {
			printf(" compatible not found and name %s found\n",
			    compat);
			return;
		}
	}
	compat[len] = 0; 
	if ((rangesize = OF_getprop(ca->ca_node, "ranges",
	    range_store, sizeof (range_store))) <= 0) {
		if (strcmp(compat, "u3-ht") == 0) {
			range_store[0] = 0xabb10113; /* appl U3; */
		} else 
			printf("range lookup failed, node %x\n", ca->ca_node);
	}
	/* translate byte(s) into item count*/

	lcp = sc->sc_pcibr = &sc->pcibr_config;

	if (ppc_proc_is_64b)
		mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
	else
		mpcpcibus_find_ranges_32 (sc, range_store, rangesize);

	addr_offset = 0;
	for (i = 0; config_offsets[i].compat != NULL; i++) {
		struct config_type *co = &config_offsets[i];
		if (strcmp(co->compat, compat) == 0) {
			addr_offset = co->addr; 
			data_offset = co->data; 
			lcp->config_type = co->config_type;
			break;
		}
	}
	if (addr_offset == 0) {
		printf("unable to find match for"
		    " compatible %s\n", compat);
		return;
	}
#ifdef DEBUG_FIXUP
	printf(" mem base %x sz %x io base %x sz %x\n"
	    " config addr %x config data %x\n",
	    sc->sc_membus_space.bus_base,
	    sc->sc_membus_space.bus_size,
	    sc->sc_iobus_space.bus_base,
	    sc->sc_iobus_space.bus_size,
	    addr_offset, data_offset);
#endif

	if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
		NBPG, 0, &lcp->ioh_cf8) != 0 )
		panic("mpcpcibus: unable to map self");

	if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
		NBPG, 0, &lcp->ioh_cfc) != 0 )
		panic("mpcpcibus: unable to map self");

	of_node = ca->ca_node;

	lcp->node = ca->ca_node;
	lcp->lc_pc.pc_conf_v = lcp;
	lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
	lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
	lcp->lc_pc.pc_make_tag = mpc_make_tag;
	lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
	lcp->lc_pc.pc_conf_read = mpc_conf_read;
	lcp->lc_pc.pc_conf_write = mpc_conf_write;
	lcp->lc_pc.pc_ether_hw_addr = of_ether_hw_addr;
	lcp->lc_iot = &sc->sc_iobus_space;
	lcp->lc_memt = &sc->sc_membus_space;

	lcp->lc_pc.pc_intr_v = lcp;
	lcp->lc_pc.pc_intr_map = mpc_intr_map;
	lcp->lc_pc.pc_intr_string = mpc_intr_string;
	lcp->lc_pc.pc_intr_line = mpc_intr_line;
	lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
	lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;

	printf(": %s, Revision 0x%x\n", compat, 
	    mpc_cfg_read_1(lcp, MPC106_PCI_REVID));

	if ((strcmp(compat, "bandit")) != 0)
		pci_addr_fixup(sc, &lcp->lc_pc, 32);

	pba.pba_dmat = &pci_bus_dma_tag;

	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_iobus_space;
	pba.pba_memt = &sc->sc_membus_space;
	pba.pba_pc = &lcp->lc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;
	pba.pba_bridgetag = NULL;

	/* we want to check pci irq settings */
	if (of_node != 0) {
		int nn;

		for (node = OF_child(of_node); node; node = nn) {
			char name[32];
			int len;
			len = OF_getprop(node, "name", name,
			    sizeof(name));
			name[len] = 0;
			fix_node_irq(node, &pba);

			/* iterate section */
			if ((nn = OF_child(node)) != 0)
				continue;

			while ((nn = OF_peer(node)) == 0) {
				node = OF_parent(node);
				if (node == of_node) {
					nn = 0; /* done */
					break;
				}
			}
		}
	}

	config_found(self, &pba, mpcpcibrprint);

}
Beispiel #2
0
void
mpcpcibrattach(struct device *parent, struct device *self, void *aux)
{
	struct pcibr_softc *sc = (struct pcibr_softc *)self;
	struct confargs *ca = aux;
	struct pcibr_config *lcp;
	struct pcibus_attach_args pba;
	int of_node = 0;
	char compat[32];
	u_int32_t addr_offset;
	u_int32_t data_offset;
	int i;
	int len;
	int rangesize;
	u_int32_t range_store[32];

	if (ca->ca_node == 0) {
		printf("invalid node on mpcpcibr config\n");
		return;
	}
	len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
	compat[len] = '\0';
	if (len > 0)
		printf(" %s", compat);

	len=OF_getprop(ca->ca_node, "compatible", compat,
	    sizeof (compat));
	if (len <= 0 ) {
		len=OF_getprop(ca->ca_node, "name", compat,
			sizeof (compat));
		if (len <= 0) {
			printf(" compatible and name not found\n");
			return;
		}
		compat[len] = 0; 
		if (strcmp (compat, "bandit") != 0) {
			printf(" compatible not found and name %s found\n",
			    compat);
			return;
		}
	}
	compat[len] = 0; 
	if ((rangesize = OF_getprop(ca->ca_node, "ranges",
	    range_store, sizeof (range_store))) <= 0) {
		if (strcmp(compat, "u3-ht") == 0) {
			range_store[0] = 0xabb10113; /* appl U3; */
		} else 
			printf("range lookup failed, node %x\n", ca->ca_node);
	}
	/* translate byte(s) into item count*/

	lcp = &sc->pcibr_config;

	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
	    "%s pciio", sc->sc_dev.dv_xname);
	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0x00000000, 0xffffffff,
	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
	    "%s pcimem", sc->sc_dev.dv_xname);
	sc->sc_memex = extent_create(sc->sc_memex_name, 0x00000000, 0xffffffff,
	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);

	if (ppc_proc_is_64b)
		mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
	else
		mpcpcibus_find_ranges_32 (sc, range_store, rangesize);

	addr_offset = 0;
	for (i = 0; config_offsets[i].compat != NULL; i++) {
		struct config_type *co = &config_offsets[i];
		if (strcmp(co->compat, compat) == 0) {
			addr_offset = co->addr; 
			data_offset = co->data; 
			lcp->config_type = co->config_type;
			break;
		}
	}
	if (addr_offset == 0) {
		printf("unable to find match for"
		    " compatible %s\n", compat);
		return;
	}
#ifdef DEBUG_FIXUP
	printf(" mem base %x sz %x io base %x sz %x\n"
	    " config addr %x config data %x\n",
	    sc->sc_membus_space.bus_base,
	    sc->sc_membus_space.bus_size,
	    sc->sc_iobus_space.bus_base,
	    sc->sc_iobus_space.bus_size,
	    addr_offset, data_offset);
#endif

	if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
		NBPG, 0, &lcp->ioh_cf8) != 0 )
		panic("mpcpcibus: unable to map self");

	if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
		NBPG, 0, &lcp->ioh_cfc) != 0 )
		panic("mpcpcibus: unable to map self");

	of_node = ca->ca_node;

	lcp->lc_pc.pc_conf_v = lcp;
	lcp->lc_pc.pc_node = ca->ca_node;
	lcp->lc_pc.pc_conf_read = mpc_conf_read;
	lcp->lc_pc.pc_conf_write = mpc_conf_write;
	lcp->lc_iot = &sc->sc_iobus_space;
	lcp->lc_memt = &sc->sc_membus_space;

	printf(": %s\n", compat);

	bzero(&pba, sizeof(pba));
	pba.pba_dmat = &pci_bus_dma_tag;

	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_iobus_space;
	pba.pba_memt = &sc->sc_membus_space;
	pba.pba_ioex = sc->sc_ioex;
	pba.pba_memex = sc->sc_memex;
	pba.pba_pc = &lcp->lc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;

	config_found(self, &pba, mpcpcibrprint);
}