Author: jkim
Date: Mon Mar 19 22:08:13 2012
New Revision: 233210
URL: http://svn.freebsd.org/changeset/base/233210

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/9/sys/dev/pci/pci.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/pci/pci.c
==============================================================================
--- stable/9/sys/dev/pci/pci.c  Mon Mar 19 21:57:31 2012        (r233209)
+++ stable/9/sys/dev/pci/pci.c  Mon Mar 19 22:08:13 2012        (r233210)
@@ -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 }
 };
 
@@ -3023,12 +3034,18 @@ xhci_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) &&
@@ -3037,18 +3054,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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to