Author: landonf
Date: Sun Sep  4 00:58:19 2016
New Revision: 305371
URL: https://svnweb.freebsd.org/changeset/base/305371
Log:
  Migrate bhndb(4) to the new bhnd_erom API.
  
  Adds support for probing and initializing bhndb(4) bridge state using
  the bhnd_erom API, ensuring that full bridge configuration is available
  *prior* to actually attaching and enumerating the bhnd(4) child device,
  allowing us to safely allocate bus-level agent/device resources during
  bhnd(4) bus enumeration.
  
  - Add a bhnd_erom_probe() method usable by bhndb(4). This is an analogue
    to the existing bhnd_erom_probe_static() method, and allows the bhndb
    bridge to discover the best available erom parser class prior to newbus
    probing of its children.
  - Add support for supplying identification hints when probing erom
    devices. This is required on early EXTIF-only chipsets, where chip
    identification registers are not available.
  - Migrate bhndb over to the new bhnd_erom API, using bhnd_core_info
    records rather than bridged bhnd(4) device_t references to determine
    the bridged chipsets' capability/bridge configuration.
  - The bhndb parent (e.g. if_bwn) is now required to supply a hardware
    priority table to the bridge. The default table is currently sufficient
    for our supported devices.
  - Drop the two-pass attach approach we used for compatibility with bhndb(4) in
    the bhnd(4) bus drivers, and instead perform bus enumeration immediately,
    and allocate bridged per-child bus-level resources during that enumeration.
  
  Approved by:  adrian (mentor)
  Differential Revision:        https://reviews.freebsd.org/D7768

Modified:
  head/sys/dev/bhnd/bcma/bcma.c
  head/sys/dev/bhnd/bcma/bcma_bhndb.c
  head/sys/dev/bhnd/bcma/bcma_erom.c
  head/sys/dev/bhnd/bcma/bcma_eromvar.h
  head/sys/dev/bhnd/bcma/bcma_nexus.c
  head/sys/dev/bhnd/bcma/bcma_subr.c
  head/sys/dev/bhnd/bcma/bcmavar.h
  head/sys/dev/bhnd/bhnd.h
  head/sys/dev/bhnd/bhnd_bus_if.m
  head/sys/dev/bhnd/bhnd_erom.c
  head/sys/dev/bhnd/bhnd_erom.h
  head/sys/dev/bhnd/bhnd_erom_if.m
  head/sys/dev/bhnd/bhnd_match.h
  head/sys/dev/bhnd/bhnd_nexus.c
  head/sys/dev/bhnd/bhnd_subr.c
  head/sys/dev/bhnd/bhndb/bhnd_bhndb.c
  head/sys/dev/bhnd/bhndb/bhndb.c
  head/sys/dev/bhnd/bhndb/bhndb_bus_if.m
  head/sys/dev/bhnd/bhndb/bhndb_if.m
  head/sys/dev/bhnd/bhndb/bhndb_pci.c
  head/sys/dev/bhnd/bhndb/bhndb_private.h
  head/sys/dev/bhnd/bhndb/bhndb_subr.c
  head/sys/dev/bhnd/bhndb/bhndbvar.h
  head/sys/dev/bhnd/cores/chipc/chipcreg.h
  head/sys/dev/bhnd/siba/siba.c
  head/sys/dev/bhnd/siba/siba_bhndb.c
  head/sys/dev/bhnd/siba/siba_erom.c
  head/sys/dev/bhnd/siba/siba_nexus.c
  head/sys/dev/bhnd/siba/sibavar.h
  head/sys/dev/bwn/if_bwn_pci.c
  head/sys/dev/bwn/if_bwn_pcivar.h
  head/sys/mips/broadcom/bcm_machdep.c
  head/sys/modules/bhnd/bhndb/Makefile

Modified: head/sys/dev/bhnd/bcma/bcma.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma.c       Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma.c       Sun Sep  4 00:58:19 2016        
(r305371)
@@ -48,6 +48,12 @@ __FBSDID("$FreeBSD$");
 /* RID used when allocating EROM table */
 #define        BCMA_EROM_RID   0
 
+static bhnd_erom_class_t *
+bcma_get_erom_class(driver_t *driver)
+{
+       return (&bcma_erom_parser);
+}
+
 int
 bcma_probe(device_t dev)
 {
@@ -55,70 +61,25 @@ bcma_probe(device_t dev)
        return (BUS_PROBE_DEFAULT);
 }
 
+/**
+ * Default bcma(4) bus driver implementation of DEVICE_ATTACH().
+ * 
+ * This implementation initializes internal bcma(4) state and performs
+ * bus enumeration, and must be called by subclassing drivers in
+ * DEVICE_ATTACH() before any other bus methods.
+ */
 int
 bcma_attach(device_t dev)
 {
-       struct bcma_devinfo     *dinfo;
-       device_t                *devs, child;
-       int                      ndevs;
-       int                      error;
+       int error;
 
-
-       if ((error = device_get_children(dev, &devs, &ndevs)))
+       /* Enumerate children */
+       if ((error = bcma_add_children(dev))) {
+               device_delete_children(dev);
                return (error);
-
-       /*
-        * Map our children's agent register block.
-        */
-       for (int i = 0; i < ndevs; i++) {
-               bhnd_addr_t     addr;
-               bhnd_size_t     size;
-               rman_res_t      r_start, r_count, r_end;
-
-               child = devs[i];
-               dinfo = device_get_ivars(child);
-
-               KASSERT(!device_is_suspended(child),
-                   ("bcma(4) stateful suspend handling requires that devices "
-                       "not be suspended before bcma_attach()"));
-               
-               /* Verify that the agent register block exists and is
-                * mappable */
-               if (bhnd_get_port_rid(child, BHND_PORT_AGENT, 0, 0) == -1)
-                       continue;
-
-               /* Fetch the address of the agent register block */
-               error = bhnd_get_region_addr(child, BHND_PORT_AGENT, 0, 0,
-                   &addr, &size);
-               if (error) {
-                       device_printf(dev, "failed fetching agent register "
-                           "block address for core %d\n", i);
-                       goto cleanup;
-               }
-
-               /* Allocate the resource */
-               r_start = addr;
-               r_count = size;
-               r_end = r_start + r_count - 1;
-
-               dinfo->rid_agent = i + 1;
-               dinfo->res_agent = BHND_BUS_ALLOC_RESOURCE(dev, dev,
-                   SYS_RES_MEMORY, &dinfo->rid_agent, r_start, r_end, r_count,
-                   RF_ACTIVE);
-               if (dinfo->res_agent == NULL) {
-                       device_printf(dev, "failed allocating agent register "
-                           "block for core %d\n", i);
-                       error = ENXIO;
-                       goto cleanup;
-               }
        }
 
-cleanup:
-       free(devs, M_BHND);
-       if (error)
-               return (error);
-       
-       return (bhnd_generic_attach(dev));
+       return (0);
 }
 
 int
@@ -191,15 +152,6 @@ bcma_get_resource_list(device_t dev, dev
        return (&dinfo->resources);
 }
 
-static device_t
-bcma_find_hostb_device(device_t dev)
-{
-       struct bcma_softc *sc = device_get_softc(dev);
-
-       /* This is set (or not) by the concrete bcma driver subclass. */
-       return (sc->hostb_dev);
-}
-
 static int
 bcma_reset_core(device_t dev, device_t child, uint16_t flags)
 {
@@ -516,8 +468,7 @@ bcma_add_children(device_t bus)
        corecfg = NULL;
 
        /* Allocate our EROM parser */
-       erom = bhnd_erom_alloc(&bcma_erom_parser, bus, BCMA_EROM_RID,
-           cid->enum_addr);
+       erom = bhnd_erom_alloc(&bcma_erom_parser, cid, bus, BCMA_EROM_RID);
        if (erom == NULL)
                return (ENODEV);
 
@@ -528,17 +479,21 @@ bcma_add_children(device_t bus)
                child = BUS_ADD_CHILD(bus, 0, NULL, -1);
                if (child == NULL) {
                        error = ENXIO;
-                       goto failed;
+                       goto cleanup;
                }
 
                /* Initialize device ivars */
                dinfo = device_get_ivars(child);
                if ((error = bcma_init_dinfo(bus, dinfo, corecfg)))
-                       goto failed;
+                       goto cleanup;
 
                /* The dinfo instance now owns the corecfg value */
                corecfg = NULL;
 
+               /* Allocate device's agent registers, if any */
+               if ((error = bcma_dinfo_alloc_agent(bus, child, dinfo)))
+                       goto cleanup;
+
                /* If pins are floating or the hardware is otherwise
                 * unpopulated, the device shouldn't be used. */
                if (bhnd_is_hw_disabled(child))
@@ -548,16 +503,19 @@ bcma_add_children(device_t bus)
                BHND_BUS_CHILD_ADDED(bus, child);
        }
 
-       /* Hit EOF parsing cores? */
+       /* EOF while parsing cores is expected */
        if (error == ENOENT)
                error = 0;
        
-failed:
+cleanup:
        bhnd_erom_free(erom);
 
        if (corecfg != NULL)
                bcma_free_corecfg(corecfg);
 
+       if (error)
+               device_delete_children(bus);
+
        return (error);
 }
 
@@ -574,7 +532,7 @@ static device_method_t bcma_methods[] = 
        DEVMETHOD(bus_get_resource_list,        bcma_get_resource_list),
 
        /* BHND interface */
-       DEVMETHOD(bhnd_bus_find_hostb_device,   bcma_find_hostb_device),
+       DEVMETHOD(bhnd_bus_get_erom_class,      bcma_get_erom_class),
        DEVMETHOD(bhnd_bus_alloc_devinfo,       bcma_alloc_bhnd_dinfo),
        DEVMETHOD(bhnd_bus_free_devinfo,        bcma_free_bhnd_dinfo),
        DEVMETHOD(bhnd_bus_reset_core,          bcma_reset_core),

Modified: head/sys/dev/bhnd/bcma/bcma_bhndb.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_bhndb.c Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma_bhndb.c Sun Sep  4 00:58:19 2016        
(r305371)
@@ -72,26 +72,21 @@ bcma_bhndb_probe(device_t dev)
 static int
 bcma_bhndb_attach(device_t dev)
 {
-       struct bcma_softc               *sc;
-       int                              error;
+       int error;
 
-       sc = device_get_softc(dev);
+       /* Perform initial attach and enumerate our children. */
+       if ((error = bcma_attach(dev)))
+               goto failed;
+
+       /* Delegate remainder to standard bhnd method implementation */
+       if ((error = bhnd_generic_attach(dev)))
+               goto failed;
 
-       /* Enumerate our children. */
-       if ((error = bcma_add_children(dev)))
-               return (error);
-
-       /* Initialize full bridge configuration */
-       error = BHNDB_INIT_FULL_CONFIG(device_get_parent(dev), dev,
-           bhndb_bcma_priority_table);
-       if (error)
-               return (error);
-
-       /* Ask our parent bridge to find the corresponding bridge core */
-       sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev);
+       return (0);
 
-       /* Call our superclass' implementation */
-       return (bcma_attach(dev));
+failed:
+       device_delete_children(dev);
+       return (error);
 }
 
 static int

Modified: head/sys/dev/bhnd/bcma/bcma_erom.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_erom.c  Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma_erom.c  Sun Sep  4 00:58:19 2016        
(r305371)
@@ -58,7 +58,13 @@ __FBSDID("$FreeBSD$");
  * marker.
  */
 
+struct bcma_erom_io;
+
 static const char      *bcma_erom_entry_type_name (uint8_t entry);
+
+static uint32_t                 bcma_eio_read4(struct bcma_erom_io *io,
+                            bus_size_t offset);
+
 static int              bcma_erom_read32(struct bcma_erom *erom,
                             uint32_t *entry);
 static int              bcma_erom_skip32(struct bcma_erom *erom);
@@ -72,8 +78,10 @@ static int            bcma_erom_seek_next(struct 
 static int              bcma_erom_region_to_port_type(struct bcma_erom *erom,
                             uint8_t region_type, bhnd_port_type *port_type);
 
+
 static int              bcma_erom_peek32(struct bcma_erom *erom,
                             uint32_t *entry);
+
 static bus_size_t       bcma_erom_tell(struct bcma_erom *erom);
 static void             bcma_erom_seek(struct bcma_erom *erom,
                             bus_size_t offset);
@@ -96,9 +104,33 @@ static void          bcma_erom_to_core_info(con
                             u_int core_idx, int core_unit,
                             struct bhnd_core_info *info);
 
+/**
+ * BCMA EROM generic I/O context
+ */
+struct bcma_erom_io {
+       struct bhnd_resource    *res;           /**< memory resource, or NULL 
if initialized
+                                                    with bus space tag and 
handle */
+       int                      rid;           /**< memory resource id, or -1 
*/
+
+       bus_space_tag_t          bst;           /**< bus space tag, if any */
+       bus_space_handle_t       bsh;           /**< bus space handle, if any */
+
+       bus_size_t               start;         /**< base read offset */
+};
+
+/**
+ * BCMA EROM per-instance state.
+ */
+struct bcma_erom {
+       struct bhnd_erom        obj;
+       device_t                dev;    /**< parent device, or NULL if none. */
+       struct bcma_erom_io     io;     /**< I/O context */
+       bus_size_t              offset; /**< current read offset */
+};
+
 #define        EROM_LOG(erom, fmt, ...)        do {                            
\
        if (erom->dev != NULL) {                                        \
-               device_printf(erom->dev, "erom[0x%llx]: " fmt,          \
+               device_printf(erom->dev, "erom[0x%llx]: " fmt,  \
                    (unsigned long long) (erom->offset), ##__VA_ARGS__);\
        } else {                                                        \
                printf("erom[0x%llx]: " fmt,                            \
@@ -106,7 +138,6 @@ static void          bcma_erom_to_core_info(con
        }                                                               \
 } while(0)
 
-
 /** Return the type name for an EROM entry */
 static const char *
 bcma_erom_entry_type_name (uint8_t entry)
@@ -123,47 +154,112 @@ bcma_erom_entry_type_name (uint8_t entry
        }
 }
 
+
+/**
+ * Read a 32-bit value from an EROM I/O context.
+ * 
+ * @param io EROM I/O context.
+ * @param offset Read offset.
+ */
+static uint32_t
+bcma_eio_read4(struct bcma_erom_io *io, bus_size_t offset)
+{
+       bus_size_t read_off;
+
+       read_off = io->start + offset;
+       if (io->res != NULL)
+               return (bhnd_bus_read_4(io->res, read_off));
+       else
+               return (bus_space_read_4(io->bst, io->bsh, read_off));
+}
+
+/* Initialize bcma_erom resource I/O context */
+static void
+bcma_eio_init(struct bcma_erom_io *io, struct bhnd_resource *res, int rid,
+    bus_size_t offset)
+{
+       io->res = res;
+       io->rid = rid;
+       io->start = offset;
+}
+
+/* Initialize bcma_erom bus space I/O context */
+static void
+bcma_eio_init_static(struct bcma_erom_io *io, bus_space_tag_t bst,
+    bus_space_handle_t bsh, bus_size_t offset)
+{
+       io->res = NULL;
+       io->rid = -1;
+       io->bst = bst;
+       io->bsh = bsh;
+       io->start = offset;
+}
+
+/* BCMA implementation of BHND_EROM_INIT() */
 static int
-bcma_erom_init(bhnd_erom_t *erom, device_t parent, int rid, bus_addr_t 
enum_addr)
+bcma_erom_init(bhnd_erom_t *erom, const struct bhnd_chipid *cid,
+    device_t parent, int rid)
 {
-       struct bcma_erom *sc = (struct bcma_erom *)erom;
+       struct bcma_erom        *sc;
+       struct bhnd_resource    *res;
 
+       sc = (struct bcma_erom *)erom;
        sc->dev = parent;
+       sc->offset = 0;
+
+       res = bhnd_alloc_resource(parent, SYS_RES_MEMORY, &rid, cid->enum_addr,
+           cid->enum_addr + BCMA_EROM_TABLE_SIZE - 1, BCMA_EROM_TABLE_SIZE,
+           RF_ACTIVE|RF_SHAREABLE);
 
-       sc->rid = rid;
-       sc->res = bhnd_alloc_resource(parent, SYS_RES_MEMORY, &sc->rid,
-           enum_addr, enum_addr + BCMA_EROM_TABLE_SIZE - 1,
-           BCMA_EROM_TABLE_SIZE, RF_ACTIVE|RF_SHAREABLE);
-       if (sc->res == NULL)
+       if (res == NULL)
                return (ENOMEM);
-       
-       sc->start = BCMA_EROM_TABLE_START;
+
+       bcma_eio_init(&sc->io, res, rid, BCMA_EROM_TABLE_START);
+
+       return (0);
+}
+
+/* BCMA implementation of BHND_EROM_INIT_STATIC() */
+static int
+bcma_erom_init_static(bhnd_erom_t *erom, const struct bhnd_chipid *cid,
+    bus_space_tag_t bst, bus_space_handle_t bsh)
+{
+       struct bcma_erom        *sc;
+
+       sc = (struct bcma_erom *)erom;
+       sc->dev = NULL;
        sc->offset = 0;
 
+       bcma_eio_init_static(&sc->io, bst, bsh, BCMA_EROM_TABLE_START);
+
        return (0);
 }
 
+/* Common implementation of BHND_EROM_PROBE/BHND_EROM_PROBE_STATIC */
 static int
-bcma_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst,
-     bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid)
+bcma_erom_probe_common(struct bcma_erom_io *io, const struct bhnd_chipid *hint,
+    struct bhnd_chipid *cid)
 {
-       uint32_t        idreg, eaddr;
-       uint8_t         chip_type;
+       uint32_t        idreg, eromptr;
 
-       idreg = bus_space_read_4(bst, bsh, CHIPC_ID);
-       chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS);
+       /* Hints aren't supported; all BCMA devices have a ChipCommon
+        * core */
+       if (hint != NULL)
+               return (EINVAL);
 
-       /* Fetch EROM physical address */
-       if (!BHND_CHIPTYPE_HAS_EROM(chip_type))
+       /* Confirm CHIPC_EROMPTR availability */
+       idreg = bcma_eio_read4(io, CHIPC_ID);
+       if (!BHND_CHIPTYPE_HAS_EROM(CHIPC_GET_BITS(idreg, CHIPC_ID_BUS)))
                return (ENXIO);
 
-       eaddr = bus_space_read_4(bst, bsh, CHIPC_EROMPTR);
+       /* Fetch EROM address */
+       eromptr = bcma_eio_read4(io, CHIPC_EROMPTR);
 
        /* Parse chip identifier */
-       *cid = bhnd_parse_chipid(idreg, eaddr);
+       *cid = bhnd_parse_chipid(idreg, eromptr);
 
        /* Verify chip type */
-       switch (chip_type) {
+       switch (cid->chip_type) {
                case BHND_CHIPTYPE_BCMA:
                        return (BUS_PROBE_DEFAULT);
 
@@ -173,37 +269,44 @@ bcma_erom_probe_static(bhnd_erom_class_t
 
                default:
                        return (ENXIO);
-       }
+       }       
 }
 
 static int
-bcma_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst,
-     bus_space_handle_t bsh)
+bcma_erom_probe(bhnd_erom_class_t *cls, struct bhnd_resource *res,
+    bus_size_t offset, const struct bhnd_chipid *hint, struct bhnd_chipid *cid)
 {
-       struct bcma_erom *sc = (struct bcma_erom *)erom;
+       struct bcma_erom_io io;
 
-       sc->dev = NULL;
-       sc->rid = -1;
-       sc->res = NULL;
-       sc->bst = bst;
-       sc->bsh = bsh;
-       sc->start = BCMA_EROM_TABLE_START;
-       sc->offset = 0;
+       bcma_eio_init(&io, res, rman_get_rid(res->res),
+           offset + BCMA_EROM_TABLE_START);
 
-       return (0);
+       return (bcma_erom_probe_common(&io, hint, cid));
 }
 
+static int
+bcma_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst,
+     bus_space_handle_t bsh, bus_addr_t paddr, const struct bhnd_chipid *hint,
+     struct bhnd_chipid *cid)
+{
+       struct bcma_erom_io io;
+
+       bcma_eio_init_static(&io, bst, bsh, BCMA_EROM_TABLE_START);
+       return (bcma_erom_probe_common(&io, hint, cid));
+}
+
+
 static void
 bcma_erom_fini(bhnd_erom_t *erom)
 {
        struct bcma_erom *sc = (struct bcma_erom *)erom;
 
-       if (sc->res != NULL) {
-               bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->rid,
-                   sc->res);
+       if (sc->io.res != NULL) {
+               bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->io.rid,
+                   sc->io.res);
 
-               sc->res = NULL;
-               sc->rid = -1;
+               sc->io.res = NULL;
+               sc->io.rid = -1;
        }
 }
 
@@ -484,19 +587,12 @@ bcma_erom_seek(struct bcma_erom *erom, b
 static int
 bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry)
 {
-       bus_size_t off;
-
-       if (erom->offset >= BCMA_EROM_TABLE_SIZE) {
+       if (erom->offset >= (BCMA_EROM_TABLE_SIZE - sizeof(uint32_t))) {
                EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n");
                return (EINVAL);
        }
-
-       off = erom->start + erom->offset;
-       if (erom->res != NULL)
-               *entry = bhnd_bus_read_4(erom->res, off);
-       else
-               *entry = bus_space_read_4(erom->bst, erom->bsh, off);
-
+       
+       *entry = bcma_eio_read4(&erom->io, erom->offset);
        return (0);
 }
 
@@ -1259,6 +1355,7 @@ failed:
 }
 
 static kobj_method_t bcma_erom_methods[] = {
+       KOBJMETHOD(bhnd_erom_probe,             bcma_erom_probe),
        KOBJMETHOD(bhnd_erom_probe_static,      bcma_erom_probe_static),
        KOBJMETHOD(bhnd_erom_init,              bcma_erom_init),
        KOBJMETHOD(bhnd_erom_init_static,       bcma_erom_init_static),

Modified: head/sys/dev/bhnd/bcma/bcma_eromvar.h
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_eromvar.h       Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma_eromvar.h       Sun Sep  4 00:58:19 2016        
(r305371)
@@ -42,25 +42,6 @@ struct bcma_erom;
 int    bcma_erom_next_corecfg(struct bcma_erom *sc,
            struct bcma_corecfg **result);
 
-/**
- * BCMA EROM per-instance state.
- */
-struct bcma_erom {
-       struct bhnd_erom         obj;
-       device_t                 dev;           /**< EROM parent device, or NULL
-                                                    if none. */
-       struct bhnd_resource    *res;           /**< EROM table resource, or
-                                                    NULL if initialized with
-                                                    bus space tag and handle */
-       int                      rid;           /**< EROM table rid, or -1 */
-
-       bus_space_tag_t          bst;           /**< EROM table bus space */
-       bus_space_handle_t       bsh;           /**< EROM table bus handle */
-
-       bus_size_t               start;         /**< EROM table offset */
-       bus_size_t               offset;        /**< current read offset */
-};
-
 /** EROM core descriptor. */
 struct bcma_erom_core {
        uint16_t        vendor;         /**< core's designer */

Modified: head/sys/dev/bhnd/bcma/bcma_nexus.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_nexus.c Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma_nexus.c Sun Sep  4 00:58:19 2016        
(r305371)
@@ -93,10 +93,19 @@ bcma_nexus_attach(device_t dev)
 {
        int error;
 
-       if ((error = bcma_add_children(dev)))
-               return (error);
-
-       return (bcma_attach(dev));
+       /* Perform initial attach and enumerate our children. */
+       if ((error = bcma_attach(dev)))
+               goto failed;
+
+       /* Delegate remainder to standard bhnd method implementation */
+       if ((error = bhnd_generic_attach(dev)))
+               goto failed;
+
+       return (0);
+
+failed:
+       device_delete_children(dev);
+       return (error);
 }
 
 static const struct bhnd_chipid *

Modified: head/sys/dev/bhnd/bcma/bcma_subr.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_subr.c  Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcma_subr.c  Sun Sep  4 00:58:19 2016        
(r305371)
@@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$");
 
 #include "bcmavar.h"
 
+/* Return the resource ID for a device's agent register allocation */
+#define        BCMA_AGENT_RID(_dinfo)  \
+    (BCMA_AGENT_RID_BASE + BCMA_DINFO_COREIDX(_dinfo))
+
  /**
  * Allocate and initialize new core config structure.
  * 
@@ -244,6 +248,63 @@ bcma_init_dinfo(device_t bus, struct bcm
        return (0);
 }
 
+
+/**
+ * Allocate the per-core agent register block for a device info structure
+ * previous initialized via bcma_init_dinfo().
+ * 
+ * If an agent0.0 region is not defined on @p dinfo, the device info
+ * agent resource is set to NULL and 0 is returned.
+ * 
+ * @param bus The requesting bus device.
+ * @param child The bcma child device.
+ * @param dinfo The device info associated with @p child
+ * 
+ * @retval 0 success
+ * @retval non-zero resource allocation failed.
+ */
+int
+bcma_dinfo_alloc_agent(device_t bus, device_t child, struct bcma_devinfo 
*dinfo)
+{
+       bhnd_addr_t     addr;
+       bhnd_size_t     size;
+       rman_res_t      r_start, r_count, r_end;
+       int             error;
+
+       KASSERT(dinfo->res_agent == NULL, ("double allocation of agent"));
+       
+       /* Verify that the agent register block exists and is
+        * mappable */
+       if (bhnd_get_port_rid(child, BHND_PORT_AGENT, 0, 0) == -1)
+               return (0);     /* nothing to do */
+
+       /* Fetch the address of the agent register block */
+       error = bhnd_get_region_addr(child, BHND_PORT_AGENT, 0, 0,
+           &addr, &size);
+       if (error) {
+               device_printf(bus, "failed fetching agent register block "
+                   "address for core %u\n", BCMA_DINFO_COREIDX(dinfo));
+               return (error);
+       }
+
+       /* Allocate the resource */
+       r_start = addr;
+       r_count = size;
+       r_end = r_start + r_count - 1;
+
+       dinfo->rid_agent = BCMA_AGENT_RID(dinfo);
+       dinfo->res_agent = BHND_BUS_ALLOC_RESOURCE(bus, bus, SYS_RES_MEMORY,
+           &dinfo->rid_agent, r_start, r_end, r_count, RF_ACTIVE);
+       if (dinfo->res_agent == NULL) {
+               device_printf(bus, "failed allocating agent register block for "
+                   "core %u\n", BCMA_DINFO_COREIDX(dinfo));
+               return (ENXIO);
+       }
+
+       return (0);
+}
+
+
 /**
  * Deallocate the given device info structure and any associated resources.
  * 

Modified: head/sys/dev/bhnd/bcma/bcmavar.h
==============================================================================
--- head/sys/dev/bhnd/bcma/bcmavar.h    Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bcma/bcmavar.h    Sun Sep  4 00:58:19 2016        
(r305371)
@@ -45,6 +45,18 @@
  * Internal definitions shared by bcma(4) driver implementations.
  */
 
+/** Base resource ID for per-core agent register allocations */
+#define        BCMA_AGENT_RID_BASE     100
+
+/**
+ * Return the device's core index.
+ * 
+ * @param _dinfo The bcma_devinfo instance to query.
+ */
+#define        BCMA_DINFO_COREIDX(_dinfo)      \
+       ((_dinfo)->corecfg->core_info.core_idx)
+
+
 /** BCMA port identifier. */
 typedef u_int          bcma_pid_t;
 #define BCMA_PID_MAX   UINT_MAX        /**< Maximum bcma_pid_t value */
@@ -72,6 +84,8 @@ struct bcma_devinfo   *bcma_alloc_dinfo(de
 int                     bcma_init_dinfo(device_t bus,
                             struct bcma_devinfo *dinfo,
                             struct bcma_corecfg *corecfg);
+int                     bcma_dinfo_alloc_agent(device_t bus, device_t child,
+                            struct bcma_devinfo *dinfo);
 void                    bcma_free_dinfo(device_t bus,
                             struct bcma_devinfo *dinfo);
 
@@ -147,7 +161,6 @@ struct bcma_devinfo {
 /** BMCA per-instance state */
 struct bcma_softc {
        struct bhnd_softc       bhnd_sc;        /**< bhnd state */
-       device_t                hostb_dev;      /**< host bridge core, or NULL 
*/
 };
 
 #endif /* _BCMA_BCMAVAR_H_ */

Modified: head/sys/dev/bhnd/bhnd.h
==============================================================================
--- head/sys/dev/bhnd/bhnd.h    Sun Sep  4 00:35:55 2016        (r305370)
+++ head/sys/dev/bhnd/bhnd.h    Sun Sep  4 00:58:19 2016        (r305371)
@@ -39,6 +39,7 @@
 
 #include "bhnd_ids.h"
 #include "bhnd_types.h"
+#include "bhnd_erom_types.h"
 #include "bhnd_debug.h"
 #include "bhnd_bus_if.h"
 #include "bhnd_match.h"
@@ -188,6 +189,12 @@ struct bhnd_resource {
                                         *   is MMIO accessible. */
 };
 
+/** Wrap the active resource @p _r in a bhnd_resource structure */
+#define        BHND_DIRECT_RESOURCE(_r)        ((struct bhnd_resource) {       
\
+       .res = (_r),                                                    \
+       .direct = true,                                                 \
+})
+
 /**
  * Device quirk table descriptor.
  */
@@ -278,6 +285,13 @@ const struct bhnd_core_info        *bhnd_find_c
                                     const struct bhnd_core_info *cores,
                                     u_int num_cores, bhnd_devclass_t class);
 
+struct bhnd_core_match          bhnd_core_get_match_desc(
+                                    const struct bhnd_core_info *core);
+
+bool                            bhnd_cores_equal(
+                                    const struct bhnd_core_info *lhs,
+                                    const struct bhnd_core_info *rhs);
+
 bool                            bhnd_core_matches(
                                     const struct bhnd_core_info *core,
                                     const struct bhnd_core_match *desc);
@@ -389,7 +403,16 @@ int                                 
bhnd_bus_generic_deactivate_reso
 bhnd_attach_type                bhnd_bus_generic_get_attach_type(device_t dev,
                                     device_t child);
 
-
+/**
+ * Return the bhnd(4) bus driver's device enumeration parser class
+ *
+ * @param driver A bhnd bus driver instance.
+ */
+static inline bhnd_erom_class_t *
+bhnd_driver_get_erom_class(driver_t *driver)
+{
+       return (BHND_BUS_GET_EROM_CLASS(driver));
+}
 
 /**
  * Return the active host bridge core for the bhnd bus, if any, or NULL if

Modified: head/sys/dev/bhnd/bhnd_bus_if.m
==============================================================================
--- head/sys/dev/bhnd/bhnd_bus_if.m     Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bhnd_bus_if.m     Sun Sep  4 00:58:19 2016        
(r305371)
@@ -29,6 +29,7 @@
 #include <sys/rman.h>
 
 #include <dev/bhnd/bhnd_types.h>
+#include <dev/bhnd/bhnd_erom_types.h>
 
 INTERFACE bhnd_bus;
 
@@ -49,7 +50,13 @@ CODE {
        #include <sys/systm.h>
 
        #include <dev/bhnd/bhndvar.h>
-       
+
+       static bhnd_erom_class_t *
+       bhnd_bus_null_get_erom_class(driver_t *driver)
+       {
+               return (NULL);
+       }
+
        static struct bhnd_chipid *
        bhnd_bus_null_get_chipid(device_t dev, device_t child)
        {
@@ -152,7 +159,7 @@ CODE {
        static device_t
        bhnd_bus_null_find_hostb_device(device_t dev)
        {
-               panic("bhnd_bus_find_hostb_device unimplemented");
+               return (NULL);
        }
 
        static bool
@@ -199,6 +206,15 @@ CODE {
 }
 
 /**
+ * Return the bhnd(4) bus driver's device enumeration parser class.
+ *
+ * @param driver       The bhnd bus driver instance.
+ */
+STATICMETHOD bhnd_erom_class_t * get_erom_class {
+       driver_t                        *driver;
+} DEFAULT bhnd_bus_null_get_erom_class;
+
+/**
  * Return the active host bridge core for the bhnd bus, if any.
  *
  * @param dev The bhnd bus device.

Modified: head/sys/dev/bhnd/bhnd_erom.c
==============================================================================
--- head/sys/dev/bhnd/bhnd_erom.c       Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bhnd_erom.c       Sun Sep  4 00:58:19 2016        
(r305371)
@@ -45,15 +45,15 @@ __FBSDID("$FreeBSD$");
  *                     be allocated.
  * @param rid          The resource ID to be used when allocating EROM
  *                     resources.
- * @param enum_addr    The base address of the device enumeration table.
+ * @param cid          The device's chip identifier.
  *
  * @retval non-NULL    success
  * @retval NULL                if an error occured allocating or initializing 
the
  *                     EROM parser.
  */
 bhnd_erom_t *
-bhnd_erom_alloc(bhnd_erom_class_t *cls, device_t parent, int rid,
-    bus_addr_t enum_addr)
+bhnd_erom_alloc(bhnd_erom_class_t *cls, const struct bhnd_chipid *cid,
+    device_t parent, int rid)
 {
        bhnd_erom_t     *erom;
        int              error;
@@ -61,9 +61,9 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, 
        erom = (bhnd_erom_t *)kobj_create((kobj_class_t)cls, M_BHND,
            M_WAITOK|M_ZERO);
 
-       if ((error = BHND_EROM_INIT(erom, parent, rid, enum_addr))) {
+       if ((error = BHND_EROM_INIT(erom, cid, parent, rid))) {
                printf("error initializing %s parser at %#jx with "
-                   "rid %d: %d\n", cls->name, (uintmax_t)enum_addr, rid,
+                   "rid %d: %d\n", cls->name, (uintmax_t)cid->enum_addr, rid,
                     error);
 
                kobj_delete((kobj_t)erom, M_BHND);
@@ -86,6 +86,7 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, 
  * @param esize                The total available number of bytes allocated 
for
  *                     @p erom. If this is less than is required by @p cls,
  *                     ENOMEM will be returned.
+ * @param cid          The device's chip identifier.
  * @param bst          Bus space tag.
  * @param bsh          Bus space handle mapping the device enumeration
  *                     space.
@@ -97,7 +98,7 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, 
  */
 int
 bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom, size_t esize,
-    bus_space_tag_t bst, bus_space_handle_t bsh)
+    const struct bhnd_chipid *cid, bus_space_tag_t bst, bus_space_handle_t bsh)
 {
        kobj_class_t    kcls;
 
@@ -109,7 +110,7 @@ bhnd_erom_init_static(bhnd_erom_class_t 
 
        /* Perform instance initialization */
        kobj_init_static((kobj_t)erom, kcls);
-       return (BHND_EROM_INIT_STATIC(erom, bst, bsh)); 
+       return (BHND_EROM_INIT_STATIC(erom, cid, bst, bsh)); 
 }
 
 /**

Modified: head/sys/dev/bhnd/bhnd_erom.h
==============================================================================
--- head/sys/dev/bhnd/bhnd_erom.h       Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bhnd_erom.h       Sun Sep  4 00:58:19 2016        
(r305371)
@@ -42,11 +42,12 @@
 #include "bhnd_erom_if.h"
 
 bhnd_erom_t                    *bhnd_erom_alloc(bhnd_erom_class_t *cls,
-                                    device_t parent, int rid,
-                                    bus_addr_t enum_addr);
+                                    const struct bhnd_chipid *cid,
+                                    device_t parent, int rid);
 
 int                             bhnd_erom_init_static(bhnd_erom_class_t *cls,
                                     bhnd_erom_t *erom, size_t esize,
+                                    const struct bhnd_chipid *cid,
                                     bus_space_tag_t bst,
                                     bus_space_handle_t bsh);
 
@@ -94,15 +95,48 @@ SET_DECLARE(bhnd_erom_class_set, bhnd_er
 
 /**
  * Probe to see if this device enumeration class supports the bhnd bus
+ * mapped by the given resource, returning a standard newbus device probe
+ * result (see BUS_PROBE_*) and the probed chip identification.
+ *
+ * @param      cls     The erom class to probe.
+ * @param      res     A resource mapping the first bus core (EXTIF or
+ *                     ChipCommon)
+ * @param      offset  Offset to the first bus core within @p res.
+ * @param      hint    Identification hint used to identify the device. If
+ *                     chipset supports standard chip identification registers
+ *                     within the first core, this parameter should be NULL.
+ * @param[out] cid     On success, the probed chip identifier.
+ *
+ * @retval 0           if this is the only possible device enumeration
+ *                     parser for the probed bus.
+ * @retval negative    if the probe succeeds, a negative value should be
+ *                     returned; the parser returning the highest negative
+ *                     value will be selected to handle device enumeration.
+ * @retval ENXIO       If the bhnd bus type is not handled by this parser.
+ * @retval positive    if an error occurs during probing, a regular unix error
+ *                     code should be returned.
+ */
+static inline int
+bhnd_erom_probe(bhnd_erom_class_t *cls, struct bhnd_resource *res,
+    bus_size_t offset, const struct bhnd_chipid *hint, struct bhnd_chipid *cid)
+{
+       return (BHND_EROM_PROBE(cls, res, offset, hint, cid));
+}
+
+/**
+ * Probe to see if this device enumeration class supports the bhnd bus
  * mapped at the given bus space tag and handle, returning a standard
  * newbus device probe result (see BUS_PROBE_*) and the probed
  * chip identification.
  *
- * @param      cls     The parser class to be probed.
+ * @param      cls     The erom class to probe.
  * @param      bst     Bus space tag.
  * @param      bsh     Bus space handle mapping the EXTIF or ChipCommon core.
  * @param      paddr   The physical address of the core mapped by @p bst and
  *                     @p bsh.
+ * @param      hint    Identification hint used to identify the device. If
+ *                     chipset supports standard chip identification registers
+ *                     within the first core, this parameter should be NULL.
  * @param[out] cid     On success, the probed chip identifier.
  *
  * @retval 0           if this is the only possible device enumeration
@@ -116,9 +150,10 @@ SET_DECLARE(bhnd_erom_class_set, bhnd_er
  */
 static inline int
 bhnd_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst,
-    bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid)
+    bus_space_handle_t bsh, bus_addr_t paddr, const struct bhnd_chipid *hint,
+    struct bhnd_chipid *cid)
 {
-       return (BHND_EROM_PROBE_STATIC(cls, bst, bsh, paddr, cid));
+       return (BHND_EROM_PROBE_STATIC(cls, bst, bsh, paddr, hint, cid));
 }
 
 /**

Modified: head/sys/dev/bhnd/bhnd_erom_if.m
==============================================================================
--- head/sys/dev/bhnd/bhnd_erom_if.m    Sun Sep  4 00:35:55 2016        
(r305370)
+++ head/sys/dev/bhnd/bhnd_erom_if.m    Sun Sep  4 00:58:19 2016        
(r305371)
@@ -45,15 +45,48 @@ INTERFACE bhnd_erom;
 
 /**
  * Probe to see if this device enumeration class supports the bhnd bus
+ * mapped by the given resource, returning a standard newbus device probe
+ * result (see BUS_PROBE_*) and the probed chip identification.
+ *
+ * @param      cls     The erom class to probe.
+ * @param      res     A resource mapping the first bus core.
+ * @param      offset  Offset to the first bus core within @p res.
+ * @param      hint    Hint used to identify the device. If chipset supports
+ *                     standard chip identification registers within the first 
+ *                     core, this parameter should be NULL.
+ * @param[out] cid     On success, the probed chip identifier.
+ *
+ * @retval 0           if this is the only possible device enumeration
+ *                     parser for the probed bus.
+ * @retval negative    if the probe succeeds, a negative value should be
+ *                     returned; the parser returning the highest negative
+ *                     value will be selected to handle device enumeration.
+ * @retval ENXIO       If the bhnd bus type is not handled by this parser.
+ * @retval positive    if an error occurs during probing, a regular unix error
+ *                     code should be returned.
+ */
+STATICMETHOD int probe {
+       bhnd_erom_class_t               *cls;
+       struct bhnd_resource            *res;
+       bus_size_t                       offset;
+       const struct bhnd_chipid        *hint;
+       struct bhnd_chipid              *cid;
+};
+
+/**
+ * Probe to see if this device enumeration class supports the bhnd bus
  * mapped at the given bus space tag and handle, returning a standard
  * newbus device probe result (see BUS_PROBE_*) and the probed
  * chip identification.
  *
- * @param      cls     The erom parse class to probe.
+ * @param      cls     The erom class to probe.
  * @param      bst     Bus space tag.
- * @param      bsh     Bus space handle mapping the EXTIF or ChipCommon core.
+ * @param      bsh     Bus space handle mapping the first bus core.
  * @param      paddr   The physical address of the core mapped by @p bst and
  *                     @p bsh.
+ * @param      hint    Hint used to identify the device. If chipset supports
+ *                     standard chip identification registers within the first 
+ *                     core, this parameter should be NULL.
  * @param[out] cid     On success, the probed chip identifier.
  *
  * @retval 0           if this is the only possible device enumeration
@@ -66,51 +99,54 @@ INTERFACE bhnd_erom;
  *                     code should be returned.
  */
 STATICMETHOD int probe_static {
-       bhnd_erom_class_t       *cls;
-       bus_space_tag_t          bst;
-       bus_space_handle_t       bsh;
-       bus_addr_t               paddr;
-       struct bhnd_chipid      *cid;
+       bhnd_erom_class_t               *cls;
+       bus_space_tag_t                  bst;
+       bus_space_handle_t               bsh;
+       bus_addr_t                       paddr;
+       const struct bhnd_chipid        *hint;
+       struct bhnd_chipid              *cid;
 };
 
 /**

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to