示例#1
0
void
mpbios_intr_fixup(void)
{
	const struct mpbios_icu_table *mpit = NULL;
	pci_chipset_tag_t pc = NULL;
	pcitag_t icutag;
	int device, maxdevs = pci_bus_maxdevs(pc, 0);

	/* Search configuration space for a known interrupt router. */
	for (device = 0; device < maxdevs; device++) {
		const struct pci_quirkdata *qd;
		int function, nfuncs;
		pcireg_t icuid;
		pcireg_t bhlcr;

		icutag = pci_make_tag(pc, 0, device, 0);
		icuid = pci_conf_read(pc, icutag, PCI_ID_REG);

		/* Invalid vendor ID value? */
		if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
			continue;

		qd = pci_lookup_quirkdata(PCI_VENDOR(icuid),
	       	    PCI_PRODUCT(icuid));

		bhlcr = pci_conf_read(pc, icutag, PCI_BHLC_REG);
		if (PCI_HDRTYPE_MULTIFN(bhlcr) || (qd != NULL &&
		    (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
			nfuncs = 8;
		else
			nfuncs = 1;

		for (function = 0; function < nfuncs; function++) {
			icutag = pci_make_tag(pc, 0, device, function);
			icuid = pci_conf_read(pc, icutag, PCI_ID_REG);

			/* Invalid vendor ID value? */
			if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
				continue;

			if ((mpit = mpbios_icu_lookup(icuid)))
				break;
		}

		if (mpit != NULL)
			break;
	}

	if (mpit)
		mpit->mpit_mpbios_fixup(pc, icutag);
}
示例#2
0
void
pci_device_foreach(struct shpcic_softc *sc, pci_chipset_tag_t pc, int maxbus,
    void (*func)(struct shpcic_softc *, pci_chipset_tag_t, pcitag_t))
{
	const struct pci_quirkdata *qd;
	int bus, device, function, maxdevs, nfuncs;
	pcireg_t id, bhlcr;
	pcitag_t tag;

	for (bus = 0; bus <= maxbus; bus++) {
		maxdevs = pci_bus_maxdevs(pc, bus);
		for (device = 0; device < maxdevs; device++) {
			tag = pci_make_tag(pc, bus, device, 0);
			id = pci_conf_read(pc, tag, PCI_ID_REG);

			/* Invalid vendor ID value? */
			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
				continue;
			/* XXX Not invalid, but we've done this ~forever. */
			if (PCI_VENDOR(id) == 0)
				continue;

			qd = pci_lookup_quirkdata(PCI_VENDOR(id),
			    PCI_PRODUCT(id));

			bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
			if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
			    (qd != NULL &&
			     (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
				nfuncs = 8;
			else
				nfuncs = 1;

			for (function = 0; function < nfuncs; function++) {
				tag = pci_make_tag(pc, bus, device, function);
				id = pci_conf_read(pc, tag, PCI_ID_REG);

				/* Invalid vendor ID value? */
				if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
					continue;
				/*
				 * XXX Not invalid, but we've done this
				 * ~forever.
				 */
				if (PCI_VENDOR(id) == 0)
					continue;
				(*func)(sc, pc, tag);
			}
		}
	}
}
示例#3
0
文件: macepcimap.c 项目: MarginC/kame
void
pciaddr_remap(pci_chipset_tag_t pc)
{
	pcitag_t devtag;
	int device;

	/* Must fix up all PCI devices, ahc_pci expects proper i/o mapping */
	for (device = 1; device < 4; device++) {
		const struct pci_quirkdata *qd;
		int function, nfuncs;
		pcireg_t bhlcr, id;

		devtag = pci_make_tag(pc, 0, device, 0);
		id = pci_conf_read(pc, devtag, PCI_ID_REG);

		/* Invalid vendor ID value? */
		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
			continue;
		/* XXX Not invalid, but we've done this ~forever. */
		if (PCI_VENDOR(id) == 0)
			continue;

		qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id));
		bhlcr = pci_conf_read(pc, devtag, PCI_BHLC_REG);

		if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
		    (qd != NULL &&
		    (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
			nfuncs = 8;
		else
			nfuncs = 1;

		for (function = 0; function < nfuncs; function++) {
			devtag = pci_make_tag(pc, 0, device, function);
			id = pci_conf_read(pc, devtag, PCI_ID_REG);

			/* Invalid vendor ID value? */
			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
				continue;
			/* Not invalid, but we've done this ~forever */
			if (PCI_VENDOR(id) == 0)
				continue;

			pciaddr_resource_manage(pc, devtag, NULL);
		}
	}
}
示例#4
0
int
pciprint(void *aux, const char *pnp)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];
	const struct pci_quirkdata *qd;

	if (pnp) {
		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
		aprint_normal("%s at %s", devinfo, pnp);
	}
	aprint_normal(" dev %d function %d", pa->pa_device, pa->pa_function);
	if (pci_config_dump) {
		printf(": ");
		pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
		if (!pnp)
			pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
		printf("%s at %s", devinfo, pnp ? pnp : "?");
		printf(" dev %d function %d (", pa->pa_device, pa->pa_function);
#ifdef __i386__
		printf("tag %#lx, intrtag %#lx, intrswiz %#lx, intrpin %#lx",
		    *(long *)&pa->pa_tag, *(long *)&pa->pa_intrtag,
		    (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
#else
		printf("intrswiz %#lx, intrpin %#lx",
		    (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
#endif
		printf(", i/o %s, mem %s,",
		    pa->pa_flags & PCI_FLAGS_IO_OKAY ? "on" : "off",
		    pa->pa_flags & PCI_FLAGS_MEM_OKAY ? "on" : "off");
		qd = pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
		    PCI_PRODUCT(pa->pa_id));
		if (qd == NULL) {
			printf(" no quirks");
		} else {
			snprintb(devinfo, sizeof (devinfo),
			    "\002\001multifn\002singlefn\003skipfunc0"
			    "\004skipfunc1\005skipfunc2\006skipfunc3"
			    "\007skipfunc4\010skipfunc5\011skipfunc6"
			    "\012skipfunc7", qd->quirks);
			printf(" quirks %s", devinfo);
		}
		printf(")");
	}
	return UNCONF;
}
示例#5
0
/*
 * We can't use the generic pci_enumerate_bus, because the hypervisor
 * may hide the function 0 from us, while other functions are
 * available
 */
int
xen_pci_enumerate_bus(struct pci_softc *sc, const int *locators,
    int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
{
	pci_chipset_tag_t pc = sc->sc_pc;
	int device, function, nfunctions, ret;
	const struct pci_quirkdata *qd;
	pcireg_t id, bhlcr;
	pcitag_t tag;

	for (device = 0; device < sc->sc_maxndevs; device++)
	{
		if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
		    (locators[PCICF_DEV] != device))
			continue;

		tag = pci_make_tag(pc, sc->sc_bus, device, 0);

		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
		id = pci_conf_read(pc, tag, PCI_ID_REG);
		qd = NULL;

		if (PCI_VENDOR(id) != PCI_VENDOR_INVALID) {
			/* XXX Not invalid, but we've done this ~forever. */
			if (PCI_VENDOR(id) == 0)
				continue;
			
			if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
				continue;

			qd = pci_lookup_quirkdata(PCI_VENDOR(id),
			    PCI_PRODUCT(id));

			if (qd != NULL &&
			      (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)
				nfunctions = 8;
			else if (qd != NULL &&
			      (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0)
				nfunctions = 1;
			else
				nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
		} else {
			/*
			 * Vendor ID invalid. This may be because there's no
			 * device, or because the hypervisor is hidding
			 * function 0 from us. Try to probe other functions
			 * anyway.
			 */
			nfunctions = 8;
		}

		for (function = 0; function < nfunctions; function++) {
			if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT)
			    && (locators[PCICF_FUNCTION] != function))
				continue;

			if (qd != NULL &&
			    (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0)
				continue;
			tag = pci_make_tag(pc, sc->sc_bus, device, function);
			ret = pci_probe_device(sc, tag, match, pap);
			if (match != NULL && ret != 0)
				return (ret);
		}
	}
	return (0);
}
示例#6
0
/*
 * Generic PCI bus enumeration routine.  Used unless machine-dependent
 * code needs to provide something else.
 */
int
pci_enumerate_bus(struct pci_softc *sc, const int *locators,
    int (*match)(const struct pci_attach_args *), struct pci_attach_args *pap)
{
	pci_chipset_tag_t pc = sc->sc_pc;
	int device, function, nfunctions, ret;
	const struct pci_quirkdata *qd;
	pcireg_t id, bhlcr;
	pcitag_t tag;
	uint8_t devs[32];
	int i, n;

	n = pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs, __arraycount(devs));
	for (i = 0; i < n; i++) {
		device = devs[i];

		if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
		    (locators[PCICF_DEV] != device))
			continue;

		tag = pci_make_tag(pc, sc->sc_bus, device, 0);

		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
		if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
			continue;

		id = pci_conf_read(pc, tag, PCI_ID_REG);

		/* Invalid vendor ID value? */
		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
			continue;
		/* XXX Not invalid, but we've done this ~forever. */
		if (PCI_VENDOR(id) == 0)
			continue;

		qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id));

		if (qd != NULL &&
		      (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)
			nfunctions = 8;
		else if (qd != NULL &&
		      (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0)
			nfunctions = 1;
		else
			nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;

#ifdef __PCI_DEV_FUNCORDER
		char funcs[8];
		int j;
		for (j = 0; j < nfunctions; j++) {
			funcs[j] = j;
		}
		if (j < __arraycount(funcs))
			funcs[j] = -1;
		if (nfunctions > 1) {
			pci_dev_funcorder(sc->sc_pc, sc->sc_bus, device,
			    nfunctions, funcs);
		}
		for (j = 0;
		     j < 8 && (function = funcs[j]) < 8 && function >= 0;
		     j++) {
#else
		for (function = 0; function < nfunctions; function++) {
#endif
			if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT)
			    && (locators[PCICF_FUNCTION] != function))
				continue;

			if (qd != NULL &&
			    (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0)
				continue;
			tag = pci_make_tag(pc, sc->sc_bus, device, function);
			ret = pci_probe_device(sc, tag, match, pap);
			if (match != NULL && ret != 0)
				return ret;
		}
	}
	return 0;
}
#endif /* PCI_MACHDEP_ENUMERATE_BUS */


/*
 * Vital Product Data (PCI 2.2)
 */

int
pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count,
    pcireg_t *data)
{
	uint32_t reg;
	int ofs, i, j;

	KASSERT(data != NULL);
	KASSERT((offset + count) < 0x7fff);

	if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, &reg) == 0)
		return 1;

	for (i = 0; i < count; offset += sizeof(*data), i++) {
		reg &= 0x0000ffff;
		reg &= ~PCI_VPD_OPFLAG;
		reg |= PCI_VPD_ADDRESS(offset);
		pci_conf_write(pc, tag, ofs, reg);

		/*
		 * PCI 2.2 does not specify how long we should poll
		 * for completion nor whether the operation can fail.
		 */
		j = 0;
		do {
			if (j++ == 20)
				return 1;
			delay(4);
			reg = pci_conf_read(pc, tag, ofs);
		} while ((reg & PCI_VPD_OPFLAG) == 0);
		data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs));
	}

	return 0;
}
示例#7
0
int
pci_bus_fixup(pci_chipset_tag_t pc, int bus)
{
	static int bus_total;
	static int bridge_cnt;
	int device, maxdevs, function, nfuncs, bridge, bus_max, bus_sub;
	const struct pci_quirkdata *qd;
	pcireg_t reg;
	pcitag_t tag;

	bus_max = bus;
	bus_sub = 0;

	if (++bus_total > 256)
		panic("pci_bus_fixup: more than 256 PCI busses?");

	/* Reset bridge configuration on this bus */
	pci_bridge_foreach(pc, bus, bus, pci_bridge_reset, 0);

	maxdevs = pci_bus_maxdevs(pc, bus);

	for (device = 0; device < maxdevs; device++) {
		tag = pci_make_tag(pc, bus, device, 0);
		reg = pci_conf_read(pc, tag, PCI_ID_REG);

		/* Invalid vendor ID value? */
		if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
			continue;
		/* XXX Not invalid, but we've done this ~forever. */
		if (PCI_VENDOR(reg) == 0)
			continue;

		qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg));

		reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
		if (PCI_HDRTYPE_MULTIFN(reg) ||
		    (qd != NULL &&
		     (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
			nfuncs = 8;
		else
			nfuncs = 1;

		for (function = 0; function < nfuncs; function++) {
			tag = pci_make_tag(pc, bus, device, function);
			reg = pci_conf_read(pc, tag, PCI_ID_REG);

			/* Invalid vendor ID value? */
			if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
				continue;
			/* XXX Not invalid, but we've done this ~forever. */
			if (PCI_VENDOR(reg) == 0)
				continue;

			aprint_debug("PCI fixup examining %02x:%02x\n",
			       PCI_VENDOR(reg), PCI_PRODUCT(reg));

			reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
			if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
			    (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI ||
			     PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
				/* Assign the bridge #. */
				bridge = bridge_cnt++;

				/* Assign the bridge's secondary bus #. */
				bus_max++;

				reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
				reg &= 0xff000000;
				reg |= bus | (bus_max << 8) | (0xff << 16);
				pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);

				/* Scan subordinate bus. */
				bus_sub = pci_bus_fixup(pc, bus_max);

				/* Configure the bridge. */
				reg &= 0xff000000;
				reg |= bus | (bus_max << 8) | (bus_sub << 16);
				pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);

				/* record relationship */
				pci_bus_parent[bus_max]=bus;

				pci_bus_tag[bus_max]=tag;

				aprint_debug("PCI bridge %d: primary %d, "
				    "secondary %d, subordinate %d\n",
				    bridge, bus, bus_max, bus_sub);

				/* Next bridge's secondary bus #. */
				bus_max = (bus_sub > bus_max) ?
				    bus_sub : bus_max;
			}
		}
	}

	return (bus_max);	/* last # of subordinate bus */
}