From 8c5b0f9aa6710819d5d0e071a7cabb53d5bb2e98 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 28 Nov 2007 11:35:40 +0000 Subject: [PATCH] - Factor out pcie_slotimpl() to check whether PCI Express slot is implemented. - Add external function to test whether PCI Express slot is implemented; this external function is sheer wrapper of pcie_slotimpl(). - Rename port type macros. - Add some comment. - Disable all hot-plug related interrupts on PCI Express root/downstream port. Add XXX comment about it. Reminded-by: joerg@ --- sys/bus/pci/pci.c | 91 ++++++++++++++++++++++++++---------------- sys/bus/pci/pci_pcib.c | 26 +++++++++++- sys/bus/pci/pcireg.h | 37 ++++++++++++----- sys/bus/pci/pcivar.h | 3 +- 4 files changed, 110 insertions(+), 47 deletions(-) diff --git a/sys/bus/pci/pci.c b/sys/bus/pci/pci.c index 65c9b429ab..3ae162ba0d 100644 --- a/sys/bus/pci/pci.c +++ b/sys/bus/pci/pci.c @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/pci/pci.c,v 1.141.2.15 2002/04/30 17:48:18 tmm Exp $ - * $DragonFly: src/sys/bus/pci/pci.c,v 1.49 2007/11/25 10:31:40 sephe Exp $ + * $DragonFly: src/sys/bus/pci/pci.c,v 1.50 2007/11/28 11:35:40 sephe Exp $ * */ @@ -66,6 +66,7 @@ devclass_t pci_devclass; const char *pcib_owner; static void pci_read_capabilities(device_t dev, pcicfgregs *cfg); +static int pcie_slotimpl(const pcicfgregs *); struct pci_quirk { u_int32_t devid; /* Vendor/device of the card */ @@ -127,6 +128,14 @@ pci_find_device(u_int16_t vendor, u_int16_t device) return (NULL); } +int +pcie_slot_implemented(device_t dev) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + + return pcie_slotimpl(&dinfo->cfg); +} + /* return base address of memory or port map */ static u_int32_t @@ -485,47 +494,61 @@ pci_read_cap_pmgt(device_t pcib, int ptr, pcicfgregs *cfg) #undef REG } -static void -pci_read_cap_expr(device_t pcib, int ptr, pcicfgregs *cfg) +static int +pcie_slotimpl(const pcicfgregs *cfg) { -#define REG(n, w) \ - PCIB_READ_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, w) - - struct pcicfg_expr *expr = &cfg->expr; + const struct pcicfg_expr *expr = &cfg->expr; uint16_t port_type; - expr->expr_ptr = ptr; - expr->expr_cap = REG(ptr + PCIER_CAPABILITY, 2); - /* * Only version 1 can be parsed currently */ if ((expr->expr_cap & PCIEM_CAP_VER_MASK) != PCIEM_CAP_VER_1) - return; + return 0; /* - * Read slot capabilities - * - * Slot capabilities exists iff current port is root port or - * down stream port, and the slot is implemented. - * - * - Testing for root port or down stream port is meanningful - * iff PCI configure has type 1 header. * - Slot implemented bit is meaningful iff current port is * root port or down stream port. + * - Testing for root port or down stream port is meanningful + * iff PCI configure has type 1 header. */ + if (cfg->hdrtype != 1) - return; + return 0; port_type = expr->expr_cap & PCIEM_CAP_PORT_TYPE; - if (port_type != PCIEM_ROOT_PORT && - port_type != PCIEM_DOWN_STREAM_PORT) - return; + if (port_type != PCIE_ROOT_PORT && port_type != PCIE_DOWN_STREAM_PORT) + return 0; if (!(expr->expr_cap & PCIEM_CAP_SLOT_IMPL)) + return 0; + + return 1; +} + +static void +pci_read_cap_expr(device_t pcib, int ptr, pcicfgregs *cfg) +{ +#define REG(n, w) \ + PCIB_READ_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, w) + + struct pcicfg_expr *expr = &cfg->expr; + + expr->expr_ptr = ptr; + expr->expr_cap = REG(ptr + PCIER_CAPABILITY, 2); + + /* + * Only version 1 can be parsed currently + */ + if ((expr->expr_cap & PCIEM_CAP_VER_MASK) != PCIEM_CAP_VER_1) return; - expr->expr_slotcap = REG(ptr + PCIER_SLOTCAP, 4); + /* + * Read slot capabilities. Slot capabilities exists iff + * current port's slot is implemented + */ + if (pcie_slotimpl(cfg)) + expr->expr_slotcap = REG(ptr + PCIER_SLOTCAP, 4); #undef REG } @@ -1360,41 +1383,39 @@ pci_print_verbose_expr(const pcicfgregs *cfg) port_type = expr->expr_cap & PCIEM_CAP_PORT_TYPE; switch (port_type) { - case PCIEM_END_POINT: + case PCIE_END_POINT: port_name = "DEVICE"; break; - case PCIEM_LEG_END_POINT: + case PCIE_LEG_END_POINT: port_name = "LEGDEV"; break; - case PCIEM_ROOT_PORT: + case PCIE_ROOT_PORT: port_name = "ROOT"; break; - case PCIEM_UP_STREAM_PORT: + case PCIE_UP_STREAM_PORT: port_name = "UPSTREAM"; break; - case PCIEM_DOWN_STREAM_PORT: + case PCIE_DOWN_STREAM_PORT: port_name = "DOWNSTRM"; break; - case PCIEM_PCIE2PCI_BRIDGE: + case PCIE_PCIE2PCI_BRIDGE: port_name = "PCIE2PCI"; break; - case PCIEM_PCI2PCIE_BRIDGE: + case PCIE_PCI2PCIE_BRIDGE: port_name = "PCI2PCIE"; break; default: port_name = NULL; break; } - if ((port_type == PCIEM_ROOT_PORT || - port_type == PCIEM_DOWN_STREAM_PORT) && + if ((port_type == PCIE_ROOT_PORT || + port_type == PCIE_DOWN_STREAM_PORT) && !(expr->expr_cap & PCIEM_CAP_SLOT_IMPL)) port_name = NULL; if (port_name != NULL) kprintf("[%s]", port_name); - if ((port_type == PCIEM_ROOT_PORT || - port_type == PCIEM_DOWN_STREAM_PORT) && - (expr->expr_cap & PCIEM_CAP_SLOT_IMPL)) { + if (pcie_slotimpl(cfg)) { kprintf(", slotcap=0x%08x", expr->expr_slotcap); if (expr->expr_slotcap & PCIEM_SLTCAP_HP_CAP) kprintf("[HOTPLUG]"); diff --git a/sys/bus/pci/pci_pcib.c b/sys/bus/pci/pci_pcib.c index 5cb6eb6bc9..b687438ca5 100644 --- a/sys/bus/pci/pci_pcib.c +++ b/sys/bus/pci/pci_pcib.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $DragonFly: src/sys/bus/pci/pci_pcib.c,v 1.7 2007/06/08 13:52:09 sephe Exp $ + * $DragonFly: src/sys/bus/pci/pci_pcib.c,v 1.8 2007/11/28 11:35:40 sephe Exp $ */ #include "opt_pci.h" @@ -172,6 +172,30 @@ pcib_attach_common(device_t dev) device_printf(dev, " Subtractively decoded bridge.\n"); } + if (pci_is_pcie(dev) && pcie_slot_implemented(dev)) { + uint16_t slot_ctrl; + uint8_t ptr; + + /* + * XXX + * Before proper PCI Express hot-plug support is in place, + * disable all hot-plug interrupts on the PCI Express root + * port or down stream port for now. + */ +#define HPINTRS (PCIEM_SLTCTL_HPINTR_MASK | PCIEM_SLTCTL_HPINTR_EN) + + ptr = pci_get_pciecap_ptr(dev); + slot_ctrl = pci_read_config(dev, ptr + PCIER_SLOTCTRL, 2); + if (slot_ctrl & HPINTRS) { + device_printf(dev, "Disable PCI Express hot-plug " + "interrupts(0x%04x)\n", slot_ctrl & HPINTRS); + slot_ctrl &= ~HPINTRS; + pci_write_config(dev, ptr + PCIER_SLOTCTRL, slot_ctrl, 2); + } + +#undef HPINTRS + } + /* * XXX If the secondary bus number is zero, we should assign a bus number * since the BIOS hasn't, then initialise the bridge. diff --git a/sys/bus/pci/pcireg.h b/sys/bus/pci/pcireg.h index 33864eecd7..ddffd6c375 100644 --- a/sys/bus/pci/pcireg.h +++ b/sys/bus/pci/pcireg.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/pci/pcireg.h,v 1.24.2.5 2002/08/31 10:06:51 gibbs Exp $ - * $DragonFly: src/sys/bus/pci/pcireg.h,v 1.15 2007/11/25 04:08:42 sephe Exp $ + * $DragonFly: src/sys/bus/pci/pcireg.h,v 1.16 2007/11/28 11:35:40 sephe Exp $ * */ @@ -422,8 +422,13 @@ #define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ #define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ -/* PCI Express definitions */ +/* + * PCI Express definitions + * According to + * PCI Express base specification, REV. 1.0a + */ +/* PCI Express capabilities, 16bits */ #define PCIER_CAPABILITY 0x2 #define PCIEM_CAP_VER_MASK 0x000f /* Version */ #define PCIEM_CAP_VER_1 0x0001 @@ -433,14 +438,15 @@ * switch downstream port */ /* PCI Express port types */ -#define PCIEM_END_POINT 0x0000 /* Endpoint device */ -#define PCIEM_LEG_END_POINT 0x0010 /* Legacy endpoint device */ -#define PCIEM_ROOT_PORT 0x0040 /* Root port */ -#define PCIEM_UP_STREAM_PORT 0x0050 /* Switch upstream port */ -#define PCIEM_DOWN_STREAM_PORT 0x0060 /* Switch downstream port */ -#define PCIEM_PCIE2PCI_BRIDGE 0x0070 /* PCI Express to PCI/PCI-X bridge */ -#define PCIEM_PCI2PCIE_BRIDGE 0x0080 /* PCI/PCI-X to PCI Express bridge */ - +#define PCIE_END_POINT 0x0000 /* Endpoint device */ +#define PCIE_LEG_END_POINT 0x0010 /* Legacy endpoint device */ +#define PCIE_ROOT_PORT 0x0040 /* Root port */ +#define PCIE_UP_STREAM_PORT 0x0050 /* Switch upstream port */ +#define PCIE_DOWN_STREAM_PORT 0x0060 /* Switch downstream port */ +#define PCIE_PCIE2PCI_BRIDGE 0x0070 /* PCI Express to PCI/PCI-X bridge */ +#define PCIE_PCI2PCIE_BRIDGE 0x0080 /* PCI/PCI-X to PCI Express bridge */ + +/* PCI Express slot capabilities, 32bits */ #define PCIER_SLOTCAP 0x14 #define PCIEM_SLTCAP_ATTEN_BTN 0x00000001 /* Attention button present */ #define PCIEM_SLTCAP_PWR_CTRL 0x00000002 /* Power controller present */ @@ -451,6 +457,17 @@ #define PCIEM_SLTCAP_HP_CAP 0x00000040 /* Hot-Plug capable */ #define PCIEM_SLTCAP_HP_MASK 0x0000007f /* Hot-Plug related bits */ +/* PCI Express slot control, 16bits */ +#define PCIER_SLOTCTRL 0x18 +#define PCIEM_SLTCTL_HPINTR_MASK 0x001f /* Hot-plug interrupts mask */ +#define PCIEM_SLTCTL_HPINTR_EN 0x0020 /* Enable hot-plug interrupts */ + /* PCI Expres hot-plug interrupts */ +#define PCIE_HPINTR_ATTEN_BTN 0x0001 /* Attention button intr */ +#define PCIE_HPINTR_PWR_FAULT 0x0002 /* Power fault intr */ +#define PCIE_HPINTR_MRL_SNS 0x0004 /* MRL sensor changed intr */ +#define PCIE_HPINTR_PRSN_DETECT 0x0008 /* Presence detect intr */ +#define PCIE_HPINTR_CMD_COMPL 0x0010 /* Command completed intr */ + /* for compatibility to FreeBSD-2.2 and 3.x versions of PCI code */ #if defined(_KERNEL) && !defined(KLD_MODULE) diff --git a/sys/bus/pci/pcivar.h b/sys/bus/pci/pcivar.h index a6fe81e715..cce3f539ce 100644 --- a/sys/bus/pci/pcivar.h +++ b/sys/bus/pci/pcivar.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/pci/pcivar.h,v 1.48 2000/09/28 00:37:32 peter Exp $ - * $DragonFly: src/sys/bus/pci/pcivar.h,v 1.14 2007/11/25 10:31:41 sephe Exp $ + * $DragonFly: src/sys/bus/pci/pcivar.h,v 1.15 2007/11/28 11:35:40 sephe Exp $ * */ @@ -378,6 +378,7 @@ PCIB_ACCESSOR(bus, BUS, u_int32_t) device_t pci_find_bsf(u_int8_t, u_int8_t, u_int8_t); device_t pci_find_device(u_int16_t, u_int16_t); +int pcie_slot_implemented(device_t); #endif /* for compatibility to FreeBSD-2.2 and 3.x versions of PCI code */ -- 2.41.0