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--