Index: sys/dev/pccbb/pccbb_pci.c =================================================================== --- sys/dev/pccbb/pccbb_pci.c +++ sys/dev/pccbb/pccbb_pci.c @@ -259,32 +259,6 @@ } /* - * Still need this because the pci code only does power for type 0 - * header devices. - */ -static void -cbb_powerstate_d0(device_t dev) -{ - u_int32_t membase, irq; - - if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { - /* Save important PCI config data. */ - membase = pci_read_config(dev, CBBR_SOCKBASE, 4); - irq = pci_read_config(dev, PCIR_INTLINE, 4); - - /* Reset the power state. */ - device_printf(dev, "chip is in D%d power mode " - "-- setting to D0\n", pci_get_powerstate(dev)); - - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - - /* Restore PCI config data. */ - pci_write_config(dev, CBBR_SOCKBASE, membase, 4); - pci_write_config(dev, PCIR_INTLINE, irq, 4); - } -} - -/* * Print out the config space */ static void @@ -321,15 +295,15 @@ sc->cbdev = NULL; sc->exca[0].pccarddev = NULL; sc->domain = pci_get_domain(brdev); - sc->bus.sec = pci_read_config(brdev, PCIR_SECBUS_2, 1); - sc->bus.sub = pci_read_config(brdev, PCIR_SUBBUS_2, 1); sc->pribus = pcib_get_bus(parent); #if defined(NEW_PCIB) && defined(PCI_RES_BUS) pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1); pcib_setup_secbus(brdev, &sc->bus, 1); +#else + sc->bus.sec = pci_read_config(brdev, PCIR_SECBUS_2, 1); + sc->bus.sub = pci_read_config(brdev, PCIR_SUBBUS_2, 1); #endif SLIST_INIT(&sc->rl); - cbb_powerstate_d0(brdev); rid = CBBR_SOCKBASE; sc->base_res = bus_alloc_resource_any(brdev, SYS_RES_MEMORY, &rid, @@ -467,18 +441,13 @@ uint32_t mux, sysctrl, reg; /* Set CardBus latency timer */ - if (pci_read_config(sc->dev, PCIR_SECLAT_1, 1) < 0x20) - pci_write_config(sc->dev, PCIR_SECLAT_1, 0x20, 1); + if (pci_read_config(sc->dev, PCIR_SECLAT_2, 1) < 0x20) + pci_write_config(sc->dev, PCIR_SECLAT_2, 0x20, 1); /* Set PCI latency timer */ if (pci_read_config(sc->dev, PCIR_LATTIMER, 1) < 0x20) pci_write_config(sc->dev, PCIR_LATTIMER, 0x20, 1); - /* Restore bus configuration */ - pci_write_config(sc->dev, PCIR_PRIBUS_2, sc->pribus, 1); - pci_write_config(sc->dev, PCIR_SECBUS_2, sc->bus.sec, 1); - pci_write_config(sc->dev, PCIR_SUBBUS_2, sc->bus.sub, 1); - /* Enable DMA, memory access for this card and I/O acces for children */ pci_enable_busmaster(sc->dev); pci_enable_io(sc->dev, SYS_RES_IOPORT); @@ -906,15 +875,10 @@ * from D0 and back to D0 cause the bridge to lose its config space, so * all the bus mappings and such are preserved. * - * For most drivers, the PCI layer handles this saving. However, since - * there's much black magic and arcane art hidden in these few lines of - * code that would be difficult to transition into the PCI - * layer. chipinit was several years of trial and error to write. + * The PCI layer handles standard PCI registers like the + * command register and BARs, but cbb-specific registers are + * handled here. */ - pci_write_config(brdev, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4); - DEVPRINTF((brdev, "PCI Memory allocated: %08lx\n", - rman_get_start(sc->base_res))); - sc->chipinit(sc); /* reset interrupt -- Do we really need to do this? */ Index: sys/dev/pci/pci.c =================================================================== --- sys/dev/pci/pci.c +++ sys/dev/pci/pci.c @@ -583,12 +583,24 @@ case PCIM_HDRTYPE_NORMAL: cfg->subvendor = REG(PCIR_SUBVEND_0, 2); cfg->subdevice = REG(PCIR_SUBDEV_0, 2); + cfg->mingnt = REG(PCIR_MINGNT, 1); + cfg->maxlat = REG(PCIR_MAXLAT, 1); 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; @@ -641,9 +653,6 @@ cfg->intpin = REG(PCIR_INTPIN, 1); cfg->intline = REG(PCIR_INTLINE, 1); - cfg->mingnt = REG(PCIR_MINGNT, 1); - cfg->maxlat = REG(PCIR_MAXLAT, 1); - cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; cfg->hdrtype &= ~PCIM_MFDEV; STAILQ_INIT(&cfg->maps); @@ -4425,9 +4434,17 @@ *result = cfg->cachelnsz; break; case PCI_IVAR_MINGNT: + if (cfg->hdrtype != PCIM_HDRTYPE_NORMAL) { + *result = -1; + return (EINVAL); + } *result = cfg->mingnt; break; case PCI_IVAR_MAXLAT: + if (cfg->hdrtype != PCIM_HDRTYPE_NORMAL) { + *result = -1; + return (EINVAL); + } *result = cfg->maxlat; break; case PCI_IVAR_LATTIMER: @@ -5125,16 +5142,6 @@ { /* - * 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 @@ -5144,16 +5151,44 @@ */ 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 @@ -5222,40 +5257,57 @@ 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 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. + * writable portion of the 'defined' part of type 0/1/2 headers. */ - 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); Index: sys/dev/pci/pci_pci.c =================================================================== --- sys/dev/pci/pci_pci.c +++ sys/dev/pci/pci_pci.c @@ -553,18 +553,22 @@ pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count) { char buf[64]; - int error, rid; + int error, rid, sec_reg; 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,20 +853,16 @@ static void pcib_cfg_save(struct pcib_softc *sc) { +#ifndef NEW_PCIB device_t dev; + uint16_t command; dev = sc->dev; - 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) + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command & PCIM_CMD_PORTEN) pcib_get_io_decode(sc); - if (sc->command & PCIM_CMD_MEMEN) + if (command & PCIM_CMD_MEMEN) pcib_get_mem_decode(sc); #endif } @@ -874,21 +874,18 @@ 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 - if (sc->command & PCIM_CMD_PORTEN) + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command & PCIM_CMD_PORTEN) pcib_set_io_decode(sc); - if (sc->command & PCIM_CMD_MEMEN) + if (command & PCIM_CMD_MEMEN) pcib_set_mem_decode(sc); #endif } @@ -922,7 +919,11 @@ * Get current bridge configuration. */ sc->domain = pci_get_domain(dev); - sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); +#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); pcib_cfg_save(sc); /* @@ -950,7 +951,7 @@ * Quirk handling. */ switch (pci_get_devid(dev)) { -#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS) +#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS)) case 0x12258086: /* Intel 82454KX/GX (Orion) */ { uint8_t supbus; @@ -976,7 +977,7 @@ sc->flags |= PCIB_SUBTRACTIVE; break; -#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS) +#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS)) /* Compaq R3000 BIOS sets wrong subordinate bus number. */ case 0x00dd10de: { @@ -1101,32 +1102,15 @@ int pcib_suspend(device_t dev) { - device_t pcib; - int dstate, error; pcib_cfg_save(device_get_softc(dev)); - error = bus_generic_suspend(dev); - if (error == 0 && pci_do_power_suspend) { - dstate = PCI_POWERSTATE_D3; - pcib = device_get_parent(device_get_parent(dev)); - if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) - pci_set_powerstate(dev, dstate); - } - return (error); + return (bus_generic_suspend(dev)); } int pcib_resume(device_t dev) { - device_t pcib; - int dstate; - - if (pci_do_power_resume) { - pcib = device_get_parent(device_get_parent(dev)); - dstate = PCI_POWERSTATE_D0; - if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) - pci_set_powerstate(dev, dstate); - } + pcib_cfg_restore(device_get_softc(dev)); return (bus_generic_resume(dev)); } Index: sys/dev/pci/pcib_private.h =================================================================== --- sys/dev/pci/pcib_private.h +++ sys/dev/pci/pcib_private.h @@ -106,7 +106,6 @@ #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 */ @@ -122,9 +121,7 @@ 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 Index: sys/dev/pci/pcivar.h =================================================================== --- sys/dev/pci/pcivar.h +++ sys/dev/pci/pcivar.h @@ -41,6 +41,15 @@ struct nvlist; +/* 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 */ @@ -190,6 +199,7 @@ uint32_t flags; /* flags defined above */ size_t devinfo_size; /* Size of devinfo for this bus type. */ + struct pcicfg_bridge bridge; /* Bridges */ struct pcicfg_pp pp; /* Power management */ struct pcicfg_vpd vpd; /* Vital product data */ struct pcicfg_msi msi; /* PCI MSI */