Hi, with kettenis' change from 2015(?) we can configure a ppb(4)'s bus information. Unfortunately the hotplug fixup code runs before that change has a chance, and it will program a single bus (with no amount of children) below it. I think that part of the hotplug fixup can go away.
The hotplug fixup also contains code for fixing up interrupt lines. On my todays machine it uses MSIs, so a missing interrupt line does not hurt me. I'm not sure if this is still needed for yesterday's machines. Apparently that code was for some ExpressCards? Patrick diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c index a9ff32ce33c..22ff8ca2b5f 100644 --- a/sys/dev/pci/ppb.c +++ b/sys/dev/pci/ppb.c @@ -117,9 +117,6 @@ void ppb_alloc_resources(struct ppb_softc *, struct pci_attach_args *); int ppb_intr(void *); void ppb_hotplug_insert(void *); void ppb_hotplug_insert_finish(void *); -int ppb_hotplug_fixup(struct pci_attach_args *); -int ppb_hotplug_fixup_type0(pci_chipset_tag_t, pcitag_t, pcitag_t); -int ppb_hotplug_fixup_type1(pci_chipset_tag_t, pcitag_t, pcitag_t); void ppb_hotplug_rescan(void *); void ppb_hotplug_remove(void *); int ppbprint(void *, const char *pnp); @@ -776,108 +773,14 @@ ppb_hotplug_insert_finish(void *arg) task_add(systq, &sc->sc_rescan_task); } -int -ppb_hotplug_fixup(struct pci_attach_args *pa) -{ - pcireg_t bhlcr; - - bhlcr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); - switch (PCI_HDRTYPE_TYPE(bhlcr)) { - case 0: - return ppb_hotplug_fixup_type0(pa->pa_pc, - pa->pa_tag, *pa->pa_bridgetag); - case 1: - return ppb_hotplug_fixup_type1(pa->pa_pc, - pa->pa_tag, *pa->pa_bridgetag); - default: - return (0); - } -} - -int -ppb_hotplug_fixup_type0(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag) -{ - pcireg_t intr; - int line; - - /* - * Fill in the interrupt line for platforms that need it. - * - * XXX We assume that the interrupt line matches the line used - * by the PCI Express bridge. This may not be true. - */ - intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); - if (PCI_INTERRUPT_PIN(intr) != PCI_INTERRUPT_PIN_NONE && - PCI_INTERRUPT_LINE(intr) == 0) { - /* Get the interrupt line from our parent. */ - intr = pci_conf_read(pc, bridgetag, PCI_INTERRUPT_REG); - line = PCI_INTERRUPT_LINE(intr); - - intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); - intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); - intr |= line << PCI_INTERRUPT_LINE_SHIFT; - pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr); - } - - return (0); -} - -int -ppb_hotplug_fixup_type1(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag) -{ - pcireg_t bhlcr, bir, csr, val; - int bus, dev, reg; - - bir = pci_conf_read(pc, bridgetag, PPB_REG_BUSINFO); - if (PPB_BUSINFO_SUBORDINATE(bir) <= PPB_BUSINFO_SECONDARY(bir)) - return (0); - - bus = PPB_BUSINFO_SECONDARY(bir); - bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO); - bir &= (0xff << 24); - bir |= bus++; - bir |= (bus << 8); - bir |= (bus << 16); - pci_conf_write(pc, tag, PPB_REG_BUSINFO, bir); - - for (reg = PPB_REG_IOSTATUS; reg < PPB_REG_BRIDGECONTROL; reg += 4) { - val = pci_conf_read(pc, bridgetag, reg); - pci_conf_write(pc, tag, reg, val); - } - - csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; - csr |= PCI_COMMAND_MASTER_ENABLE; - csr |= PCI_COMMAND_INVALIDATE_ENABLE; - csr |= PCI_COMMAND_SERR_ENABLE; - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); - - for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) { - tag = pci_make_tag(pc, bus, dev, 0); - - bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); - if (PCI_HDRTYPE_TYPE(bhlcr) != 0) - continue; - - ppb_hotplug_fixup_type0(pc, tag, bridgetag); - } - - return (0); -} - void ppb_hotplug_rescan(void *xsc) { struct ppb_softc *sc = xsc; struct pci_softc *psc = (struct pci_softc *)sc->sc_psc; - if (psc) { - /* Assign resources. */ - pci_enumerate_bus(psc, ppb_hotplug_fixup, NULL); - - /* Attach devices. */ + if (psc) pci_enumerate_bus(psc, NULL, NULL); - } } void