svn commit: r305366 - in head/sys: conf dev/bhnd dev/bhnd/bcma dev/bhnd/bhndb dev/bhnd/siba mips/broadcom modules/bhnd modules/bhnd/bcma modules/bhnd/bcma_bhndb modules/bhnd/siba modules/bhnd/siba_...
Landon J. Fuller
landonf at FreeBSD.org
Sat Sep 3 23:57:19 UTC 2016
Author: landonf
Date: Sat Sep 3 23:57:17 2016
New Revision: 305366
URL: https://svnweb.freebsd.org/changeset/base/305366
Log:
Implement a generic bhnd(4) device enumeration table API.
This defines a new bhnd_erom_if API, providing a common interface to device
enumeration on siba(4) and bcma(4) devices, for use both in the bhndb bridge
and SoC early boot contexts, and migrates mips/broadcom over to the new API.
This also replaces the previous adhoc device enumeration support implemented
for mips/broadcom.
Migration of bhndb to the new API will be implemented in a follow-up commit.
- Defined new bhnd_erom_if interface for bhnd(4) device enumeration, along
with bcma(4) and siba(4)-specific implementations.
- Fixed a minor bug in bhndb that logged an error when we attempted to map the
full siba(4) bus space (18000000-17FFFFFF) in the siba EROM parser.
- Reverted use of the resource's start address as the ChipCommon enum_addr in
bhnd_read_chipid(). When called from bhndb, this address is found within the
host address space, resulting in an invalid bridged enum_addr.
- Added support for falling back on standard bus_activate_resource() in
bhnd_bus_generic_activate_resource(), enabling allocation of the bhnd_erom's
bhnd_resource directly from a nexus-attached bhnd(4) device.
- Removed BHND_BUS_GET_CORE_TABLE(); it has been replaced by the erom API.
- Added support for statically initializing bhnd_erom instances, for use prior
to malloc availability. The statically allocated buffer size is verified both
at runtime, and via a compile-time assertion (see BHND_EROM_STATIC_BYTES).
- bhnd_erom classes are registered within a module via a linker set, allowing
mips/broadcom to probe available EROM parser instances without creating a
strong reference to bcma/siba-specific symbols.
- Migrated mips/broadcom to bhnd_erom_if, replacing the previous MIPS-specific
device enumeration implementation.
Approved by: adrian (mentor)
Differential Revision: https://reviews.freebsd.org/D7748
Added:
head/sys/dev/bhnd/bhnd_erom.c (contents, props changed)
head/sys/dev/bhnd/bhnd_erom.h (contents, props changed)
head/sys/dev/bhnd/bhnd_erom_if.m (contents, props changed)
head/sys/dev/bhnd/bhnd_erom_types.h (contents, props changed)
head/sys/dev/bhnd/siba/siba_erom.c (contents, props changed)
Deleted:
head/sys/mips/broadcom/bcm_bcma.c
head/sys/mips/broadcom/bcm_siba.c
Modified:
head/sys/conf/files
head/sys/dev/bhnd/bcma/bcma.c
head/sys/dev/bhnd/bcma/bcma.h
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/bcmavar.h
head/sys/dev/bhnd/bhnd.h
head/sys/dev/bhnd/bhnd_bus_if.m
head/sys/dev/bhnd/bhnd_subr.c
head/sys/dev/bhnd/bhndb/bhndb.c
head/sys/dev/bhnd/siba/siba.c
head/sys/dev/bhnd/siba/siba.h
head/sys/dev/bhnd/siba/siba_subr.c
head/sys/dev/bhnd/siba/sibareg.h
head/sys/dev/bhnd/siba/sibavar.h
head/sys/mips/broadcom/bcm_machdep.c
head/sys/mips/broadcom/bcm_machdep.h
head/sys/mips/broadcom/bcm_pmu.c
head/sys/mips/broadcom/files.broadcom
head/sys/modules/bhnd/Makefile
head/sys/modules/bhnd/bcma/Makefile
head/sys/modules/bhnd/bcma_bhndb/Makefile
head/sys/modules/bhnd/siba/Makefile
head/sys/modules/bhnd/siba_bhndb/Makefile
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Sat Sep 3 23:04:56 2016 (r305365)
+++ head/sys/conf/files Sat Sep 3 23:57:17 2016 (r305366)
@@ -1140,6 +1140,8 @@ dev/bce/if_bce.c optional bce
dev/bfe/if_bfe.c optional bfe
dev/bge/if_bge.c optional bge
dev/bhnd/bhnd.c optional bhnd
+dev/bhnd/bhnd_erom.c optional bhnd
+dev/bhnd/bhnd_erom_if.m optional bhnd
dev/bhnd/bhnd_nexus.c optional bhnd siba_nexus | \
bhnd bcma_nexus
dev/bhnd/bhnd_subr.c optional bhnd
@@ -1188,6 +1190,7 @@ dev/bhnd/nvram/bhnd_sprom.c optional bh
dev/bhnd/nvram/bhnd_sprom_parser.c optional bhnd
dev/bhnd/siba/siba.c optional siba bhnd
dev/bhnd/siba/siba_bhndb.c optional siba bhnd bhndb
+dev/bhnd/siba/siba_erom.c optional siba bhnd
dev/bhnd/siba/siba_nexus.c optional siba_nexus siba bhnd
dev/bhnd/siba/siba_subr.c optional siba bhnd
#
Modified: head/sys/dev/bhnd/bcma/bcma.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma.c Sat Sep 3 23:04:56 2016 (r305365)
+++ head/sys/dev/bhnd/bcma/bcma.c Sat Sep 3 23:57:17 2016 (r305366)
@@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$");
#include "bcma_eromvar.h"
#include <dev/bhnd/bhnd_core.h>
+/* RID used when allocating EROM table */
+#define BCMA_EROM_RID 0
+
int
bcma_probe(device_t dev)
{
@@ -492,76 +495,35 @@ bcma_free_bhnd_dinfo(device_t dev, struc
bcma_free_dinfo(dev, (struct bcma_devinfo *)dinfo);
}
-
-static int
-bcma_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores,
- u_int *num_cores)
-{
- struct bcma_softc *sc;
- struct bcma_erom erom;
- const struct bhnd_chipid *cid;
- struct resource *r;
- int error;
- int rid;
-
- sc = device_get_softc(dev);
-
- /* Map the EROM table. */
- cid = BHND_BUS_GET_CHIPID(dev, dev);
- rid = 0;
- r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr,
- cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE,
- RF_ACTIVE);
- if (r == NULL) {
- device_printf(dev, "failed to allocate EROM resource\n");
- return (ENXIO);
- }
-
- /* Enumerate all declared cores */
- if ((error = bcma_erom_open(&erom, r, BCMA_EROM_TABLE_START)))
- goto cleanup;
-
- error = bcma_erom_get_core_info(&erom, cores, num_cores);
-
-cleanup:
- bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
- return (error);
-}
-
/**
- * Scan a device enumeration ROM table, adding all valid discovered cores to
+ * Scan the device enumeration ROM table, adding all valid discovered cores to
* the bus.
*
* @param bus The bcma bus.
- * @param erom_res An active resource mapping the EROM core.
- * @param erom_offset Base offset of the EROM core's register mapping.
*/
int
-bcma_add_children(device_t bus, struct resource *erom_res, bus_size_t erom_offset)
+bcma_add_children(device_t bus)
{
- struct bcma_erom erom;
- struct bcma_corecfg *corecfg;
- struct bcma_devinfo *dinfo;
- device_t child;
- int error;
+ bhnd_erom_t *erom;
+ struct bcma_erom *bcma_erom;
+ const struct bhnd_chipid *cid;
+ struct bcma_corecfg *corecfg;
+ struct bcma_devinfo *dinfo;
+ device_t child;
+ int error;
+ cid = BHND_BUS_GET_CHIPID(bus, bus);
corecfg = NULL;
- /* Initialize our reader */
- error = bcma_erom_open(&erom, erom_res, erom_offset);
- if (error)
- return (error);
+ /* Allocate our EROM parser */
+ erom = bhnd_erom_alloc(&bcma_erom_parser, bus, BCMA_EROM_RID,
+ cid->enum_addr);
+ if (erom == NULL)
+ return (ENODEV);
/* Add all cores. */
- while (!error) {
- /* Parse next core */
- error = bcma_erom_parse_corecfg(&erom, &corecfg);
- if (error && error == ENOENT) {
- return (0);
- } else if (error) {
- goto failed;
- }
-
+ bcma_erom = (struct bcma_erom *)erom;
+ while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) {
/* Add the child device */
child = BUS_ADD_CHILD(bus, 0, NULL, -1);
if (child == NULL) {
@@ -588,9 +550,11 @@ bcma_add_children(device_t bus, struct r
/* Hit EOF parsing cores? */
if (error == ENOENT)
- return (0);
+ error = 0;
failed:
+ bhnd_erom_free(erom);
+
if (corecfg != NULL)
bcma_free_corecfg(corecfg);
@@ -613,7 +577,6 @@ static device_method_t bcma_methods[] =
DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device),
DEVMETHOD(bhnd_bus_alloc_devinfo, bcma_alloc_bhnd_dinfo),
DEVMETHOD(bhnd_bus_free_devinfo, bcma_free_bhnd_dinfo),
- DEVMETHOD(bhnd_bus_get_core_table, bcma_get_core_table),
DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core),
DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core),
DEVMETHOD(bhnd_bus_read_config, bcma_read_config),
Modified: head/sys/dev/bhnd/bcma/bcma.h
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma.h Sat Sep 3 23:04:56 2016 (r305365)
+++ head/sys/dev/bhnd/bcma/bcma.h Sat Sep 3 23:57:17 2016 (r305366)
@@ -45,5 +45,6 @@
*/
DECLARE_CLASS(bcma_driver);
+DECLARE_CLASS(bcma_erom_parser);
-#endif /* _BCMA_BCMA_H_ */
\ No newline at end of file
+#endif /* _BCMA_BCMA_H_ */
Modified: head/sys/dev/bhnd/bcma/bcma_bhndb.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_bhndb.c Sat Sep 3 23:04:56 2016 (r305365)
+++ head/sys/dev/bhnd/bcma/bcma_bhndb.c Sat Sep 3 23:57:17 2016 (r305366)
@@ -73,29 +73,12 @@ static int
bcma_bhndb_attach(device_t dev)
{
struct bcma_softc *sc;
- const struct bhnd_chipid *cid;
- struct resource *erom_res;
int error;
- int rid;
sc = device_get_softc(dev);
- /* Map the EROM resource and enumerate our children. */
- cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev);
- rid = 0;
- erom_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr,
- cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE,
- RF_ACTIVE);
- if (erom_res == NULL) {
- device_printf(dev, "failed to allocate EROM resource\n");
- return (ENXIO);
- }
-
- error = bcma_add_children(dev, erom_res, BCMA_EROM_TABLE_START);
-
- /* Clean up */
- bus_release_resource(dev, SYS_RES_MEMORY, rid, erom_res);
- if (error)
+ /* Enumerate our children. */
+ if ((error = bcma_add_children(dev)))
return (error);
/* Initialize full bridge configuration */
Modified: head/sys/dev/bhnd/bcma/bcma_erom.c
==============================================================================
--- head/sys/dev/bhnd/bcma/bcma_erom.c Sat Sep 3 23:04:56 2016 (r305365)
+++ head/sys/dev/bhnd/bcma/bcma_erom.c Sat Sep 3 23:57:17 2016 (r305366)
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
+#include <dev/bhnd/cores/chipc/chipcreg.h>
+
#include "bcma_eromreg.h"
#include "bcma_eromvar.h"
@@ -56,17 +58,43 @@ __FBSDID("$FreeBSD$");
* marker.
*/
-static const char *erom_entry_type_name (uint8_t entry);
-static int erom_read32(struct bcma_erom *erom, uint32_t *entry);
-static int erom_skip32(struct bcma_erom *erom);
-
-static int erom_skip_core(struct bcma_erom *erom);
-static int erom_skip_mport(struct bcma_erom *erom);
-static int erom_skip_sport_region(struct bcma_erom *erom);
-
-static int erom_seek_next(struct bcma_erom *erom, uint8_t etype);
-static int erom_region_to_port_type(struct bcma_erom *erom,
- uint8_t region_type, bhnd_port_type *port_type);
+static const char *bcma_erom_entry_type_name (uint8_t entry);
+static int bcma_erom_read32(struct bcma_erom *erom,
+ uint32_t *entry);
+static int bcma_erom_skip32(struct bcma_erom *erom);
+
+static int bcma_erom_skip_core(struct bcma_erom *erom);
+static int bcma_erom_skip_mport(struct bcma_erom *erom);
+static int bcma_erom_skip_sport_region(struct bcma_erom *erom);
+
+static int bcma_erom_seek_next(struct bcma_erom *erom,
+ uint8_t etype);
+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);
+static void bcma_erom_reset(struct bcma_erom *erom);
+
+static int bcma_erom_seek_matching_core(struct bcma_erom *sc,
+ const struct bhnd_core_match *desc,
+ struct bhnd_core_info *core);
+
+static int bcma_erom_parse_core(struct bcma_erom *erom,
+ struct bcma_erom_core *core);
+
+static int bcma_erom_parse_mport(struct bcma_erom *erom,
+ struct bcma_erom_mport *mport);
+
+static int bcma_erom_parse_sport_region(struct bcma_erom *erom,
+ struct bcma_erom_sport_region *region);
+
+static void bcma_erom_to_core_info(const struct bcma_erom_core *core,
+ u_int core_idx, int core_unit,
+ struct bhnd_core_info *info);
#define EROM_LOG(erom, fmt, ...) do { \
if (erom->dev != NULL) { \
@@ -78,58 +106,10 @@ static int erom_region_to_port_type(st
} \
} while(0)
-/**
- * Open an EROM table for reading.
- *
- * @param[out] erom On success, will be populated with a valid EROM
- * read state.
- * @param r An active resource mapping the EROM core.
- * @param offset Offset of the EROM core within @p resource.
- *
- * @retval 0 success
- * @retval non-zero if the erom table could not be opened.
- */
-int
-bcma_erom_open(struct bcma_erom *erom, struct resource *r,
- bus_size_t offset)
-{
- return (bhnd_erom_bus_space_open(erom, rman_get_device(r),
- rman_get_bustag(r), rman_get_bushandle(r), offset));
-
- return (0);
-}
-
-/**
- * Open an EROM table for reading using the provided bus space tag and
- * handle.
- *
- * @param[out] erom On success, will be populated with a valid EROM
- * read state.
- * @param dev The owning device, or NULL if none.
- * @param bst EROM table bus space tag.
- * @param bsh EROM table bus space handle.
- * @param offset Offset of the EROM core from @p resource.
- *
- * @retval 0 success
- * @retval non-zero if the erom table could not be opened.
- */
-int
-bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t dev,
- bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset)
-{
- /* Initialize the EROM reader */
- erom->dev = dev;
- erom->bst = bst;
- erom->bsh = bsh;
- erom->start = offset + BCMA_EROM_TABLE_START;
- erom->offset = 0;
-
- return (0);
-}
/** Return the type name for an EROM entry */
static const char *
-erom_entry_type_name (uint8_t entry)
+bcma_erom_entry_type_name (uint8_t entry)
{
switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) {
case BCMA_EROM_ENTRY_TYPE_CORE:
@@ -143,10 +123,340 @@ erom_entry_type_name (uint8_t entry)
}
}
+static int
+bcma_erom_init(bhnd_erom_t *erom, device_t parent, int rid, bus_addr_t enum_addr)
+{
+ struct bcma_erom *sc = (struct bcma_erom *)erom;
+
+ sc->dev = parent;
+
+ 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)
+ return (ENOMEM);
+
+ sc->start = BCMA_EROM_TABLE_START;
+ sc->offset = 0;
+
+ return (0);
+}
+
+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)
+{
+ uint32_t idreg, eaddr;
+ uint8_t chip_type;
+
+ idreg = bus_space_read_4(bst, bsh, CHIPC_ID);
+ chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS);
+
+ /* Fetch EROM physical address */
+ if (!BHND_CHIPTYPE_HAS_EROM(chip_type))
+ return (ENXIO);
+
+ eaddr = bus_space_read_4(bst, bsh, CHIPC_EROMPTR);
+
+ /* Parse chip identifier */
+ *cid = bhnd_parse_chipid(idreg, eaddr);
+
+ /* Verify chip type */
+ switch (chip_type) {
+ case BHND_CHIPTYPE_BCMA:
+ return (BUS_PROBE_DEFAULT);
+
+ case BHND_CHIPTYPE_BCMA_ALT:
+ case BHND_CHIPTYPE_UBUS:
+ return (BUS_PROBE_GENERIC);
+
+ default:
+ return (ENXIO);
+ }
+}
+
+static int
+bcma_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst,
+ bus_space_handle_t bsh)
+{
+ struct bcma_erom *sc = (struct bcma_erom *)erom;
+
+ sc->dev = NULL;
+ sc->rid = -1;
+ sc->res = NULL;
+ sc->bst = bst;
+ sc->bsh = bsh;
+ sc->start = BCMA_EROM_TABLE_START;
+ sc->offset = 0;
+
+ return (0);
+}
+
+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);
+
+ sc->res = NULL;
+ sc->rid = -1;
+ }
+}
+
+static int
+bcma_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc,
+ struct bhnd_core_info *core)
+{
+ struct bcma_erom *sc = (struct bcma_erom *)erom;
+
+ /* Search for the first matching core */
+ return (bcma_erom_seek_matching_core(sc, desc, core));
+}
+
+static int
+bcma_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc,
+ bhnd_port_type port_type, u_int port_num, u_int region_num,
+ struct bhnd_core_info *core, bhnd_addr_t *addr, bhnd_size_t *size)
+{
+ struct bcma_erom *sc;
+ struct bcma_erom_core ec;
+ uint32_t entry;
+ uint8_t region_port, region_type;
+ bool found;
+ int error;
+
+ sc = (struct bcma_erom *)erom;
+
+ /* Seek to the first matching core and provide the core info
+ * to the caller */
+ if ((error = bcma_erom_seek_matching_core(sc, desc, core)))
+ return (error);
+
+ if ((error = bcma_erom_parse_core(sc, &ec)))
+ return (error);
+
+ /* Skip master ports */
+ for (u_long i = 0; i < ec.num_mport; i++) {
+ if ((error = bcma_erom_skip_mport(sc)))
+ return (error);
+ }
+
+ /* Seek to the region block for the given port type */
+ found = false;
+ while (1) {
+ bhnd_port_type p_type;
+ uint8_t r_type;
+
+ if ((error = bcma_erom_peek32(sc, &entry)))
+ return (error);
+
+ if (!BCMA_EROM_ENTRY_IS(entry, REGION))
+ return (ENOENT);
+
+ /* Expected region type? */
+ r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
+ error = bcma_erom_region_to_port_type(sc, r_type, &p_type);
+ if (error)
+ return (error);
+
+ if (p_type == port_type) {
+ found = true;
+ break;
+ }
+
+ /* Skip to next entry */
+ if ((error = bcma_erom_skip_sport_region(sc)))
+ return (error);
+ }
+
+ if (!found)
+ return (ENOENT);
+
+ /* Found the appropriate port type block; now find the region records
+ * for the given port number */
+ found = false;
+ for (u_int i = 0; i <= port_num; i++) {
+ bhnd_port_type p_type;
+
+ if ((error = bcma_erom_peek32(sc, &entry)))
+ return (error);
+
+ if (!BCMA_EROM_ENTRY_IS(entry, REGION))
+ return (ENOENT);
+
+ /* Fetch the type/port of the first region entry */
+ region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
+ region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
+
+ /* Have we found the region entries for the desired port? */
+ if (i == port_num) {
+ error = bcma_erom_region_to_port_type(sc, region_type,
+ &p_type);
+ if (error)
+ return (error);
+
+ if (p_type == port_type)
+ found = true;
+
+ break;
+ }
+
+ /* Otherwise, seek to next block of region records */
+ while (1) {
+ uint8_t next_type, next_port;
+
+ if ((error = bcma_erom_skip_sport_region(sc)))
+ return (error);
+
+ if ((error = bcma_erom_peek32(sc, &entry)))
+ return (error);
+
+ if (!BCMA_EROM_ENTRY_IS(entry, REGION))
+ return (ENOENT);
+
+ next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
+ next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
+
+ if (next_type != region_type ||
+ next_port != region_port)
+ break;
+ }
+ }
+
+ if (!found)
+ return (ENOENT);
+
+ /* Finally, search for the requested region number */
+ for (u_int i = 0; i <= region_num; i++) {
+ struct bcma_erom_sport_region region;
+ uint8_t next_port, next_type;
+
+ if ((error = bcma_erom_peek32(sc, &entry)))
+ return (error);
+
+ if (!BCMA_EROM_ENTRY_IS(entry, REGION))
+ return (ENOENT);
+
+ /* Check for the end of the region block */
+ next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
+ next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT);
+
+ if (next_type != region_type ||
+ next_port != region_port)
+ break;
+
+ /* Parse the region */
+ if ((error = bcma_erom_parse_sport_region(sc, ®ion)))
+ return (error);
+
+ /* Is this our target region_num? */
+ if (i == region_num) {
+ /* Found */
+ *addr = region.base_addr;
+ *size = region.size;
+ return (0);
+ }
+ }
+
+ /* Not found */
+ return (ENOENT);
+};
+
+static int
+bcma_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores,
+ u_int *num_cores)
+{
+ struct bcma_erom *sc;
+ struct bhnd_core_info *buffer;
+ bus_size_t initial_offset;
+ u_int count;
+ int error;
+
+ sc = (struct bcma_erom *)erom;
+
+ buffer = NULL;
+ initial_offset = bcma_erom_tell(sc);
+
+ /* Determine the core count */
+ bcma_erom_reset(sc);
+ for (count = 0, error = 0; !error; count++) {
+ struct bcma_erom_core core;
+
+ /* Seek to the first readable core entry */
+ error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE);
+ if (error == ENOENT)
+ break;
+ else if (error)
+ goto cleanup;
+
+ /* Read past the core descriptor */
+ if ((error = bcma_erom_parse_core(sc, &core)))
+ goto cleanup;
+ }
+
+ /* Allocate our output buffer */
+ buffer = malloc(sizeof(struct bhnd_core_info) * count, M_BHND,
+ M_NOWAIT);
+ if (buffer == NULL) {
+ error = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Parse all core descriptors */
+ bcma_erom_reset(sc);
+ for (u_int i = 0; i < count; i++) {
+ struct bcma_erom_core core;
+ int unit;
+
+ /* Parse the core */
+ error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE);
+ if (error)
+ goto cleanup;
+
+ error = bcma_erom_parse_core(sc, &core);
+ if (error)
+ goto cleanup;
+
+ /* Determine the unit number */
+ unit = 0;
+ for (u_int j = 0; j < i; j++) {
+ if (buffer[i].vendor == buffer[j].vendor &&
+ buffer[i].device == buffer[j].device)
+ unit++;
+ }
+
+ /* Convert to a bhnd info record */
+ bcma_erom_to_core_info(&core, i, unit, &buffer[i]);
+ }
+
+cleanup:
+ if (!error) {
+ *cores = buffer;
+ *num_cores = count;
+ } else {
+ if (buffer != NULL)
+ free(buffer, M_BHND);
+ }
+
+ /* Restore the initial position */
+ bcma_erom_seek(sc, initial_offset);
+ return (error);
+}
+
+static void
+bcma_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores)
+{
+ free(cores, M_BHND);
+}
+
/**
* Return the current read position.
*/
-bus_size_t
+static bus_size_t
bcma_erom_tell(struct bcma_erom *erom)
{
return (erom->offset);
@@ -155,7 +465,7 @@ bcma_erom_tell(struct bcma_erom *erom)
/**
* Seek to an absolute read position.
*/
-void
+static void
bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset)
{
erom->offset = offset;
@@ -171,16 +481,22 @@ bcma_erom_seek(struct bcma_erom *erom, b
* @retval ENOENT The end of the EROM table was reached.
* @retval non-zero The read could not be completed.
*/
-int
+static int
bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry)
{
+ bus_size_t off;
+
if (erom->offset >= BCMA_EROM_TABLE_SIZE) {
EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n");
return (EINVAL);
}
- *entry = bus_space_read_4(erom->bst, erom->bsh,
- erom->start + erom->offset);
+ 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);
+
return (0);
}
@@ -194,7 +510,7 @@ bcma_erom_peek32(struct bcma_erom *erom,
* @retval non-zero The read could not be completed.
*/
static int
-erom_read32(struct bcma_erom *erom, uint32_t *entry)
+bcma_erom_read32(struct bcma_erom *erom, uint32_t *entry)
{
int error;
@@ -213,11 +529,11 @@ erom_read32(struct bcma_erom *erom, uint
* @retval non-zero The read could not be completed.
*/
static int
-erom_skip32(struct bcma_erom *erom)
+bcma_erom_skip32(struct bcma_erom *erom)
{
uint32_t entry;
- return erom_read32(erom, &entry);
+ return bcma_erom_read32(erom, &entry);
}
/**
@@ -229,7 +545,7 @@ erom_skip32(struct bcma_erom *erom)
* @retval non-zero The read could not be completed.
*/
static int
-erom_skip_core(struct bcma_erom *erom)
+bcma_erom_skip_core(struct bcma_erom *erom)
{
struct bcma_erom_core core;
return (bcma_erom_parse_core(erom, &core));
@@ -244,7 +560,7 @@ erom_skip_core(struct bcma_erom *erom)
* @retval non-zero The read could not be completed.
*/
static int
-erom_skip_mport(struct bcma_erom *erom)
+bcma_erom_skip_mport(struct bcma_erom *erom)
{
struct bcma_erom_mport mp;
return (bcma_erom_parse_mport(erom, &mp));
@@ -259,7 +575,7 @@ erom_skip_mport(struct bcma_erom *erom)
* @retval non-zero The read could not be completed.
*/
static int
-erom_skip_sport_region(struct bcma_erom *erom)
+bcma_erom_skip_sport_region(struct bcma_erom *erom)
{
struct bcma_erom_sport_region r;
return (bcma_erom_parse_sport_region(erom, &r));
@@ -276,7 +592,7 @@ erom_skip_sport_region(struct bcma_erom
* @retval non-zero Reading or parsing the descriptor failed.
*/
static int
-erom_seek_next(struct bcma_erom *erom, uint8_t etype)
+bcma_erom_seek_next(struct bcma_erom *erom, uint8_t etype)
{
uint32_t entry;
int error;
@@ -298,19 +614,19 @@ erom_seek_next(struct bcma_erom *erom, u
/* Skip non-matching entry types. */
switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) {
case BCMA_EROM_ENTRY_TYPE_CORE:
- if ((error = erom_skip_core(erom)))
+ if ((error = bcma_erom_skip_core(erom)))
return (error);
break;
case BCMA_EROM_ENTRY_TYPE_MPORT:
- if ((error = erom_skip_mport(erom)))
+ if ((error = bcma_erom_skip_mport(erom)))
return (error);
break;
case BCMA_EROM_ENTRY_TYPE_REGION:
- if ((error = erom_skip_sport_region(erom)))
+ if ((error = bcma_erom_skip_sport_region(erom)))
return (error);
break;
@@ -328,62 +644,100 @@ erom_seek_next(struct bcma_erom *erom, u
*
* @param erom EROM read state.
*/
-void
+static void
bcma_erom_reset(struct bcma_erom *erom)
{
erom->offset = 0;
}
/**
- * Seek to the next core entry.
- *
- * @param erom EROM read state.
- * @retval 0 success
- * @retval ENOENT The end of the EROM table was reached.
- * @retval non-zero Reading or parsing failed.
- */
-int
-bcma_erom_seek_next_core(struct bcma_erom *erom)
-{
- return (erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE));
-}
-
-/**
- * Seek to the requested core entry.
+ * Seek to the first core entry matching @p desc.
*
* @param erom EROM read state.
- * @param core_index Index of the core to seek to.
+ * @param desc The core match descriptor.
+ * @param[out] core On success, the matching core info. If the core info
+ * is not desired, a NULL pointer may be provided.
* @retval 0 success
* @retval ENOENT The end of the EROM table was reached before @p index was
* found.
* @retval non-zero Reading or parsing failed.
*/
-int
-bcma_erom_seek_core_index(struct bcma_erom *erom, u_int core_index)
+static int
+bcma_erom_seek_matching_core(struct bcma_erom *sc,
+ const struct bhnd_core_match *desc, struct bhnd_core_info *core)
{
- int error;
+ struct bhnd_core_match imatch;
+ bus_size_t core_offset, next_offset;
+ int error;
- /* Start search at top of EROM */
- bcma_erom_reset(erom);
+ /* Seek to table start. */
+ bcma_erom_reset(sc);
- /* Skip core descriptors till we hit the requested entry */
- for (u_int i = 0; i < core_index; i++) {
- struct bcma_erom_core core;
+ /* We can't determine a core's unit number during the initial scan. */
+ imatch = *desc;
+ imatch.m.match.core_unit = 0;
+
+ /* Locate the first matching core */
+ for (u_int i = 0; i < UINT_MAX; i++) {
+ struct bcma_erom_core ec;
+ struct bhnd_core_info ci;
- /* Read past the core descriptor */
- if ((error = bcma_erom_parse_core(erom, &core)))
+ /* Seek to the next core */
+ error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE);
+ if (error)
return (error);
- /* Seek to the next readable core entry */
- error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE);
- if (error)
+ /* Save the core offset */
+ core_offset = bcma_erom_tell(sc);
+
+ /* Parse the core */
+ if ((error = bcma_erom_parse_core(sc, &ec)))
return (error);
+
+ bcma_erom_to_core_info(&ec, i, 0, &ci);
+
+ /* Check for initial match */
+ if (!bhnd_core_matches(&ci, &imatch))
+ continue;
+
+ /* Re-scan preceding cores to determine the unit number. */
+ next_offset = bcma_erom_tell(sc);
+ bcma_erom_reset(sc);
+ for (u_int j = 0; j < i; j++) {
+ /* Parse the core */
+ error = bcma_erom_seek_next(sc,
+ BCMA_EROM_ENTRY_TYPE_CORE);
+ if (error)
+ return (error);
+
+ if ((error = bcma_erom_parse_core(sc, &ec)))
+ return (error);
+
+ /* Bump the unit number? */
+ if (ec.vendor == ci.vendor && ec.device == ci.device)
+ ci.unit++;
+ }
+
+ /* Check for full match against now-valid unit number */
+ if (!bhnd_core_matches(&ci, desc)) {
+ /* Reposition to allow reading the next core */
+ bcma_erom_seek(sc, next_offset);
+ continue;
+ }
+
+ /* Found; seek to the core's initial offset and provide
+ * the core info to the caller */
+ bcma_erom_seek(sc, core_offset);
+ if (core != NULL)
+ *core = ci;
+
+ return (0);
}
- return (0);
+ /* Not found, or a parse error occured */
+ return (error);
}
-
/**
* Read the next core descriptor from the EROM table.
*
@@ -394,14 +748,14 @@ bcma_erom_seek_core_index(struct bcma_er
* @retval ENOENT The end of the EROM table was reached.
* @retval non-zero Reading or parsing the core descriptor failed.
*/
-int
+static int
bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core)
{
uint32_t entry;
int error;
/* Parse CoreDescA */
- if ((error = erom_read32(erom, &entry)))
+ if ((error = bcma_erom_read32(erom, &entry)))
return (error);
/* Handle EOF */
@@ -410,7 +764,7 @@ bcma_erom_parse_core(struct bcma_erom *e
if (!BCMA_EROM_ENTRY_IS(entry, CORE)) {
EROM_LOG(erom, "Unexpected EROM entry 0x%x (type=%s)\n",
- entry, erom_entry_type_name(entry));
+ entry, bcma_erom_entry_type_name(entry));
return (EINVAL);
}
@@ -419,7 +773,7 @@ bcma_erom_parse_core(struct bcma_erom *e
core->device = BCMA_EROM_GET_ATTR(entry, COREA_ID);
/* Parse CoreDescB */
- if ((error = erom_read32(erom, &entry)))
+ if ((error = bcma_erom_read32(erom, &entry)))
return (error);
if (!BCMA_EROM_ENTRY_IS(entry, CORE)) {
@@ -436,153 +790,6 @@ bcma_erom_parse_core(struct bcma_erom *e
}
/**
- * Seek to a region record associated with @p core_index.
- *
- * @param erom EROM read state.
- * @param core_index The index of the core record to be searched.
- * @param port_type The port type to search for.
- * @param port_num The port number to search for.
- * @param region_num The region number to search for.
- * @retval 0 success
- * @retval ENOENT The requested region was not found.
- * @retval non-zero Reading or parsing failed.
- */
-int
-bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index,
- bhnd_port_type port_type, u_int port_num, u_int region_num)
-{
- struct bcma_erom_core core;
- uint32_t entry;
- uint8_t region_port, region_type;
- bool found;
- int error;
-
- if ((error = bcma_erom_seek_core_index(erom, core_index)))
- return (error);
-
- if ((error = bcma_erom_parse_core(erom, &core)))
- return (error);
-
- /* Skip master ports */
- for (u_long i = 0; i < core.num_mport; i++) {
- if ((error = erom_skip_mport(erom)))
- return (error);
- }
-
- /* Seek to the region block for the given port type */
- found = false;
- while (1) {
- bhnd_port_type p_type;
- uint8_t r_type;
-
- if ((error = bcma_erom_peek32(erom, &entry)))
- return (error);
-
- if (!BCMA_EROM_ENTRY_IS(entry, REGION))
- return (ENOENT);
-
- /* Expected region type? */
- r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE);
- if ((error = erom_region_to_port_type(erom, r_type, &p_type)))
- return (error);
-
- if (p_type == port_type) {
- found = true;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list