cbb(4): Rework secondary bus number setup; aware of PCI domain
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 5 Jul 2009 04:19:47 +0000 (12:19 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 8 Jul 2009 10:50:41 +0000 (18:50 +0800)
Obtained-from: FreeBSD

sys/dev/pccard/pccbb/pccbb.c
sys/dev/pccard/pccbb/pccbb_pci.c
sys/dev/pccard/pccbb/pccbbvar.h

index 0ef6538..074b324 100644 (file)
@@ -1487,6 +1487,9 @@ cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
        struct cbb_softc *sc = device_get_softc(brdev);
 
        switch (which) {
+       case PCIB_IVAR_DOMAIN:
+               *result = sc->domain;
+               return (0);
        case PCIB_IVAR_BUS:
                *result = sc->secbus;
                return (0);
@@ -1500,6 +1503,8 @@ cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
        struct cbb_softc *sc = device_get_softc(brdev);
 
        switch (which) {
+       case PCIB_IVAR_DOMAIN:
+               return (EINVAL);
        case PCIB_IVAR_BUS:
                sc->secbus = value;
                break;
index e297a6b..dba8ca7 100644 (file)
@@ -299,19 +299,21 @@ static int
 cbb_pci_attach(device_t brdev)
 {
        static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
+
        struct cbb_softc *sc = device_get_softc(brdev);
-       int rid, bus, pribus;
-       device_t parent, grand_parent;
+       int rid, pribus;
+       device_t parent;
 
        parent = device_get_parent(brdev);
-       grand_parent = device_get_parent(parent);
 
        sc->chipset = cbb_chipset(pci_get_devid(brdev), NULL);
        sc->dev = brdev;
        sc->cbdev = NULL;
        sc->exca[0].pccarddev = NULL;
+       sc->domain = pci_get_domain(brdev);
        sc->secbus = pci_read_config(brdev, PCIR_SECBUS_2, 1);
        sc->subbus = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
+       sc->pribus = pcib_get_bus(parent);
        SLIST_INIT(&sc->rl);
        cbb_powerstate_d0(brdev);
 
@@ -368,24 +370,22 @@ cbb_pci_attach(device_t brdev)
         * reserve 1 extra bus just in case and (2) all sub busses 
         * are in an appropriate range.
         */
-       bus = pci_read_config(brdev, PCIR_SECBUS_2, 1);
-       pribus = pcib_get_bus(grand_parent);
-       DEVPRINTF((brdev, "Secondary bus is %d\n", bus));
-       if (bus == 0) {
-               if (curr_bus_number <= pribus)
-                       curr_bus_number = pribus + 1;
-               if (pci_read_config(brdev, PCIR_PRIBUS_2, 1) != pribus) {
-                       DEVPRINTF((brdev, "Setting primary bus to %d\n", pribus));
-                       pci_write_config(brdev, PCIR_PRIBUS_2, pribus, 1);
+       DEVPRINTF((brdev, "Secondary bus is %d\n", sc->secbus));
+       pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1);
+       if (sc->secbus == 0 || sc->pribus != pribus) {
+               if (curr_bus_number <= sc->pribus)
+                       curr_bus_number = sc->pribus + 1;
+               if (pribus != sc->pribus) {
+                       DEVPRINTF((brdev, "Setting primary bus to %d\n",
+                           sc->pribus));
+                       pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
                }
-               bus = curr_bus_number;
-               DEVPRINTF((brdev, "Secondary bus set to %d subbus %d\n", bus,
-                   bus + 1));
-               sc->secbus = bus;
-               sc->subbus = bus + 1;
-               pci_write_config(brdev, PCIR_SECBUS_2, bus, 1);
-               pci_write_config(brdev, PCIR_SUBBUS_2, bus + 1, 1);
-               curr_bus_number += 2;
+               sc->secbus = curr_bus_number++;
+               sc->subbus = curr_bus_number++;
+               DEVPRINTF((brdev, "Secondary bus set to %d subbus %d\n",
+                   sc->secbus, sc->subbus));
+               pci_write_config(brdev, PCIR_SECBUS_2, sc->secbus, 1);
+               pci_write_config(brdev, PCIR_SUBBUS_2, sc->subbus, 1);
        }
 
        /* attach children */
index 9671796..e925cb3 100644 (file)
@@ -63,6 +63,8 @@ struct cbb_softc {
        void            *intrhand;
        bus_space_tag_t bst;
        bus_space_handle_t bsh;
+       u_int32_t       domain;
+       u_int8_t        pribus;
        u_int8_t        secbus;
        u_int8_t        subbus;
        u_int32_t       flags;