summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c107
-rw-r--r--sys/dev/pci/pci_pci.c41
-rw-r--r--sys/dev/pci/pcib_private.h3
-rw-r--r--sys/dev/pci/pcivar.h10
4 files changed, 54 insertions, 107 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 8b1a283..e5db8e2 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -590,19 +590,9 @@ pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
cfg->nummaps = PCI_MAXMAPS_0;
break;
case PCIM_HDRTYPE_BRIDGE:
- cfg->bridge.br_seclat = REG(PCIR_SECLAT_1, 1);
- cfg->bridge.br_subbus = REG(PCIR_SUBBUS_1, 1);
- cfg->bridge.br_secbus = REG(PCIR_SECBUS_1, 1);
- cfg->bridge.br_pribus = REG(PCIR_PRIBUS_1, 1);
- cfg->bridge.br_control = REG(PCIR_BRIDGECTL_1, 2);
cfg->nummaps = PCI_MAXMAPS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
- cfg->bridge.br_seclat = REG(PCIR_SECLAT_2, 1);
- cfg->bridge.br_subbus = REG(PCIR_SUBBUS_2, 1);
- cfg->bridge.br_secbus = REG(PCIR_SECBUS_2, 1);
- cfg->bridge.br_pribus = REG(PCIR_PRIBUS_2, 1);
- cfg->bridge.br_control = REG(PCIR_BRIDGECTL_2, 2);
cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
cfg->nummaps = PCI_MAXMAPS_2;
@@ -4948,6 +4938,16 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
{
/*
+ * Only do header type 0 devices. Type 1 devices are bridges,
+ * which we know need special treatment. Type 2 devices are
+ * cardbus bridges which also require special treatment.
+ * Other types are unknown, and we err on the side of safety
+ * by ignoring them.
+ */
+ if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL)
+ return;
+
+ /*
* Restore the device to full power mode. We must do this
* before we restore the registers because moving from D3 to
* D0 will cause the chip's BARs and some other registers to
@@ -4957,44 +4957,16 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
*/
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0)
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_restore_bars(dev);
pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2);
pci_write_config(dev, PCIR_INTLINE, dinfo->cfg.intline, 1);
pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1);
+ pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1);
+ pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1);
pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1);
pci_write_config(dev, PCIR_LATTIMER, dinfo->cfg.lattimer, 1);
pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1);
pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1);
- switch (dinfo->cfg.hdrtype & PCIM_HDRTYPE) {
- case PCIM_HDRTYPE_NORMAL:
- pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1);
- pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1);
- break;
- case PCIM_HDRTYPE_BRIDGE:
- pci_write_config(dev, PCIR_SECLAT_1,
- dinfo->cfg.bridge.br_seclat, 1);
- pci_write_config(dev, PCIR_SUBBUS_1,
- dinfo->cfg.bridge.br_subbus, 1);
- pci_write_config(dev, PCIR_SECBUS_1,
- dinfo->cfg.bridge.br_secbus, 1);
- pci_write_config(dev, PCIR_PRIBUS_1,
- dinfo->cfg.bridge.br_pribus, 1);
- pci_write_config(dev, PCIR_BRIDGECTL_1,
- dinfo->cfg.bridge.br_control, 2);
- break;
- case PCIM_HDRTYPE_CARDBUS:
- pci_write_config(dev, PCIR_SECLAT_2,
- dinfo->cfg.bridge.br_seclat, 1);
- pci_write_config(dev, PCIR_SUBBUS_2,
- dinfo->cfg.bridge.br_subbus, 1);
- pci_write_config(dev, PCIR_SECBUS_2,
- dinfo->cfg.bridge.br_secbus, 1);
- pci_write_config(dev, PCIR_PRIBUS_2,
- dinfo->cfg.bridge.br_pribus, 1);
- pci_write_config(dev, PCIR_BRIDGECTL_2,
- dinfo->cfg.bridge.br_control, 2);
- break;
- }
- pci_restore_bars(dev);
/*
* Restore extended capabilities for PCI-Express and PCI-X
@@ -5063,57 +5035,40 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
int ps;
/*
+ * Only do header type 0 devices. Type 1 devices are bridges, which
+ * we know need special treatment. Type 2 devices are cardbus bridges
+ * which also require special treatment. Other types are unknown, and
+ * we err on the side of safety by ignoring them. Powering down
+ * bridges should not be undertaken lightly.
+ */
+ if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL)
+ return;
+
+ /*
* Some drivers apparently write to these registers w/o updating our
* cached copy. No harm happens if we update the copy, so do so here
* so we can restore them. The COMMAND register is modified by the
* bus w/o updating the cache. This should represent the normally
- * writable portion of the 'defined' part of type 0/1/2 headers.
+ * writable portion of the 'defined' part of type 0 headers. In
+ * theory we also need to save/restore the PCI capability structures
+ * we know about, but apart from power we don't know any that are
+ * writable.
*/
+ dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_0, 2);
+ dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_0, 2);
dinfo->cfg.vendor = pci_read_config(dev, PCIR_VENDOR, 2);
dinfo->cfg.device = pci_read_config(dev, PCIR_DEVICE, 2);
dinfo->cfg.cmdreg = pci_read_config(dev, PCIR_COMMAND, 2);
dinfo->cfg.intline = pci_read_config(dev, PCIR_INTLINE, 1);
dinfo->cfg.intpin = pci_read_config(dev, PCIR_INTPIN, 1);
+ dinfo->cfg.mingnt = pci_read_config(dev, PCIR_MINGNT, 1);
+ dinfo->cfg.maxlat = pci_read_config(dev, PCIR_MAXLAT, 1);
dinfo->cfg.cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
dinfo->cfg.lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
dinfo->cfg.baseclass = pci_read_config(dev, PCIR_CLASS, 1);
dinfo->cfg.subclass = pci_read_config(dev, PCIR_SUBCLASS, 1);
dinfo->cfg.progif = pci_read_config(dev, PCIR_PROGIF, 1);
dinfo->cfg.revid = pci_read_config(dev, PCIR_REVID, 1);
- switch (dinfo->cfg.hdrtype & PCIM_HDRTYPE) {
- case PCIM_HDRTYPE_NORMAL:
- dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_0, 2);
- dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_0, 2);
- dinfo->cfg.mingnt = pci_read_config(dev, PCIR_MINGNT, 1);
- dinfo->cfg.maxlat = pci_read_config(dev, PCIR_MAXLAT, 1);
- break;
- case PCIM_HDRTYPE_BRIDGE:
- dinfo->cfg.bridge.br_seclat = pci_read_config(dev,
- PCIR_SECLAT_1, 1);
- dinfo->cfg.bridge.br_subbus = pci_read_config(dev,
- PCIR_SUBBUS_1, 1);
- dinfo->cfg.bridge.br_secbus = pci_read_config(dev,
- PCIR_SECBUS_1, 1);
- dinfo->cfg.bridge.br_pribus = pci_read_config(dev,
- PCIR_PRIBUS_1, 1);
- dinfo->cfg.bridge.br_control = pci_read_config(dev,
- PCIR_BRIDGECTL_1, 2);
- break;
- case PCIM_HDRTYPE_CARDBUS:
- dinfo->cfg.bridge.br_seclat = pci_read_config(dev,
- PCIR_SECLAT_2, 1);
- dinfo->cfg.bridge.br_subbus = pci_read_config(dev,
- PCIR_SUBBUS_2, 1);
- dinfo->cfg.bridge.br_secbus = pci_read_config(dev,
- PCIR_SECBUS_2, 1);
- dinfo->cfg.bridge.br_pribus = pci_read_config(dev,
- PCIR_PRIBUS_2, 1);
- dinfo->cfg.bridge.br_control = pci_read_config(dev,
- PCIR_BRIDGECTL_2, 2);
- dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_2, 2);
- dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_2, 2);
- break;
- }
if (dinfo->cfg.pcie.pcie_location != 0)
pci_cfg_save_pcie(dev, dinfo);
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 30cb681..62ddc3d 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -549,22 +549,18 @@ void
pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count)
{
char buf[64];
- int error, rid, sec_reg;
+ int error, rid;
switch (pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_BRIDGE:
- sec_reg = PCIR_SECBUS_1;
bus->sub_reg = PCIR_SUBBUS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
- sec_reg = PCIR_SECBUS_2;
bus->sub_reg = PCIR_SUBBUS_2;
break;
default:
panic("not a PCI bridge");
}
- bus->sec = pci_read_config(dev, sec_reg, 1);
- bus->sub = pci_read_config(dev, bus->sub_reg, 1);
bus->dev = dev;
bus->rman.rm_start = 0;
bus->rman.rm_end = PCI_BUSMAX;
@@ -849,16 +845,20 @@ pcib_set_mem_decode(struct pcib_softc *sc)
static void
pcib_cfg_save(struct pcib_softc *sc)
{
-#ifndef NEW_PCIB
device_t dev;
- uint16_t command;
dev = sc->dev;
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if (command & PCIM_CMD_PORTEN)
+ sc->command = pci_read_config(dev, PCIR_COMMAND, 2);
+ sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1);
+ sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1);
+ sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1);
+ sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
+ sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1);
+#ifndef NEW_PCIB
+ if (sc->command & PCIM_CMD_PORTEN)
pcib_get_io_decode(sc);
- if (command & PCIM_CMD_MEMEN)
+ if (sc->command & PCIM_CMD_MEMEN)
pcib_get_mem_decode(sc);
#endif
}
@@ -870,18 +870,21 @@ static void
pcib_cfg_restore(struct pcib_softc *sc)
{
device_t dev;
-#ifndef NEW_PCIB
- uint16_t command;
-#endif
+
dev = sc->dev;
+ pci_write_config(dev, PCIR_COMMAND, sc->command, 2);
+ pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1);
+ pci_write_config(dev, PCIR_SECBUS_1, sc->bus.sec, 1);
+ pci_write_config(dev, PCIR_SUBBUS_1, sc->bus.sub, 1);
+ pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2);
+ pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1);
#ifdef NEW_PCIB
pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM);
#else
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if (command & PCIM_CMD_PORTEN)
+ if (sc->command & PCIM_CMD_PORTEN)
pcib_set_io_decode(sc);
- if (command & PCIM_CMD_MEMEN)
+ if (sc->command & PCIM_CMD_MEMEN)
pcib_set_mem_decode(sc);
#endif
}
@@ -915,11 +918,7 @@ pcib_attach_common(device_t dev)
* Get current bridge configuration.
*/
sc->domain = pci_get_domain(dev);
-#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
- sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1);
- sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1);
-#endif
- sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
+ sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2);
pcib_cfg_save(sc);
/*
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index 8cf2280..cbc2b85 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -106,6 +106,7 @@ struct pcib_softc
#define PCIB_DISABLE_MSI 0x2
#define PCIB_DISABLE_MSIX 0x4
#define PCIB_ENABLE_ARI 0x8
+ uint16_t command; /* command register */
u_int domain; /* domain number */
u_int pribus; /* primary bus number */
struct pcib_secbus bus; /* secondary bus numbers */
@@ -121,7 +122,9 @@ struct pcib_softc
uint32_t iobase; /* base address of port window */
uint32_t iolimit; /* topmost address of port window */
#endif
+ uint16_t secstat; /* secondary bus status register */
uint16_t bridgectl; /* bridge control register */
+ uint8_t seclat; /* secondary bus latency timer */
};
#define PCIB_SUPPORTED_ARI_VER 1
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 4eb50e2..0157ee7 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -39,15 +39,6 @@
typedef uint64_t pci_addr_t;
-/* Config registers for PCI-PCI and PCI-Cardbus bridges. */
-struct pcicfg_bridge {
- uint8_t br_seclat;
- uint8_t br_subbus;
- uint8_t br_secbus;
- uint8_t br_pribus;
- uint16_t br_control;
-};
-
/* Interesting values for PCI power management */
struct pcicfg_pp {
uint16_t pp_cap; /* PCI power management capabilities */
@@ -188,7 +179,6 @@ typedef struct pcicfg {
uint8_t slot; /* config space slot address */
uint8_t func; /* config space function number */
- struct pcicfg_bridge bridge; /* Bridges */
struct pcicfg_pp pp; /* Power management */
struct pcicfg_vpd vpd; /* Vital product data */
struct pcicfg_msi msi; /* PCI MSI */
OpenPOWER on IntegriCloud