diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2007-11-26 13:20:29 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2007-11-26 13:20:29 +0000 |
commit | b2e70517f47cbe6832a7f91cc516866c53bc2760 (patch) | |
tree | 0c1dcf314629c819b277c41aa72dbd9821f56339 /sys/dev/pci | |
parent | 03fc186892cc696b1dfd66f6501a24ea9d92c344 (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.c | 79 | ||||
-rw-r--r-- | sys/dev/pci/pcireg.h | 12 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 8 |
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, ®) == 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, ®) == 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); |