summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorjsg <jsg@openbsd.org>2007-11-26 13:20:28 +0000
committerjsg <jsg@openbsd.org>2007-11-26 13:20:28 +0000
commit0f495ccd6e0074cf2b331af9f91b97058fb24cbe (patch)
tree2596a1bc2cb6cde0298b7039340e6904adc45008 /sys/dev/pci/pci.c
parentimplement -C for continuing ftp, http(s), and file transfers (diff)
downloadwireguard-openbsd-0f495ccd6e0074cf2b331af9f91b97058fb24cbe.tar.xz
wireguard-openbsd-0f495ccd6e0074cf2b331af9f91b97058fb24cbe.zip
Add PCI VPD read/write functions from NetBSD required for some things
dlg is playing with. 'put it in' dlg@
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 4bf343f8862..3ff8b37700f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.52 2007/11/17 23:20:38 brad Exp $ */
+/* $OpenBSD: pci.c,v 1.53 2007/11/26 13:20:28 jsg Exp $ */
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
@@ -482,6 +482,83 @@ pci_enumerate_bus(struct pci_softc *sc,
}
#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);
+}
+
+int
+pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count,
+ pcireg_t *data)
+{
+ pcireg_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++) {
+ pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), 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(1);
+ reg = pci_conf_read(pc, tag, ofs);
+ } while (reg & PCI_VPD_OPFLAG);
+ }
+
+ return (0);
+}
+
int
pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids,
int nent)