Subject: looking for devices on PCI bus [II]
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 05/03/2001 23:07:52
--azLHFNyN32YCQGCU
Content-Type: text/plain; charset=us-ascii

Hi
I've implemented a function looking for devices on pci busses
based on pci_probe_bus() (pci_probe_bus() is just a wrapper now).

While doing this I figured that the 2 functions (one matching by ID and one by
class) could be collapsed in one:
void
pci_find_device(int bus, int vendor, int product, int rev,
    int class, int subclass, int interface,
    void *arg, void (*f) __P((void *, struct pci_attach_args *)))

Using wildcards it's possible to do what the 2 previous functions did, and
much more (it's possible to find all devices matching  vendor = VIA and
class/subclass = PCI/ISA bridge :)

Patch attached. Comments ?

--
Manuel Bouyer <bouyer@antioche.eu.org>
--

--azLHFNyN32YCQGCU
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: pci.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/pci.c,v
retrieving revision 1.51
diff -u -r1.51 pci.c
--- pci.c	2001/03/02 06:24:17	1.51
+++ pci.c	2001/05/03 21:07:08
@@ -70,6 +70,9 @@
 };
 
 void	pci_probe_bus __P((struct device *));
+void	pci_probe_bus_callback __P((void *, struct pci_attach_args *));
+void	_pci_find_device __P((struct pci_softc *, int, int, int, int, int, int,
+	    void *, void (*f)__P((void *, struct pci_attach_args *))));
 int	pciprint __P((void *, const char *));
 int	pcisubmatch __P((struct device *, struct cfdata *, void *));
 
@@ -135,6 +138,26 @@
 	struct device *self;
 {
 	struct pci_softc *sc = (struct pci_softc *)self;
+	_pci_find_device(sc, PCI_VENDOR_ANY, PCI_PRODUCT_ANY, PCI_REV_ANY,
+	    PCI_CLASS_ANY, PCI_SUBCLASS_ANY, PCI_INTERFACE_ANY,
+	    sc, pci_probe_bus_callback);
+}
+
+void
+pci_probe_bus_callback(arg, pa)
+	void *arg;
+	struct pci_attach_args *pa;
+{
+	config_found_sm(arg, pa, pciprint, pcisubmatch);
+}
+
+void
+_pci_find_device(sc, vendor, product, rev, class, subclass, interface, arg, f)
+	struct pci_softc *sc;
+	int vendor, product, rev, class, subclass, interface;
+	void *arg;
+	void (*f) __P((void *, struct pci_attach_args *));
+{
 	bus_space_tag_t iot, memt;
 	pci_chipset_tag_t pc;
 	const struct pci_quirkdata *qd;
@@ -160,7 +183,7 @@
 #endif
 	{
 		pcitag_t tag;
-		pcireg_t id, class, intr, bhlcr, csr;
+		pcireg_t id, pciclass, intr, bhlcr, csr;
 		struct pci_attach_args pa;
 		int pin;
 
@@ -195,7 +218,7 @@
 			tag = pci_make_tag(pc, bus, device, function);
 			id = pci_conf_read(pc, tag, PCI_ID_REG);
 			csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
-			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+			pciclass = pci_conf_read(pc, tag, PCI_CLASS_REG);
 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
 
 			/* Invalid vendor ID value? */
@@ -204,6 +227,24 @@
 			/* XXX Not invalid, but we've done this ~forever. */
 			if (PCI_VENDOR(id) == 0)
 				continue;
+			if (vendor != PCI_VENDOR_ANY &&
+			    PCI_VENDOR(id) != vendor)
+				continue;
+			if (product != PCI_PRODUCT_ANY &&
+			    PCI_PRODUCT(id) != product)
+				continue;
+			if (rev != PCI_REV_ANY &&
+			    PCI_REVISION(pciclass) != rev)
+				continue;
+			if (class != PCI_CLASS_ANY &&
+			    PCI_CLASS(pciclass) != class)
+				continue;
+			if (subclass != PCI_SUBCLASS_ANY &&
+			    PCI_SUBCLASS(pciclass) != subclass)
+				continue;
+			if (interface != PCI_INTERFACE_ANY &&
+			    PCI_INTERFACE(pciclass) != interface)
+				continue;
 
 			pa.pa_iot = iot;
 			pa.pa_memt = memt;
@@ -213,7 +254,7 @@
 			pa.pa_function = function;
 			pa.pa_tag = tag;
 			pa.pa_id = id;
-			pa.pa_class = class;
+			pa.pa_class = pciclass;
 
 			/*
 			 * Set up memory, I/O enable, and PCI command flags
@@ -246,9 +287,26 @@
 				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
 			}
 			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
-
-			config_found_sm(self, &pa, pciprint, pcisubmatch);
+			f(arg, &pa);
 		}
+	}
+}
+
+void
+pci_find_device(bus, vendor, product, rev, class, subclass, interface, arg, f)
+	int bus, vendor, product, rev, class, subclass, interface;
+	void *arg;
+	void (*f) __P((void *, struct pci_attach_args *));
+{
+	struct pci_softc **psc;
+	extern struct cfdriver pci_cd;
+
+	for (psc = (struct pci_softc **)pci_cd.cd_devs; *psc; psc++) {
+		if (bus != PCI_BUS_ANY &&
+		    (*psc)->sc_dev.dv_unit != bus)
+			continue;
+		_pci_find_device(*psc,
+		    vendor, product, rev, class, subclass, interface, arg, f);
 	}
 }
 
Index: pcivar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/pcivar.h,v
retrieving revision 1.45
diff -u -r1.45 pcivar.h
--- pcivar.h	2001/03/05 23:50:02	1.45
+++ pcivar.h	2001/05/03 21:07:08
@@ -175,6 +175,19 @@
 	pci_lookup_quirkdata __P((pci_vendor_id_t, pci_product_id_t));
 
 /*
+ * bus scan function
+ */
+void	pci_find_device __P((int, int, int, int, int, int, int,
+	    void *, void (*f)__P((void *, struct pci_attach_args *))));
+#define PCI_BUS_ANY		(-1)
+#define PCI_VENDOR_ANY		(-1)
+#define PCI_PRODUCT_ANY		(-1)
+#define PCI_REV_ANY		(-1)
+#define PCI_CLASS_ANY		(-1)
+#define PCI_SUBCLASS_ANY	(-1)
+#define PCI_INTERFACE_ANY	(-1)
+
+/*
  * Misc.
  */
 char   *pci_findvendor __P((pcireg_t));

--azLHFNyN32YCQGCU--