Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Sep 2016 23:57:18 +0000 (UTC)
From:      "Landon J. Fuller" <landonf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   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_...
Message-ID:  <201609032357.u83NvIxf008190@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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, &region)))
+			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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609032357.u83NvIxf008190>