diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/pci.c | 107 | ||||
-rw-r--r-- | sys/dev/pci/pci_pci.c | 41 | ||||
-rw-r--r-- | sys/dev/pci/pcib_private.h | 3 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 10 |
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 */ |