diff options
| author | msaitoh <msaitoh@NetBSD.org> | 2015-10-02 05:22:49 +0000 |
|---|---|---|
| committer | msaitoh <msaitoh@NetBSD.org> | 2015-10-02 05:22:49 +0000 |
| commit | 998866035fb2f446df656a6ae9e4b0ee4ddc445c (patch) | |
| tree | d95622964c21680e079f5097dd6a20e673e3c349 /sys | |
| parent | 058cde2471e6b21a2d85f267a5be1ec6b7a472b9 (diff) | |
PCI Extended Configuration stuff written by nonaka@:
- Add PCI Extended Configuration Space support into x86.
- Check register offset of pci_conf_read() in MD part. It returns (pcireg_t)-1
if it isn't accessible.
- Decode Extended Capability in PCI Extended Configuration Space.
Currently the following extended capabilities are decoded:
- Advanced Error Reporting
- Virtual Channel
- Device Serial Number
- Power Budgeting
- Root Complex Link Declaration
- Root Complex Event Collector Association
- Access Control Services
- Alternative Routing-ID Interpretation
- Address Translation Services
- Single Root IO Virtualization
- Page Request
- TPH Requester
- Latency Tolerance Reporting
- Secondary PCI Express
- Process Address Space ID
- LN Requester
- L1 PM Substates
The following extended capabilities are not decoded yet:
- Root Complex Internal Link Control
- Multi-Function Virtual Channel
- RCRB Header
- Vendor Unique
- Configuration Access Correction
- Multiple Root IO Virtualization
- Multicast
- Resizable BAR
- Dynamic Power Allocation
- Protocol Multiplexing
- Downstream Port Containment
- Precision Time Management
- M-PCIe
- Function Reading Status Queueing
- Readiness Time Reporting
- Designated Vendor-Specific
Diffstat (limited to 'sys')
75 files changed, 3153 insertions, 169 deletions
diff --git a/sys/arch/algor/pci/vtpbc.c b/sys/arch/algor/pci/vtpbc.c index f5e34781813..589f0363d64 100644 --- a/sys/arch/algor/pci/vtpbc.c +++ b/sys/arch/algor/pci/vtpbc.c @@ -1,4 +1,4 @@ -/* $NetBSD: vtpbc.c,v 1.9 2012/10/27 17:17:25 chs Exp $ */ +/* $NetBSD: vtpbc.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vtpbc.c,v 1.9 2012/10/27 17:17:25 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vtpbc.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -165,6 +165,9 @@ vtpbc_conf_addr(struct vtpbc_config *vt, pcitag_t tag, int offset, { int b, d, f; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (1); + vtpbc_decompose_tag(vt, tag, &b, &d, &f); if (b == 0) { diff --git a/sys/arch/alpha/pci/apecs_pci.c b/sys/arch/alpha/pci/apecs_pci.c index 1161db2176c..5cb66b2b0f3 100644 --- a/sys/arch/alpha/pci/apecs_pci.c +++ b/sys/arch/alpha/pci/apecs_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: apecs_pci.c,v 1.25 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: apecs_pci.c,v 1.26 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,7 +29,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: apecs_pci.c,v 1.25 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apecs_pci.c,v 1.26 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -101,6 +101,9 @@ apecs_conf_read(void *cpv, pcitag_t tag, int offset) int s, secondary, ba; int32_t old_haxr2; /* XXX */ + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = 0; /* XXX gcc -Wuninitialized */ old_haxr2 = 0; /* XXX gcc -Wuninitialized */ @@ -146,6 +149,9 @@ apecs_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) int s, secondary; int32_t old_haxr2; /* XXX */ + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + s = 0; /* XXX gcc -Wuninitialized */ old_haxr2 = 0; /* XXX gcc -Wuninitialized */ diff --git a/sys/arch/alpha/pci/cia_pci.c b/sys/arch/alpha/pci/cia_pci.c index 82bac7e0999..183c2bac735 100644 --- a/sys/arch/alpha/pci/cia_pci.c +++ b/sys/arch/alpha/pci/cia_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: cia_pci.c,v 1.32 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: cia_pci.c,v 1.33 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,7 +29,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: cia_pci.c,v 1.32 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cia_pci.c,v 1.33 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -101,6 +101,9 @@ cia_conf_read(void *cpv, pcitag_t tag, int offset) int s, secondary, ba; uint32_t old_cfg, errbits; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + #ifdef __GNUC__ s = 0; /* XXX gcc -Wuninitialized */ old_cfg = 0; /* XXX gcc -Wuninitialized */ @@ -196,6 +199,9 @@ cia_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) int s, secondary; uint32_t old_cfg; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + #ifdef __GNUC__ s = 0; /* XXX gcc -Wuninitialized */ old_cfg = 0; /* XXX gcc -Wuninitialized */ diff --git a/sys/arch/alpha/pci/dwlpx_pci.c b/sys/arch/alpha/pci/dwlpx_pci.c index 6fdb4729874..b04e2645b14 100644 --- a/sys/arch/alpha/pci/dwlpx_pci.c +++ b/sys/arch/alpha/pci/dwlpx_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: dwlpx_pci.c,v 1.18 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: dwlpx_pci.c,v 1.19 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1997 by Matthew Jacob @@ -32,7 +32,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: dwlpx_pci.c,v 1.18 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwlpx_pci.c,v 1.19 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -125,6 +125,9 @@ dwlpx_conf_read(void *cpv, pcitag_t tag, int offset) int secondary, i, s = 0; uint32_t rvp; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (data); + if (ccp == NULL) { panic("NULL ccp in dwlpx_conf_read"); } @@ -191,6 +194,9 @@ dwlpx_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) int secondary, i, s = 0; uint32_t rvp; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + if (ccp == NULL) { panic("NULL ccp in dwlpx_conf_write"); } diff --git a/sys/arch/alpha/pci/irongate_pci.c b/sys/arch/alpha/pci/irongate_pci.c index 5ba5874f43e..e5af3ebc800 100644 --- a/sys/arch/alpha/pci/irongate_pci.c +++ b/sys/arch/alpha/pci/irongate_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: irongate_pci.c,v 1.9 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: irongate_pci.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: irongate_pci.c,v 1.9 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: irongate_pci.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -116,6 +116,9 @@ irongate_conf_read(void *ipv, pcitag_t tag, int offset) { int d; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* * The AMD 751 appears in PCI configuration space, but * that is ... counter-intuitive to the way we normally @@ -136,6 +139,9 @@ irongate_conf_read0(void *ipv, pcitag_t tag, int offset) pcireg_t data; int s; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + PCI_CONF_LOCK(s); REGVAL(PCI_CONF_ADDR) = (CONFADDR_ENABLE | tag | (offset & 0xff)); alpha_mb(); @@ -152,6 +158,9 @@ irongate_conf_write(void *ipv, pcitag_t tag, int offset, pcireg_t data) { int s; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + PCI_CONF_LOCK(s); REGVAL(PCI_CONF_ADDR) = (CONFADDR_ENABLE | tag | (offset & 0xff)); alpha_mb(); diff --git a/sys/arch/alpha/pci/lca_pci.c b/sys/arch/alpha/pci/lca_pci.c index 4de95c958f2..162ec5c65ae 100644 --- a/sys/arch/alpha/pci/lca_pci.c +++ b/sys/arch/alpha/pci/lca_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: lca_pci.c,v 1.21 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: lca_pci.c,v 1.22 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,7 +29,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: lca_pci.c,v 1.21 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lca_pci.c,v 1.22 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -103,6 +103,9 @@ lca_conf_read(void *cpv, pcitag_t tag, int offset) pcireg_t *datap, data; int s, secondary, device, ba; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = 0; /* XXX gcc -Wuninitialized */ /* secondary if bus # != 0 */ @@ -153,6 +156,9 @@ lca_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) pcireg_t *datap; int s, secondary, device; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + s = 0; /* XXX gcc -Wuninitialized */ /* secondary if bus # != 0 */ diff --git a/sys/arch/alpha/pci/mcpcia_pci.c b/sys/arch/alpha/pci/mcpcia_pci.c index 71cc153ca2d..64618a0ce69 100644 --- a/sys/arch/alpha/pci/mcpcia_pci.c +++ b/sys/arch/alpha/pci/mcpcia_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: mcpcia_pci.c,v 1.11 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: mcpcia_pci.c,v 1.12 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1998 by Matthew Jacob @@ -32,7 +32,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: mcpcia_pci.c,v 1.11 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mcpcia_pci.c,v 1.12 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -108,6 +108,9 @@ mcpcia_conf_read(void *cpv, pcitag_t tag, int offset) pcireg_t *dp, data = (pcireg_t) -1; unsigned long paddr; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (data); + /* * There's nothing in slot 0 on a primary bus- don't even try. */ @@ -136,6 +139,9 @@ mcpcia_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) pcireg_t *dp; unsigned long paddr; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + /* * There's nothing in slot 0 on a primary bus- don't even try. */ diff --git a/sys/arch/alpha/pci/tsp_pci.c b/sys/arch/alpha/pci/tsp_pci.c index 0dbc53c8c6a..6542a50e739 100644 --- a/sys/arch/alpha/pci/tsp_pci.c +++ b/sys/arch/alpha/pci/tsp_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: tsp_pci.c,v 1.9 2011/06/14 15:34:22 matt Exp $ */ +/* $NetBSD: tsp_pci.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 1999 by Ross Harvey. All rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tsp_pci.c,v 1.9 2011/06/14 15:34:22 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tsp_pci.c,v 1.10 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -110,6 +110,9 @@ tsp_conf_read(void *cpv, pcitag_t tag, int offset) pcireg_t *datap, data; struct tsp_config *pcp = cpv; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + datap = S_PAGE(pcp->pc_iobase | P_PCI_CONFIG | tag | (offset & ~3)); alpha_mb(); data = *datap; @@ -123,6 +126,9 @@ tsp_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) pcireg_t *datap; struct tsp_config *pcp = cpv; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + datap = S_PAGE(pcp->pc_iobase | P_PCI_CONFIG | tag | (offset & ~3)); alpha_mb(); *datap = data; diff --git a/sys/arch/alpha/pci/ttwoga_pci.c b/sys/arch/alpha/pci/ttwoga_pci.c index bf2f90e8ce1..531afecf20b 100644 --- a/sys/arch/alpha/pci/ttwoga_pci.c +++ b/sys/arch/alpha/pci/ttwoga_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ttwoga_pci.c,v 1.7 2012/02/06 02:14:15 matt Exp $ */ +/* $NetBSD: ttwoga_pci.c,v 1.8 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: ttwoga_pci.c,v 1.7 2012/02/06 02:14:15 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ttwoga_pci.c,v 1.8 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -146,6 +146,9 @@ ttwoga_conf_read(void *cpv, pcitag_t tag, int offset) paddr_t addr; uint64_t old_hae3; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + pci_decompose_tag(&tcp->tc_pc, tag, &b, &d, &f); addr = b ? tag : ttwoga_make_type0addr(d, f); @@ -198,6 +201,9 @@ ttwoga_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) paddr_t addr; uint64_t old_hae3; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + pci_decompose_tag(&tcp->tc_pc, tag, &b, &d, &f); addr = b ? tag : ttwoga_make_type0addr(d, f); diff --git a/sys/arch/amiga/pci/cv3dpb.c b/sys/arch/amiga/pci/cv3dpb.c index a4546da5d76..c17a8090d6a 100644 --- a/sys/arch/amiga/pci/cv3dpb.c +++ b/sys/arch/amiga/pci/cv3dpb.c @@ -1,4 +1,4 @@ -/* $NetBSD: cv3dpb.c,v 1.2 2012/10/27 17:17:32 chs Exp $ */ +/* $NetBSD: cv3dpb.c,v 1.3 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2011, 2012 The NetBSD Foundation, Inc. @@ -150,6 +150,9 @@ cv3dpb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { uint32_t data; uint32_t bus, dev, func; + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; pci_decompose_tag(pc, tag, &bus, &dev, &func); @@ -167,6 +170,9 @@ void cv3dpb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) { uint32_t bus, dev, func; + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; pci_decompose_tag(pc, tag, &bus, &dev, &func); diff --git a/sys/arch/amiga/pci/em4k.c b/sys/arch/amiga/pci/em4k.c index dc0c6e1d23a..8a05e39b3ad 100644 --- a/sys/arch/amiga/pci/em4k.c +++ b/sys/arch/amiga/pci/em4k.c @@ -1,4 +1,4 @@ -/* $NetBSD: em4k.c,v 1.3 2014/03/22 01:52:44 christos Exp $ */ +/* $NetBSD: em4k.c,v 1.4 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -314,6 +314,9 @@ em4k_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { uint32_t data; uint32_t bus, dev, func; + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; pci_decompose_tag(pc, tag, &bus, &dev, &func); @@ -333,6 +336,9 @@ em4k_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) { uint32_t bus, dev, func; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); bus_space_write_4(pc->pci_conf_datat, pc->pci_conf_datah, diff --git a/sys/arch/amiga/pci/empb.c b/sys/arch/amiga/pci/empb.c index 1938f0674e5..50a72ed1fef 100644 --- a/sys/arch/amiga/pci/empb.c +++ b/sys/arch/amiga/pci/empb.c @@ -1,4 +1,4 @@ -/* $NetBSD: empb.c,v 1.10 2013/01/29 00:49:43 rkujawa Exp $ */ +/* $NetBSD: empb.c,v 1.11 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -394,6 +394,9 @@ empb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) struct empb_softc *sc; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + sc = pc->cookie; pci_decompose_tag(pc, tag, &bus, &dev, &func); @@ -424,6 +427,9 @@ empb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) struct empb_softc *sc; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + sc = pc->cookie; pci_decompose_tag(pc, tag, &bus, &dev, &func); diff --git a/sys/arch/amiga/pci/mppb.c b/sys/arch/amiga/pci/mppb.c index 91af8fefb63..3532d61c515 100644 --- a/sys/arch/amiga/pci/mppb.c +++ b/sys/arch/amiga/pci/mppb.c @@ -1,4 +1,4 @@ -/* $NetBSD: mppb.c,v 1.7 2012/10/27 17:17:34 chs Exp $ */ +/* $NetBSD: mppb.c,v 1.8 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -197,6 +197,9 @@ mppb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { uint32_t data; uint32_t bus, dev, func; + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; pci_decompose_tag(pc, tag, &bus, &dev, &func); @@ -215,6 +218,9 @@ mppb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) { uint32_t bus, dev, func; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); bus_space_write_4(pc->pci_conf_datat, pc->pci_conf_datah, diff --git a/sys/arch/amiga/pci/p5pb.c b/sys/arch/amiga/pci/p5pb.c index 56aa207be3c..c72da9c62d2 100644 --- a/sys/arch/amiga/pci/p5pb.c +++ b/sys/arch/amiga/pci/p5pb.c @@ -1,4 +1,4 @@ -/* $NetBSD: p5pb.c,v 1.13 2014/03/22 01:52:44 christos Exp $ */ +/* $NetBSD: p5pb.c,v 1.14 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 2011, 2012 The NetBSD Foundation, Inc. @@ -344,6 +344,9 @@ p5pb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) uint32_t bus, dev, func; uint32_t offset; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return 0xFFFFFFFF; + pci_decompose_tag(pc, tag, &bus, &dev, &func); offset = (OFF_PCI_DEVICE << dev) + reg; @@ -376,6 +379,9 @@ p5pb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) uint32_t bus, dev, func; uint32_t offset; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); offset = (OFF_PCI_DEVICE << dev) + reg; diff --git a/sys/arch/arc/pci/necpb.c b/sys/arch/arc/pci/necpb.c index a9fd47c3b1a..48d99b5c0d4 100644 --- a/sys/arch/arc/pci/necpb.c +++ b/sys/arch/arc/pci/necpb.c @@ -1,4 +1,4 @@ -/* $NetBSD: necpb.c,v 1.41 2014/03/29 19:28:26 christos Exp $ */ +/* $NetBSD: necpb.c,v 1.42 2015/10/02 05:22:49 msaitoh Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: necpb.c,v 1.41 2014/03/29 19:28:26 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: necpb.c,v 1.42 2015/10/02 05:22:49 msaitoh Exp $"); #include "opt_pci.h" @@ -314,6 +314,9 @@ necpb_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) pcireg_t data; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = splhigh(); out32(RD94_SYS_PCI_CONFADDR, tag | reg); data = in32(RD94_SYS_PCI_CONFDATA); @@ -328,6 +331,9 @@ necpb_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + s = splhigh(); out32(RD94_SYS_PCI_CONFADDR, tag | reg); out32(RD94_SYS_PCI_CONFDATA, data); diff --git a/sys/arch/arm/broadcom/bcm53xx_pax.c b/sys/arch/arm/broadcom/bcm53xx_pax.c index 1053be60bbb..777abea0214 100644 --- a/sys/arch/arm/broadcom/bcm53xx_pax.c +++ b/sys/arch/arm/broadcom/bcm53xx_pax.c @@ -34,7 +34,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: bcm53xx_pax.c,v 1.14 2015/02/25 13:52:42 joerg Exp $"); +__KERNEL_RCSID(1, "$NetBSD: bcm53xx_pax.c,v 1.15 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -435,6 +435,9 @@ bcmpax_conf_read(void *v, pcitag_t tag, int reg) { struct bcmpax_softc * const sc = v; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return 0xffffffff; + /* * Even in RC mode, the PCI Express Root Complex return itself * as BCM Ethernet Controller!. We could change ppb.c to match it @@ -471,6 +474,9 @@ bcmpax_conf_write(void *v, pcitag_t tag, int reg, pcireg_t val) { struct bcmpax_softc * const sc = v; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + mutex_enter(sc->sc_cfg_lock); bus_size_t data_reg = bcmpax_conf_addr_write(sc, tag | reg); diff --git a/sys/arch/arm/footbridge/footbridge_pci.c b/sys/arch/arm/footbridge/footbridge_pci.c index 198d1398d45..e6deee2b27f 100644 --- a/sys/arch/arm/footbridge/footbridge_pci.c +++ b/sys/arch/arm/footbridge/footbridge_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: footbridge_pci.c,v 1.27 2014/03/30 01:19:20 christos Exp $ */ +/* $NetBSD: footbridge_pci.c,v 1.28 2015/10/02 05:22:49 msaitoh Exp $ */ /* * Copyright (c) 1997,1998 Mark Brinicombe. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: footbridge_pci.c,v 1.27 2014/03/30 01:19:20 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: footbridge_pci.c,v 1.28 2015/10/02 05:22:49 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -180,6 +180,9 @@ footbridge_pci_conf_read(void *pcv, pcitag_t tag, int reg) u_int address; pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + footbridge_pci_decompose_tag(pcv, tag, &bus, &device, &function); if (bus == 0) /* Limited to 12 devices or we exceed type 0 config space */ @@ -204,6 +207,9 @@ footbridge_pci_conf_write(void *pcv, pcitag_t tag, int reg, pcireg_t data) int bus, device, function; u_int address; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + footbridge_pci_decompose_tag(pcv, tag, &bus, &device, &function); if (bus == 0) address = DC21285_PCI_TYPE_0_CONFIG_VBASE | (3 << 22) | (device << 11); diff --git a/sys/arch/arm/gemini/gemini_pci.c b/sys/arch/arm/gemini/gemini_pci.c index 3cfed9267eb..5c327fdf2cb 100644 --- a/sys/arch/arm/gemini/gemini_pci.c +++ b/sys/arch/arm/gemini/gemini_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: gemini_pci.c,v 1.17 2014/03/30 01:19:20 christos Exp $ */ +/* $NetBSD: gemini_pci.c,v 1.18 2015/10/02 05:22:50 msaitoh Exp $ */ /* adapted from: * NetBSD: i80312_pci.c,v 1.9 2005/12/11 12:16:51 christos Exp @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gemini_pci.c,v 1.17 2014/03/30 01:19:20 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gemini_pci.c,v 1.18 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_gemini.h" #include "opt_pci.h" @@ -285,6 +285,10 @@ static int gemini_pci_conf_setup(struct obio_softc *sc, pcitag_t tag, int offset, struct pciconf_state *ps) { + + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (1); + gemini_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); ps->ps_addr_val = diff --git a/sys/arch/arm/ixp12x0/ixp12x0_pci.c b/sys/arch/arm/ixp12x0/ixp12x0_pci.c index e16920f1aa6..2842ef308e8 100644 --- a/sys/arch/arm/ixp12x0/ixp12x0_pci.c +++ b/sys/arch/arm/ixp12x0/ixp12x0_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ixp12x0_pci.c,v 1.14 2013/08/18 15:58:19 matt Exp $ */ +/* $NetBSD: ixp12x0_pci.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. * All rights reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixp12x0_pci.c,v 1.14 2013/08/18 15:58:19 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixp12x0_pci.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $"); /* * PCI configuration support for IXP12x0 Network Processor chip. @@ -164,6 +164,9 @@ ixp12x0_pci_conf_setup(void *v, struct ixp12x0_softc *sc, pcitag_t tag, int offs int bus, device, function; vaddr_t addr; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return 0; + ixp12x0_pci_decompose_tag(v, tag, &bus, &device, &function); if (bus == 0) { diff --git a/sys/arch/arm/marvell/pci_machdep.c b/sys/arch/arm/marvell/pci_machdep.c index f75e36fce98..73d7a6f31b5 100644 --- a/sys/arch/arm/marvell/pci_machdep.c +++ b/sys/arch/arm/marvell/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.8 2014/03/30 01:19:20 christos Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.9 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.8 2014/03/30 01:19:20 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.9 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_mvsoc.h" #include "gtpci.h" @@ -266,6 +266,9 @@ gtpci_mbus_conf_read(void *v, pcitag_t tag, int reg) struct gtpci_softc *sc = v; const pcireg_t addr = tag | reg; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA, addr | GTPCI_CA_CONFIGEN); if ((addr | GTPCI_CA_CONFIGEN) != @@ -281,6 +284,9 @@ gtpci_mbus_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) struct gtpci_softc *sc = v; pcireg_t addr = tag | (reg & 0xfc); + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA, addr | GTPCI_CA_CONFIGEN); if ((addr | GTPCI_CA_CONFIGEN) != @@ -374,6 +380,9 @@ mvpex_mbus_conf_read(void *v, pcitag_t tag, int reg) uint32_t stat; int bus, dev, func, pexbus, pexdev; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + mvpex_decompose_tag(v, tag, &bus, &dev, &func); stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT); diff --git a/sys/arch/arm/nvidia/tegra_pcie.c b/sys/arch/arm/nvidia/tegra_pcie.c index dfb9690ffb7..07dee9b221f 100644 --- a/sys/arch/arm/nvidia/tegra_pcie.c +++ b/sys/arch/arm/nvidia/tegra_pcie.c @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_pcie.c,v 1.2 2015/05/03 01:26:44 jmcneill Exp $ */ +/* $NetBSD: tegra_pcie.c,v 1.3 2015/10/02 05:22:50 msaitoh Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> @@ -29,7 +29,7 @@ #include "locators.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.2 2015/05/03 01:26:44 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.3 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -298,6 +298,9 @@ tegra_pcie_conf_read(void *v, pcitag_t tag, int offset) int b, d, f; u_int reg; + if ((unsigned int)offset >= PCI_EXTCONF_SIZE) + return (pcireg_t) -1; + tegra_pcie_decompose_tag(v, tag, &b, &d, &f); if (b == 0) { @@ -319,6 +322,9 @@ tegra_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) int b, d, f; u_int reg; + if ((unsigned int)offset >= PCI_EXTCONF_SIZE) + return; + tegra_pcie_decompose_tag(v, tag, &b, &d, &f); if (b == 0) { diff --git a/sys/arch/arm/s3c2xx0/s3c2800_pci.c b/sys/arch/arm/s3c2xx0/s3c2800_pci.c index 453b2cfaccd..b4539f43baf 100644 --- a/sys/arch/arm/s3c2xx0/s3c2800_pci.c +++ b/sys/arch/arm/s3c2xx0/s3c2800_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: s3c2800_pci.c,v 1.21 2014/03/29 19:28:26 christos Exp $ */ +/* $NetBSD: s3c2800_pci.c,v 1.22 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2002 Fujitsu Component Limited @@ -100,7 +100,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.21 2014/03/29 19:28:26 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.22 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -445,6 +445,10 @@ s3c2800_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) static vaddr_t make_pci_conf_va(struct sspci_softc * sc, pcitag_t tag, int offset) { + + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (vaddr_t) -1; + if ((tag & BUSNO_MASK) == 0) { /* configuration type 0 */ int devno = tag_to_devno(tag); diff --git a/sys/arch/arm/xscale/becc_pci.c b/sys/arch/arm/xscale/becc_pci.c index c5bd1b9dc90..118ef1f7fdb 100644 --- a/sys/arch/arm/xscale/becc_pci.c +++ b/sys/arch/arm/xscale/becc_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: becc_pci.c,v 1.17 2014/03/30 21:52:09 htodd Exp $ */ +/* $NetBSD: becc_pci.c,v 1.18 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002 Wasabi Systems, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: becc_pci.c,v 1.17 2014/03/30 21:52:09 htodd Exp $"); +__KERNEL_RCSID(0, "$NetBSD: becc_pci.c,v 1.18 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -194,6 +194,9 @@ becc_pci_conf_setup(struct becc_softc *sc, pcitag_t tag, int offset, struct pciconf_state *ps) { + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (1); + becc_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); /* diff --git a/sys/arch/arm/xscale/i80312_pci.c b/sys/arch/arm/xscale/i80312_pci.c index 77b0a1ba829..75be0b1925c 100644 --- a/sys/arch/arm/xscale/i80312_pci.c +++ b/sys/arch/arm/xscale/i80312_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: i80312_pci.c,v 1.15 2014/01/28 12:02:48 martin Exp $ */ +/* $NetBSD: i80312_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: i80312_pci.c,v 1.15 2014/01/28 12:02:48 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i80312_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -180,6 +180,9 @@ i80312_pci_conf_setup(struct i80312_softc *sc, pcitag_t tag, int offset, pcireg_t binfo; int pbus, sbus; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (1); + i80312_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); binfo = bus_space_read_4(sc->sc_st, sc->sc_ppb_sh, PPB_REG_BUSINFO); diff --git a/sys/arch/arm/xscale/i80321_pci.c b/sys/arch/arm/xscale/i80321_pci.c index 8213dd5705d..75d6bb99cc2 100644 --- a/sys/arch/arm/xscale/i80321_pci.c +++ b/sys/arch/arm/xscale/i80321_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: i80321_pci.c,v 1.15 2013/08/18 15:58:20 matt Exp $ */ +/* $NetBSD: i80321_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: i80321_pci.c,v 1.15 2013/08/18 15:58:20 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i80321_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $"); #include "opt_pci.h" #include "opt_i80321.h" @@ -185,6 +185,9 @@ i80321_pci_conf_setup(struct i80321_softc *sc, pcitag_t tag, int offset, { uint32_t busno; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (1); + i80321_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); diff --git a/sys/arch/arm/xscale/ixp425_pci.c b/sys/arch/arm/xscale/ixp425_pci.c index a5e339c7633..3be0b6930e7 100644 --- a/sys/arch/arm/xscale/ixp425_pci.c +++ b/sys/arch/arm/xscale/ixp425_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ixp425_pci.c,v 1.11 2012/11/12 18:00:38 skrll Exp $ */ +/* $NetBSD: ixp425_pci.c,v 1.12 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2003 @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixp425_pci.c,v 1.11 2012/11/12 18:00:38 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixp425_pci.c,v 1.12 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -187,6 +187,9 @@ ixp425_pci_conf_read(void *v, pcitag_t tag, int offset) int i; #endif + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + PCI_CONF_LOCK(s); ixp425_pci_conf_setup(v, sc, tag, offset); @@ -226,6 +229,9 @@ ixp425_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) uint32_t data; int s; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + PCI_CONF_LOCK(s); ixp425_pci_conf_setup(v, sc, tag, offset); diff --git a/sys/arch/atari/pci/pci_hades.c b/sys/arch/atari/pci/pci_hades.c index 1a38b8ceea8..86d0073de10 100644 --- a/sys/arch/atari/pci/pci_hades.c +++ b/sys/arch/atari/pci/pci_hades.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_hades.c,v 1.13 2012/02/13 20:00:00 jdc Exp $ */ +/* $NetBSD: pci_hades.c,v 1.14 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 1996 Leo Weppelman. All rights reserved. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_hades.c,v 1.13 2012/02/13 20:00:00 jdc Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_hades.c,v 1.14 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -79,6 +79,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { u_long data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + data = *(u_long *)(pci_conf_addr + pci_config_offset(tag) + reg); return (bswap32(data)); } @@ -86,6 +89,10 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + *((u_long *)(pci_conf_addr + pci_config_offset(tag) + reg)) = bswap32(data); } diff --git a/sys/arch/atari/pci/pci_milan.c b/sys/arch/atari/pci/pci_milan.c index f2572aee5ed..61ca8a0a050 100644 --- a/sys/arch/atari/pci/pci_milan.c +++ b/sys/arch/atari/pci/pci_milan.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_milan.c,v 1.13 2012/08/12 20:50:39 martin Exp $ */ +/* $NetBSD: pci_milan.c,v 1.14 2015/10/02 05:22:50 msaitoh Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_milan.c,v 1.13 2012/08/12 20:50:39 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_milan.c,v 1.14 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -67,6 +67,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { u_long data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return 0xffffffff; + data = bswap32(milan_pci_confread(tag | reg)); if ((plx_status) & 0xf9000000) { /* @@ -81,6 +84,10 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + milan_pci_confwrite(tag | reg, bswap32(data)); } diff --git a/sys/arch/cobalt/pci/pci_machdep.c b/sys/arch/cobalt/pci/pci_machdep.c index 821d6970acc..25579852a59 100644 --- a/sys/arch/cobalt/pci/pci_machdep.c +++ b/sys/arch/cobalt/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.37 2015/06/09 22:47:59 matt Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.38 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2000 Soren S. Jorvang. All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.37 2015/06/09 22:47:59 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.38 2015/10/02 05:22:50 msaitoh Exp $"); #define _MIPS_BUS_DMA_PRIVATE @@ -100,6 +100,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) KASSERT(pc != NULL); + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + pci_decompose_tag(pc, tag, &bus, &dev, &func); /* @@ -125,6 +128,9 @@ void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR, PCICFG_ENABLE | tag | reg); bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_DATA, data); diff --git a/sys/arch/dreamcast/dev/g2/gapspci_pci.c b/sys/arch/dreamcast/dev/g2/gapspci_pci.c index 7ae8e97057c..0452e09cc25 100644 --- a/sys/arch/dreamcast/dev/g2/gapspci_pci.c +++ b/sys/arch/dreamcast/dev/g2/gapspci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: gapspci_pci.c,v 1.15 2014/03/31 13:12:55 christos Exp $ */ +/* $NetBSD: gapspci_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $ */ /*- * Copyright (c) 2001 Marcus Comstedt. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: gapspci_pci.c,v 1.15 2014/03/31 13:12:55 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gapspci_pci.c,v 1.16 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -162,6 +162,9 @@ gaps_conf_read(void *v, pcitag_t tag, int reg) if (tag != GAPS_PCITAG_MAGIC) return -1; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + if (reg == (PCI_MAPREG_START + 4)) { /* * We fake the BAR -- just return the physical address @@ -181,6 +184,9 @@ gaps_conf_write(void *v, pcitag_t tag, int reg, pcireg_t val) if (tag != GAPS_PCITAG_MAGIC) return; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + /* Disallow writing to the "BAR" ... it doesn't actually exist. */ if (reg == (PCI_MAPREG_START + 4) && val != 0x01000000) return; diff --git a/sys/arch/evbarm/ifpga/ifpga_pci.c b/sys/arch/evbarm/ifpga/ifpga_pci.c index 4cf0f7b7d93..440592b051b 100644 --- a/sys/arch/evbarm/ifpga/ifpga_pci.c +++ b/sys/arch/evbarm/ifpga/ifpga_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ifpga_pci.c,v 1.18 2014/03/29 19:28:27 christos Exp $ */ +/* $NetBSD: ifpga_pci.c,v 1.19 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright (c) 2001 ARM Ltd @@ -64,7 +64,7 @@ #define _ARM32_BUS_DMA_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ifpga_pci.c,v 1.18 2014/03/29 19:28:27 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ifpga_pci.c,v 1.19 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -212,6 +212,9 @@ ifpga_pci_conf_read(void *pcv, pcitag_t tag, int reg) int bus, device, function; u_int address; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + ifpga_pci_decompose_tag(pcv, tag, &bus, &device, &function); /* Reset the appertures so that we can talk to the register space. */ @@ -264,6 +267,9 @@ ifpga_pci_conf_write(void *pcv, pcitag_t tag, int reg, pcireg_t data) pcv, tag, reg, data); #endif + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + ifpga_pci_decompose_tag(pcv, tag, &bus, &device, &function); /* Reset the appertures so that we can talk to the register space. */ diff --git a/sys/arch/evbmips/loongson/dev/glx.c b/sys/arch/evbmips/loongson/dev/glx.c index 0bc23477e99..48715bd89df 100644 --- a/sys/arch/evbmips/loongson/dev/glx.c +++ b/sys/arch/evbmips/loongson/dev/glx.c @@ -1,4 +1,4 @@ -/* $NetBSD: glx.c,v 1.4 2012/03/11 00:02:04 mrg Exp $ */ +/* $NetBSD: glx.c,v 1.5 2015/10/02 05:22:50 msaitoh Exp $ */ /* $OpenBSD: glx.c,v 1.6 2010/10/14 21:23:04 pirofti Exp $ */ /* @@ -22,7 +22,7 @@ * XXX too many hardcoded numbers... need to expand glxreg.h */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.4 2012/03/11 00:02:04 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.5 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -215,6 +215,9 @@ glx_pci_read_hook(void *v, pcitag_t tag, int offset) int bus, dev, fn; pcireg_t data; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* * Do not get in the way of MSR programming */ @@ -260,6 +263,9 @@ glx_pci_write_hook(void *v, pcitag_t tag, { int bus, dev, fn; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + /* * Do not get in the way of MSR programming */ diff --git a/sys/arch/evbmips/malta/dev/gt.c b/sys/arch/evbmips/malta/dev/gt.c index dc9163a66f1..61888e72d44 100644 --- a/sys/arch/evbmips/malta/dev/gt.c +++ b/sys/arch/evbmips/malta/dev/gt.c @@ -1,4 +1,4 @@ -/* $NetBSD: gt.c,v 1.14 2015/06/07 07:19:21 matt Exp $ */ +/* $NetBSD: gt.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gt.c,v 1.14 2015/06/07 07:19:21 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gt.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -164,6 +164,9 @@ gt_conf_read(void *v, pcitag_t tag, int offset) pcireg_t data; int bus, dev, func, s; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + gt_decompose_tag(NULL /* XXX */, tag, &bus, &dev, &func); /* The galileo has problems accessing device 31. */ @@ -196,6 +199,9 @@ gt_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data) { int bus, dev, func, s; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + gt_decompose_tag(NULL /* XXX */, tag, &bus, &dev, &func); /* The galileo has problems accessing device 31. */ diff --git a/sys/arch/hpcmips/dev/plum.c b/sys/arch/hpcmips/dev/plum.c index 72eeef4cb41..3248598e24c 100644 --- a/sys/arch/hpcmips/dev/plum.c +++ b/sys/arch/hpcmips/dev/plum.c @@ -1,4 +1,4 @@ -/* $NetBSD: plum.c,v 1.14 2012/10/27 17:17:52 chs Exp $ */ +/* $NetBSD: plum.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: plum.c,v 1.14 2012/10/27 17:17:52 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: plum.c,v 1.15 2015/10/02 05:22:50 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -172,6 +172,9 @@ plum_conf_read(bus_space_tag_t t, bus_space_handle_t h, int o) { plumreg_t reg; + if ((unsigned int)o >= PCI_CONF_SIZE) + return (pcireg_t) -1; + reg = bus_space_read_4(t, h, o); return (reg); @@ -181,6 +184,9 @@ void plum_conf_write(bus_space_tag_t t, bus_space_handle_t h, int o, plumreg_t v) { + if ((unsigned int)o >= PCI_CONF_SIZE) + return; + bus_space_write_4(t, h, o, v); } diff --git a/sys/arch/hpcmips/vr/vrc4172pci.c b/sys/arch/hpcmips/vr/vrc4172pci.c index 566f1c2aec9..b0d60c03ec3 100644 --- a/sys/arch/hpcmips/vr/vrc4172pci.c +++ b/sys/arch/hpcmips/vr/vrc4172pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: vrc4172pci.c,v 1.17 2014/03/29 19:28:28 christos Exp $ */ +/* $NetBSD: vrc4172pci.c,v 1.18 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2002 TAKEMURA Shin @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vrc4172pci.c,v 1.17 2014/03/29 19:28:28 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vrc4172pci.c,v 1.18 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -261,6 +261,9 @@ vrc4172pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) struct vrc4172pci_softc *sc = device_private(pc->pc_dev); u_int32_t val; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + #ifdef VRC4172PCI_MCR700_SUPPORT if (sc->sc_fake_baseaddr != 0 && tag == vrc4172pci_make_tag(pc, 0, 0, 1) && @@ -293,6 +296,9 @@ vrc4172pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, DPRINTF(("%s: conf_write: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n", device_xname(sc->sc_dev), (u_int32_t)tag, reg, (u_int32_t)data)); + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + #ifdef VRC4172PCI_MCR700_SUPPORT if (sc->sc_fake_baseaddr != 0 && tag == vrc4172pci_make_tag(pc, 0, 0, 1) && diff --git a/sys/arch/hpcmips/vr/vrpciu.c b/sys/arch/hpcmips/vr/vrpciu.c index 6753e37c781..09533ba8502 100644 --- a/sys/arch/hpcmips/vr/vrpciu.c +++ b/sys/arch/hpcmips/vr/vrpciu.c @@ -1,4 +1,4 @@ -/* $NetBSD: vrpciu.c,v 1.21 2014/03/31 20:46:41 christos Exp $ */ +/* $NetBSD: vrpciu.c,v 1.22 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2001 Enami Tsugutomo. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vrpciu.c,v 1.21 2014/03/31 20:46:41 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vrpciu.c,v 1.22 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -424,6 +424,9 @@ vrpciu_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) u_int32_t val; int bus, device, function; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + pci_decompose_tag(pc, tag, &bus, &device, &function); if (bus == 0) { if (device > 21) @@ -452,6 +455,10 @@ vrpciu_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, printf("%s: conf_write: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n", device_xname(sc->sc_dev), (u_int32_t)tag, reg, (u_int32_t)data); #endif + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + vrpciu_decompose_tag(pc, tag, &bus, &device, &function); if (bus == 0) { if (device > 21) diff --git a/sys/arch/hppa/dev/dino.c b/sys/arch/hppa/dev/dino.c index df656221590..aa18252658d 100644 --- a/sys/arch/hppa/dev/dino.c +++ b/sys/arch/hppa/dev/dino.c @@ -1,4 +1,4 @@ -/* $NetBSD: dino.c,v 1.2 2014/03/31 20:51:20 christos Exp $ */ +/* $NetBSD: dino.c,v 1.3 2015/10/02 05:22:51 msaitoh Exp $ */ /* $OpenBSD: dino.c,v 1.5 2004/02/13 20:39:31 mickey Exp $ */ @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.2 2014/03/31 20:51:20 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.3 2015/10/02 05:22:51 msaitoh Exp $"); /* #include "cardbus.h" */ @@ -338,6 +338,9 @@ dino_conf_read(void *v, pcitag_t tag, int reg) pcireg_t data; uint32_t pamr; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* fix arbitration errata by disabling all pci devs on config read */ pamr = r->pamr; r->pamr = 0; @@ -358,6 +361,9 @@ dino_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) volatile struct dino_regs *r = sc->sc_regs; uint32_t pamr; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + /* fix arbitration errata by disabling all pci devs on config read */ pamr = r->pamr; r->pamr = 0; diff --git a/sys/arch/hppa/dev/elroy.c b/sys/arch/hppa/dev/elroy.c index 1dc6f366341..da7b3be065b 100644 --- a/sys/arch/hppa/dev/elroy.c +++ b/sys/arch/hppa/dev/elroy.c @@ -1,4 +1,4 @@ -/* $NetBSD: elroy.c,v 1.1 2014/02/24 07:23:42 skrll Exp $ */ +/* $NetBSD: elroy.c,v 1.2 2015/10/02 05:22:51 msaitoh Exp $ */ /* $OpenBSD: elroy.c,v 1.5 2009/03/30 21:24:57 kettenis Exp $ */ @@ -257,6 +257,10 @@ elroy_conf_read(void *v, pcitag_t tag, int reg) pcireg_t data; /* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */ + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ((pcireg_t) -1); + arb_mask = elroy_read32(&r->arb_mask); err_cfg = elroy_read32(&r->err_cfg); control = elroy_read32(&r->control); @@ -291,6 +295,10 @@ elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) uint32_t arb_mask, err_cfg, control; /* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */ + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + arb_mask = elroy_read32(&r->arb_mask); err_cfg = elroy_read32(&r->err_cfg); control = elroy_read32(&r->control); diff --git a/sys/arch/ia64/pci/pci_machdep.c b/sys/arch/ia64/pci/pci_machdep.c index d7e921e3eaa..c75d4ff4214 100644 --- a/sys/arch/ia64/pci/pci_machdep.c +++ b/sys/arch/ia64/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.3 2013/01/12 08:40:51 kiyohara Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.4 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright (c) 2009, 2010 KIYOHARA Takashi * All rights reserved. @@ -25,7 +25,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.3 2013/01/12 08:40:51 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.4 2015/10/02 05:22:51 msaitoh Exp $"); #include <machine/bus.h> #include <machine/sal.h> @@ -78,6 +78,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { struct ia64_sal_result res; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + res = ia64_sal_entry(SAL_PCI_CONFIG_READ, tag | reg, sizeof(pcireg_t), 0, 0, 0, 0, 0); if (res.sal_status < 0) @@ -91,6 +94,9 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) { struct ia64_sal_result res; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + res = ia64_sal_entry(SAL_PCI_CONFIG_WRITE, tag | reg, sizeof(pcireg_t), val, 0, 0, 0, 0); if (res.sal_status < 0) diff --git a/sys/arch/macppc/pci/bandit.c b/sys/arch/macppc/pci/bandit.c index 561d8e62f65..5a81d6cf53c 100644 --- a/sys/arch/macppc/pci/bandit.c +++ b/sys/arch/macppc/pci/bandit.c @@ -1,4 +1,4 @@ -/* $NetBSD: bandit.c,v 1.30 2011/10/26 04:56:23 macallan Exp $ */ +/* $NetBSD: bandit.c,v 1.31 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2000 Tsubai Masanari. All rights reserved. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bandit.c,v 1.30 2011/10/26 04:56:23 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bandit.c,v 1.31 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -156,6 +156,9 @@ bandit_conf_read(void *cookie, pcitag_t tag, int reg) int bus, dev, func, s; uint32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + pci_decompose_tag(pc, tag, &bus, &dev, &func); /* @@ -195,6 +198,9 @@ bandit_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) int bus, dev, func, s; u_int32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); if (func > 7) diff --git a/sys/arch/macppc/pci/grackle.c b/sys/arch/macppc/pci/grackle.c index bdefc881b1e..61530925273 100644 --- a/sys/arch/macppc/pci/grackle.c +++ b/sys/arch/macppc/pci/grackle.c @@ -1,4 +1,4 @@ -/* $NetBSD: grackle.c,v 1.15 2011/10/26 04:56:23 macallan Exp $ */ +/* $NetBSD: grackle.c,v 1.16 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2000 Tsubai Masanari. All rights reserved. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: grackle.c,v 1.15 2011/10/26 04:56:23 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: grackle.c,v 1.16 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -155,6 +155,9 @@ grackle_conf_read(void *cookie, pcitag_t tag, int reg) pcireg_t data; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = splhigh(); out32rb(pc->pc_addr, tag | reg); @@ -174,6 +177,9 @@ grackle_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) pci_chipset_tag_t pc = cookie; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + s = splhigh(); out32rb(pc->pc_addr, tag | reg); diff --git a/sys/arch/macppc/pci/u3.c b/sys/arch/macppc/pci/u3.c index af74e93499a..1733080c9aa 100644 --- a/sys/arch/macppc/pci/u3.c +++ b/sys/arch/macppc/pci/u3.c @@ -1,4 +1,4 @@ -/* $NetBSD: u3.c,v 1.7 2013/04/30 10:16:25 macallan Exp $ */ +/* $NetBSD: u3.c,v 1.8 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright 2006 Kyma Systems LLC. @@ -171,6 +171,9 @@ ibmcpc_conf_read(void *cookie, pcitag_t tag, int reg) pcireg_t data; u_int32_t bus, dev, func, x, devfn; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + pci_decompose_tag(pc, tag, &bus, &dev, &func); devfn = PCI_DEVFN(dev, func); @@ -201,6 +204,9 @@ ibmcpc_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) u_int32_t bus, dev, func; u_int32_t x, devfn; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); devfn = PCI_DEVFN(dev, func); diff --git a/sys/arch/macppc/pci/uninorth.c b/sys/arch/macppc/pci/uninorth.c index 2736e5eb91a..276fa76ae07 100644 --- a/sys/arch/macppc/pci/uninorth.c +++ b/sys/arch/macppc/pci/uninorth.c @@ -1,4 +1,4 @@ -/* $NetBSD: uninorth.c,v 1.17 2013/05/01 14:24:48 macallan Exp $ */ +/* $NetBSD: uninorth.c,v 1.18 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2000 Tsubai Masanari. All rights reserved. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uninorth.c,v 1.17 2013/05/01 14:24:48 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uninorth.c,v 1.18 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -194,6 +194,9 @@ uninorth_conf_read(void *cookie, pcitag_t tag, int reg) int bus, dev, func, s; uint32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; @@ -236,6 +239,9 @@ uninorth_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) int bus, dev, func, s; uint32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; @@ -272,6 +278,9 @@ uninorth_conf_read_v3(void *cookie, pcitag_t tag, int reg) int bus, dev, func, s; uint32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; @@ -304,6 +313,9 @@ uninorth_conf_write_v3(void *cookie, pcitag_t tag, int reg, pcireg_t data) int bus, dev, func, s; uint32_t x; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; diff --git a/sys/arch/mips/adm5120/dev/admpci.c b/sys/arch/mips/adm5120/dev/admpci.c index e1284947373..672fb5801c4 100644 --- a/sys/arch/mips/adm5120/dev/admpci.c +++ b/sys/arch/mips/adm5120/dev/admpci.c @@ -1,4 +1,4 @@ -/* $NetBSD: admpci.c,v 1.12 2015/06/26 22:20:58 matt Exp $ */ +/* $NetBSD: admpci.c,v 1.13 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2007 David Young. All rights reserved. @@ -61,7 +61,7 @@ #include "pci.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: admpci.c,v 1.12 2015/06/26 22:20:58 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: admpci.c,v 1.13 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -324,6 +324,10 @@ admpci_tag_to_addr(void *v, pcitag_t tag, int reg, bus_addr_t *addrp) int bus, device, function; KASSERT(addrp != NULL); + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + /* panics if tag is not well-formed */ admpci_decompose_tag(v, tag, &bus, &device, &function); if (reg > __SHIFTOUT_MASK(ADMPCI_TAG_REGISTER_MASK)) diff --git a/sys/arch/mips/alchemy/dev/aupci.c b/sys/arch/mips/alchemy/dev/aupci.c index f5424e7e5de..c11c7aa3b5d 100644 --- a/sys/arch/mips/alchemy/dev/aupci.c +++ b/sys/arch/mips/alchemy/dev/aupci.c @@ -1,4 +1,4 @@ -/* $NetBSD: aupci.c,v 1.16 2015/06/27 03:33:18 matt Exp $ */ +/* $NetBSD: aupci.c,v 1.17 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -35,7 +35,7 @@ #include "pci.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: aupci.c,v 1.16 2015/06/27 03:33:18 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: aupci.c,v 1.17 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -334,6 +334,9 @@ aupci_conf_access(void *v, int dir, pcitag_t tag, int reg, pcireg_t *datap) int b, d, f; bus_space_handle_t h; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return false; + aupci_decompose_tag(v, tag, &b, &d, &f); if (b) { /* configuration type 1 */ diff --git a/sys/arch/mips/atheros/dev/arpci.c b/sys/arch/mips/atheros/dev/arpci.c index 813384fe8f6..e3e0a6fdf35 100644 --- a/sys/arch/mips/atheros/dev/arpci.c +++ b/sys/arch/mips/atheros/dev/arpci.c @@ -1,4 +1,4 @@ -/* $NetBSD: arpci.c,v 1.4 2015/06/26 22:20:58 matt Exp $ */ +/* $NetBSD: arpci.c,v 1.5 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -30,7 +30,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: arpci.c,v 1.4 2015/06/26 22:20:58 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: arpci.c,v 1.5 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -133,6 +133,9 @@ arpci_conf_read(void *v, pcitag_t tag, int reg) struct arpci_softc * const sc = v; pcireg_t rv = 0xffffffff; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return rv; + if ((tag & 0x00ff0001) == 1) { KASSERT(((tag >> 11) & 31) > 20); /* @@ -176,6 +179,9 @@ arpci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) { struct arpci_softc * const sc = v; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + if ((tag & 0x00ff0001) == 1) { KASSERT(((tag >> 11) & 31) > 20); /* diff --git a/sys/arch/mips/bonito/bonito_pci.c b/sys/arch/mips/bonito/bonito_pci.c index 02671404654..3e77cc63419 100644 --- a/sys/arch/mips/bonito/bonito_pci.c +++ b/sys/arch/mips/bonito/bonito_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: bonito_pci.c,v 1.11 2014/03/11 08:19:45 mrg Exp $ */ +/* $NetBSD: bonito_pci.c,v 1.12 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bonito_pci.c,v 1.11 2014/03/11 08:19:45 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bonito_pci.c,v 1.12 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -119,6 +119,9 @@ bonito_conf_addr(struct bonito_config *bc, pcitag_t tag, int offset, { int b, d, f; + if ((unsigned int)offset >= PCI_CONF_SIZE) + return true; + bonito_decompose_tag(bc, tag, &b, &d, &f); if (b == 0) { diff --git a/sys/arch/mips/rmi/rmixl_pcie.c b/sys/arch/mips/rmi/rmixl_pcie.c index 31437af5f8f..1e9017afcd5 100644 --- a/sys/arch/mips/rmi/rmixl_pcie.c +++ b/sys/arch/mips/rmi/rmixl_pcie.c @@ -1,4 +1,4 @@ -/* $NetBSD: rmixl_pcie.c,v 1.11 2014/04/04 01:41:05 christos Exp $ */ +/* $NetBSD: rmixl_pcie.c,v 1.12 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rmixl_pcie.c,v 1.11 2014/04/04 01:41:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rmixl_pcie.c,v 1.12 2015/10/02 05:22:51 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -953,7 +953,9 @@ rmixl_pcie_conf_setup(struct rmixl_pcie_softc *sc, ecfg_oba = ba; } bsh = ecfg_bsh; - } else { + } else if ((*offp > 0x700) && (*offp <= PCI_EXTCONF_SIZE)) { + return -1; + } else { #ifdef DEBUG panic("%s: offset %#x: unknown", __func__, *offp); #endif diff --git a/sys/arch/mips/rmi/rmixl_pcix.c b/sys/arch/mips/rmi/rmixl_pcix.c index 69dfd874b86..e735d717305 100644 --- a/sys/arch/mips/rmi/rmixl_pcix.c +++ b/sys/arch/mips/rmi/rmixl_pcix.c @@ -1,4 +1,4 @@ -/* $NetBSD: rmixl_pcix.c,v 1.12 2014/04/04 16:41:55 ozaki-r Exp $ */ +/* $NetBSD: rmixl_pcix.c,v 1.13 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rmixl_pcix.c,v 1.12 2014/04/04 16:41:55 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rmixl_pcix.c,v 1.13 2015/10/02 05:22:51 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -693,9 +693,6 @@ rmixl_pcix_conf_setup(rmixl_pcix_softc_t *sc, } bsh = cfg_bsh; } else { -#ifdef DEBUG - panic("%s: offset %#x: unknown", __func__, *offp); -#endif return -1; } diff --git a/sys/arch/mips/sibyte/pci/sbbrz_pci.c b/sys/arch/mips/sibyte/pci/sbbrz_pci.c index 9ebf885035f..94401a34d3d 100644 --- a/sys/arch/mips/sibyte/pci/sbbrz_pci.c +++ b/sys/arch/mips/sibyte/pci/sbbrz_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: sbbrz_pci.c,v 1.5 2014/03/29 19:28:29 christos Exp $ */ +/* $NetBSD: sbbrz_pci.c,v 1.6 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright 2000, 2001 @@ -64,7 +64,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: sbbrz_pci.c,v 1.5 2014/03/29 19:28:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sbbrz_pci.c,v 1.6 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -181,6 +181,9 @@ sbbrz_pci_conf_read(void *cpv, pcitag_t tag, int offset) panic ("pci_conf_read: misaligned"); #endif + if ((unsigned int)offset >= PCI_CONF_SIZE) + return 0xffffffff; + addr = A_PHYS_LDTPCI_CFG_MATCH_BITS + tag + offset; addr = MIPS_PHYS_TO_XKPHYS(MIPS3_TLB_ATTR_UNCACHED, addr); @@ -202,6 +205,9 @@ sbbrz_pci_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) panic ("pci_conf_write: misaligned"); #endif + if ((unsigned int)offset >= PCI_CONF_SIZE) + return; + addr = A_PHYS_LDTPCI_CFG_MATCH_BITS + tag + offset; addr = MIPS_PHYS_TO_XKPHYS(MIPS3_TLB_ATTR_UNCACHED, addr); diff --git a/sys/arch/powerpc/booke/pci/pq3pci.c b/sys/arch/powerpc/booke/pci/pq3pci.c index eb2cdf0849f..23ca163ee68 100644 --- a/sys/arch/powerpc/booke/pci/pq3pci.c +++ b/sys/arch/powerpc/booke/pci/pq3pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: pq3pci.c,v 1.20 2014/12/27 16:19:33 nonaka Exp $ */ +/* $NetBSD: pq3pci.c,v 1.21 2015/10/02 05:22:51 msaitoh Exp $ */ /*- * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -44,7 +44,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.20 2014/12/27 16:19:33 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.21 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -1058,8 +1058,10 @@ pq3pci_conf_read(void *v, pcitag_t tag, int reg) struct pq3pci_softc * const sc = v; struct genppc_pci_chipset * const pc = &sc->sc_pc; - if (reg >= 256) { - if (!sc->sc_pcie) + if (reg < 0) + return 0xffffffff; + if (reg >= PCI_CONF_SIZE) { + if (!sc->sc_pcie || reg >= PCI_EXTCONF_SIZE) return 0xffffffff; reg = (reg & 0xff) | ((reg & 0xf00) << 16); } @@ -1096,8 +1098,10 @@ pq3pci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) struct pq3pci_softc * const sc = v; struct genppc_pci_chipset * const pc = &sc->sc_pc; - if (reg >= 256) { - if (!sc->sc_pcie) + if (reg < 0) + return; + if (reg >= PCI_CONF_SIZE) { + if (!sc->sc_pcie || reg >= PCI_EXTCONF_SIZE) return; reg = (reg & 0xff) | ((reg & 0xf00) << 16); } diff --git a/sys/arch/powerpc/ibm4xx/pci/pci_machdep.c b/sys/arch/powerpc/ibm4xx/pci/pci_machdep.c index d17bae7dea1..e59f392185d 100644 --- a/sys/arch/powerpc/ibm4xx/pci/pci_machdep.c +++ b/sys/arch/powerpc/ibm4xx/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.10 2011/06/22 18:06:34 matt Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.11 2015/10/02 05:22:51 msaitoh Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.10 2011/06/22 18:06:34 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.11 2015/10/02 05:22:51 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -131,6 +131,9 @@ ibm4xx_pci_conf_read(void *v, pcitag_t tag, int reg) { pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + /* 405GT BIOS disables interrupts here. Should we? --Art */ bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, tag | reg); data = bus_space_read_4(&pci_iot, pci_ioh, PCIC_CFGDATA); @@ -143,6 +146,9 @@ void ibm4xx_pci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) { + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, tag | reg); bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGDATA, data); /* 405GP pass2 errata #6 */ diff --git a/sys/arch/powerpc/pci/pciconf_indirect.c b/sys/arch/powerpc/pci/pciconf_indirect.c index ee1d547384a..d9d218ecd8a 100644 --- a/sys/arch/powerpc/pci/pciconf_indirect.c +++ b/sys/arch/powerpc/pci/pciconf_indirect.c @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf_indirect.c,v 1.5 2011/06/18 06:41:43 matt Exp $ */ +/* $NetBSD: pciconf_indirect.c,v 1.6 2015/10/02 05:22:52 msaitoh Exp $ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pciconf_indirect.c,v 1.5 2011/06/18 06:41:43 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciconf_indirect.c,v 1.6 2015/10/02 05:22:52 msaitoh Exp $"); #define _POWERPC_BUS_DMA_PRIVATE @@ -107,6 +107,9 @@ genppc_pci_indirect_conf_read(void *v, pcitag_t tag, int reg) pcireg_t data; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = splhigh(); out32rb(pc->pc_addr, tag | reg); data = in32rb(pc->pc_data); @@ -122,6 +125,9 @@ genppc_pci_indirect_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) pci_chipset_tag_t pc = (pci_chipset_tag_t)v; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + s = splhigh(); out32rb(pc->pc_addr, tag | reg); out32rb(pc->pc_data, data); diff --git a/sys/arch/powerpc/pci/pciconf_ofmethod.c b/sys/arch/powerpc/pci/pciconf_ofmethod.c index e0b95122e1e..43317dbae8f 100644 --- a/sys/arch/powerpc/pci/pciconf_ofmethod.c +++ b/sys/arch/powerpc/pci/pciconf_ofmethod.c @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf_ofmethod.c,v 1.4 2011/06/18 06:41:43 matt Exp $ */ +/* $NetBSD: pciconf_ofmethod.c,v 1.5 2015/10/02 05:22:52 msaitoh Exp $ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pciconf_ofmethod.c,v 1.4 2011/06/18 06:41:43 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciconf_ofmethod.c,v 1.5 2015/10/02 05:22:52 msaitoh Exp $"); #define _POWERPC_BUS_DMA_PRIVATE @@ -103,6 +103,9 @@ genppc_pci_ofmethod_conf_read(void *v, pcitag_t tag, int reg) pci_chipset_tag_t pc = (pci_chipset_tag_t)v; pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + tag &= OFW_PCI_PHYS_HI_BUSMASK | OFW_PCI_PHYS_HI_DEVICEMASK | OFW_PCI_PHYS_HI_FUNCTIONMASK; tag |= reg & OFW_PCI_PHYS_HI_REGISTERMASK; @@ -117,6 +120,9 @@ genppc_pci_ofmethod_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) { pci_chipset_tag_t pc = (pci_chipset_tag_t)v; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + tag &= OFW_PCI_PHYS_HI_BUSMASK | OFW_PCI_PHYS_HI_DEVICEMASK | OFW_PCI_PHYS_HI_FUNCTIONMASK; tag |= reg & OFW_PCI_PHYS_HI_REGISTERMASK; diff --git a/sys/arch/prep/pci/prep_pciconf_direct.c b/sys/arch/prep/pci/prep_pciconf_direct.c index b90441f93ed..b9a593571ec 100644 --- a/sys/arch/prep/pci/prep_pciconf_direct.c +++ b/sys/arch/prep/pci/prep_pciconf_direct.c @@ -1,4 +1,4 @@ -/* $NetBSD: prep_pciconf_direct.c,v 1.8 2011/07/01 16:56:52 dyoung Exp $ */ +/* $NetBSD: prep_pciconf_direct.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 2002 Klaus J. Klein. All rights reserved. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: prep_pciconf_direct.c,v 1.8 2011/07/01 16:56:52 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: prep_pciconf_direct.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -158,6 +158,9 @@ prep_pci_direct_conf_read(void *v, pcitag_t tag, int reg) int bus, device, function; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) ~0; + prep_pci_direct_decompose_tag(v, tag, &bus, &device, &function); if (bus == 0) { @@ -186,6 +189,9 @@ prep_pci_direct_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) DPRINTF(("prep_pci_direct_conf_write(0x%lx, 0x%x, 0x%02x, 0x%08lx) ", (unsigned long)v, tag, reg, (unsigned long)data)); + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + prep_pci_direct_decompose_tag(v, tag, &bus, &device, &function); if (bus == 0) { diff --git a/sys/arch/sandpoint/pci/pci_machdep.c b/sys/arch/sandpoint/pci/pci_machdep.c index 7e33b2d369b..479d666b9ae 100644 --- a/sys/arch/sandpoint/pci/pci_machdep.c +++ b/sys/arch/sandpoint/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.33 2014/03/29 19:28:30 christos Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.34 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.33 2014/03/29 19:28:30 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.34 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_pci.h" @@ -213,6 +213,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + out32rb(SANDPOINT_PCI_CONFIG_ADDR, tag | reg); data = in32rb(SANDPOINT_PCI_CONFIG_DATA); out32rb(SANDPOINT_PCI_CONFIG_ADDR, 0); @@ -223,6 +226,9 @@ void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + out32rb(SANDPOINT_PCI_CONFIG_ADDR, tag | reg); out32rb(SANDPOINT_PCI_CONFIG_DATA, data); out32rb(SANDPOINT_PCI_CONFIG_ADDR, 0); diff --git a/sys/arch/sgimips/gio/pci_gio.c b/sys/arch/sgimips/gio/pci_gio.c index bda69398116..2b018132295 100644 --- a/sys/arch/sgimips/gio/pci_gio.c +++ b/sys/arch/sgimips/gio/pci_gio.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_gio.c,v 1.14 2015/02/18 16:47:58 macallan Exp $ */ +/* $NetBSD: pci_gio.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 2006 Stephen M. Rumble @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_gio.c,v 1.14 2015/02/18 16:47:58 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_gio.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $"); /* * Glue for PCI devices that are connected to the GIO bus by various little @@ -250,6 +250,9 @@ giopci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) int bus, dev, func; pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + pci_decompose_tag(pc, tag, &bus, &dev, &func); if (bus != 0 || dev != 0 || func != 0) return (0); @@ -273,6 +276,9 @@ giopci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) struct giopci_softc *sc = pc->cookie; int bus, dev, func; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + pci_decompose_tag(pc, tag, &bus, &dev, &func); if (bus != 0 || dev != 0 || func != 0) return; diff --git a/sys/arch/sgimips/mace/pci_mace.c b/sys/arch/sgimips/mace/pci_mace.c index 5ffd466b5ad..c9b7059f162 100644 --- a/sys/arch/sgimips/mace/pci_mace.c +++ b/sys/arch/sgimips/mace/pci_mace.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_mace.c,v 1.19 2015/09/24 17:56:59 macallan Exp $ */ +/* $NetBSD: pci_mace.c,v 1.20 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 2001,2003 Christopher Sekiya @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_mace.c,v 1.19 2015/09/24 17:56:59 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_mace.c,v 1.20 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -212,6 +212,9 @@ macepci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, (tag | reg)); data = bus_space_read_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_DATA); bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, 0); @@ -223,6 +226,9 @@ void macepci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, (tag | reg)); bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_DATA, data); bus_space_write_4(pc->iot, pc->ioh, MACE_PCI_CONFIG_ADDR, 0); diff --git a/sys/arch/sh3/dev/shpcic.c b/sys/arch/sh3/dev/shpcic.c index 04832b06fde..c7a34a75b35 100644 --- a/sys/arch/sh3/dev/shpcic.c +++ b/sys/arch/sh3/dev/shpcic.c @@ -1,4 +1,4 @@ -/* $NetBSD: shpcic.c,v 1.17 2012/01/27 18:53:01 para Exp $ */ +/* $NetBSD: shpcic.c,v 1.18 2015/10/02 05:22:52 msaitoh Exp $ */ /*- * Copyright (C) 2005 NONAKA Kimihiro <nonaka@netbsd.org> @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: shpcic.c,v 1.17 2012/01/27 18:53:01 para Exp $"); +__KERNEL_RCSID(0, "$NetBSD: shpcic.c,v 1.18 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_pci.h" @@ -295,6 +295,9 @@ shpcic_conf_read(void *v, pcitag_t tag, int reg) pcireg_t data; int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return (pcireg_t) -1; + s = splhigh(); _reg_write_4(SH4_PCIPAR, tag | reg); data = _reg_read_4(SH4_PCIPDR); @@ -309,6 +312,9 @@ shpcic_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) { int s; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + s = splhigh(); _reg_write_4(SH4_PCIPAR, tag | reg); _reg_write_4(SH4_PCIPDR, data); diff --git a/sys/arch/sparc/sparc/pci_machdep.c b/sys/arch/sparc/sparc/pci_machdep.c index fd1b344f9f7..2856743bd19 100644 --- a/sys/arch/sparc/sparc/pci_machdep.c +++ b/sys/arch/sparc/sparc/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.20 2014/03/29 19:28:30 christos Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.21 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 1999, 2000 Matthew R. Green @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.20 2014/03/29 19:28:30 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.21 2015/10/02 05:22:52 msaitoh Exp $"); #if defined(DEBUG) && !defined(SPARC_PCI_DEBUG) #define SPARC_PCI_DEBUG @@ -347,8 +347,6 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) #ifdef DIAGNOSTIC if (reg & 0x3) panic("pci_conf_read: reg %x unaligned", reg); - if (reg & ~0xff) - panic("pci_conf_read: reg %x out of range", reg); #endif if (PCITAG_NODE(tag) == -1) { @@ -356,6 +354,9 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) return ~0; } + if ((unsigned int)reg >= PCI_CONF_SIZE) + return ~0; + mode1_addr = PCITAG_OFFSET(tag) | reg; mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA | (reg & PCI_MODE1_DATA_REG_MASK); @@ -384,8 +385,6 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) #ifdef DIAGNOSTIC if (reg & 0x3) panic("pci_conf_write: reg %x unaligned", reg); - if (reg & ~0xff) - panic("pci_conf_write: reg %x out of range", reg); #endif if (PCITAG_NODE(tag) == -1) { @@ -393,6 +392,9 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) return; } + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + mode1_addr = PCITAG_OFFSET(tag) | reg; mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA | (reg & PCI_MODE1_DATA_REG_MASK); diff --git a/sys/arch/sparc64/dev/psycho.c b/sys/arch/sparc64/dev/psycho.c index 0a2f00ebe4b..d1e4186ab2a 100644 --- a/sys/arch/sparc64/dev/psycho.c +++ b/sys/arch/sparc64/dev/psycho.c @@ -1,4 +1,4 @@ -/* $NetBSD: psycho.c,v 1.120 2014/10/18 08:33:27 snj Exp $ */ +/* $NetBSD: psycho.c,v 1.121 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 1999, 2000 Matthew R. Green @@ -55,7 +55,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.120 2014/10/18 08:33:27 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.121 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_ddb.h" @@ -1405,7 +1405,7 @@ psycho_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) DPRINTF(PDB_CONF, ("%s: tag %lx reg %x ", __func__, (long)tag, reg)); - if (PCITAG_NODE(tag) != -1) { + if (PCITAG_NODE(tag) != -1 && (unsigned int)reg < PCI_CONF_SIZE) { DPRINTF(PDB_CONF, ("asi=%x addr=%qx (offset=%x) ...", sc->sc_configaddr._asi, @@ -1451,7 +1451,10 @@ psycho_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data DPRINTF(PDB_CONF, ("%s: bad addr", __func__)); return; } - + + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(sc->sc_configtag, sc->sc_configaddr, PCITAG_OFFSET(tag) + reg, data); } diff --git a/sys/arch/sparc64/dev/pyro.c b/sys/arch/sparc64/dev/pyro.c index c5d190fe196..730f633cd27 100644 --- a/sys/arch/sparc64/dev/pyro.c +++ b/sys/arch/sparc64/dev/pyro.c @@ -1,4 +1,4 @@ -/* $NetBSD: pyro.c,v 1.15 2013/08/10 00:48:04 mrg Exp $ */ +/* $NetBSD: pyro.c,v 1.16 2015/10/02 05:22:52 msaitoh Exp $ */ /* from: $OpenBSD: pyro.c,v 1.20 2010/12/05 15:15:14 kettenis Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pyro.c,v 1.15 2013/08/10 00:48:04 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pyro.c,v 1.16 2015/10/02 05:22:52 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -295,7 +295,7 @@ pyro_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) int s; DPRINTF(PDB_CONF, ("%s: tag %lx reg %x ", __func__, (long)tag, reg)); - if (PCITAG_NODE(tag) != -1) { + if (PCITAG_NODE(tag) != -1 && (unsigned int)reg < PCI_CONF_SIZE) { s = splhigh(); ci->ci_pci_probe = true; membar_Sync(); @@ -325,6 +325,9 @@ pyro_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) return; } + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(pp->pp_cfgt, pp->pp_cfgh, (PCITAG_OFFSET(tag) << 4) + reg, data); DPRINTF(PDB_CONF, (" .. done\n")); diff --git a/sys/arch/sparc64/dev/schizo.c b/sys/arch/sparc64/dev/schizo.c index c23df6ee9c4..2629e4b56ec 100644 --- a/sys/arch/sparc64/dev/schizo.c +++ b/sys/arch/sparc64/dev/schizo.c @@ -1,4 +1,4 @@ -/* $NetBSD: schizo.c,v 1.32 2014/09/21 16:39:12 christos Exp $ */ +/* $NetBSD: schizo.c,v 1.33 2015/10/02 05:22:52 msaitoh Exp $ */ /* $OpenBSD: schizo.c,v 1.55 2008/08/18 20:29:37 brad Exp $ */ /* @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: schizo.c,v 1.32 2014/09/21 16:39:12 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: schizo.c,v 1.33 2015/10/02 05:22:52 msaitoh Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -497,7 +497,7 @@ schizo_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) int s; DPRINTF(SDB_CONF, ("%s: tag %lx reg %x ", __func__, (long)tag, reg)); - if (PCITAG_NODE(tag) != -1) { + if (PCITAG_NODE(tag) != -1 && (unsigned int)reg < PCI_CONF_SIZE) { s = splhigh(); ci->ci_pci_probe = true; membar_Sync(); @@ -527,6 +527,9 @@ schizo_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) return; } + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + bus_space_write_4(sp->sp_cfgt, sp->sp_cfgh, PCITAG_OFFSET(tag) + reg, data); DPRINTF(SDB_CONF, (" .. done\n")); diff --git a/sys/arch/x86/acpi/acpi_machdep.c b/sys/arch/x86/acpi/acpi_machdep.c index 1ccca7d18cc..1b2d310000f 100644 --- a/sys/arch/x86/acpi/acpi_machdep.c +++ b/sys/arch/x86/acpi/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.c,v 1.8 2014/05/12 11:51:34 joerg Exp $ */ +/* $NetBSD: acpi_machdep.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.8 2014/05/12 11:51:34 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -51,9 +51,11 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.8 2014/05/12 11:51:34 joerg Exp $ #include <uvm/uvm_extern.h> #include <machine/cpufunc.h> +#include <machine/bootinfo.h> #include <dev/acpi/acpica.h> #include <dev/acpi/acpivar.h> +#include <dev/acpi/acpi_mcfg.h> #include <machine/acpi_machdep.h> #include <machine/mpbiosvar.h> @@ -338,6 +340,94 @@ acpi_md_ncpus(void) return kcpuset_countset(kcpuset_attached); } +static bool +acpi_md_mcfg_validate(uint64_t addr, int bus_start, int *bus_end) +{ + struct btinfo_memmap *bim; + uint64_t size, mapaddr, mapsize; + uint32_t type; + int i, n; + + bim = lookup_bootinfo(BTINFO_MEMMAP); + if (bim == NULL) + return false; + + size = (*bus_end - bus_start + 1) * ACPIMCFG_SIZE_PER_BUS; + for (i = 0; i < bim->num; i++) { + mapaddr = bim->entry[i].addr; + mapsize = bim->entry[i].size; + type = bim->entry[i].type; + + aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64 "-0x%016" PRIx64 + ", size=0x%016" PRIx64 ", type=%d(%s)\n", + mapaddr, mapaddr + mapsize - 1, mapsize, type, + (type == BIM_Memory) ? "Memory" : + (type == BIM_Reserved) ? "Reserved" : + (type == BIM_ACPI) ? "ACPI" : + (type == BIM_NVS) ? "NVS" : + "unknown"); + + switch (type) { + case BIM_ACPI: + case BIM_Reserved: + if (addr < mapaddr || addr >= mapaddr + mapsize) + break; + + /* full map */ + if (addr + size <= mapaddr + mapsize) + return true; + + /* partial map */ + n = (mapsize - (addr - mapaddr)) / + ACPIMCFG_SIZE_PER_BUS; + /* bus_start == bus_end is not allowed. */ + if (n > 1) { + *bus_end = bus_start + n - 1; + return true; + } + aprint_debug("MCFG: bus %d-%d, address 0x%016" PRIx64 + ": invalid size: request 0x%016" PRIx64 ", " + "actual 0x%016" PRIx64 "\n", + bus_start, *bus_end, addr, size, mapsize); + break; + } + } + aprint_debug("MCFG: bus %d-%d, address 0x%016" PRIx64 ": " + "no valid region\n", bus_start, *bus_end, addr); + return false; +} + +static uint32_t +acpi_md_mcfg_read(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t addr) +{ + vaddr_t va = bsh + addr; + uint32_t data = (uint32_t) -1; + + KASSERT(bst == x86_bus_space_mem); + + __asm("movl %1, %0" : "=a" (data) : "m" (*(volatile uint32_t *)va)); + + return data; +} + +static void +acpi_md_mcfg_write(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t addr, + uint32_t data) +{ + vaddr_t va = bsh + addr; + + KASSERT(bst == x86_bus_space_mem); + + __asm("movl %1, %0" : "=m" (*(volatile uint32_t *)va) : "a" (data)); +} + +static const struct acpimcfg_ops acpi_md_mcfg_ops = { + .ao_validate = acpi_md_mcfg_validate, + + .ao_read = acpi_md_mcfg_read, + .ao_write = acpi_md_mcfg_write, +}; + void acpi_md_callback(struct acpi_softc *sc) { @@ -349,4 +439,6 @@ acpi_md_callback(struct acpi_softc *sc) #ifndef XEN acpi_md_sleep_init(); #endif + + acpimcfg_init(x86_bus_space_mem, &acpi_md_mcfg_ops); } diff --git a/sys/arch/x86/pci/pci_machdep.c b/sys/arch/x86/pci/pci_machdep.c index 08abef3c2f1..01cf0d4c92c 100644 --- a/sys/arch/x86/pci/pci_machdep.c +++ b/sys/arch/x86/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.70 2015/04/27 07:03:58 knakahara Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.71 2015/10/02 05:22:52 msaitoh Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.70 2015/04/27 07:03:58 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.71 2015/10/02 05:22:52 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -137,6 +137,10 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.70 2015/04/27 07:03:58 knakahara E #if NACPICA > 0 #include <machine/mpacpi.h> +#if !defined(NO_PCI_EXTENDED_CONFIG) +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpi_mcfg.h> +#endif #endif #include <machine/mpconfig.h> @@ -509,6 +513,10 @@ pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba) pba->pba_flags &= ~PCI_FLAGS_MSIX_OKAY; } #endif /* __HAVE_PCI_MSI_MSIX */ + +#if NACPICA > 0 && !defined(NO_PCI_EXTENDED_CONFIG) + acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); +#endif } int @@ -604,6 +612,7 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) pci_chipset_tag_t ipc; pcireg_t data; struct pci_conf_lock ocl; + int dev; KASSERT((reg & 0x3) == 0); @@ -613,6 +622,23 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) return (*ipc->pc_ov->ov_conf_read)(ipc->pc_ctx, pc, tag, reg); } + pci_decompose_tag(pc, tag, NULL, &dev, NULL); + if (__predict_false(pci_mode == 2 && dev >= 16)) + return (pcireg_t) -1; + + if (reg < 0) + return (pcireg_t) -1; + if (reg >= PCI_CONF_SIZE) { +#if NACPICA > 0 && !defined(NO_PCI_EXTENDED_CONFIG) + if (reg >= PCI_EXTCONF_SIZE) + return (pcireg_t) -1; + acpimcfg_conf_read(pc, tag, reg, &data); + return data; +#else + return (pcireg_t) -1; +#endif + } + pci_conf_lock(&ocl, pci_conf_selector(tag, reg)); data = inl(pci_conf_port(tag, reg)); pci_conf_unlock(&ocl); @@ -624,6 +650,7 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { pci_chipset_tag_t ipc; struct pci_conf_lock ocl; + int dev; KASSERT((reg & 0x3) == 0); @@ -635,6 +662,22 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) return; } + pci_decompose_tag(pc, tag, NULL, &dev, NULL); + if (__predict_false(pci_mode == 2 && dev >= 16)) { + return; + } + + if (reg < 0) + return; + if (reg >= PCI_CONF_SIZE) { +#if NACPICA > 0 && !defined(NO_PCI_EXTENDED_CONFIG) + if (reg >= PCI_EXTCONF_SIZE) + return; + acpimcfg_conf_write(pc, tag, reg, data); +#endif + return; + } + pci_conf_lock(&ocl, pci_conf_selector(tag, reg)); outl(pci_conf_port(tag, reg), data); pci_conf_unlock(&ocl); diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 3780df0d982..d55896a8f6a 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $ */ +/* $NetBSD: acpi.c,v 1.261 2015/10/02 05:22:52 msaitoh Exp $ */ /*- * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. @@ -100,7 +100,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.261 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_acpi.h" #include "opt_pcifixup.h" @@ -118,6 +118,7 @@ __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.260 2015/08/18 10:41:28 christos Exp $"); #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> +#include <dev/acpi/acpi_mcfg.h> #include <dev/acpi/acpi_osd.h> #include <dev/acpi/acpi_pci.h> #include <dev/acpi/acpi_power.h> @@ -483,6 +484,11 @@ acpi_attach(device_t parent, device_t self, void *aux) */ acpi_build_tree(sc); + /* + * Probe MCFG table + */ + acpimcfg_probe(sc); + acpi_md_callback(sc); /* diff --git a/sys/dev/acpi/acpi_mcfg.c b/sys/dev/acpi/acpi_mcfg.c new file mode 100644 index 00000000000..87d8153ee27 --- /dev/null +++ b/sys/dev/acpi/acpi_mcfg.c @@ -0,0 +1,697 @@ +/* $NetBSD: acpi_mcfg.c,v 1.1 2015/10/02 05:22:52 msaitoh Exp $ */ + +/*- + * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: acpi_mcfg.c,v 1.1 2015/10/02 05:22:52 msaitoh Exp $"); + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/kmem.h> +#include <sys/systm.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpi_mcfg.h> + +#include "locators.h" + +#define EXTCONF_OFFSET(d, f, r) ((((d) * 8 + (f)) * PCI_EXTCONF_SIZE) + (r)) + +#define EXTCONF_SET_VALID(mb, d, f) ((mb)->valid_devs[(d)] |= __BIT((f))) +#define EXTCONF_SET_INVALID(mb, d, f) ((mb)->valid_devs[(d)] &= ~__BIT((f))) +#define EXTCONF_IS_VALID(mb, d, f) ((mb)->valid_devs[(d)] & __BIT((f))) + +struct mcfg_segment { + uint64_t ms_address; /* Base address */ + int ms_segment; /* Segment # */ + int ms_bus_start; /* Start bus # */ + int ms_bus_end; /* End bus # */ + bus_space_tag_t ms_bst; + struct mcfg_bus { + bus_space_handle_t bsh[32][8]; + uint8_t valid_devs[32]; + int valid_ndevs; + pcitag_t last_probed; + } *ms_bus; +}; + +static struct mcfg_segment *mcfg_segs; +static int mcfg_nsegs; +static ACPI_TABLE_MCFG *mcfg; +static int mcfg_inited; +static struct acpi_softc *acpi_sc; + +static const struct acpimcfg_ops mcfg_default_ops = { + .ao_validate = acpimcfg_default_validate, + + .ao_read = acpimcfg_default_read, + .ao_write = acpimcfg_default_write, +}; +static const struct acpimcfg_ops *mcfg_ops = &mcfg_default_ops; + +/* + * default operations. + */ +bool +acpimcfg_default_validate(uint64_t address, int bus_start, int *bus_end) +{ + + /* Always Ok */ + return true; +} + +uint32_t +acpimcfg_default_read(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t addr) +{ + + return bus_space_read_4(bst, bsh, addr); +} + +void +acpimcfg_default_write(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t addr, uint32_t data) +{ + + bus_space_write_4(bst, bsh, addr, data); +} + + +/* + * Check MCFG memory region at system resource + */ +struct acpimcfg_memrange { + const char *hid; + uint64_t address; + int bus_start; + int bus_end; + bool found; +}; + +static ACPI_STATUS +acpimcfg_parse_callback(ACPI_RESOURCE *res, void *ctx) +{ + struct acpimcfg_memrange *mr = ctx; + const char *type; + uint64_t size, mapaddr, mapsize; + int n; + + switch (res->Type) { + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + type = "FIXED_MEMORY32"; + mapaddr = res->Data.FixedMemory32.Address; + mapsize = res->Data.FixedMemory32.AddressLength; + break; + + case ACPI_RESOURCE_TYPE_ADDRESS32: + /* XXX Only fixed size supported for now */ + if (res->Data.Address32.Address.AddressLength == 0 || + res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) + goto out; + + if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE) + goto out; + + if (res->Data.Address32.MinAddressFixed != ACPI_ADDRESS_FIXED || + res->Data.Address32.MaxAddressFixed != ACPI_ADDRESS_FIXED) + goto out; + + type = "ADDRESS32"; + mapaddr = res->Data.Address32.Address.Minimum; + mapsize = res->Data.Address32.Address.AddressLength; + break; + +#ifdef _LP64 + case ACPI_RESOURCE_TYPE_ADDRESS64: + /* XXX Only fixed size supported for now */ + if (res->Data.Address64.Address.AddressLength == 0 || + res->Data.Address64.ProducerConsumer != ACPI_CONSUMER) + goto out; + + if (res->Data.Address64.ResourceType != ACPI_MEMORY_RANGE) + goto out; + + if (res->Data.Address64.MinAddressFixed != ACPI_ADDRESS_FIXED || + res->Data.Address64.MaxAddressFixed != ACPI_ADDRESS_FIXED) + goto out; + + type = "ADDRESS64"; + mapaddr = res->Data.Address64.Address.Minimum; + mapsize = res->Data.Address64.Address.AddressLength; + break; +#endif + + default: + out: + aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d\n", + mr->hid, res->Type); + return_ACPI_STATUS(AE_OK); + } + + aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d(%s), " + "Address=0x%016" PRIx64 ", Length=0x%016" PRIx64 "\n", + mr->hid, res->Type, type, mapaddr, mapsize); + + if (mr->address < mapaddr || mr->address >= mapaddr + mapsize) + return_ACPI_STATUS(AE_OK); + + size = (mr->bus_end - mr->bus_start + 1) * ACPIMCFG_SIZE_PER_BUS; + + /* full map */ + if (mr->address + size <= mapaddr + mapsize) { + mr->found = true; + return_ACPI_STATUS(AE_CTRL_TERMINATE); + } + + /* partial map */ + n = (mapsize - (mr->address - mapaddr)) / ACPIMCFG_SIZE_PER_BUS; + /* bus_start == bus_end is not allowed. */ + if (n > 1) { + mr->bus_end = mr->bus_start + n - 1; + mr->found = true; + return_ACPI_STATUS(AE_CTRL_TERMINATE); + } + + aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d-%d, " + "address 0x%016" PRIx64 ": invalid size: request 0x%016" PRIx64 + ", actual 0x%016" PRIx64 "\n", + mr->bus_start, mr->bus_end, mr->address, size, mapsize); + + return_ACPI_STATUS(AE_OK); +} + +static ACPI_STATUS +acpimcfg_check_system_resource(ACPI_HANDLE handle, UINT32 level, void *ctx, + void **retval) +{ + struct acpimcfg_memrange *mr = ctx; + ACPI_STATUS status; + + status = AcpiWalkResources(handle, "_CRS", acpimcfg_parse_callback, mr); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + + if (mr->found) + return_ACPI_STATUS(AE_CTRL_TERMINATE); + + aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: bus %d-%d, " + "address 0x%016" PRIx64 ": no valid region\n", mr->hid, + mr->bus_start, mr->bus_end, mr->address); + + return_ACPI_STATUS(AE_OK); +} + +static bool +acpimcfg_find_system_resource(uint64_t address, int bus_start, int *bus_end) +{ + static const char *system_resource_hid[] = { + "PNP0C01", /* System Board */ + "PNP0C02" /* General ID for reserving resources */ + }; + struct acpimcfg_memrange mr; + ACPI_STATUS status; + int i; + + mr.address = address; + mr.bus_start = bus_start; + mr.bus_end = *bus_end; + mr.found = false; + + for (i = 0; i < __arraycount(system_resource_hid); i++) { + mr.hid = system_resource_hid[i]; + status = AcpiGetDevices(__UNCONST(system_resource_hid[i]), + acpimcfg_check_system_resource, &mr, NULL); + if (ACPI_FAILURE(status)) + continue; + if (mr.found) { + *bus_end = mr.bus_end; + return true; + } + } + return false; +} + + +/* + * ACPI MCFG + */ +void +acpimcfg_probe(struct acpi_softc *sc) +{ + ACPI_MCFG_ALLOCATION *ama; + ACPI_STATUS status; + uint32_t offset; + int i, nsegs; + + if (acpi_sc != NULL) + panic("acpi_sc != NULL"); + acpi_sc = sc; + + status = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); + if (ACPI_FAILURE(status)) { + mcfg = NULL; + return; + } + + nsegs = 0; + offset = sizeof(ACPI_TABLE_MCFG); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); + for (i = 0; offset < mcfg->Header.Length; i++) { + aprint_debug_dev(sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n", + ama->PciSegment, ama->StartBusNumber, ama->EndBusNumber, + ama->Address); + nsegs++; + offset += sizeof(ACPI_MCFG_ALLOCATION); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, ama, offset); + } + if (nsegs == 0) { + mcfg = NULL; + return; + } + + mcfg_segs = kmem_zalloc(sizeof(*mcfg_segs) * nsegs, KM_SLEEP); + mcfg_nsegs = nsegs; +} + +int +acpimcfg_init(bus_space_tag_t memt, const struct acpimcfg_ops *ops) +{ + ACPI_MCFG_ALLOCATION *ama; + struct mcfg_segment *seg; + uint32_t offset; + int i, n, nsegs, bus_end; + + if (mcfg == NULL) + return ENXIO; + + if (mcfg_inited) + return 0; + + if (ops != NULL) + mcfg_ops = ops; + + nsegs = 0; + offset = sizeof(ACPI_TABLE_MCFG); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); + for (i = 0; offset < mcfg->Header.Length; i++) { +#ifndef _LP64 + if (ama->Address >= 0x100000000ULL) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 + ": ignore (64bit address)\n", ama->PciSegment, + ama->StartBusNumber, ama->EndBusNumber, + ama->Address); + goto next; + } +#endif + /* + * Some (broken?) BIOSen have an MCFG table for an empty + * bus range. Ignore those tables. + */ + if (ama->StartBusNumber == ama->EndBusNumber) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 + ": ignore (bus %d == %d)\n", ama->PciSegment, + ama->StartBusNumber, ama->EndBusNumber, + ama->Address, ama->StartBusNumber, + ama->EndBusNumber); + goto next; + } + if (ama->StartBusNumber > ama->EndBusNumber) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 + ": ignore (bus %d > %d)\n", ama->PciSegment, + ama->StartBusNumber, ama->EndBusNumber, + ama->Address, ama->StartBusNumber, + ama->EndBusNumber); + goto next; + } + + /* Validate MCFG memory range */ + bus_end = ama->EndBusNumber; + if (mcfg_ops->ao_validate != NULL && + !mcfg_ops->ao_validate(ama->Address, ama->StartBusNumber, + &bus_end)) { + if (!acpimcfg_find_system_resource( ama->Address, + ama->StartBusNumber, &bus_end)) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, " + "address 0x%016" PRIx64 + ": ignore (invalid address)\n", + ama->PciSegment, + ama->StartBusNumber, ama->EndBusNumber, + ama->Address); + goto next; + } + } + if (ama->EndBusNumber != bus_end) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 + " -> bus %d-%d\n", ama->PciSegment, + ama->StartBusNumber, ama->EndBusNumber, + ama->Address, ama->StartBusNumber, bus_end); + } + + if (ama->PciSegment != 0) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 + ": ignore (non PCI segment 0)\n", ama->PciSegment, + ama->StartBusNumber, bus_end, ama->Address); + goto next; + } + + seg = &mcfg_segs[nsegs++]; + seg->ms_address = ama->Address; + seg->ms_segment = ama->PciSegment; + seg->ms_bus_start = ama->StartBusNumber; + seg->ms_bus_end = bus_end; + seg->ms_bst = memt; + n = seg->ms_bus_end - seg->ms_bus_start + 1; + seg->ms_bus = kmem_zalloc(sizeof(*seg->ms_bus) * n, KM_SLEEP); + + next: + offset += sizeof(ACPI_MCFG_ALLOCATION); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, ama, offset); + } + if (nsegs == 0) + return ENOENT; + + for (i = 0; i < nsegs; i++) { + seg = &mcfg_segs[i]; + aprint_verbose_dev(acpi_sc->sc_dev, + "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n", + seg->ms_segment, seg->ms_bus_start, seg->ms_bus_end, + seg->ms_address); + } + + /* Update # of segment */ + mcfg_nsegs = nsegs; + mcfg_inited = true; + + return 0; +} + +static int +acpimcfg_ext_conf_is_aliased(pci_chipset_tag_t pc, pcitag_t tag) +{ + pcireg_t id; + int i; + + id = pci_conf_read(pc, tag, PCI_ID_REG); + for (i = PCI_CONF_SIZE; i < PCI_EXTCONF_SIZE; i += PCI_CONF_SIZE) { + if (pci_conf_read(pc, tag, i) != id) + return false; + } + return true; +} + +static struct mcfg_segment * +acpimcfg_get_segment(int bus) +{ + struct mcfg_segment *seg; + int i; + + for (i = 0; i < mcfg_nsegs; i++) { + seg = &mcfg_segs[i]; + if (bus >= seg->ms_bus_start && bus <= seg->ms_bus_end) + return seg; + } + return NULL; +} + +static int +acpimcfg_device_probe(const struct pci_attach_args *pa) +{ + pci_chipset_tag_t pc = pa->pa_pc; + struct mcfg_segment *seg; + struct mcfg_bus *mb; + pcitag_t tag; + pcireg_t reg; + int bus = pa->pa_bus; + int dev = pa->pa_device; + int func = pa->pa_function; + int last_dev, last_func, end_func; + int alias = 0; + int i, j; + + seg = acpimcfg_get_segment(bus); + if (seg == NULL) + return 0; + + mb = &seg->ms_bus[bus - seg->ms_bus_start]; + tag = pci_make_tag(pc, bus, dev, func); + + /* Mark invalid between last probed device to probed device. */ + pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func); + if (dev != 0 || func != 0) { + for (i = last_dev; i <= dev; i++) { + end_func = (i == dev) ? func : 8; + for (j = last_func; j < end_func; j++) { + if (i == last_dev && j == last_func) + continue; + EXTCONF_SET_INVALID(mb, i, j); + } + last_func = 0; + } + } + mb->last_probed = tag; + + /* Probe extended configuration space. */ + if (((reg = pci_conf_read(pc, tag, PCI_CONF_SIZE)) == (pcireg_t)-1) || + (alias = acpimcfg_ext_conf_is_aliased(pc, tag))) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: %03d:%02d:%d: invalid config space " + "(cfg[0x%03x]=0x%08x, alias=%s)\n", bus, dev, func, + PCI_CONF_SIZE, reg, alias ? "true" : "false"); + EXTCONF_SET_INVALID(mb, dev, func); + } else { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: %03d:%02d:%d: Ok (cfg[0x%03x]=0x%08x)\n", + bus, dev, func, PCI_CONF_SIZE, reg); + mb->valid_ndevs++; + } + + return 0; +} + +static void +acpimcfg_scan_bus(struct pci_softc *sc, pci_chipset_tag_t pc, int bus) +{ + static const int wildcard[PCICF_NLOCS] = { + PCICF_DEV_DEFAULT, PCICF_FUNCTION_DEFAULT + }; + + sc->sc_bus = bus; /* XXX */ + + pci_enumerate_bus(sc, wildcard, acpimcfg_device_probe, NULL); +} + +int +acpimcfg_map_bus(device_t self, pci_chipset_tag_t pc, int bus) +{ + struct pci_softc *sc = device_private(self); + struct mcfg_segment *seg = NULL; + struct mcfg_bus *mb; + bus_space_handle_t bsh; + bus_addr_t baddr; + int boff; + int last_dev, last_func; + int i, j; + int error; + + if (!mcfg_inited) + return ENXIO; + + seg = acpimcfg_get_segment(bus); + if (seg == NULL) + return ENOENT; + + boff = bus - seg->ms_bus_start; + if (seg->ms_bus[boff].valid_ndevs > 0) + return 0; + + mb = &seg->ms_bus[boff]; + baddr = seg->ms_address + (boff * ACPIMCFG_SIZE_PER_BUS); + + /* Map extended configration space of all dev/func. */ + error = bus_space_map(seg->ms_bst, baddr, ACPIMCFG_SIZE_PER_BUS, 0, + &bsh); + if (error != 0) + return error; + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) { + error = bus_space_subregion(seg->ms_bst, bsh, + EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE, + &mb->bsh[i][j]); + if (error != 0) + break; + } + } + if (error != 0) + return error; + + aprint_debug("\n"); + + /* Probe extended configuration space of all devices. */ + memset(mb->valid_devs, 0xff, sizeof(mb->valid_devs)); + mb->valid_ndevs = 0; + mb->last_probed = pci_make_tag(pc, bus, 0, 0); + + acpimcfg_scan_bus(sc, pc, bus); + + /* Unmap extended configration space of all dev/func. */ + bus_space_unmap(seg->ms_bst, bsh, ACPIMCFG_SIZE_PER_BUS); + memset(mb->bsh, 0, sizeof(mb->bsh)); + + if (mb->valid_ndevs == 0) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: bus %d: no valid devices.\n", bus); + memset(mb->valid_devs, 0, sizeof(mb->valid_devs)); + goto out; + } + + /* Mark invalid on remaining all devices. */ + pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func); + for (i = last_dev; i < 32; i++) { + for (j = last_func; j < 8; j++) { + if (i == last_dev && j == last_func) { + /* Don't mark invalid to last probed device. */ + continue; + } + EXTCONF_SET_INVALID(mb, i, j); + } + last_func = 0; + } + + /* Map extended configuration space per dev/func. */ + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) { + if (!EXTCONF_IS_VALID(mb, i, j)) + continue; + error = bus_space_map(seg->ms_bst, + baddr + EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE, + 0, &mb->bsh[i][j]); + if (error != 0) { + /* Unmap all handles when map failed. */ + do { + while (--j >= 0) { + if (!EXTCONF_IS_VALID(mb, i, j)) + continue; + bus_space_unmap(seg->ms_bst, + mb->bsh[i][j], + PCI_EXTCONF_SIZE); + } + j = 8; + } while (--i >= 0); + memset(mb->valid_devs, 0, + sizeof(mb->valid_devs)); + goto out; + } + } + } + + aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d: valid devices\n", bus); + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) { + if (EXTCONF_IS_VALID(mb, i, j)) { + aprint_debug_dev(acpi_sc->sc_dev, + "MCFG: %03d:%02d:%d\n", bus, i, j); + } + } + } + + error = 0; +out: + aprint_debug_dev(acpi_sc->sc_dev, "%s done", __func__); + + return error; +} + +int +acpimcfg_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) +{ + struct mcfg_segment *seg = NULL; + struct mcfg_bus *mb; + int bus, dev, func; + + KASSERT(reg < PCI_EXTCONF_SIZE); + KASSERT((reg & 3) == 0); + + if (!mcfg_inited) { + *data = -1; + return ENXIO; + } + + pci_decompose_tag(pc, tag, &bus, &dev, &func); + + seg = acpimcfg_get_segment(bus); + if (seg == NULL) { + *data = -1; + return ERANGE; + } + + mb = &seg->ms_bus[bus - seg->ms_bus_start]; + if (!EXTCONF_IS_VALID(mb, dev, func)) { + *data = -1; + return EINVAL; + } + + *data = mcfg_ops->ao_read(seg->ms_bst, mb->bsh[dev][func], reg); + return 0; +} + +int +acpimcfg_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) +{ + struct mcfg_segment *seg = NULL; + struct mcfg_bus *mb; + int bus, dev, func; + + KASSERT(reg < PCI_EXTCONF_SIZE); + KASSERT((reg & 3) == 0); + + if (!mcfg_inited) + return ENXIO; + + pci_decompose_tag(pc, tag, &bus, &dev, &func); + + seg = acpimcfg_get_segment(bus); + if (seg == NULL) + return ERANGE; + + mb = &seg->ms_bus[bus - seg->ms_bus_start]; + if (!EXTCONF_IS_VALID(mb, dev, func)) + return EINVAL; + + mcfg_ops->ao_write(seg->ms_bst, mb->bsh[dev][func], reg, data); + return 0; +} diff --git a/sys/dev/acpi/acpi_mcfg.h b/sys/dev/acpi/acpi_mcfg.h new file mode 100644 index 00000000000..b67c360373c --- /dev/null +++ b/sys/dev/acpi/acpi_mcfg.h @@ -0,0 +1,58 @@ +/* $NetBSD: acpi_mcfg.h,v 1.1 2015/10/02 05:22:52 msaitoh Exp $ */ + +/*- + * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_DEV_ACPI_ACPI_MCFG_H +#define _SYS_DEV_ACPI_ACPI_MCFG_H + +struct acpimcfg_ops; +void acpimcfg_probe(struct acpi_softc *); +int acpimcfg_init(bus_space_tag_t, const struct acpimcfg_ops *); +int acpimcfg_map_bus(device_t, pci_chipset_tag_t, int); + +int acpimcfg_conf_read(pci_chipset_tag_t, pcitag_t, int, pcireg_t *); +int acpimcfg_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); + +struct acpimcfg_ops { + /* validate MCFG memory region */ + bool (*ao_validate)(uint64_t, int, int *); + + /* override default bus_space(9) function */ + uint32_t (*ao_read)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t); + void (*ao_write)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint32_t); +}; + +#define ACPIMCFG_SIZE_PER_BUS (PCI_EXTCONF_SIZE * 32/*dev*/ * 8/*func*/) + +bool acpimcfg_default_validate(uint64_t, int, int *); +uint32_t acpimcfg_default_read(bus_space_tag_t, bus_space_handle_t, + bus_addr_t); +void acpimcfg_default_write(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint32_t); + +#endif /* _SYS_DEV_ACPI_ACPI_PCI_H */ diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index e08e4fed80d..514f27df64d 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.96 2015/09/21 12:32:06 nonaka Exp $ +# $NetBSD: files.acpi,v 1.97 2015/10/02 05:22:52 msaitoh Exp $ include "dev/acpi/acpica/files.acpica" @@ -18,6 +18,7 @@ device acpi: acpica, acpiapmbus, acpinodebus, acpiecdtbus, acpihpetbus, acpiwdrt attach acpi at acpibus file dev/acpi/acpi.c acpi file dev/acpi/acpi_debug.c acpi +file dev/acpi/acpi_mcfg.c acpi file dev/acpi/acpi_pci.c acpi file dev/acpi/acpi_pci_link.c acpi file dev/acpi/acpi_power.c acpi diff --git a/sys/dev/marvell/gtpci.c b/sys/dev/marvell/gtpci.c index 5d52cd7f866..88014b130f0 100644 --- a/sys/dev/marvell/gtpci.c +++ b/sys/dev/marvell/gtpci.c @@ -1,4 +1,4 @@ -/* $NetBSD: gtpci.c,v 1.31 2013/11/06 06:20:12 mrg Exp $ */ +/* $NetBSD: gtpci.c,v 1.32 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 2008, 2009 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.31 2013/11/06 06:20:12 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.32 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -567,6 +567,9 @@ gtpci_conf_read(void *v, pcitag_t tag, int reg) struct gtpci_softc *sc = v; const pcireg_t addr = tag | reg; + if ((unsigned int)reg >= PCI_CONF_SIZE) + return -1; + GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN); if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA)) return -1; @@ -580,6 +583,9 @@ gtpci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) struct gtpci_softc *sc = v; pcireg_t addr = tag | (reg & 0xfc); + if ((unsigned int)reg >= PCI_CONF_SIZE) + return; + GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN); if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA)) return; diff --git a/sys/dev/marvell/mvpex.c b/sys/dev/marvell/mvpex.c index 2a697022ec3..f291b01ebea 100644 --- a/sys/dev/marvell/mvpex.c +++ b/sys/dev/marvell/mvpex.c @@ -1,4 +1,4 @@ -/* $NetBSD: mvpex.c,v 1.14 2015/07/28 01:57:55 knakahara Exp $ */ +/* $NetBSD: mvpex.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.14 2015/07/28 01:57:55 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvpex.c,v 1.15 2015/10/02 05:22:52 msaitoh Exp $"); #include "opt_pci.h" #include "pci.h" @@ -507,6 +507,9 @@ mvpex_conf_read(void *v, pcitag_t tag, int reg) uint32_t stat; int bus, dev, func, pexbus, pexdev; + if ((unsigned int)reg >= PCI_EXTCONF_SIZE) + return -1; + mvpex_decompose_tag(v, tag, &bus, &dev, &func); stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT); @@ -552,6 +555,9 @@ mvpex_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) uint32_t stat; int bus, dev, func, pexbus, pexdev; + if ((unsigned int)reg >= PCI_EXTCONF_SIZE) + return; + mvpex_decompose_tag(v, tag, &bus, &dev, &func); stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index ec928d5909e..674e1332623 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci.c,v 1.148 2015/08/24 23:55:04 pooka Exp $ */ +/* $NetBSD: pci.c,v 1.149 2015/10/02 05:22:53 msaitoh Exp $ */ /* * Copyright (c) 1995, 1996, 1997, 1998 @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.148 2015/08/24 23:55:04 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.149 2015/10/02 05:22:53 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_pci.h" @@ -68,9 +68,6 @@ int pciprint(void *, const char *); #ifdef PCI_MACHDEP_ENUMERATE_BUS #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS -#else -int pci_enumerate_bus(struct pci_softc *, const int *, - int (*)(const struct pci_attach_args *), struct pci_attach_args *); #endif /* @@ -614,6 +611,43 @@ pci_msix_count(pci_chipset_tag_t pc, pcitag_t tag) } int +pci_get_ext_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, + int *offset, pcireg_t *value) +{ + pcireg_t reg; + unsigned int ofs; + + /* Only supported for PCI-express devices */ + if (!pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, NULL, NULL)) + return 0; + + ofs = PCI_EXTCAPLIST_BASE; + reg = pci_conf_read(pc, tag, ofs); + if (reg == 0xffffffff || reg == 0) + return 0; + + for (;;) { +#ifdef DIAGNOSTIC + if ((ofs & 3) || ofs < PCI_EXTCAPLIST_BASE) + panic("%s: invalid offset %u", __func__, ofs); +#endif + if (PCI_EXTCAPLIST_CAP(reg) == capid) { + if (offset != NULL) + *offset = ofs; + if (value != NULL) + *value = reg; + return 1; + } + ofs = PCI_EXTCAPLIST_NEXT(reg); + if (ofs == 0) + break; + reg = pci_conf_read(pc, tag, ofs); + } + + return 0; +} + +int pci_find_device(struct pci_attach_args *pa, int (*match)(const struct pci_attach_args *)) { diff --git a/sys/dev/pci/pci_subr.c b/sys/dev/pci/pci_subr.c index a2353191c4a..20a8b669a66 100644 --- a/sys/dev/pci/pci_subr.c +++ b/sys/dev/pci/pci_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $ */ +/* $NetBSD: pci_subr.c,v 1.135 2015/10/02 05:22:53 msaitoh Exp $ */ /* * Copyright (c) 1997 Zubin D. Dittia. All rights reserved. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.135 2015/10/02 05:22:53 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_pci.h" @@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.134 2015/07/27 15:46:03 msaitoh Exp $ #include <pci.h> #include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #endif @@ -1841,6 +1842,26 @@ static struct { { PCI_CAP_PCIAF, "Advanced Features", pci_conf_print_pciaf_cap } }; +static int +pci_conf_find_cap(const pcireg_t *regs, int capoff, unsigned int capid, + int *offsetp) +{ + pcireg_t rval; + int off; + + for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]); + off != 0; + off = PCI_CAPLIST_NEXT(rval)) { + rval = regs[o2i(off)]; + if (capid == PCI_CAPLIST_CAP(rval)) { + if (offsetp != NULL) + *offsetp = off; + return 1; + } + } + return 0; +} + static void pci_conf_print_caplist( #ifdef _KERNEL @@ -1889,16 +1910,1177 @@ pci_conf_print_caplist( * the same. This is required because some capabilities * appear multiple times (e.g. HyperTransport capability). */ - for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]); - off != 0; - off = PCI_CAPLIST_NEXT(regs[o2i(off)])) { + if (pci_conf_find_cap(regs, capoff, i, &off)) { rval = regs[o2i(off)]; - foundcap = PCI_CAPLIST_CAP(rval); - if ((i == foundcap) - && (pci_captab[foundcap].printfunc != NULL)) - pci_captab[foundcap].printfunc(regs, off); + if (pci_captab[i].printfunc != NULL) + pci_captab[i].printfunc(regs, off); + } + } +} + +/* Extended Capability */ + +static void +pci_conf_print_aer_cap_uc(pcireg_t reg) +{ + + onoff("Undefined", reg, PCI_AER_UC_UNDEFINED); + onoff("Data Link Protocol Error", reg, PCI_AER_UC_DL_PROTOCOL_ERROR); + onoff("Surprise Down Error", reg, PCI_AER_UC_SURPRISE_DOWN_ERROR); + onoff("Poisoned TLP", reg, PCI_AER_UC_POISONED_TLP); + onoff("Flow Control Protocol Error", reg, PCI_AER_UC_FC_PROTOCOL_ERROR); + onoff("Completion Timeout", reg, PCI_AER_UC_COMPLETION_TIMEOUT); + onoff("Completer Abort", reg, PCI_AER_UC_COMPLETER_ABORT); + onoff("Unexpected Completion", reg, PCI_AER_UC_UNEXPECTED_COMPLETION); + onoff("Receiver Overflow", reg, PCI_AER_UC_RECEIVER_OVERFLOW); + onoff("Malformed TLP", reg, PCI_AER_UC_MALFORMED_TLP); + onoff("ECRC Error", reg, PCI_AER_UC_ECRC_ERROR); + onoff("Unsupported Request Error", reg, + PCI_AER_UC_UNSUPPORTED_REQUEST_ERROR); + onoff("ACS Violation", reg, PCI_AER_UC_ACS_VIOLATION); + onoff("Uncorrectable Internal Error", reg, PCI_AER_UC_INTERNAL_ERROR); + onoff("MC Blocked TLP", reg, PCI_AER_UC_MC_BLOCKED_TLP); + onoff("AtomicOp Egress BLK", reg, PCI_AER_UC_ATOMIC_OP_EGRESS_BLOCKED); + onoff("TLP Prefix Blocked Error", reg, + PCI_AER_UC_TLP_PREFIX_BLOCKED_ERROR); +} + +static void +pci_conf_print_aer_cap_cor(pcireg_t reg) +{ + + onoff("Receiver Error", reg, PCI_AER_COR_RECEIVER_ERROR); + onoff("Bad TLP", reg, PCI_AER_COR_BAD_TLP); + onoff("Bad DLLP", reg, PCI_AER_COR_BAD_DLLP); + onoff("REPLAY_NUM Rollover", reg, PCI_AER_COR_REPLAY_NUM_ROLLOVER); + onoff("Replay Timer Timeout", reg, PCI_AER_COR_REPLAY_TIMER_TIMEOUT); + onoff("Advisory Non-Fatal Error", reg, PCI_AER_COR_ADVISORY_NF_ERROR); + onoff("Corrected Internal Error", reg, PCI_AER_COR_INTERNAL_ERROR); + onoff("Header Log Overflow", reg, PCI_AER_COR_HEADER_LOG_OVERFLOW); +} + +static void +pci_conf_print_aer_cap_control(pcireg_t reg, bool *tlp_prefix_log) +{ + + printf(" First Error Pointer: 0x%04x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_AER_FIRST_ERROR_PTR)); + onoff("ECRC Generation Capable", reg, PCI_AER_ECRC_GEN_CAPABLE); + onoff("ECRC Generation Enable", reg, PCI_AER_ECRC_GEN_ENABLE); + onoff("ECRC Check Capable", reg, PCI_AER_ECRC_CHECK_CAPABLE); + onoff("ECRC Check Enab", reg, PCI_AER_ECRC_CHECK_ENABLE); + onoff("Multiple Header Recording Capable", reg, + PCI_AER_MULT_HDR_CAPABLE); + onoff("Multiple Header Recording Enable", reg, PCI_AER_MULT_HDR_ENABLE); + + /* This bit is RsvdP if the End-End TLP Prefix Supported bit is Clear */ + if (!tlp_prefix_log) + return; + onoff("TLP Prefix Log Present", reg, PCI_AER_TLP_PREFIX_LOG_PRESENT); + *tlp_prefix_log = (reg & PCI_AER_TLP_PREFIX_LOG_PRESENT) ? true : false; +} + +static void +pci_conf_print_aer_cap_rooterr_cmd(pcireg_t reg) +{ + + onoff("Correctable Error Reporting Enable", reg, + PCI_AER_ROOTERR_COR_ENABLE); + onoff("Non-Fatal Error Reporting Enable", reg, + PCI_AER_ROOTERR_NF_ENABLE); + onoff("Fatal Error Reporting Enable", reg, PCI_AER_ROOTERR_F_ENABLE); +} + +static void +pci_conf_print_aer_cap_rooterr_status(pcireg_t reg) +{ + + onoff("ERR_COR Received", reg, PCI_AER_ROOTERR_COR_ERR); + onoff("Multiple ERR_COR Received", reg, PCI_AER_ROOTERR_MULTI_COR_ERR); + onoff("ERR_FATAL/NONFATAL_ERR Received", reg, PCI_AER_ROOTERR_UC_ERR); + onoff("Multiple ERR_FATAL/NONFATAL_ERR Received", reg, + PCI_AER_ROOTERR_MULTI_UC_ERR); + onoff("First Uncorrectable Fatal", reg, PCI_AER_ROOTERR_FIRST_UC_FATAL); + onoff("Non-Fatal Error Messages Received", reg, PCI_AER_ROOTERR_NF_ERR); + onoff("Fatal Error Messages Received", reg, PCI_AER_ROOTERR_F_ERR); + printf(" Advanced Error Interrupt Message Number: 0x%u\n", + (pcireg_t)__SHIFTOUT(reg, PCI_AER_ROOTERR_INT_MESSAGE)); +} + +static void +pci_conf_print_aer_cap_errsrc_id(pcireg_t reg) +{ + + printf(" Correctable Source ID: 0x%04x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_AER_ERRSRC_ID_ERR_COR)); + printf(" ERR_FATAL/NONFATAL Source ID: 0x%04x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_AER_ERRSRC_ID_ERR_UC)); +} + +static void +pci_conf_print_aer_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + int pcie_capoff; + int pcie_devtype = -1; + bool tlp_prefix_log = false; + + if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)) { + reg = regs[o2i(pcie_capoff)]; + pcie_devtype = reg & PCIE_XCAP_TYPE_MASK; + /* PCIe DW9 to DW14 is for PCIe 2.0 and newer */ + if (__SHIFTOUT(reg, PCIE_XCAP_VER_MASK) >= 2) { + reg = regs[o2i(pcie_capoff + PCIE_DCAP2)]; + /* End-End TLP Prefix Supported */ + if (reg & PCIE_DCAP2_EETLP_PREF) { + tlp_prefix_log = true; + } } } + + printf("\n Advanced Error Reporting Register\n"); + + reg = regs[o2i(extcapoff + PCI_AER_UC_STATUS)]; + printf(" Uncorrectable Error Status register: 0x%08x\n", reg); + pci_conf_print_aer_cap_uc(reg); + reg = regs[o2i(extcapoff + PCI_AER_UC_MASK)]; + printf(" Uncorrectable Error Mask register: 0x%08x\n", reg); + pci_conf_print_aer_cap_uc(reg); + reg = regs[o2i(extcapoff + PCI_AER_UC_SEVERITY)]; + printf(" Uncorrectable Error Severity register: 0x%08x\n", reg); + pci_conf_print_aer_cap_uc(reg); + + reg = regs[o2i(extcapoff + PCI_AER_COR_STATUS)]; + printf(" Correctable Error Status register: 0x%08x\n", reg); + pci_conf_print_aer_cap_cor(reg); + reg = regs[o2i(extcapoff + PCI_AER_COR_MASK)]; + printf(" Correctable Error Mask register: 0x%08x\n", reg); + pci_conf_print_aer_cap_cor(reg); + + reg = regs[o2i(extcapoff + PCI_AER_CAP_CONTROL)]; + printf(" Advanced Error Capabilities and Control register: 0x%08x\n", + reg); + pci_conf_print_aer_cap_control(reg, &tlp_prefix_log); + reg = regs[o2i(extcapoff + PCI_AER_HEADER_LOG)]; + printf(" Header Log register:\n"); + pci_conf_print_regs(regs, extcapoff + PCI_AER_HEADER_LOG, + extcapoff + PCI_AER_ROOTERR_CMD); + + switch (pcie_devtype) { + case PCIE_XCAP_TYPE_ROOT: /* Root Port of PCI Express Root Complex */ + case PCIE_XCAP_TYPE_ROOT_EVNTC: /* Root Complex Event Collector */ + reg = regs[o2i(extcapoff + PCI_AER_ROOTERR_CMD)]; + printf(" Root Error Command register: 0x%08x\n", reg); + pci_conf_print_aer_cap_rooterr_cmd(reg); + reg = regs[o2i(extcapoff + PCI_AER_ROOTERR_STATUS)]; + printf(" Root Error Status register: 0x%08x\n", reg); + pci_conf_print_aer_cap_rooterr_status(reg); + + reg = regs[o2i(extcapoff + PCI_AER_ERRSRC_ID)]; + printf(" Error Source Identification: 0x%04x\n", reg); + pci_conf_print_aer_cap_errsrc_id(reg); + break; + } + + if (tlp_prefix_log) { + reg = regs[o2i(extcapoff + PCI_AER_TLP_PREFIX_LOG)]; + printf(" TLP Prefix Log register: 0x%08x\n", reg); + } +} + +static void +pci_conf_print_vc_cap_arbtab(const pcireg_t *regs, int off, const char *name, + pcireg_t parbsel, int parbsize) +{ + pcireg_t reg; + int num = 16 << parbsel; + int num_per_reg = sizeof(pcireg_t) / parbsize; + int i, j; + + /* First, dump the table */ + for (i = 0; i < num; i += num_per_reg) { + reg = regs[o2i(off + i / num_per_reg)]; + printf(" %s Arbitration Table: 0x%08x\n", name, reg); + } + /* And then, decode each entry */ + for (i = 0; i < num; i += num_per_reg) { + reg = regs[o2i(off + i / num_per_reg)]; + for (j = 0; j < num_per_reg; j++) + printf(" Phase[%d]: %d\n", j, reg); + } +} + +static void +pci_conf_print_vc_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, n; + int parbtab, parbsize; + pcireg_t parbsel; + int varbtab, varbsize; + pcireg_t varbsel; + int i, count; + + printf("\n Virtual Channel Register\n"); + reg = regs[o2i(extcapoff + PCI_VC_CAP1)]; + printf(" Port VC Capability register 1: 0x%08x\n", reg); + count = __SHIFTOUT(reg, PCI_VC_CAP1_EXT_COUNT); + printf(" Extended VC Count: %d\n", count); + n = __SHIFTOUT(reg, PCI_VC_CAP1_LOWPRI_EXT_COUNT); + printf(" Low Priority Extended VC Count: %u\n", n); + n = __SHIFTOUT(reg, PCI_VC_CAP1_REFCLK); + printf(" Reference Clock: %s\n", + (n == PCI_VC_CAP1_REFCLK_100NS) ? "100" : "unknown"); + parbsize = 1 << __SHIFTOUT(reg, PCI_VC_CAP1_PORT_ARB_TABLE_SIZE); + printf(" Port Arbitration Table Entry Size: %dbit\n", parbsize); + + reg = regs[o2i(extcapoff + PCI_VC_CAP2)]; + printf(" Port VC Capability register 2: 0x%08x\n", reg); + onoff("Hardware fixed arbitration scheme", + reg, PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME); + onoff("WRR arbitration with 32 phases", + reg, PCI_VC_CAP2_ARB_CAP_WRR_32); + onoff("WRR arbitration with 64 phases", + reg, PCI_VC_CAP2_ARB_CAP_WRR_64); + onoff("WRR arbitration with 128 phases", + reg, PCI_VC_CAP2_ARB_CAP_WRR_128); + varbtab = __SHIFTOUT(reg, PCI_VC_CAP2_ARB_TABLE_OFFSET); + printf(" VC Arbitration Table Offset: 0x%x\n", varbtab); + + reg = regs[o2i(extcapoff + PCI_VC_CONTROL)] & 0xffff; + printf(" Port VC Control register: 0x%04x\n", reg); + varbsel = __SHIFTOUT(reg, PCI_VC_CONTROL_VC_ARB_SELECT); + printf(" VC Arbitration Select: 0x%x\n", varbsel); + + reg = regs[o2i(extcapoff + PCI_VC_STATUS)] >> 16; + printf(" Port VC Status register: 0x%04x\n", reg); + onoff("VC Arbitration Table Status", + reg, PCI_VC_STATUS_LOAD_VC_ARB_TABLE); + + for (i = 0; i < count + 1; i++) { + reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CAP(i))]; + printf(" VC number %d\n", i); + printf(" VC Resource Capability Register: 0x%08x\n", reg); + onoff(" Non-configurable Hardware fixed arbitration scheme", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME); + onoff(" WRR arbitration with 32 phases", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32); + onoff(" WRR arbitration with 64 phases", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64); + onoff(" WRR arbitration with 128 phases", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128); + onoff(" Time-based WRR arbitration with 128 phases", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128); + onoff(" WRR arbitration with 256 phases", + reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256); + onoff(" Advanced Packet Switching", + reg, PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH); + onoff(" Reject Snoop Transaction", + reg, PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS); + n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS) + 1; + printf(" Maximum Time Slots: %d\n", n); + parbtab = reg >> PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_S; + printf(" Port Arbitration Table offset: 0x%02x\n", + parbtab); + + reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CTL(i))]; + printf(" VC Resource Control Register: 0x%08x\n", reg); + printf(" TC/VC Map: %02x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_TCVC_MAP)); + /* + * The load Port Arbitration Table bit is used to update + * the Port Arbitration logic and it's always 0 on read, so + * we don't print it. + */ + parbsel = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT); + printf(" Port Arbitration Select: %x\n", parbsel); + n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_VC_ID); + printf(" VC ID %d\n", n); + onoff(" VC Enable", reg, PCI_VC_RESOURCE_CTL_VC_ENABLE); + + reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_STA(i))] >> 16; + printf(" VC Resource Status Register: 0x%08x\n", reg); + onoff(" Port Arbitration Table Status", + reg, PCI_VC_RESOURCE_STA_PORT_ARB_TABLE); + onoff(" VC Negotiation Pending", + reg, PCI_VC_RESOURCE_STA_VC_NEG_PENDING); + + if ((parbtab != 0) && (parbsel != 0)) + pci_conf_print_vc_cap_arbtab(regs, extcapoff + parbtab, + "Port", parbsel, parbsize); + } + + varbsize = 8; + if ((varbtab != 0) && (varbsel != 0)) + pci_conf_print_vc_cap_arbtab(regs, extcapoff + varbtab, + " VC", varbsel, varbsize); +} + +static const char * +pci_conf_print_pwrbdgt_base_power(uint8_t reg) +{ + + switch (reg) { + case 0xf0: + return "250W"; + case 0xf1: + return "275W"; + case 0xf2: + return "300W"; + default: + return "Unknown"; + } +} + +static const char * +pci_conf_print_pwrbdgt_data_scale(uint8_t reg) +{ + + switch (reg) { + case 0x00: + return "1.0x"; + case 0x01: + return "0.1x"; + case 0x02: + return "0.01x"; + case 0x03: + return "0.001x"; + default: + return "wrong value!"; + } +} + +static const char * +pci_conf_print_pwrbdgt_type(uint8_t reg) +{ + + switch (reg) { + case 0x00: + return "PME Aux"; + case 0x01: + return "Auxilary"; + case 0x02: + return "Idle"; + case 0x03: + return "Sustained"; + case 0x07: + return "Maximun"; + default: + return "Unknown"; + } +} + +static const char * +pci_conf_print_pwrbdgt_pwrrail(uint8_t reg) +{ + + switch (reg) { + case 0x00: + return "Power(12V)"; + case 0x01: + return "Power(3.3V)"; + case 0x02: + return "Power(1.5V or 1.8V)"; + case 0x07: + return "Thermal"; + default: + return "Unknown"; + } +} + +static void +pci_conf_print_pwrbdgt_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + + printf("\n Power Budget Register\n"); + + reg = regs[o2i(extcapoff + PCI_PWRBDGT_DSEL)]; + printf(" Data Select register: 0x%08x\n", reg); + + reg = regs[o2i(extcapoff + PCI_PWRBDGT_DATA)]; + printf(" Data register: 0x%08x\n", reg); + printf(" Base Power: %s\n", + pci_conf_print_pwrbdgt_base_power((uint8_t)reg)); + printf(" Data Scale: %s\n", + pci_conf_print_pwrbdgt_data_scale( + (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_DATA_SCALE)))); + printf(" PM Sub State: 0x%hhx\n", + (uint8_t)__SHIFTOUT(reg, PCI_PWRBDGT_PM_SUBSTAT)); + printf(" PM State: D%u\n", + (unsigned int)__SHIFTOUT(reg, PCI_PWRBDGT_PM_STAT)); + printf(" Type: %s\n", + pci_conf_print_pwrbdgt_type( + (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_TYPE)))); + printf(" Power Rail: %s\n", + pci_conf_print_pwrbdgt_pwrrail( + (uint8_t)(__SHIFTOUT(reg, PCI_PWRBDGT_PWRRAIL)))); + + reg = regs[o2i(extcapoff + PCI_PWRBDGT_CAP)]; + printf(" Power Budget Capability register: 0x%08x\n", reg); + onoff("System Allocated", + reg, PCI_PWRBDGT_CAP_SYSALLOC); +} + +static const char * +pci_conf_print_rclink_dcl_cap_elmtype(unsigned char type) +{ + + switch (type) { + case 0x00: + return "Configuration Space Element"; + case 0x01: + return "System Egress Port or internal sink (memory)"; + case 0x02: + return "Internal Root Complex Link"; + default: + return "Unknown"; + } +} + +static void +pci_conf_print_rclink_dcl_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + unsigned char nent, linktype; + int i; + + printf("\n Root Complex Link Declaration\n"); + + reg = regs[o2i(extcapoff + PCI_RCLINK_DCL_ESDESC)]; + printf(" Element Self Description Register: 0x%08x\n", reg); + printf(" Element Type: %s\n", + pci_conf_print_rclink_dcl_cap_elmtype((unsigned char)reg)); + nent = __SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_NUMLINKENT); + printf(" Number of Link Entries: %hhu\n", nent); + printf(" Component ID: %hhu\n", + (uint8_t)__SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_COMPID)); + printf(" Port Number: %hhu\n", + (uint8_t)__SHIFTOUT(reg, PCI_RCLINK_DCL_ESDESC_PORTNUM)); + for (i = 0; i < nent; i++) { + reg = regs[o2i(extcapoff + PCI_RCLINK_DCL_LINKDESC(i))]; + printf(" Link Description Register: 0x%08x\n", reg); + onoff("Link Valid", reg,PCI_RCLINK_DCL_LINKDESC_LVALID); + linktype = reg & PCI_RCLINK_DCL_LINKDESC_LTYPE; + onoff2("Link Type", reg, PCI_RCLINK_DCL_LINKDESC_LTYPE, + "Configuration Space", "Memory-Mapped Space"); + onoff("Associated RCRB Header", reg, + PCI_RCLINK_DCL_LINKDESC_ARCRBH); + printf(" Target Component ID: %hhu\n", + (unsigned char)__SHIFTOUT(reg, + PCI_RCLINK_DCL_LINKDESC_TCOMPID)); + printf(" Target Port Number: %hhu\n", + (unsigned char)__SHIFTOUT(reg, + PCI_RCLINK_DCL_LINKDESC_TPNUM)); + + if (linktype == 0) { + /* Memory-Mapped Space */ + reg = regs[o2i(extcapoff + + PCI_RCLINK_DCL_LINKADDR_LT0_LO(i))]; + printf(" Link Address Low Register: 0x%08x\n", reg); + reg = regs[o2i(extcapoff + + PCI_RCLINK_DCL_LINKADDR_LT0_HI(i))]; + printf(" Link Address High Register: 0x%08x\n",reg); + } else { + unsigned int nb; + pcireg_t lo, hi; + + /* Configuration Space */ + lo = regs[o2i(extcapoff + + PCI_RCLINK_DCL_LINKADDR_LT1_LO(i))]; + printf(" Configuration Space Low Register: 0x%08x" + "\n", lo); + hi = regs[o2i(extcapoff + + PCI_RCLINK_DCL_LINKADDR_LT1_HI(i))]; + printf(" Configuration Space High Register: 0x%08x" + "\n", hi); + nb = __SHIFTOUT(lo, PCI_RCLINK_DCL_LINKADDR_LT1_N); + printf(" N: %u\n", nb); + printf(" Func: %hhu\n", + (unsigned char)__SHIFTOUT(lo, + PCI_RCLINK_DCL_LINKADDR_LT1_FUNC)); + printf(" Dev: %hhu\n", + (unsigned char)__SHIFTOUT(lo, + PCI_RCLINK_DCL_LINKADDR_LT1_DEV)); + printf(" Bus: %hhu\n", + (unsigned char)__SHIFTOUT(lo, + PCI_RCLINK_DCL_LINKADDR_LT1_BUS(nb))); + lo &= PCI_RCLINK_DCL_LINKADDR_LT1_BAL(i); + printf(" Configuration Space Base Address: 0x%016" + PRIx64 "\n", ((uint64_t)hi << 32) + lo); + } + } +} + +/* XXX pci_conf_print_rclink_ctl_cap */ + +static void +pci_conf_print_rcec_assoc_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + + printf("\n Root Complex Event Collector Association\n"); + + reg = regs[o2i(extcapoff + PCI_RCEC_ASSOC_ASSOCBITMAP)]; + printf(" Association Bitmap for Root Complex Integrated Devices:" + " 0x%08x\n", reg); +} + +/* XXX pci_conf_print_mfvc_cap */ +/* XXX pci_conf_print_vc2_cap */ +/* XXX pci_conf_print_rcrb_cap */ +/* XXX pci_conf_print_vendor_cap */ +/* XXX pci_conf_print_cac_cap */ + +static void +pci_conf_print_acs_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, cap, ctl; + unsigned int size, i; + + printf("\n Access Control Services\n"); + + reg = regs[o2i(extcapoff + PCI_ACS_CAP)]; + cap = reg & 0xffff; + ctl = reg >> 16; + printf(" ACS Capability register: 0x%08x\n", cap); + onoff("ACS Source Validation", cap, PCI_ACS_CAP_V); + onoff("ACS Transaction Blocking", cap, PCI_ACS_CAP_B); + onoff("ACS P2P Request Redirect", cap, PCI_ACS_CAP_R); + onoff("ACS P2P Completion Redirect", cap, PCI_ACS_CAP_C); + onoff("ACS Upstream Forwarding", cap, PCI_ACS_CAP_U); + onoff("ACS Egress Control", cap, PCI_ACS_CAP_E); + onoff("ACS Direct Translated P2P", cap, PCI_ACS_CAP_T); + size = __SHIFTOUT(cap, PCI_ACS_CAP_ECVSIZE); + if (size == 0) + size = 256; + printf(" Egress Control Vector Size: %u\n", size); + printf(" ACS Control register: 0x%08x\n", ctl); + onoff("ACS Source Validation Enable", ctl, PCI_ACS_CTL_V); + onoff("ACS Transaction Blocking Enable", ctl, PCI_ACS_CTL_B); + onoff("ACS P2P Request Redirect Enable", ctl, PCI_ACS_CTL_R); + onoff("ACS P2P Completion Redirect Enable", ctl, PCI_ACS_CTL_C); + onoff("ACS Upstream Forwarding Enable", ctl, PCI_ACS_CTL_U); + onoff("ACS Egress Control Enable", ctl, PCI_ACS_CTL_E); + onoff("ACS Direct Translated P2P Enable", ctl, PCI_ACS_CTL_T); + + /* + * If the P2P Egress Control Capability bit is 0, ignore the Egress + * Control vector. + */ + if ((cap & PCI_ACS_CAP_E) == 0) + return; + for (i = 0; i < size; i += 32) + printf(" Egress Control Vector [%u..%u]: %x\n", i + 31, + i, regs[o2i(extcapoff + PCI_ACS_ECV + (i / 32) * 4 )]); +} + +static void +pci_conf_print_ari_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, cap, ctl; + + printf("\n Alternative Routing-ID Interpretation Register\n"); + + reg = regs[o2i(extcapoff + PCI_ARI_CAP)]; + cap = reg & 0xffff; + ctl = reg >> 16; + printf(" Capability register: 0x%08x\n", cap); + onoff("MVFC Function Groups Capability", reg, PCI_ARI_CAP_M); + onoff("ACS Function Groups Capability", reg, PCI_ARI_CAP_A); + printf(" Next Function Number: %u\n", + (unsigned int)__SHIFTOUT(reg, PCI_ARI_CAP_NXTFN)); + printf(" Control register: 0x%08x\n", ctl); + onoff("MVFC Function Groups Enable", reg, PCI_ARI_CTL_M); + onoff("ACS Function Groups Enable", reg, PCI_ARI_CTL_A); + printf(" Function Group: %u\n", + (unsigned int)__SHIFTOUT(reg, PCI_ARI_CTL_FUNCGRP)); +} + +static void +pci_conf_print_ats_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, cap, ctl; + unsigned int num; + + printf("\n Address Translation Services\n"); + + reg = regs[o2i(extcapoff + PCI_ARI_CAP)]; + cap = reg & 0xffff; + ctl = reg >> 16; + printf(" Capability register: 0x%04x\n", cap); + num = __SHIFTOUT(reg, PCI_ATS_CAP_INVQDEPTH); + if (num == 0) + num = 32; + printf(" Invalidate Queue Depth: %u\n", num); + onoff("Page Aligned Request", reg, PCI_ATS_CAP_PALIGNREQ); + + printf(" Control register: 0x%04x\n", ctl); + printf(" Smallest Translation Unit: %u\n", + (unsigned int)__SHIFTOUT(reg, PCI_ATS_CTL_STU)); + onoff("Enable", reg, PCI_ATS_CTL_EN); +} + +static void +pci_conf_print_sernum_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t lo, hi; + + printf("\n Device Serial Number Register\n"); + + lo = regs[o2i(extcapoff + PCI_SERIAL_LOW)]; + hi = regs[o2i(extcapoff + PCI_SERIAL_HIGH)]; + printf(" Serial Number: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + hi >> 24, (hi >> 16) & 0xff, (hi >> 8) & 0xff, hi & 0xff, + lo >> 24, (lo >> 16) & 0xff, (lo >> 8) & 0xff, lo & 0xff); +} + +static void +pci_conf_print_sriov_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + char buf[sizeof("99999 MB")]; + pcireg_t reg; + pcireg_t total_vfs; + int i; + bool first; + + printf("\n Single Root IO Virtualization Register\n"); + + reg = regs[o2i(extcapoff + PCI_SRIOV_CAP)]; + printf(" Capabilities register: 0x%08x\n", reg); + onoff("VF Migration Capable", reg, PCI_SRIOV_CAP_VF_MIGRATION); + onoff("ARI Capable Hierarchy Preserved", reg, + PCI_SRIOV_CAP_ARI_CAP_HIER_PRESERVED); + if (reg & PCI_SRIOV_CAP_VF_MIGRATION) { + printf(" VF Migration Interrupt Message Number: 0x%u\n", + (pcireg_t)__SHIFTOUT(reg, + PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N)); + } + + reg = regs[o2i(extcapoff + PCI_SRIOV_CTL)] & 0xffff; + printf(" Control register: 0x%04x\n", reg); + onoff("VF Enable", reg, PCI_SRIOV_CTL_VF_ENABLE); + onoff("VF Migration Enable", reg, PCI_SRIOV_CTL_VF_MIGRATION_SUPPORT); + onoff("VF Migration Interrupt Enable", reg, + PCI_SRIOV_CTL_VF_MIGRATION_INT_ENABLE); + onoff("VF Memory Space Enable", reg, PCI_SRIOV_CTL_VF_MSE); + onoff("ARI Capable Hierarchy", reg, PCI_SRIOV_CTL_ARI_CAP_HIER); + + reg = regs[o2i(extcapoff + PCI_SRIOV_STA)] >> 16; + printf(" Status register: 0x%04x\n", reg); + onoff("VF Migration Status", reg, PCI_SRIOV_STA_VF_MIGRATION); + + reg = regs[o2i(extcapoff + PCI_SRIOV_INITIAL_VFS)] & 0xffff; + printf(" InitialVFs register: 0x%04x\n", reg); + total_vfs = reg = regs[o2i(extcapoff + PCI_SRIOV_TOTAL_VFS)] >> 16; + printf(" TotalVFs register: 0x%04x\n", reg); + reg = regs[o2i(extcapoff + PCI_SRIOV_NUM_VFS)] & 0xffff; + printf(" NumVFs register: 0x%04x\n", reg); + + reg = regs[o2i(extcapoff + PCI_SRIOV_FUNC_DEP_LINK)] >> 16; + printf(" Function Dependency Link register: 0x%04x\n", reg); + + reg = regs[o2i(extcapoff + PCI_SRIOV_VF_OFF)] & 0xffff; + printf(" First VF Offset register: 0x%04x\n", reg); + reg = regs[o2i(extcapoff + PCI_SRIOV_VF_STRIDE)] >> 16; + printf(" VF Stride register: 0x%04x\n", reg); + + reg = regs[o2i(extcapoff + PCI_SRIOV_PAGE_CAP)]; + printf(" Supported Page Sizes register: 0x%08x\n", reg); + printf(" Supported Page Size:"); + for (i = 0, first = true; i < 32; i++) { + if (reg & __BIT(i)) { +#ifdef _KERNEL + format_bytes(buf, sizeof(buf), 1LL << (i + 12)); +#else + humanize_number(buf, sizeof(buf), 1LL << (i + 12), "B", + HN_AUTOSCALE, 0); +#endif + printf("%s %s", first ? "" : ",", buf); + first = false; + } + } + printf("\n"); + + reg = regs[o2i(extcapoff + PCI_SRIOV_PAGE_SIZE)]; + printf(" System Page Sizes register: 0x%08x\n", reg); + printf(" Page Size: "); + if (reg != 0) { +#ifdef _KERNEL + format_bytes(buf, sizeof(buf), 1LL << (ffs(reg) + 12)); +#else + humanize_number(buf, sizeof(buf), 1LL << (ffs(reg) + 12), "B", + HN_AUTOSCALE, 0); +#endif + printf("%s", buf); + } else { + printf("unknown"); + } + printf("\n"); + + for (i = 0; i < 6; i++) { + reg = regs[o2i(extcapoff + PCI_SRIOV_BAR(i))]; + printf(" VF BAR%d register: 0x%08x\n", i, reg); + } + + if (total_vfs > 0) { + reg = regs[o2i(extcapoff + PCI_SRIOV_VF_MIG_STA_AR)]; + printf(" VF Migration State Array Offset register: 0x%08x\n", + reg); + printf(" VF Migration State Offset: 0x%08x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_SRIOV_VF_MIG_STA_OFFSET)); + i = __SHIFTOUT(reg, PCI_SRIOV_VF_MIG_STA_BIR); + printf(" VF Migration State BIR: "); + if (i >= 0 && i <= 5) { + printf("BAR%d", i); + } else { + printf("unknown BAR (%d)", i); + } + printf("\n"); + } +} + +/* XXX pci_conf_print_mriov_cap */ +/* XXX pci_conf_print_multicast_cap */ + +static void +pci_conf_print_page_req_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, ctl, sta; + + printf("\n Page Request\n"); + + reg = regs[o2i(extcapoff + PCI_PAGE_REQ_CTL)]; + ctl = reg & 0xffff; + sta = reg >> 16; + printf(" Control Register: 0x%04x\n", ctl); + onoff("Enalbe", reg, PCI_PAGE_REQ_CTL_E); + onoff("Reset", reg, PCI_PAGE_REQ_CTL_R); + + printf(" Status Register: 0x%04x\n", sta); + onoff("Response Failure", reg, PCI_PAGE_REQ_STA_RF); + onoff("Unexpected Page Request Group Index", reg, + PCI_PAGE_REQ_STA_UPRGI); + onoff("Stopped", reg, PCI_PAGE_REQ_STA_S); + + reg = regs[o2i(extcapoff + PCI_PAGE_REQ_OUTSTCAPA)]; + printf(" Outstanding Page Request Capacity: %u\n", reg); + reg = regs[o2i(extcapoff + PCI_PAGE_REQ_OUTSTALLOC)]; + printf(" Outstanding Page Request Allocation: %u\n", reg); +} + +/* XXX pci_conf_print_amd_cap */ +/* XXX pci_conf_print_resize_bar_cap */ +/* XXX pci_conf_print_dpa_cap */ + +static const char * +pci_conf_print_tph_req_cap_sttabloc(unsigned char val) +{ + + switch (val) { + case 0x0: + return "Not Present"; + case 0x1: + return "in the TPH Requester Capability Structure"; + case 0x2: + return "in the MSI-X Table"; + default: + return "Unknown"; + } +} + +static void +pci_conf_print_tph_req_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + int size, i, j; + + printf("\n TPH Requester Extended Capability\n"); + + reg = regs[o2i(extcapoff + PCI_TPH_REQ_CAP)]; + printf(" TPH Requester Capabililty register: 0x%08x\n", reg); + onoff("No ST Mode Supported", reg, PCI_TPH_REQ_CAP_NOST); + onoff("Interrupt Vector Mode Supported", reg, PCI_TPH_REQ_CAP_INTVEC); + onoff("Device Specific Mode Supported", reg, PCI_TPH_REQ_CAP_DEVSPEC); + onoff("Extend TPH Reqester Supported", reg, PCI_TPH_REQ_CAP_XTPHREQ); + printf(" ST Table Location: %s\n", + pci_conf_print_tph_req_cap_sttabloc( + (unsigned char)__SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLLOC))); + size = __SHIFTOUT(reg, PCI_TPH_REQ_CAP_STTBLSIZ) + 1; + printf(" ST Table Size: %d\n", size); + for (i = 0; i < size ; i += 2) { + reg = regs[o2i(extcapoff + PCI_TPH_REQ_STTBL + i / 2)]; + for (j = 0; j < 2 ; j++) { + uint16_t entry = reg; + + if (j != 0) + entry >>= 16; + entry &= 0xffff; + printf(" TPH ST Table Entry (%d): 0x%04hx\n", + i + j, entry); + } + } +} + +static void +pci_conf_print_ltr_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + + printf("\n Latency Tolerance Reporting\n"); + reg = regs[o2i(extcapoff + PCI_LTR_MAXSNOOPLAT)] & 0xffff; + printf(" Max Snoop Latency Register: 0x%04x\n", reg); + printf(" Max Snoop LatencyValue: %u\n", + (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_VAL)); + printf(" Max Snoop LatencyScale: %uns\n", + PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXSNOOPLAT_SCALE))); + reg = regs[o2i(extcapoff + PCI_LTR_MAXNOSNOOPLAT)] >> 16; + printf(" Max No-Snoop Latency Register: 0x%04x\n", reg); + printf(" Max No-Snoop LatencyValue: %u\n", + (pcireg_t)__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_VAL)); + printf(" Max No-Snoop LatencyScale: %uns\n", + PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_LTR_MAXNOSNOOPLAT_SCALE))); +} + +static void +pci_conf_print_sec_pcie_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + int pcie_capoff; + pcireg_t reg; + int i, maxlinkwidth; + + printf("\n Secondary PCI Express Register\n"); + + reg = regs[o2i(extcapoff + PCI_SECPCIE_LCTL3)]; + printf(" Link Control 3 register: 0x%08x\n", reg); + onoff("Perform Equalization", reg, PCI_SECPCIE_LCTL3_PERFEQ); + onoff("Link Equalization Request Interrupt Enable", + reg, PCI_SECPCIE_LCTL3_LINKEQREQ_IE); + + reg = regs[o2i(extcapoff + PCI_SECPCIE_LANEERR_STA)]; + printf(" Lane Error Status register: 0x%08x\n", reg); + + /* Get Max Link Width */ + if (pci_conf_find_cap(regs, capoff, PCI_CAP_PCIEXPRESS, &pcie_capoff)){ + reg = regs[o2i(pcie_capoff + PCIE_LCAP)]; + maxlinkwidth = __SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH); + } else { + printf("error: falied to get PCIe capablity\n"); + return; + } + for (i = 0; i < maxlinkwidth; i++) { + reg = regs[o2i(extcapoff + PCI_SECPCIE_EQCTL(i))]; + if (i % 2 != 0) + reg >>= 16; + else + reg &= 0xffff; + printf(" Equalization Control Register (Link %d): %04x\n", + i, reg); + printf(" Downstream Port Transmit Preset: 0x%x\n", + (pcireg_t)__SHIFTOUT(reg, + PCI_SECPCIE_EQCTL_DP_XMIT_PRESET)); + printf(" Downstream Port Receive Hint: 0x%x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_SECPCIE_EQCTL_DP_RCV_HINT)); + printf(" Upstream Port Transmit Preset: 0x%x\n", + (pcireg_t)__SHIFTOUT(reg, + PCI_SECPCIE_EQCTL_UP_XMIT_PRESET)); + printf(" Upstream Port Receive Hint: 0x%x\n", + (pcireg_t)__SHIFTOUT(reg, PCI_SECPCIE_EQCTL_UP_RCV_HINT)); + } +} + +/* XXX pci_conf_print_pmux_cap */ + +static void +pci_conf_print_pasid_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, cap, ctl; + unsigned int num; + + printf("\n Process Address Space ID\n"); + + reg = regs[o2i(extcapoff + PCI_PASID_CAP)]; + cap = reg & 0xffff; + ctl = reg >> 16; + printf(" PASID Capability Register: 0x%04x\n", cap); + onoff("Execute Permission Supported", reg, PCI_PASID_CAP_XPERM); + onoff("Privileged Mode Supported", reg, PCI_PASID_CAP_PRIVMODE); + num = (1 << __SHIFTOUT(reg, PCI_PASID_CAP_MAXPASIDW)) - 1; + printf(" Max PASID Width: %u\n", num); + + printf(" PASID Control Register: 0x%04x\n", ctl); + onoff("PASID Enable", reg, PCI_PASID_CTL_PASID_EN); + onoff("Execute Permission Enable", reg, PCI_PASID_CTL_XPERM_EN); + onoff("Privileged Mode Enable", reg, PCI_PASID_CTL_PRIVMODE_EN); +} + +static void +pci_conf_print_lnr_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg, cap, ctl; + unsigned int num; + + printf("\n LN Requester\n"); + + reg = regs[o2i(extcapoff + PCI_LNR_CAP)]; + cap = reg & 0xffff; + ctl = reg >> 16; + printf(" LNR Capability register: 0x%04x\n", cap); + onoff("LNR-64 Supported", reg, PCI_LNR_CAP_64); + onoff("LNR-128 Supported", reg, PCI_LNR_CAP_128); + num = 1 << __SHIFTOUT(reg, PCI_LNR_CAP_REGISTMAX); + printf(" LNR Registration MAX: %u\n", num); + + printf(" LNR Control register: 0x%04x\n", ctl); + onoff("LNR Enable", reg, PCI_LNR_CTL_EN); + onoff("LNR CLS", reg, PCI_LNR_CTL_CLS); + num = 1 << __SHIFTOUT(reg, PCI_LNR_CTL_REGISTLIM); + printf(" LNR Registration Limit: %u\n", num); +} + +/* XXX pci_conf_print_dpc_cap */ + +static int +pci_conf_l1pm_cap_tposcale(unsigned char scale) +{ + + /* Return scale in us */ + switch (scale) { + case 0x0: + return 2; + case 0x1: + return 10; + case 0x2: + return 100; + default: + return -1; + } +} + +static void +pci_conf_print_l1pm_cap(const pcireg_t *regs, int capoff, int extcapoff) +{ + pcireg_t reg; + int scale, val; + + printf("\n L1 PM Substates\n"); + + reg = regs[o2i(extcapoff + PCI_L1PM_CAP)]; + printf(" L1 PM Substates Capability register: 0x%08x\n", reg); + onoff("PCI-PM L1.2 Supported", reg, PCI_L1PM_CAP_PCIPM12); + onoff("PCI-PM L1.1 Supported", reg, PCI_L1PM_CAP_PCIPM11); + onoff("ASPM L1.2 Supported", reg, PCI_L1PM_CAP_ASPM12); + onoff("ASPM L1.1 Supported", reg, PCI_L1PM_CAP_ASPM11); + onoff("L1 PM Substates Supported", reg, PCI_L1PM_CAP_L1PM); + printf(" Port Common Mode Restore Time: %uus\n", + (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CAP_PCMRT)); + scale = pci_conf_l1pm_cap_tposcale( + __SHIFTOUT(reg, PCI_L1PM_CAP_PTPOSCALE)); + val = __SHIFTOUT(reg, PCI_L1PM_CAP_PTPOVAL); + printf(" Port T_POWER_ON: "); + if (scale == -1) + printf("unknown\n"); + else + printf("%dus\n", val * scale); + + reg = regs[o2i(extcapoff + PCI_L1PM_CTL1)]; + printf(" L1 PM Substates Control register 1: 0x%08x\n", reg); + onoff("PCI-PM L1.2 Enable", reg, PCI_L1PM_CTL1_PCIPM12_EN); + onoff("PCI-PM L1.1 Enable", reg, PCI_L1PM_CTL1_PCIPM11_EN); + onoff("ASPM L1.2 Enable", reg, PCI_L1PM_CTL1_ASPM12_EN); + onoff("ASPM L1.1 Enable", reg, PCI_L1PM_CTL1_ASPM11_EN); + printf(" Common Mode Restore Time: %uus\n", + (unsigned int)__SHIFTOUT(reg, PCI_L1PM_CTL1_CMRT)); + scale = PCI_LTR_SCALETONS(__SHIFTOUT(reg, PCI_L1PM_CTL1_LTRTHSCALE)); + val = __SHIFTOUT(reg, PCI_L1PM_CTL1_LTRTHVAL); + printf(" LTR L1.2 THRESHOLD: %dus\n", val * scale); + + reg = regs[o2i(extcapoff + PCI_L1PM_CTL2)]; + printf(" L1 PM Substates Control register 2: 0x%08x\n", reg); + scale = pci_conf_l1pm_cap_tposcale( + __SHIFTOUT(reg, PCI_L1PM_CTL2_TPOSCALE)); + val = __SHIFTOUT(reg, PCI_L1PM_CTL2_TPOVAL); + printf(" T_POWER_ON: "); + if (scale == -1) + printf("unknown\n"); + else + printf("%dus\n", val * scale); +} + +/* XXX pci_conf_print_ptm_cap */ +/* XXX pci_conf_print_mpcie_cap */ +/* XXX pci_conf_print_frsq_cap */ +/* XXX pci_conf_print_rtr_cap */ +/* XXX pci_conf_print_desigvndsp_cap */ + +#undef MS +#undef SM +#undef RW + +static struct { + pcireg_t cap; + const char *name; + void (*printfunc)(const pcireg_t *, int, int); +} pci_extcaptab[] = { + { 0, "reserved", + NULL }, + { PCI_EXTCAP_AER, "Advanced Error Reporting", + pci_conf_print_aer_cap }, + { PCI_EXTCAP_VC, "Virtual Channel", + pci_conf_print_vc_cap }, + { PCI_EXTCAP_SERNUM, "Device Serial Number", + pci_conf_print_sernum_cap }, + { PCI_EXTCAP_PWRBDGT, "Power Budgeting", + pci_conf_print_pwrbdgt_cap }, + { PCI_EXTCAP_RCLINK_DCL,"Root Complex Link Declaration", + pci_conf_print_rclink_dcl_cap }, + { PCI_EXTCAP_RCLINK_CTL,"Root Complex Internal Link Control", + NULL }, + { PCI_EXTCAP_RCEC_ASSOC,"Root Complex Event Collector Association", + pci_conf_print_rcec_assoc_cap }, + { PCI_EXTCAP_MFVC, "Multi-Function Virtual Channel", + NULL }, + { PCI_EXTCAP_VC2, "Virtual Channel", + NULL }, + { PCI_EXTCAP_RCRB, "RCRB Header", + NULL }, + { PCI_EXTCAP_VENDOR, "Vendor Unique", + NULL }, + { PCI_EXTCAP_CAC, "Configuration Access Correction", + NULL }, + { PCI_EXTCAP_ACS, "Access Control Services", + pci_conf_print_acs_cap }, + { PCI_EXTCAP_ARI, "Alternative Routing-ID Interpretation", + pci_conf_print_ari_cap }, + { PCI_EXTCAP_ATS, "Address Translation Services", + pci_conf_print_ats_cap }, + { PCI_EXTCAP_SRIOV, "Single Root IO Virtualization", + pci_conf_print_sriov_cap }, + { PCI_EXTCAP_MRIOV, "Multiple Root IO Virtualization", + NULL }, + { PCI_EXTCAP_MULTICAST, "Multicast", + NULL }, + { PCI_EXTCAP_PAGE_REQ, "Page Request", + pci_conf_print_page_req_cap }, + { PCI_EXTCAP_AMD, "Reserved for AMD", + NULL }, + { PCI_EXTCAP_RESIZE_BAR,"Resizable BAR", + NULL }, + { PCI_EXTCAP_DPA, "Dynamic Power Allocation", + NULL }, + { PCI_EXTCAP_TPH_REQ, "TPH Requester", + pci_conf_print_tph_req_cap }, + { PCI_EXTCAP_LTR, "Latency Tolerance Reporting", + pci_conf_print_ltr_cap }, + { PCI_EXTCAP_SEC_PCIE, "Secondary PCI Express", + pci_conf_print_sec_pcie_cap }, + { PCI_EXTCAP_PMUX, "Protocol Multiplexing", + NULL }, + { PCI_EXTCAP_PASID, "Process Address Space ID", + pci_conf_print_pasid_cap }, + { PCI_EXTCAP_LN_REQ, "LN Requester", + pci_conf_print_lnr_cap }, + { PCI_EXTCAP_DPC, "Downstream Port Containment", + NULL }, + { PCI_EXTCAP_L1PM, "L1 PM Substates", + pci_conf_print_l1pm_cap }, + { PCI_EXTCAP_PTM, "Precision Time Management", + NULL }, + { PCI_EXTCAP_MPCIE, "M-PCIe", + NULL }, + { PCI_EXTCAP_FRSQ, "Function Reading Status Queueing", + NULL }, + { PCI_EXTCAP_RTR, "Readiness Time Reporting", + NULL }, + { PCI_EXTCAP_DESIGVNDSP, "Designated Vendor-Specific", + NULL }, +}; + +static int +pci_conf_find_extcap(const pcireg_t *regs, int capoff, unsigned int capid, + int *offsetp) +{ + int off; + pcireg_t rval; + + for (off = PCI_EXTCAPLIST_BASE; + off != 0; + off = PCI_EXTCAPLIST_NEXT(rval)) { + rval = regs[o2i(off)]; + if (capid == PCI_EXTCAPLIST_CAP(rval)) { + if (offsetp != NULL) + *offsetp = off; + return 1; + } + } + return 0; +} + +static void +pci_conf_print_extcaplist( +#ifdef _KERNEL + pci_chipset_tag_t pc, pcitag_t tag, +#endif + const pcireg_t *regs, int capoff) +{ + int off; + pcireg_t foundcap; + pcireg_t rval; + bool foundtable[__arraycount(pci_extcaptab)]; + unsigned int i; + + /* Check Extended capability structure */ + off = PCI_EXTCAPLIST_BASE; + rval = regs[o2i(off)]; + if (rval == 0xffffffff || rval == 0) + return; + + /* Clear table */ + for (i = 0; i < __arraycount(pci_extcaptab); i++) + foundtable[i] = false; + + /* Print extended capability register's offset and the type first */ + for (;;) { + printf(" Extended Capability Register at 0x%02x\n", off); + + foundcap = PCI_EXTCAPLIST_CAP(rval); + printf(" type: 0x%04x (", foundcap); + if (foundcap < __arraycount(pci_extcaptab)) { + printf("%s)\n", pci_extcaptab[foundcap].name); + /* Mark as found */ + foundtable[foundcap] = true; + } else + printf("unknown)\n"); + printf(" version: %d\n", PCI_EXTCAPLIST_VERSION(rval)); + + off = PCI_EXTCAPLIST_NEXT(rval); + if (off == 0) + break; + rval = regs[o2i(off)]; + } + + /* + * And then, print the detail of each capability registers + * in capability value's order. + */ + for (i = 0; i < __arraycount(pci_extcaptab); i++) { + if (foundtable[i] == false) + continue; + + /* + * The type was found. Search capability list again and + * print all capabilities that the capabiliy type is + * the same. + */ + if (pci_conf_find_extcap(regs, capoff, i, &off) == 0) + continue; + rval = regs[o2i(off)]; + if ((PCI_EXTCAPLIST_VERSION(rval) <= 0) + || (pci_extcaptab[i].printfunc == NULL)) + continue; + + pci_extcaptab[i].printfunc(regs, capoff, off); + + } } /* Print the Secondary Status Register. */ @@ -2216,8 +3398,8 @@ pci_conf_print_type2( printf(" Capability list pointer: 0x%02x\n", PCI_CAPLIST_PTR(rval)); else - printf(" Reserved @ 0x14: 0x%04" PRIxMAX "\n", - __SHIFTOUT(rval, __BITS(15, 0))); + printf(" Reserved @ 0x14: 0x%04x\n", + (pcireg_t)__SHIFTOUT(rval, __BITS(15, 0))); pci_conf_print_ssr(__SHIFTOUT(rval, __BITS(31, 16))); rval = regs[o2i(PCI_BRIDGE_BUS_REG)]; @@ -2306,7 +3488,7 @@ pci_conf_print( #endif ) { - pcireg_t regs[o2i(256)]; + pcireg_t regs[o2i(PCI_EXTCONF_SIZE)]; int off, capoff, endoff, hdrtype; const char *type_name; #ifdef _KERNEL @@ -2319,7 +3501,7 @@ pci_conf_print( printf("PCI configuration registers:\n"); - for (off = 0; off < 256; off += 4) { + for (off = 0; off < PCI_EXTCONF_SIZE; off += 4) { #ifdef _KERNEL regs[o2i(off)] = pci_conf_read(pc, tag, off); #else @@ -2409,7 +3591,7 @@ pci_conf_print( /* device-dependent header */ printf(" Device-dependent header:\n"); - pci_conf_print_regs(regs, endoff, 256); + pci_conf_print_regs(regs, endoff, PCI_CONF_SIZE); printf("\n"); #ifdef _KERNEL if (printfn) @@ -2418,4 +3600,19 @@ pci_conf_print( printf(" Don't know how to pretty-print device-dependent header.\n"); printf("\n"); #endif /* _KERNEL */ + + if (regs[o2i(PCI_EXTCAPLIST_BASE)] == 0xffffffff || + regs[o2i(PCI_EXTCAPLIST_BASE)] == 0) + return; + +#ifdef _KERNEL + pci_conf_print_extcaplist(pc, tag, regs, capoff); +#else + pci_conf_print_extcaplist(regs, capoff); +#endif + printf("\n"); + + /* Extended Configuration Space, if present */ + printf(" Extended Configuration Space:\n"); + pci_conf_print_regs(regs, PCI_EXTCAPLIST_BASE, PCI_EXTCONF_SIZE); } diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index 90911e3e5be..d89c6e7da74 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcireg.h,v 1.103 2015/07/27 15:46:03 msaitoh Exp $ */ +/* $NetBSD: pcireg.h,v 1.104 2015/10/02 05:22:53 msaitoh Exp $ */ /* * Copyright (c) 1995, 1996, 1999, 2000 @@ -1319,7 +1319,7 @@ struct pci_rom { #define PCI32_DMA_BOUNCE_THRESHOLD 0x100000000ULL /* - * PCI-X 2.0 Extended Capability List + * PCI-X 2.0/ PCI-express Extended Capability List */ #define PCI_EXTCAPLIST_BASE 0x100 @@ -1328,6 +1328,502 @@ struct pci_rom { #define PCI_EXTCAPLIST_VERSION(ecr) (((ecr) >> 16) & 0xf) #define PCI_EXTCAPLIST_NEXT(ecr) (((ecr) >> 20) & 0xfff) +/* Extended Capability Identification Numbers */ + +#define PCI_EXTCAP_AER 0x0001 /* Advanced Error Reporting */ +#define PCI_EXTCAP_VC 0x0002 /* Virtual Channel if MFVC Ext Cap not set */ +#define PCI_EXTCAP_SERNUM 0x0003 /* Device Serial Number */ +#define PCI_EXTCAP_PWRBDGT 0x0004 /* Power Budgeting */ +#define PCI_EXTCAP_RCLINK_DCL 0x0005 /* Root Complex Link Declaration */ +#define PCI_EXTCAP_RCLINK_CTL 0x0006 /* Root Complex Internal Link Control */ +#define PCI_EXTCAP_RCEC_ASSOC 0x0007 /* Root Complex Event Collector Association */ +#define PCI_EXTCAP_MFVC 0x0008 /* Multi-Function Virtual Channel */ +#define PCI_EXTCAP_VC2 0x0009 /* Virtual Channel if MFVC Ext Cap set */ +#define PCI_EXTCAP_RCRB 0x000a /* RCRB Header */ +#define PCI_EXTCAP_VENDOR 0x000b /* Vendor Unique */ +#define PCI_EXTCAP_CAC 0x000c /* Configuration Access Correction -- obsolete */ +#define PCI_EXTCAP_ACS 0x000d /* Access Control Services */ +#define PCI_EXTCAP_ARI 0x000e /* Alternative Routing-ID Interpretation */ +#define PCI_EXTCAP_ATS 0x000f /* Address Translation Services */ +#define PCI_EXTCAP_SRIOV 0x0010 /* Single Root IO Virtualization */ +#define PCI_EXTCAP_MRIOV 0x0011 /* Multiple Root IO Virtualization */ +#define PCI_EXTCAP_MULTICAST 0x0012 /* Multicast */ +#define PCI_EXTCAP_PAGE_REQ 0x0013 /* Page Request */ +#define PCI_EXTCAP_AMD 0x0014 /* Reserved for AMD */ +#define PCI_EXTCAP_RESIZE_BAR 0x0015 /* Resizable BAR */ +#define PCI_EXTCAP_DPA 0x0016 /* Dynamic Power Allocation */ +#define PCI_EXTCAP_TPH_REQ 0x0017 /* TPH Requester */ +#define PCI_EXTCAP_LTR 0x0018 /* Latency Tolerance Reporting */ +#define PCI_EXTCAP_SEC_PCIE 0x0019 /* Secondary PCI Express */ +#define PCI_EXTCAP_PMUX 0x001a /* Protocol Multiplexing */ +#define PCI_EXTCAP_PASID 0x001b /* Process Address Space ID */ +#define PCI_EXTCAP_LN_REQ 0x001c /* LN Requester */ +#define PCI_EXTCAP_DPC 0x001d /* Downstream Port Containment */ +#define PCI_EXTCAP_L1PM 0x001e /* L1 PM Substates */ +#define PCI_EXTCAP_PTM 0x001f /* Precision Time Management */ +#define PCI_EXTCAP_MPCIE 0x0020 /* M-PCIe */ +#define PCI_EXTCAP_FRSQ 0x0021 /* Function Reading Status Queueing */ +#define PCI_EXTCAP_RTR 0x0022 /* Readiness Time Reporting */ +#define PCI_EXTCAP_DESIGVNDSP 0x0023 /* Designated Vendor-Specific */ + +/* + * Extended capability ID: 0x0001 + * Advanced Error Reporting + */ +#define PCI_AER_UC_STATUS 0x04 /* Uncorrectable Error Status Register */ +#define PCI_AER_UC_UNDEFINED __BIT(0) +#define PCI_AER_UC_DL_PROTOCOL_ERROR __BIT(4) +#define PCI_AER_UC_SURPRISE_DOWN_ERROR __BIT(5) +#define PCI_AER_UC_POISONED_TLP __BIT(12) +#define PCI_AER_UC_FC_PROTOCOL_ERROR __BIT(13) +#define PCI_AER_UC_COMPLETION_TIMEOUT __BIT(14) +#define PCI_AER_UC_COMPLETER_ABORT __BIT(15) +#define PCI_AER_UC_UNEXPECTED_COMPLETION __BIT(16) +#define PCI_AER_UC_RECEIVER_OVERFLOW __BIT(17) +#define PCI_AER_UC_MALFORMED_TLP __BIT(18) +#define PCI_AER_UC_ECRC_ERROR __BIT(19) +#define PCI_AER_UC_UNSUPPORTED_REQUEST_ERROR __BIT(20) +#define PCI_AER_UC_ACS_VIOLATION __BIT(21) +#define PCI_AER_UC_INTERNAL_ERROR __BIT(22) +#define PCI_AER_UC_MC_BLOCKED_TLP __BIT(23) +#define PCI_AER_UC_ATOMIC_OP_EGRESS_BLOCKED __BIT(24) +#define PCI_AER_UC_TLP_PREFIX_BLOCKED_ERROR __BIT(25) +#define PCI_AER_UC_MASK 0x08 /* Uncorrectable Error Mask Register */ + /* Shares bits with UC_STATUS */ +#define PCI_AER_UC_SEVERITY 0x0c /* Uncorrectable Error Severity Register */ + /* Shares bits with UC_STATUS */ +#define PCI_AER_COR_STATUS 0x10 /* Correctable Error Status Register */ +#define PCI_AER_COR_RECEIVER_ERROR __BIT(0) +#define PCI_AER_COR_BAD_TLP __BIT(6) +#define PCI_AER_COR_BAD_DLLP __BIT(7) +#define PCI_AER_COR_REPLAY_NUM_ROLLOVER __BIT(8) +#define PCI_AER_COR_REPLAY_TIMER_TIMEOUT __BIT(12) +#define PCI_AER_COR_ADVISORY_NF_ERROR __BIT(13) +#define PCI_AER_COR_INTERNAL_ERROR __BIT(14) +#define PCI_AER_COR_HEADER_LOG_OVERFLOW __BIT(15) +#define PCI_AER_COR_MASK 0x14 /* Correctable Error Mask Register */ + /* Shares bits with COR_STATUS */ +#define PCI_AER_CAP_CONTROL 0x18 /* Advanced Error Capabilities and Control Register */ +#define PCI_AER_FIRST_ERROR_PTR __BITS(4, 0) +#define PCI_AER_FIRST_ERROR_PTR_S 0 +#define PCI_AER_FIRST_ERROR_PTR_M 0x1f +#define PCI_AER_ECRC_GEN_CAPABLE __BIT(5) +#define PCI_AER_ECRC_GEN_ENABLE __BIT(6) +#define PCI_AER_ECRC_CHECK_CAPABLE __BIT(7) +#define PCI_AER_ECRC_CHECK_ENABLE __BIT(8) +#define PCI_AER_MULT_HDR_CAPABLE __BIT(9) +#define PCI_AER_MULT_HDR_ENABLE __BIT(10) +#define PCI_AER_TLP_PREFIX_LOG_PRESENT __BIT(11) +#define PCI_AER_HEADER_LOG 0x1c /* Header Log Register */ +#define PCI_AER_ROOTERR_CMD 0x2c /* Root Error Command Register */ + /* Only for root complex ports */ +#define PCI_AER_ROOTERR_COR_ENABLE __BIT(0) +#define PCI_AER_ROOTERR_NF_ENABLE __BIT(1) +#define PCI_AER_ROOTERR_F_ENABLE __BIT(2) +#define PCI_AER_ROOTERR_STATUS 0x30 /* Root Error Status Register */ + /* Only for root complex ports */ +#define PCI_AER_ROOTERR_COR_ERR __BIT(0) +#define PCI_AER_ROOTERR_MULTI_COR_ERR __BIT(1) +#define PCI_AER_ROOTERR_UC_ERR __BIT(2) +#define PCI_AER_ROOTERR_MULTI_UC_ERR __BIT(3) +#define PCI_AER_ROOTERR_FIRST_UC_FATAL __BIT(4) +#define PCI_AER_ROOTERR_NF_ERR __BIT(5) +#define PCI_AER_ROOTERR_F_ERR __BIT(6) +#define PCI_AER_ROOTERR_INT_MESSAGE __BITS(31, 27) +#define PCI_AER_ROOTERR_INT_MESSAGE_S 27 +#define PCI_AER_ROOTERR_INT_MESSAGE_M 0x1f +#define PCI_AER_ERRSRC_ID 0x34 /* Error Source Identification Register */ +#define PCI_AER_ERRSRC_ID_ERR_COR __BITS(15, 0) +#define PCI_AER_ERRSRC_ID_ERR_COR_S 0 +#define PCI_AER_ERRSRC_ID_ERR_COR_M 0xffff +#define PCI_AER_ERRSRC_ID_ERR_UC __BITS(31, 16) +#define PCI_AER_ERRSRC_ID_ERR_UC_S 16 +#define PCI_AER_ERRSRC_ID_ERR_UC_M 0xffff + /* Only for root complex ports */ +#define PCI_AER_TLP_PREFIX_LOG 0x38 /*TLP Prefix Log Register */ + /* Only for TLP prefix functions */ + +/* + * Extended capability ID: 0x0002, 0x0009 + * Virtual Channel + */ +#define PCI_VC_CAP1 0x04 /* Port VC Capability Register 1 */ +#define PCI_VC_CAP1_EXT_COUNT __BITS(2, 0) +#define PCI_VC_CAP1_EXT_COUNT_S 0 +#define PCI_VC_CAP1_EXT_COUNT_M 0x7 +#define PCI_VC_CAP1_LOWPRI_EXT_COUNT __BITS(6, 4) +#define PCI_VC_CAP1_LOWPRI_EXT_COUNT_S 4 +#define PCI_VC_CAP1_LOWPRI_EXT_COUNT_M 0x7 +#define PCI_VC_CAP1_REFCLK __BITS(9, 8) +#define PCI_VC_CAP1_REFCLK_S 8 +#define PCI_VC_CAP1_REFCLK_M 0x3 +#define PCI_VC_CAP1_REFCLK_100NS 0x0 +#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE __BITS(11, 10) +#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE_S 10 +#define PCI_VC_CAP1_PORT_ARB_TABLE_SIZE_M 0x3 +#define PCI_VC_CAP2 0x08 /* Port VC Capability Register 2 */ +#define PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME __BIT(0) +#define PCI_VC_CAP2_ARB_CAP_WRR_32 __BIT(1) +#define PCI_VC_CAP2_ARB_CAP_WRR_64 __BIT(2) +#define PCI_VC_CAP2_ARB_CAP_WRR_128 __BIT(3) +#define PCI_VC_CAP2_ARB_TABLE_OFFSET __BITS(31, 24) +#define PCI_VC_CAP2_ARB_TABLE_OFFSET_S 24 +#define PCI_VC_CAP2_ARB_TABLE_OFFSET_M 0xff +#define PCI_VC_CONTROL 0x0c /* Port VC Control Register (16bit) */ +#define PCI_VC_CONTROL_LOAD_VC_ARB_TABLE __BIT(0) +#define PCI_VC_CONTROL_VC_ARB_SELECT __BITS(3, 1) +#define PCI_VC_CONTROL_VC_ARB_SELECT_S 1 +#define PCI_VC_CONTROL_VC_ARB_SELECT_M 0x7 +#define PCI_VC_STATUS 0x0e /* Port VC Status Register (16bit) */ +#define PCI_VC_STATUS_LOAD_VC_ARB_TABLE __BIT(0) +#define PCI_VC_RESOURCE_CAP(n) (0x10 + ((n) * 0x0c)) /* VC Resource Capability Register */ +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME __BIT(0) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32 __BIT(1) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64 __BIT(2) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128 __BIT(3) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128 __BIT(4) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256 __BIT(5) +#define PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH __BIT(14) +#define PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS __BIT(15) +#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS __BITS(22, 16) +#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS_S 16 +#define PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS_M 0x7f +#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET __BITS(31, 24) +#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_S 24 +#define PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_M 0xff +#define PCI_VC_RESOURCE_CTL(n) (0x14 + ((n) * 0x0c)) /* VC Resource Control Register */ +#define PCI_VC_RESOURCE_CTL_TCVC_MAP __BITS(7, 0) +#define PCI_VC_RESOURCE_CTL_TCVC_MAP_S 0 +#define PCI_VC_RESOURCE_CTL_TCVC_MAP_M 0xff +#define PCI_VC_RESOURCE_CTL_LOAD_PORT_ARB_TABLE __BIT(16) +#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT __BITS(19, 17) +#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT_S 17 +#define PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT_M 0x7 +#define PCI_VC_RESOURCE_CTL_VC_ID __BITS(26, 24) +#define PCI_VC_RESOURCE_CTL_VC_ID_S 24 +#define PCI_VC_RESOURCE_CTL_VC_ID_M 0x7 +#define PCI_VC_RESOURCE_CTL_VC_ENABLE __BIT(31) +#define PCI_VC_RESOURCE_STA(n) (0x18 + ((n) * 0x0c)) /* VC Resource Status Register */ +#define PCI_VC_RESOURCE_STA_PORT_ARB_TABLE __BIT(0) +#define PCI_VC_RESOURCE_STA_VC_NEG_PENDING __BIT(1) + +/* + * Extended capability ID: 0x0003 + * Serial Number + */ +#define PCI_SERIAL_LOW 0x04 +#define PCI_SERIAL_HIGH 0x08 + +/* + * Extended capability ID: 0x0004 + * Power Budgeting + */ +#define PCI_PWRBDGT_DSEL 0x04 /* Data Select */ +#define PCI_PWRBDGT_DATA 0x08 /* Data */ +#define PCI_PWRBDGT_DATA_BASEPWR __BITS(7, 0) /* Base Power */ +#define PCI_PWRBDGT_DATA_SCALE __BITS(9, 8) /* Data Scale */ +#define PCI_PWRBDGT_PM_SUBSTAT __BITS(12, 10) /* PM Sub State */ +#define PCI_PWRBDGT_PM_STAT __BITS(14, 13) /* PM State */ +#define PCI_PWRBDGT_TYPE __BITS(17, 15) /* Type */ +#define PCI_PWRBDGT_PWRRAIL __BITS(20, 18) /* Power Rail */ +#define PCI_PWRBDGT_CAP 0x0c /* Capability */ +#define PCI_PWRBDGT_CAP_SYSALLOC __BIT(0) /* System Allocated */ + +/* + * Extended capability ID: 0x0005 + * Root Complex Link Declaration + */ +#define PCI_RCLINK_DCL_ESDESC 0x04 /* Element Self Description */ +#define PCI_RCLINK_DCL_ESDESC_ELMTYPE __BITS(3, 0) /* Element Type */ +#define PCI_RCLINK_DCL_ESDESC_NUMLINKENT __BITS(15, 8) /* Num of Link Entries*/ +#define PCI_RCLINK_DCL_ESDESC_COMPID __BITS(23, 16) /* Component ID */ +#define PCI_RCLINK_DCL_ESDESC_PORTNUM __BITS(31, 24) /* Port Number */ +#define PCI_RCLINK_DCL_LINKENTS 0x10 /* Link Entries */ +#define PCI_RCLINK_DCL_LINKDESC(x) /* Link Description */ \ + (PCI_RCLINK_DCL_LINKENTS + ((x) * 16)) +#define PCI_RCLINK_DCL_LINKDESC_LVALID __BIT(0) /* Link Valid */ +#define PCI_RCLINK_DCL_LINKDESC_LTYPE __BIT(1) /* Link Type */ +#define PCI_RCLINK_DCL_LINKDESC_ARCRBH __BIT(2) /* Associate RCRB Header */ +#define PCI_RCLINK_DCL_LINKDESC_TCOMPID __BITS(23, 16) /* Target Component ID*/ +#define PCI_RCLINK_DCL_LINKDESC_TPNUM __BITS(31, 24) /* Target Port Number */ +#define PCI_RCLINK_DCL_LINKADDR_LT0_LO(x) /* LT0: Link Address Low */ \ + (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x08) +#define PCI_RCLINK_DCL_LINKADDR_LT0_HI(x) /* LT0: Link Address High */ \ + (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x0c) +#define PCI_RCLINK_DCL_LINKADDR_LT1_LO(x) /* LT1: Config Space (low) */ \ + (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x08) +#define PCI_RCLINK_DCL_LINKADDR_LT1_N __BITS(2, 0) /* N */ +#define PCI_RCLINK_DCL_LINKADDR_LT1_FUNC __BITS(14, 12) /* Function Number */ +#define PCI_RCLINK_DCL_LINKADDR_LT1_DEV __BITS(19, 15) /* Device Number */ +#define PCI_RCLINK_DCL_LINKADDR_LT1_BUS(N) __BITS(19 + (N), 20) /* Bus Number*/ +#define PCI_RCLINK_DCL_LINKADDR_LT1_BAL(N) __BITS(31, 20 + (N)) /* BAddr(L) */ +#define PCI_RCLINK_DCL_LINKADDR_LT1_HI(x) /* LT1: Config Space Base Addr(H) */\ + (PCI_RCLINK_DCL_LINKENTS + ((x) * 16) + 0x0c) + +/* + * Extended capability ID: 0x0006 + * Root Complex Internal Link Control + */ + +/* + * Extended capability ID: 0x0007 + * Root Complex Event Collector Association + */ +#define PCI_RCEC_ASSOC_ASSOCBITMAP 0x04 + +/* + * Extended capability ID: 0x0008 + * Multi-Function Virtual Channel + */ + +/* + * Extended capability ID: 0x0009 + * Virtual Channel if MFVC Ext Cap set + */ + +/* + * Extended capability ID: 0x000a + * RCRB Header + */ + +/* + * Extended capability ID: 0x000b + * Vendor Unique + */ + +/* + * Extended capability ID: 0x000c + * Configuration Access Correction + */ + +/* + * Extended capability ID: 0x000d + * Access Control Services + */ +#define PCI_ACS_CAP 0x04 /* Capability Register */ +#define PCI_ACS_CAP_V __BIT(0) /* Source Validation */ +#define PCI_ACS_CAP_B __BIT(1) /* Transaction Blocking */ +#define PCI_ACS_CAP_R __BIT(2) /* P2P Request Redirect */ +#define PCI_ACS_CAP_C __BIT(3) /* P2P Completion Redirect */ +#define PCI_ACS_CAP_U __BIT(4) /* Upstream Forwarding */ +#define PCI_ACS_CAP_E __BIT(5) /* Egress Control */ +#define PCI_ACS_CAP_T __BIT(6) /* Direct Translated P2P */ +#define PCI_ACS_CAP_ECVSIZE __BITS(15, 8) /* Egress Control Vector Size */ +#define PCI_ACS_CTL 0x04 /* Control Register */ +#define PCI_ACS_CTL_V __BIT(0 + 16) /* Source Validation Enable */ +#define PCI_ACS_CTL_B __BIT(1 + 16) /* Transaction Blocking Enable */ +#define PCI_ACS_CTL_R __BIT(2 + 16) /* P2P Request Redirect Enable */ +#define PCI_ACS_CTL_C __BIT(3 + 16) /* P2P Completion Redirect Enable */ +#define PCI_ACS_CTL_U __BIT(4 + 16) /* Upstream Forwarding Enable */ +#define PCI_ACS_CTL_E __BIT(5 + 16) /* Egress Control Enable */ +#define PCI_ACS_CTL_T __BIT(6 + 16) /* Direct Translated P2P Enable */ +#define PCI_ACS_ECV 0x08 /* Egress Control Vector */ + +/* + * Extended capability ID: 0x000e + * ARI + */ +#define PCI_ARI_CAP 0x04 /* Capability Register */ +#define PCI_ARI_CAP_M __BIT(0) /* MFVC Function Groups Cap. */ +#define PCI_ARI_CAP_A __BIT(1) /* ACS Function Groups Cap. */ +#define PCI_ARI_CAP_NXTFN __BITS(15, 8) /* Next Function Number */ +#define PCI_ARI_CTL 0x04 /* Control Register */ +#define PCI_ARI_CTL_M __BIT(16) /* MFVC Function Groups Ena. */ +#define PCI_ARI_CTL_A __BIT(17) /* ACS Function Groups Ena. */ +#define PCI_ARI_CTL_FUNCGRP __BITS(31, 24) /* Function Group */ + +/* + * Extended capability ID: 0x000f + * Address Translation Services + */ +#define PCI_ATS_CAP 0x04 /* Capability Register */ +#define PCI_ATS_CAP_INVQDEPTH __BITS(4, 0) /* Invalidate Queue Depth */ +#define PCI_ATS_CAP_PALIGNREQ __BIT(5) /* Page Aligned Request */ +#define PCI_ATS_CTL 0x04 /* Control Register */ +#define PCI_ATS_CTL_STU __BITS(20, 16) /* Smallest Translation Unit */ +#define PCI_ATS_CTL_EN __BIT(31) /* Enable */ + +/* + * Extended capability ID: 0x0010 + * SR-IOV + */ +#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */ +#define PCI_SRIOV_CAP_VF_MIGRATION __BIT(0) +#define PCI_SRIOV_CAP_ARI_CAP_HIER_PRESERVED __BIT(1) +#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N __BITS(31, 21) +#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N_S 21 +#define PCI_SRIOV_CAP_VF_MIGRATION_INTMSG_N_M 0x7ff +#define PCI_SRIOV_CTL 0x08 /* SR-IOV Control (16bit) */ +#define PCI_SRIOV_CTL_VF_ENABLE __BIT(0) +#define PCI_SRIOV_CTL_VF_MIGRATION_SUPPORT __BIT(1) +#define PCI_SRIOV_CTL_VF_MIGRATION_INT_ENABLE __BIT(2) +#define PCI_SRIOV_CTL_VF_MSE __BIT(3) +#define PCI_SRIOV_CTL_ARI_CAP_HIER __BIT(4) +#define PCI_SRIOV_STA 0x0a /* SR-IOV Status (16bit) */ +#define PCI_SRIOV_STA_VF_MIGRATION __BIT(0) +#define PCI_SRIOV_INITIAL_VFS 0x0c /* InitialVFs (16bit) */ +#define PCI_SRIOV_TOTAL_VFS 0x0e /* TotalVFs (16bit) */ +#define PCI_SRIOV_NUM_VFS 0x10 /* NumVFs (16bit) */ +#define PCI_SRIOV_FUNC_DEP_LINK 0x12 /* Function Dependency Link (16bit) */ +#define PCI_SRIOV_VF_OFF 0x14 /* First VF Offset (16bit) */ +#define PCI_SRIOV_VF_STRIDE 0x16 /* VF Stride (16bit) */ +#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID (16bit) */ +#define PCI_SRIOV_PAGE_CAP 0x1c /* Supported Page Sizes */ +#define PCI_SRIOV_PAGE_SIZE 0x20 /* System Page Size */ +#define PCI_SRIOV_BASE_PAGE_SHIFT 12 +#define PCI_SRIOV_BARS 0x24 /* VF BAR0-5 */ +#define PCI_SRIOV_BAR(x) (PCI_SRIOV_BARS + ((x) * 4)) +#define PCI_SRIOV_VF_MIG_STA_AR 0x3c /* VF Migration State Array Offset */ +#define PCI_SRIOV_VF_MIG_STA_OFFSET __BITS(31, 3) +#define PCI_SRIOV_VF_MIG_STA_OFFSET_S 3 +#define PCI_SRIOV_VF_MIG_STA_OFFSET_M 0x1fffffff +#define PCI_SRIOV_VF_MIG_STA_BIR __BITS(2, 0) +#define PCI_SRIOV_VF_MIG_STA_BIR_S 0 +#define PCI_SRIOV_VF_MIG_STA_BIR_M 0x7 + +/* + * Extended capability ID: 0x0011 + * Multiple Root IO Virtualization + */ + +/* + * Extended capability ID: 0x0012 + * Multicast + */ + +/* + * Extended capability ID: 0x0013 + * Page Request + */ +#define PCI_PAGE_REQ_CTL 0x04 /* Control Register */ +#define PCI_PAGE_REQ_CTL_E __BIT(0) /* Enalbe */ +#define PCI_PAGE_REQ_CTL_R __BIT(1) /* Reset */ +#define PCI_PAGE_REQ_STA 0x04 /* Status Register */ +#define PCI_PAGE_REQ_STA_RF __BIT(0+16) /* Response Failure */ +#define PCI_PAGE_REQ_STA_UPRGI __BIT(1+16) /* Unexpected Page Req Grp Idx */ +#define PCI_PAGE_REQ_STA_S __BIT(8+16) /* Stopped */ +#define PCI_PAGE_REQ_OUTSTCAPA 0x08 /* Outstanding Page Request Capacity */ +#define PCI_PAGE_REQ_OUTSTALLOC 0x0c /* Outstanding Page Request Allocation */ + +/* + * Extended capability ID: 0x0014 + * (Reserved for AMD) + */ + +/* + * Extended capability ID: 0x0015 + * Resizable BAR + */ + +/* + * Extended capability ID: 0x0016 + * Dynamic Power Allocation + */ + +/* + * Extended capability ID: 0x0017 + * TPH Requester + */ +#define PCI_TPH_REQ_CAP 0x04 /* TPH Requester Capability */ +#define PCI_TPH_REQ_CAP_NOST __BIT(0) /* No ST Mode Supported */ +#define PCI_TPH_REQ_CAP_INTVEC __BIT(1) /* Intr Vec Mode Supported */ +#define PCI_TPH_REQ_CAP_DEVSPEC __BIT(2) /* Device Specific Mode Supported */ +#define PCI_TPH_REQ_CAP_XTPHREQ __BIT(8) /* Extend TPH Reqester Supported */ +#define PCI_TPH_REQ_CAP_STTBLLOC __BITS(10, 9) /* ST Table Location */ +#define PCI_TPH_REQ_CAP_STTBLSIZ __BITS(26, 16) /* ST Table Size */ +#define PCI_TPH_REQ_CTL 0x08 /* TPH Requester Control */ +#define PCI_TPH_REQ_CTL_STSEL _BITS(2, 0) /* ST Mode Select */ +#define PCI_TPH_REQ_CTL_TPHREQEN _BITS(9, 8) /* TPH Requester Enable */ +#define PCI_TPH_REQ_STTBL 0x0c /* TPH ST Table */ + +/* + * Extended capability ID: 0x0018 + * Latency Tolerance Reporting + */ +#define PCI_LTR_MAXSNOOPLAT 0x04 /* Max Snoop Latency */ +#define PCI_LTR_MAXSNOOPLAT_VAL __BITS(9, 0) /* Max Snoop LatencyValue */ +#define PCI_LTR_MAXSNOOPLAT_SCALE __BITS(12, 10) /* Max Snoop LatencyScale */ +#define PCI_LTR_MAXNOSNOOPLAT 0x04 /* Max No-Snoop Latency */ +#define PCI_LTR_MAXNOSNOOPLAT_VAL __BITS(25, 16) /* Max No-Snoop LatencyValue*/ +#define PCI_LTR_MAXNOSNOOPLAT_SCALE __BITS(28, 26) /*Max NoSnoop LatencyScale*/ +#define PCI_LTR_SCALETONS(x) ((32 << (x)) / 32) + +/* + * Extended capability ID: 0x0019 + * Seconday PCI Express Extended Capability + */ +#define PCI_SECPCIE_LCTL3 0x04 /* Link Control 3 */ +#define PCI_SECPCIE_LCTL3_PERFEQ __BIT(0) /* Perform Equalization */ +#define PCI_SECPCIE_LCTL3_LINKEQREQ_IE __BIT(1) /* Link Eq. Req. Int. Ena. */ +#define PCI_SECPCIE_LANEERR_STA 0x08 /* Lane Error Status */ +#define PCI_SECPCIE_EQCTLS 0x0c /* Equalization Control [0-maxlane] */ +#define PCI_SECPCIE_EQCTL(x) (PCI_SECPCIE_EQCTLS + ((x) * 2)) +#define PCI_SECPCIE_EQCTL_DP_XMIT_PRESET __BITS(3, 0) /* DwnStPort Xmit Pres */ +#define PCI_SECPCIE_EQCTL_DP_RCV_HINT __BITS(6, 4) /* DwnStPort Rcv PreHnt */ +#define PCI_SECPCIE_EQCTL_UP_XMIT_PRESET __BITS(11, 8) /* UpStPort Xmit Pres */ +#define PCI_SECPCIE_EQCTL_UP_RCV_HINT __BITS(14, 12) /* UpStPort Rcv PreHnt*/ + +/* + * Extended capability ID: 0x001a + * Protocol Multiplexing + */ + +/* + * Extended capability ID: 0x001b + * Process Address Space ID + */ +#define PCI_PASID_CAP 0x04 /* Capability Register */ +#define PCI_PASID_CAP_XPERM __BIT(1) /* Execute Permission Supported */ +#define PCI_PASID_CAP_PRIVMODE __BIT(2) /* Privileged Mode Supported */ +#define PCI_PASID_CAP_MAXPASIDW __BITS(12, 8) /* Max PASID Width */ +#define PCI_PASID_CTL 0x04 /* Control Register */ +#define PCI_PASID_CTL_PASID_EN __BIT(0) /* PASID Enable */ +#define PCI_PASID_CTL_XPERM_EN __BIT(1) /* Execute Permission Enable */ +#define PCI_PASID_CTL_PRIVMODE_EN __BIT(2) /* Privileged Mode Enable */ + +/* + * Extended capability ID: 0x001c + * LN Requester + */ +#define PCI_LNR_CAP 0x04 /* Capability Register */ +#define PCI_LNR_CAP_64 __BIT(0) /* LNR-64 Supported */ +#define PCI_LNR_CAP_128 __BIT(1) /* LNR-128 Supported */ +#define PCI_LNR_CAP_REGISTMAX __BITS(12, 8) /* LNR Registration MAX */ +#define PCI_LNR_CTL 0x04 /* Control Register */ +#define PCI_LNR_CTL_EN __BIT(0+16) /* LNR Enable */ +#define PCI_LNR_CTL_CLS __BIT(1+16) /* LNR CLS */ +#define PCI_LNR_CTL_REGISTLIM __BITS(28, 24) /* LNR Registration Limit */ + +/* + * Extended capability ID: 0x001d + * Downstream Port Containment + */ + +/* + * Extended capability ID: 0x001e + * L1 PM Substates + */ +#define PCI_L1PM_CAP 0x04 /* Capabilities Register */ +#define PCI_L1PM_CAP_PCIPM12 __BIT(0) /* PCI-PM L1.2 Supported */ +#define PCI_L1PM_CAP_PCIPM11 __BIT(1) /* PCI-PM L1.1 Supported */ +#define PCI_L1PM_CAP_ASPM12 __BIT(2) /* ASPM L1.2 Supported */ +#define PCI_L1PM_CAP_ASPM11 __BIT(3) /* ASPM L1.1 Supported */ +#define PCI_L1PM_CAP_L1PM __BIT(4) /* L1 PM Substates Supported */ +#define PCI_L1PM_CAP_PCMRT __BITS(15, 8) /*Port Common Mode Restore Time*/ +#define PCI_L1PM_CAP_PTPOSCALE __BITS(17, 16) /* Port T_POWER_ON Scale */ +#define PCI_L1PM_CAP_PTPOVAL __BITS(23, 19) /* Port T_POWER_ON Value */ +#define PCI_L1PM_CTL1 0x08 /* Control Register 1 */ +#define PCI_L1PM_CTL1_PCIPM12_EN __BIT(0) /* PCI-PM L1.2 Enable */ +#define PCI_L1PM_CTL1_PCIPM11_EN __BIT(1) /* PCI-PM L1.1 Enable */ +#define PCI_L1PM_CTL1_ASPM12_EN __BIT(2) /* ASPM L1.2 Enable */ +#define PCI_L1PM_CTL1_ASPM11_EN __BIT(3) /* ASPM L1.1 Enable */ +#define PCI_L1PM_CTL1_CMRT __BITS(15, 8) /* Common Mode Restore Time */ +#define PCI_L1PM_CTL1_LTRTHVAL __BITS(25, 16) /* LTR L1.2 THRESHOLD Value */ +#define PCI_L1PM_CTL1_LTRTHSCALE __BITS(31, 29) /* LTR L1.2 THRESHOLD Scale */ +#define PCI_L1PM_CTL2 0x0c /* Control Register 2 */ +#define PCI_L1PM_CTL2_TPOSCALE __BITS(1, 0) /* T_POWER_ON Scale */ +#define PCI_L1PM_CTL2_TPOVAL __BITS(7, 3) /* T_POWER_ON Value */ + /* * Local constants */ diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 8bd2fcb1e5d..5bdd392cf75 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcivar.h,v 1.104 2015/08/17 06:16:03 knakahara Exp $ */ +/* $NetBSD: pcivar.h,v 1.105 2015/10/02 05:22:53 msaitoh Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -278,14 +278,22 @@ int pci_find_rom(const struct pci_attach_args *, bus_space_tag_t, bus_space_handle_t, bus_size_t, int, bus_space_handle_t *, bus_size_t *); -int pci_get_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *); -int pci_get_ht_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *); +int pci_get_capability(pci_chipset_tag_t, pcitag_t, int, int *, pcireg_t *); +int pci_get_ht_capability(pci_chipset_tag_t, pcitag_t, int, int *, + pcireg_t *); +int pci_get_ext_capability(pci_chipset_tag_t, pcitag_t, int, int *, + pcireg_t *); + int pci_msi_count(pci_chipset_tag_t, pcitag_t); int pci_msix_count(pci_chipset_tag_t, pcitag_t); /* * Helper functions for autoconfiguration. */ +#ifndef PCI_MACHDEP_ENUMERATE_BUS +int pci_enumerate_bus(struct pci_softc *, const int *, + int (*)(const struct pci_attach_args *), struct pci_attach_args *); +#endif int pci_probe_device(struct pci_softc *, pcitag_t tag, int (*)(const struct pci_attach_args *), struct pci_attach_args *); |
