svn commit: r233214 - stable/8/sys/dev/pci

Jung-uk Kim jkim at FreeBSD.org
Mon Mar 19 22:26:03 UTC 2012


Author: jkim
Date: Mon Mar 19 22:26:02 2012
New Revision: 233214
URL: http://svn.freebsd.org/changeset/base/233214

Log:
  MFC:	r232991
  
  Add a PCI quirk to ignore PCI map registers from configuration space.
  This works around a resource conflict, e. g., MSI K9AGM2 motherboard.

Modified:
  stable/8/sys/dev/pci/pci.c
Directory Properties:
  stable/8/sys/   (props changed)

Modified: stable/8/sys/dev/pci/pci.c
==============================================================================
--- stable/8/sys/dev/pci/pci.c	Mon Mar 19 22:23:52 2012	(r233213)
+++ stable/8/sys/dev/pci/pci.c	Mon Mar 19 22:26:02 2012	(r233214)
@@ -188,6 +188,7 @@ struct pci_quirk {
 #define	PCI_QUIRK_MAP_REG	1 /* PCI map register in weird place */
 #define	PCI_QUIRK_DISABLE_MSI	2 /* MSI/MSI-X doesn't work */
 #define	PCI_QUIRK_ENABLE_MSI_VM	3 /* Older chipset in VM where MSI works */
+#define	PCI_QUIRK_UNMAP_REG	4 /* Ignore PCI map register */
 	int	arg1;
 	int	arg2;
 };
@@ -236,6 +237,16 @@ static const struct pci_quirk const pci_
 	 */
 	{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM,	0,	0 },
 
+	/*
+	 * HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
+	 * controller depending on SoftPciRst register (PM_IO 0x55 [7]).
+	 * It prevents us from attaching hpet(4) when the bit is unset.
+	 * Note this quirk only affects SB600 revision A13 and earlier.
+	 * For SB600 A21 and later, firmware must set the bit to hide it.
+	 * For SB700 and later, it is unused and hardcoded to zero.
+	 */
+	{ 0x43851002, PCI_QUIRK_UNMAP_REG,	0x14,	0 },
+
 	{ 0 }
 };
 
@@ -2790,12 +2801,18 @@ ehci_early_takeover(device_t self)
 void
 pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
 {
-	struct pci_devinfo *dinfo = device_get_ivars(dev);
-	pcicfgregs *cfg = &dinfo->cfg;
-	struct resource_list *rl = &dinfo->resources;
+	struct pci_devinfo *dinfo;
+	pcicfgregs *cfg;
+	struct resource_list *rl;
 	const struct pci_quirk *q;
+	uint32_t devid;
 	int i;
 
+	dinfo = device_get_ivars(dev);
+	cfg = &dinfo->cfg;
+	rl = &dinfo->resources;
+	devid = (cfg->device << 16) | cfg->vendor;
+
 	/* ATA devices needs special map treatment */
 	if ((pci_get_class(dev) == PCIC_STORAGE) &&
 	    (pci_get_subclass(dev) == PCIS_STORAGE_IDE) &&
@@ -2804,18 +2821,29 @@ pci_add_resources(device_t bus, device_t
 	      !pci_read_config(dev, PCIR_BAR(2), 4))) )
 		pci_ata_maps(bus, dev, rl, force, prefetchmask);
 	else
-		for (i = 0; i < cfg->nummaps;)
+		for (i = 0; i < cfg->nummaps;) {
+			/*
+			 * Skip quirked resources.
+			 */
+			for (q = &pci_quirks[0]; q->devid != 0; q++)
+				if (q->devid == devid &&
+				    q->type == PCI_QUIRK_UNMAP_REG &&
+				    q->arg1 == PCIR_BAR(i))
+					break;
+			if (q->devid != 0) {
+				i++;
+				continue;
+			}
 			i += pci_add_map(bus, dev, PCIR_BAR(i), rl, force,
 			    prefetchmask & (1 << i));
+		}
 
 	/*
 	 * Add additional, quirked resources.
 	 */
-	for (q = &pci_quirks[0]; q->devid; q++) {
-		if (q->devid == ((cfg->device << 16) | cfg->vendor)
-		    && q->type == PCI_QUIRK_MAP_REG)
+	for (q = &pci_quirks[0]; q->devid != 0; q++)
+		if (q->devid == devid && q->type == PCI_QUIRK_MAP_REG)
 			pci_add_map(bus, dev, q->arg1, rl, force, 0);
-	}
 
 	if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) {
 #ifdef __PCI_REROUTE_INTERRUPT


More information about the svn-src-all mailing list