summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2007-11-26 13:20:29 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2007-11-26 13:20:29 +0000
commitb2e70517f47cbe6832a7f91cc516866c53bc2760 (patch)
tree0c1dcf314629c819b277c41aa72dbd9821f56339 /sys/dev/pci
parent03fc186892cc696b1dfd66f6501a24ea9d92c344 (diff)
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')
-rw-r--r--sys/dev/pci/pci.c79
-rw-r--r--sys/dev/pci/pcireg.h12
-rw-r--r--sys/dev/pci/pcivar.h8
3 files changed, 96 insertions, 3 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)
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index 506feb8335a..142a7f259da 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcireg.h,v 1.33 2007/11/25 01:36:48 kettenis Exp $ */
+/* $OpenBSD: pcireg.h,v 1.34 2007/11/26 13:20:28 jsg Exp $ */
/* $NetBSD: pcireg.h,v 1.26 2000/05/10 16:58:42 thorpej Exp $ */
/*
@@ -486,6 +486,16 @@ typedef u_int8_t pci_revision_t;
#define PCI_CAP_MSIX 0x11
/*
+ * Vital Product Data; access via capability pointer (PCI rev 2.2).
+ */
+#define PCI_VPD_ADDRESS_MASK 0x7fff
+#define PCI_VPD_ADDRESS_SHIFT 16
+#define PCI_VPD_ADDRESS(ofs) \
+ (((ofs) & PCI_VPD_ADDRESS_MASK) << PCI_VPD_ADDRESS_SHIFT)
+#define PCI_VPD_DATAREG(ofs) ((ofs) + 4)
+#define PCI_VPD_OPFLAG 0x80000000
+
+/*
* Power Management Control Status Register; access via capability pointer.
*/
#define PCI_PMCSR 0x04
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 1e2ed3bbea5..157e4fe0de8 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.55 2007/10/22 03:08:53 fgsch Exp $ */
+/* $OpenBSD: pcivar.h,v 1.56 2007/11/26 13:20:28 jsg Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -226,6 +226,12 @@ int pci_matchbyid(struct pci_attach_args *, const struct pci_matchid *, int);
int pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int);
/*
+ * Vital Product Data (PCI 2.2)
+ */
+int pci_vpd_read(pci_chipset_tag_t, pcitag_t, int, int, pcireg_t *);
+int pci_vpd_write(pci_chipset_tag_t, pcitag_t, int, int, pcireg_t *);
+
+/*
* Helper functions for autoconfiguration.
*/
const char *pci_findvendor(pcireg_t);