Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 May 2009 21:04:29 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r191799 - in stable/7/sys: . amd64/include amd64/pci contrib/pf dev/acpica dev/ath/ath_hal dev/cxgb i386/include i386/pci
Message-ID:  <200905042104.n44L4TcW057206@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon May  4 21:04:29 2009
New Revision: 191799
URL: http://svn.freebsd.org/changeset/base/191799

Log:
  MFC: Expand the support for PCI-e memory mapped configuration space access.
  Note that unlike in HEAD, this defaults to off and must be explicitly
  enabled by setting the loader tunable hw.pci.mcfg=1.
  - Add support for the Intel 915GM chipsets by reading the BAR.
  - Add parsing of the ACPI MCFG table to discover memory mapped configuration
    access on modern machines.
  - Port the memory mapped config acess to amd64.  On amd64 it uses the direct
    map.
  - For config requests to busses not listed in ACPI's min/max valid buses,
    fall back to using type #1 configuration access instead.
  - Add a workaround for some K8 chipsets that do not expose all devices on
    bus 0 via MCFG and fall back to type #1 for those devices instead.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/amd64/include/pci_cfgreg.h
  stable/7/sys/amd64/pci/pci_cfgreg.c
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/acpica/acpi.c
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/i386/include/pci_cfgreg.h
  stable/7/sys/i386/pci/pci_cfgreg.c

Modified: stable/7/sys/amd64/include/pci_cfgreg.h
==============================================================================
--- stable/7/sys/amd64/include/pci_cfgreg.h	Mon May  4 21:00:43 2009	(r191798)
+++ stable/7/sys/amd64/include/pci_cfgreg.h	Mon May  4 21:04:29 2009	(r191799)
@@ -37,6 +37,7 @@
 #define CONF1_ENABLE_MSK1  0x80000001ul
 #define CONF1_ENABLE_RES1  0x80000000ul
 
+int		pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus);
 int		pci_cfgregopen(void);
 u_int32_t	pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
 void		pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);

Modified: stable/7/sys/amd64/pci/pci_cfgreg.c
==============================================================================
--- stable/7/sys/amd64/pci/pci_cfgreg.c	Mon May  4 21:00:43 2009	(r191798)
+++ stable/7/sys/amd64/pci/pci_cfgreg.c	Mon May  4 21:04:29 2009	(r191799)
@@ -33,15 +33,36 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/lock.h>
+#include <sys/kernel.h>
 #include <sys/mutex.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
 #include <machine/pci_cfgreg.h>
 
+enum {
+	CFGMECH_NONE = 0,
+	CFGMECH_1,
+	CFGMECH_PCIE,
+};
+
+static uint32_t	pci_docfgregread(int bus, int slot, int func, int reg,
+		    int bytes);
+static int	pciereg_cfgread(int bus, unsigned slot, unsigned func,
+		    unsigned reg, unsigned bytes);
+static void	pciereg_cfgwrite(int bus, unsigned slot, unsigned func,
+		    unsigned reg, int data, unsigned bytes);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 
+static int cfgmech;
+static vm_offset_t pcie_base;
+static int pcie_minbus, pcie_maxbus;
+static uint32_t pcie_badslots;
 static struct mtx pcicfg_mtx;
+static int mcfg_enable = 0;
+TUNABLE_INT("hw.pci.mcfg", &mcfg_enable);
 
 /* 
  * Initialise access to PCI configuration space 
@@ -49,15 +70,62 @@ static struct mtx pcicfg_mtx;
 int
 pci_cfgregopen(void)
 {
-	static int		opened = 0;
+	static int once = 0;
+	uint64_t pciebar;
+	uint16_t did, vid;
+
+	if (!once) {
+		mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
+		once = 1;
+	}
 
-	if (opened)
+	if (cfgmech != CFGMECH_NONE)
 		return (1);
-	mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
-	opened = 1;
+	cfgmech = CFGMECH_1;
+
+	/*
+	 * Grope around in the PCI config space to see if this is a
+	 * chipset that is capable of doing memory-mapped config cycles.
+	 * This also implies that it can do PCIe extended config cycles.
+	 */
+
+	/* Check for supported chipsets */
+	vid = pci_cfgregread(0, 0, 0, PCIR_VENDOR, 2);
+	did = pci_cfgregread(0, 0, 0, PCIR_DEVICE, 2);
+	switch (vid) {
+	case 0x8086:
+		switch (did) {
+		case 0x3590:
+		case 0x3592:
+			/* Intel 7520 or 7320 */
+			pciebar = pci_cfgregread(0, 0, 0, 0xce, 2) << 16;
+			pcie_cfgregopen(pciebar, 0, 255);
+			break;
+		case 0x2580:
+		case 0x2584:
+		case 0x2590:
+			/* Intel 915, 925, or 915GM */
+			pciebar = pci_cfgregread(0, 0, 0, 0x48, 4);
+			pcie_cfgregopen(pciebar, 0, 255);
+			break;
+		}
+	}
+
 	return (1);
 }
 
+static uint32_t
+pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
+{
+
+	if (cfgmech == CFGMECH_PCIE &&
+	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
+	    (bus != 0 || !(1 << slot & pcie_badslots)))
+		return (pciereg_cfgread(bus, slot, func, reg, bytes));
+	else
+		return (pcireg_cfgread(bus, slot, func, reg, bytes));
+}
+
 /* 
  * Read configuration space register
  */
@@ -75,12 +143,12 @@ pci_cfgregread(int bus, int slot, int fu
 	 * as an invalid IRQ.
 	 */
 	if (reg == PCIR_INTLINE && bytes == 1) {
-		line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+		line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1);
 		if (line == 0 || line >= 128)
 			line = PCI_INVALID_IRQ;
 		return (line);
 	}
-	return (pcireg_cfgread(bus, slot, func, reg, bytes));
+	return (pci_docfgregread(bus, slot, func, reg, bytes));
 }
 
 /* 
@@ -90,7 +158,12 @@ void
 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
 {
 
-	pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
+	if (cfgmech == CFGMECH_PCIE &&
+	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
+	    (bus != 0 || !(1 << slot & pcie_badslots)))
+		pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
+	else
+		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
 }
 
 /* 
@@ -173,3 +246,106 @@ pcireg_cfgwrite(int bus, int slot, int f
 	}
 	mtx_unlock_spin(&pcicfg_mtx);
 }
+
+int
+pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
+{
+	uint32_t val1, val2;
+	int slot;
+
+	if (!mcfg_enable)
+		return (0);
+
+	if (minbus != 0)
+		return (0);
+
+	if (bootverbose)
+		printf("PCIe: Memory Mapped configuration base @ 0x%lx\n",
+		    base);
+
+	/* XXX: We should make sure this really fits into the direct map. */
+	pcie_base = (vm_offset_t)pmap_mapdev(base, (maxbus + 1) << 20);
+	pcie_minbus = minbus;
+	pcie_maxbus = maxbus;
+	cfgmech = CFGMECH_PCIE;
+
+	/*
+	 * On some AMD systems, some of the devices on bus 0 are
+	 * inaccessible using memory-mapped PCI config access.  Walk
+	 * bus 0 looking for such devices.  For these devices, we will
+	 * fall back to using type 1 config access instead.
+	 */
+	if (pci_cfgregopen() != 0) {
+		for (slot = 0; slot < 32; slot++) {
+			val1 = pcireg_cfgread(0, slot, 0, 0, 4);
+			if (val1 == 0xffffffff)
+				continue;
+
+			val2 = pciereg_cfgread(0, slot, 0, 0, 4);
+			if (val2 != val1)
+				pcie_badslots |= (1 << slot);
+		}
+	}
+
+	return (1);
+}
+
+#define PCIE_VADDR(base, reg, bus, slot, func)	\
+	((base)				+	\
+	((((bus) & 0xff) << 20)		|	\
+	(((slot) & 0x1f) << 15)		|	\
+	(((func) & 0x7) << 12)		|	\
+	((reg) & 0xfff)))
+
+static int
+pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
+    unsigned bytes)
+{
+	volatile vm_offset_t va;
+	int data = -1;
+
+	if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 ||
+	    func > PCI_FUNCMAX || reg >= 0x1000)
+		return (-1);
+
+	va = PCIE_VADDR(pcie_base, reg, bus, slot, func);
+
+	switch (bytes) {
+	case 4:
+		data = *(volatile uint32_t *)(va);
+		break;
+	case 2:
+		data = *(volatile uint16_t *)(va);
+		break;
+	case 1:
+		data = *(volatile uint8_t *)(va);
+		break;
+	}
+
+	return (data);
+}
+
+static void
+pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data,
+    unsigned bytes)
+{
+	volatile vm_offset_t va;
+
+	if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 ||
+	    func > PCI_FUNCMAX || reg >= 0x1000)
+		return;
+
+	va = PCIE_VADDR(pcie_base, reg, bus, slot, func);
+
+	switch (bytes) {
+	case 4:
+		*(volatile uint32_t *)(va) = data;
+		break;
+	case 2:
+		*(volatile uint16_t *)(va) = data;
+		break;
+	case 1:
+		*(volatile uint8_t *)(va) = data;
+		break;
+	}
+}

Modified: stable/7/sys/dev/acpica/acpi.c
==============================================================================
--- stable/7/sys/dev/acpica/acpi.c	Mon May  4 21:00:43 2009	(r191798)
+++ stable/7/sys/dev/acpica/acpi.c	Mon May  4 21:04:29 2009	(r191799)
@@ -48,6 +48,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/sbuf.h>
 #include <sys/smp.h>
 
+#if defined(__i386__) || defined(__amd64__)
+#include <machine/pci_cfgreg.h>
+#endif
 #include <machine/resource.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
@@ -153,6 +156,9 @@ static int	acpi_child_location_str_metho
 					       char *buf, size_t buflen);
 static int	acpi_child_pnpinfo_str_method(device_t acdev, device_t child,
 					      char *buf, size_t buflen);
+#if defined(__i386__) || defined(__amd64__)
+static void	acpi_enable_pcie(void);
+#endif
 
 static device_method_t acpi_methods[] = {
     /* Device interface */
@@ -455,6 +461,11 @@ acpi_attach(device_t dev)
 	goto out;
     }
 
+#if defined(__i386__) || defined(__amd64__)
+    /* Handle MCFG table if present. */
+    acpi_enable_pcie();
+#endif
+
     /* Install the default address space handlers. */
     status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
 		ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
@@ -1473,6 +1484,36 @@ acpi_isa_pnp_probe(device_t bus, device_
     return_VALUE (result);
 }
 
+#if defined(__i386__) || defined(__amd64__)
+/*
+ * Look for a MCFG table.  If it is present, use the settings for
+ * domain (segment) 0 to setup PCI config space access via the memory
+ * map.
+ */
+static void
+acpi_enable_pcie(void)
+{
+	ACPI_TABLE_HEADER *hdr;
+	ACPI_MCFG_ALLOCATION *alloc, *end;
+	ACPI_STATUS status;
+
+	status = AcpiGetTable(ACPI_SIG_MCFG, 1, &hdr);
+	if (ACPI_FAILURE(status))
+		return;
+
+	end = (ACPI_MCFG_ALLOCATION *)((char *)hdr + hdr->Length);
+	alloc = (ACPI_MCFG_ALLOCATION *)((ACPI_TABLE_MCFG *)hdr + 1);
+	while (alloc < end) {
+		if (alloc->PciSegment == 0) {
+			pcie_cfgregopen(alloc->Address, alloc->StartBusNumber,
+			    alloc->EndBusNumber);
+			return;
+		}
+		alloc++;
+	}
+}
+#endif
+
 /*
  * Scan all of the ACPI namespace and attach child devices.
  *

Modified: stable/7/sys/i386/include/pci_cfgreg.h
==============================================================================
--- stable/7/sys/i386/include/pci_cfgreg.h	Mon May  4 21:00:43 2009	(r191798)
+++ stable/7/sys/i386/include/pci_cfgreg.h	Mon May  4 21:04:29 2009	(r191799)
@@ -43,6 +43,7 @@
 #define CONF2_ENABLE_CHK   0x0e
 #define CONF2_ENABLE_RES   0x0e
 
+int		pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus);
 int		pci_cfgregopen(void);
 u_int32_t	pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
 void		pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);

Modified: stable/7/sys/i386/pci/pci_cfgreg.c
==============================================================================
--- stable/7/sys/i386/pci/pci_cfgreg.c	Mon May  4 21:00:43 2009	(r191798)
+++ stable/7/sys/i386/pci/pci_cfgreg.c	Mon May  4 21:04:29 2009	(r191799)
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/lock.h>
+#include <sys/kernel.h>
 #include <sys/mutex.h>
 #include <sys/malloc.h>
 #include <sys/queue.h>
@@ -75,20 +76,24 @@ enum {
 };
 
 static TAILQ_HEAD(pcie_cfg_list, pcie_cfg_elem) pcie_list[MAXCPU];
-static uint32_t pciebar;
+static uint64_t pcie_base;
+static int pcie_minbus, pcie_maxbus;
+static uint32_t pcie_badslots;
 static int cfgmech;
 static int devmax;
 static struct mtx pcicfg_mtx;
+static int mcfg_enable = 0;
+TUNABLE_INT("hw.pci.mcfg", &mcfg_enable);
 
+static uint32_t	pci_docfgregread(int bus, int slot, int func, int reg,
+		    int bytes);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 static int	pcireg_cfgopen(void);
-
-static int	pciereg_cfgopen(void);
-static int	pciereg_cfgread(int bus, int slot, int func, int reg,
-				int bytes);
-static void	pciereg_cfgwrite(int bus, int slot, int func, int reg,
-				 int data, int bytes);
+static int	pciereg_cfgread(int bus, unsigned slot, unsigned func,
+		    unsigned reg, unsigned bytes);
+static void	pciereg_cfgwrite(int bus, unsigned slot, unsigned func,
+		    unsigned reg, int data, unsigned bytes);
 
 /*
  * Some BIOS writers seem to want to ignore the spec and put
@@ -133,14 +138,15 @@ int
 pci_cfgregopen(void)
 {
 	static int		opened = 0;
+	uint64_t		pciebar;
 	u_int16_t		vid, did;
 	u_int16_t		v;
 
 	if (opened)
-		return(1);
+		return (1);
 
-	if (pcireg_cfgopen() == 0)
-		return(0);
+	if (cfgmech == CFGMECH_NONE && pcireg_cfgopen() == 0)
+		return (0);
 
 	v = pcibios_get_version();
 	if (v > 0)
@@ -153,6 +159,9 @@ pci_cfgregopen(void)
 	if (v >= 0x0210)
 		pci_pir_open();
 
+	if (cfgmech == CFGMECH_PCIE)
+		return (1);	
+
 	/*
 	 * Grope around in the PCI config space to see if this is a
 	 * chipset that is capable of doing memory-mapped config cycles.
@@ -162,21 +171,40 @@ pci_cfgregopen(void)
 	/* Check for supported chipsets */
 	vid = pci_cfgregread(0, 0, 0, PCIR_VENDOR, 2);
 	did = pci_cfgregread(0, 0, 0, PCIR_DEVICE, 2);
-	if (vid == 0x8086) {
-		if (did == 0x3590 || did == 0x3592) {
+	switch (vid) {
+	case 0x8086:
+		switch (did) {
+		case 0x3590:
+		case 0x3592:
 			/* Intel 7520 or 7320 */
 			pciebar = pci_cfgregread(0, 0, 0, 0xce, 2) << 16;
-			pciereg_cfgopen();
-		} else if (did == 0x2580 || did == 0x2584) {
-			/* Intel 915 or 925 */
+			pcie_cfgregopen(pciebar, 0, 255);
+			break;
+		case 0x2580:
+		case 0x2584:
+		case 0x2590:
+			/* Intel 915, 925, or 915GM */
 			pciebar = pci_cfgregread(0, 0, 0, 0x48, 4);
-			pciereg_cfgopen();
+			pcie_cfgregopen(pciebar, 0, 255);
+			break;
 		}
 	}
 
 	return(1);
 }
 
+static uint32_t
+pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
+{
+
+	if (cfgmech == CFGMECH_PCIE &&
+	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
+	    (bus != 0 || !(1 << slot & pcie_badslots)))
+		return (pciereg_cfgread(bus, slot, func, reg, bytes));
+	else
+		return (pcireg_cfgread(bus, slot, func, reg, bytes));
+}
+
 /* 
  * Read configuration space register
  */
@@ -191,10 +219,10 @@ pci_cfgregread(int bus, int slot, int fu
 	 * the code uses 255 as an invalid IRQ.
 	 */
 	if (reg == PCIR_INTLINE && bytes == 1) {
-		line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+		line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1);
 		return (pci_i386_map_intline(line));
 	}
-	return (pcireg_cfgread(bus, slot, func, reg, bytes));
+	return (pci_docfgregread(bus, slot, func, reg, bytes));
 }
 
 /* 
@@ -204,7 +232,12 @@ void
 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
 {
 
-	pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
+	if (cfgmech == CFGMECH_PCIE &&
+	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
+	    (bus != 0 || !(1 << slot & pcie_badslots)))
+		pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
+	else
+		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
 }
 
 /* 
@@ -258,6 +291,7 @@ pci_cfgenable(unsigned bus, unsigned slo
 	    && (unsigned) bytes <= 4
 	    && (reg & (bytes - 1)) == 0) {
 		switch (cfgmech) {
+		case CFGMECH_PCIE:
 		case CFGMECH_1:
 			outl(CONF1_ADDR_PORT, (1 << 31)
 			    | (bus << 16) | (slot << 11) 
@@ -279,6 +313,7 @@ static void
 pci_cfgdisable(void)
 {
 	switch (cfgmech) {
+	case CFGMECH_PCIE:
 	case CFGMECH_1:
 		/*
 		 * Do nothing for the config mechanism 1 case.
@@ -299,11 +334,6 @@ pcireg_cfgread(int bus, int slot, int fu
 	int data = -1;
 	int port;
 
-	if (cfgmech == CFGMECH_PCIE) {
-		data = pciereg_cfgread(bus, slot, func, reg, bytes);
-		return (data);
-	}
-
 	mtx_lock_spin(&pcicfg_mtx);
 	port = pci_cfgenable(bus, slot, func, reg, bytes);
 	if (port != 0) {
@@ -329,11 +359,6 @@ pcireg_cfgwrite(int bus, int slot, int f
 {
 	int port;
 
-	if (cfgmech == CFGMECH_PCIE) {
-		pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
-		return;
-	}
-
 	mtx_lock_spin(&pcicfg_mtx);
 	port = pci_cfgenable(bus, slot, func, reg, bytes);
 	if (port != 0) {
@@ -481,8 +506,8 @@ pcireg_cfgopen(void)
 	return (cfgmech);
 }
 
-static int
-pciereg_cfgopen(void)
+int
+pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
 {
 	struct pcie_cfg_list *pcielist;
 	struct pcie_cfg_elem *pcie_array, *elem;
@@ -490,10 +515,28 @@ pciereg_cfgopen(void)
 	struct pcpu *pc;
 #endif
 	vm_offset_t va;
-	int i;
+	uint32_t val1, val2;
+	int i, slot;
 
+	if (!mcfg_enable)
+		return (0);
+
+	if (minbus != 0)
+		return (0);
+
+#ifndef PAE
+	if (base >= 0x100000000) {
+		if (bootverbose)
+			printf(
+	    "PCI: Memory Mapped PCI configuration area base 0x%jx too high\n",
+			    (uintmax_t)base);
+		return (0);
+	}
+#endif
+		
 	if (bootverbose)
-		printf("Setting up PCIe mappings for BAR 0x%x\n", pciebar);
+		printf("PCIe: Memory Mapped configuration base @ 0x%jx\n",
+		    (uintmax_t)base);
 
 #ifdef SMP
 	SLIST_FOREACH(pc, &cpuhead, pc_allcpu)
@@ -525,9 +568,30 @@ pciereg_cfgopen(void)
 		}
 	}
 
-	
+	pcie_base = base;
+	pcie_minbus = minbus;
+	pcie_maxbus = maxbus;
 	cfgmech = CFGMECH_PCIE;
 	devmax = 32;
+
+	/*
+	 * On some AMD systems, some of the devices on bus 0 are
+	 * inaccessible using memory-mapped PCI config access.  Walk
+	 * bus 0 looking for such devices.  For these devices, we will
+	 * fall back to using type 1 config access instead.
+	 */
+	if (pci_cfgregopen() != 0) {
+		for (slot = 0; slot < 32; slot++) {
+			val1 = pcireg_cfgread(0, slot, 0, 0, 4);
+			if (val1 == 0xffffffff)
+				continue;
+
+			val2 = pciereg_cfgread(0, slot, 0, 0, 4);
+			if (val2 != val1)
+				pcie_badslots |= (1 << slot);
+		}
+	}
+
 	return (1);
 }
 
@@ -574,15 +638,20 @@ pciereg_findelem(vm_paddr_t papage)
 }
 
 static int
-pciereg_cfgread(int bus, int slot, int func, int reg, int bytes)
+pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
+    unsigned bytes)
 {
 	struct pcie_cfg_elem *elem;
 	volatile vm_offset_t va;
 	vm_paddr_t pa, papage;
-	int data;
+	int data = -1;
+
+	if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 ||
+	    func > PCI_FUNCMAX || reg >= 0x1000 || bytes > 4 || bytes == 3)
+		return (-1);
 
 	critical_enter();
-	pa = PCIE_PADDR(pciebar, reg, bus, slot, func);
+	pa = PCIE_PADDR(pcie_base, reg, bus, slot, func);
 	papage = pa & ~PAGE_MASK;
 	elem = pciereg_findelem(papage);
 	va = elem->vapage | (pa & PAGE_MASK);
@@ -597,8 +666,6 @@ pciereg_cfgread(int bus, int slot, int f
 	case 1:
 		data = *(volatile uint8_t *)(va);
 		break;
-	default:
-		panic("pciereg_cfgread: invalid width");
 	}
 
 	critical_exit();
@@ -606,14 +673,19 @@ pciereg_cfgread(int bus, int slot, int f
 }
 
 static void
-pciereg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
+pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data,
+    unsigned bytes)
 {
 	struct pcie_cfg_elem *elem;
 	volatile vm_offset_t va;
 	vm_paddr_t pa, papage;
 
+	if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 ||
+	    func > PCI_FUNCMAX || reg >= 0x1000)
+		return;
+
 	critical_enter();
-	pa = PCIE_PADDR(pciebar, reg, bus, slot, func);
+	pa = PCIE_PADDR(pcie_base, reg, bus, slot, func);
 	papage = pa & ~PAGE_MASK;
 	elem = pciereg_findelem(papage);
 	va = elem->vapage | (pa & PAGE_MASK);
@@ -628,8 +700,6 @@ pciereg_cfgwrite(int bus, int slot, int 
 	case 1:
 		*(volatile uint8_t *)(va) = data;
 		break;
-	default:
-		panic("pciereg_cfgwrite: invalid width");
 	}
 
 	critical_exit();



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905042104.n44L4TcW057206>