From 664a74970833402c37182bc52d64175f4750cbfa Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Sat, 3 Sep 2016 23:57:17 +0000 Subject: [PATCH] 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 --- sys/conf/files | 3 + sys/dev/bhnd/bcma/bcma.c | 83 +- sys/dev/bhnd/bcma/bcma.h | 3 +- sys/dev/bhnd/bcma/bcma_bhndb.c | 21 +- sys/dev/bhnd/bcma/bcma_erom.c | 1164 ++++++++++++++------------ sys/dev/bhnd/bcma/bcma_eromvar.h | 64 +- sys/dev/bhnd/bcma/bcma_nexus.c | 23 +- sys/dev/bhnd/bcma/bcmavar.h | 3 +- sys/dev/bhnd/bhnd.h | 26 - sys/dev/bhnd/bhnd_bus_if.m | 33 - sys/dev/bhnd/bhnd_erom.c | 140 ++++ sys/dev/bhnd/bhnd_erom.h | 208 +++++ sys/dev/bhnd/bhnd_erom_if.m | 207 +++++ sys/dev/bhnd/bhnd_erom_types.h | 42 + sys/dev/bhnd/bhnd_subr.c | 36 +- sys/dev/bhnd/bhndb/bhndb.c | 4 + sys/dev/bhnd/siba/siba.c | 102 +-- sys/dev/bhnd/siba/siba.h | 3 +- sys/dev/bhnd/siba/siba_erom.c | 420 ++++++++++ sys/dev/bhnd/siba/siba_subr.c | 87 +- sys/dev/bhnd/siba/sibareg.h | 8 +- sys/dev/bhnd/siba/sibavar.h | 10 +- sys/mips/broadcom/bcm_bcma.c | 100 --- sys/mips/broadcom/bcm_machdep.c | 255 ++++-- sys/mips/broadcom/bcm_machdep.h | 37 +- sys/mips/broadcom/bcm_pmu.c | 8 +- sys/mips/broadcom/bcm_siba.c | 64 -- sys/mips/broadcom/files.broadcom | 2 - sys/modules/bhnd/Makefile | 3 + sys/modules/bhnd/bcma/Makefile | 3 +- sys/modules/bhnd/bcma_bhndb/Makefile | 3 +- sys/modules/bhnd/siba/Makefile | 6 +- sys/modules/bhnd/siba_bhndb/Makefile | 3 +- 33 files changed, 2050 insertions(+), 1124 deletions(-) create mode 100644 sys/dev/bhnd/bhnd_erom.c create mode 100644 sys/dev/bhnd/bhnd_erom.h create mode 100644 sys/dev/bhnd/bhnd_erom_if.m create mode 100644 sys/dev/bhnd/bhnd_erom_types.h create mode 100644 sys/dev/bhnd/siba/siba_erom.c delete mode 100644 sys/mips/broadcom/bcm_bcma.c delete mode 100644 sys/mips/broadcom/bcm_siba.c diff --git a/sys/conf/files b/sys/conf/files index dd8c828759ee..a6f9cbf9862a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 bhnd 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 # diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c index 745a94a8781e..ebb93e360381 100644 --- a/sys/dev/bhnd/bcma/bcma.c +++ b/sys/dev/bhnd/bcma/bcma.c @@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$"); #include "bcma_eromvar.h" #include +/* 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, struct bhnd_devinfo *dinfo) 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 resource *erom_res, bus_size_t erom_offse /* 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), diff --git a/sys/dev/bhnd/bcma/bcma.h b/sys/dev/bhnd/bcma/bcma.h index cd18b5883301..02fc427e0dff 100644 --- a/sys/dev/bhnd/bcma/bcma.h +++ b/sys/dev/bhnd/bcma/bcma.h @@ -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_ */ diff --git a/sys/dev/bhnd/bcma/bcma_bhndb.c b/sys/dev/bhnd/bcma/bcma_bhndb.c index 48642f721ec6..b1092f7c350b 100644 --- a/sys/dev/bhnd/bcma/bcma_bhndb.c +++ b/sys/dev/bhnd/bcma/bcma_bhndb.c @@ -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 */ diff --git a/sys/dev/bhnd/bcma/bcma_erom.c b/sys/dev/bhnd/bcma/bcma_erom.c index 2089159dd807..553f1d2f239b 100644 --- a/sys/dev/bhnd/bcma/bcma_erom.c +++ b/sys/dev/bhnd/bcma/bcma_erom.c @@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #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 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 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 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 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 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(struct bcma_erom *erom, } \ } 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,329 +123,125 @@ erom_entry_type_name (uint8_t entry) } } -/** - * Return the current read position. - */ -bus_size_t -bcma_erom_tell(struct bcma_erom *erom) +static int +bcma_erom_init(bhnd_erom_t *erom, device_t parent, int rid, bus_addr_t enum_addr) { - return (erom->offset); -} + struct bcma_erom *sc = (struct bcma_erom *)erom; -/** - * Seek to an absolute read position. - */ -void -bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset) -{ - erom->offset = offset; -} + sc->dev = parent; -/** - * Read a 32-bit entry value from the EROM table without advancing the - * read position. - * - * @param erom EROM read state. - * @param entry Will contain the read result on success. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ -int -bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry) -{ - if (erom->offset >= BCMA_EROM_TABLE_SIZE) { - EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n"); - return (EINVAL); - } + 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; - *entry = bus_space_read_4(erom->bst, erom->bsh, - erom->start + erom->offset); return (0); } -/** - * Read a 32-bit entry value from the EROM table. - * - * @param erom EROM read state. - * @param entry Will contain the read result on success. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ static int -erom_read32(struct bcma_erom *erom, uint32_t *entry) +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) { - int error; + uint32_t idreg, eaddr; + uint8_t chip_type; - if ((error = bcma_erom_peek32(erom, entry)) == 0) - erom->offset += 4; + idreg = bus_space_read_4(bst, bsh, CHIPC_ID); + chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); - return (error); -} + /* Fetch EROM physical address */ + if (!BHND_CHIPTYPE_HAS_EROM(chip_type)) + return (ENXIO); -/** - * Read and discard 32-bit entry value from the EROM table. - * - * @param erom EROM read state. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ -static int -erom_skip32(struct bcma_erom *erom) -{ - uint32_t entry; + eaddr = bus_space_read_4(bst, bsh, CHIPC_EROMPTR); - return erom_read32(erom, &entry); -} + /* Parse chip identifier */ + *cid = bhnd_parse_chipid(idreg, eaddr); -/** - * Read and discard a core descriptor from the EROM table. - * - * @param erom EROM read state. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ -static int -erom_skip_core(struct bcma_erom *erom) -{ - struct bcma_erom_core core; - return (bcma_erom_parse_core(erom, &core)); -} + /* Verify chip type */ + switch (chip_type) { + case BHND_CHIPTYPE_BCMA: + return (BUS_PROBE_DEFAULT); -/** - * Read and discard a master port descriptor from the EROM table. - * - * @param erom EROM read state. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ -static int -erom_skip_mport(struct bcma_erom *erom) -{ - struct bcma_erom_mport mp; - return (bcma_erom_parse_mport(erom, &mp)); -} - -/** - * Read and discard a port region descriptor from the EROM table. - * - * @param erom EROM read state. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero The read could not be completed. - */ -static int -erom_skip_sport_region(struct bcma_erom *erom) -{ - struct bcma_erom_sport_region r; - return (bcma_erom_parse_sport_region(erom, &r)); -} - -/** - * Seek to the next entry matching the given EROM entry type. - * - * @param erom EROM read state. - * @param etype One of BCMA_EROM_ENTRY_TYPE_CORE, - * BCMA_EROM_ENTRY_TYPE_MPORT, or BCMA_EROM_ENTRY_TYPE_REGION. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero Reading or parsing the descriptor failed. - */ -static int -erom_seek_next(struct bcma_erom *erom, uint8_t etype) -{ - uint32_t entry; - int error; - - /* Iterate until we hit an entry matching the requested type. */ - while (!(error = bcma_erom_peek32(erom, &entry))) { - /* Handle EOF */ - if (entry == BCMA_EROM_TABLE_EOF) - return (ENOENT); - - /* Invalid entry */ - if (!BCMA_EROM_GET_ATTR(entry, ENTRY_ISVALID)) - return (EINVAL); - - /* Entry type matches? */ - if (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE) == etype) - return (0); - - /* 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))) - return (error); - - break; - - case BCMA_EROM_ENTRY_TYPE_MPORT: - if ((error = erom_skip_mport(erom))) - return (error); - - break; - - case BCMA_EROM_ENTRY_TYPE_REGION: - if ((error = erom_skip_sport_region(erom))) - return (error); - break; + case BHND_CHIPTYPE_BCMA_ALT: + case BHND_CHIPTYPE_UBUS: + return (BUS_PROBE_GENERIC); default: - /* Unknown entry type! */ - return (EINVAL); - } + return (ENXIO); } - - return (error); } -/** - * Return the read position to the start of the EROM table. - * - * @param erom EROM read state. - */ -void -bcma_erom_reset(struct bcma_erom *erom) +static int +bcma_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst, + bus_space_handle_t bsh) { - erom->offset = 0; -} + struct bcma_erom *sc = (struct bcma_erom *)erom; -/** - * 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. - * - * @param erom EROM read state. - * @param core_index Index of the core to seek to. - * @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) -{ - int error; - - /* Start search at top of EROM */ - bcma_erom_reset(erom); - - /* Skip core descriptors till we hit the requested entry */ - for (u_int i = 0; i < core_index; i++) { - struct bcma_erom_core core; - - /* Read past the core descriptor */ - if ((error = bcma_erom_parse_core(erom, &core))) - return (error); - - /* Seek to the next readable core entry */ - error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); - if (error) - return (error); - } + 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); } - -/** - * Read the next core descriptor from the EROM table. - * - * @param erom EROM read state. - * @param[out] core On success, will be populated with the parsed core - * descriptor data. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero Reading or parsing the core descriptor failed. - */ -int -bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core) +static void +bcma_erom_fini(bhnd_erom_t *erom) { - uint32_t entry; - int error; + struct bcma_erom *sc = (struct bcma_erom *)erom; - /* Parse CoreDescA */ - if ((error = erom_read32(erom, &entry))) - return (error); - - /* Handle EOF */ - if (entry == BCMA_EROM_TABLE_EOF) - return (ENOENT); - - if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { - EROM_LOG(erom, "Unexpected EROM entry 0x%x (type=%s)\n", - entry, erom_entry_type_name(entry)); - - return (EINVAL); + if (sc->res != NULL) { + bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->rid, + sc->res); + + sc->res = NULL; + sc->rid = -1; } - - core->vendor = BCMA_EROM_GET_ATTR(entry, COREA_DESIGNER); - core->device = BCMA_EROM_GET_ATTR(entry, COREA_ID); - - /* Parse CoreDescB */ - if ((error = erom_read32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { - return (EINVAL); - } - - core->rev = BCMA_EROM_GET_ATTR(entry, COREB_REV); - core->num_mport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_MP); - core->num_dport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_DP); - core->num_mwrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP); - core->num_swrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WSP); - - return (0); } -/** - * 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) +static int +bcma_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + struct bhnd_core_info *core) { - struct bcma_erom_core core; - uint32_t entry; - uint8_t region_port, region_type; - bool found; - int error; + struct bcma_erom *sc = (struct bcma_erom *)erom; - if ((error = bcma_erom_seek_core_index(erom, core_index))) + /* 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(erom, &core))) + if ((error = bcma_erom_parse_core(sc, &ec))) return (error); /* Skip master ports */ - for (u_long i = 0; i < core.num_mport; i++) { - if ((error = erom_skip_mport(erom))) + for (u_long i = 0; i < ec.num_mport; i++) { + if ((error = bcma_erom_skip_mport(sc))) return (error); } @@ -475,7 +251,7 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, bhnd_port_type p_type; uint8_t r_type; - if ((error = bcma_erom_peek32(erom, &entry))) + if ((error = bcma_erom_peek32(sc, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, REGION)) @@ -483,7 +259,8 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, /* Expected region type? */ r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - if ((error = erom_region_to_port_type(erom, r_type, &p_type))) + error = bcma_erom_region_to_port_type(sc, r_type, &p_type); + if (error) return (error); if (p_type == port_type) { @@ -492,7 +269,7 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, } /* Skip to next entry */ - if ((error = erom_skip_sport_region(erom))) + if ((error = bcma_erom_skip_sport_region(sc))) return (error); } @@ -505,7 +282,7 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, for (u_int i = 0; i <= port_num; i++) { bhnd_port_type p_type; - if ((error = bcma_erom_peek32(erom, &entry))) + if ((error = bcma_erom_peek32(sc, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, REGION)) @@ -517,7 +294,7 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, /* Have we found the region entries for the desired port? */ if (i == port_num) { - error = erom_region_to_port_type(erom, region_type, + error = bcma_erom_region_to_port_type(sc, region_type, &p_type); if (error) return (error); @@ -532,10 +309,10 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, while (1) { uint8_t next_type, next_port; - if ((error = erom_skip_sport_region(erom))) + if ((error = bcma_erom_skip_sport_region(sc))) return (error); - if ((error = bcma_erom_peek32(erom, &entry))) + if ((error = bcma_erom_peek32(sc, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, REGION)) @@ -555,9 +332,10 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, /* Finally, search for the requested region number */ for (u_int i = 0; i <= region_num; i++) { - uint8_t next_port, next_type; + struct bcma_erom_sport_region region; + uint8_t next_port, next_type; - if ((error = bcma_erom_peek32(erom, &entry))) + if ((error = bcma_erom_peek32(sc, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, REGION)) @@ -571,181 +349,52 @@ bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, next_port != region_port) break; - if (i == region_num) - return (0); - - if ((error = erom_skip_sport_region(erom))) + /* 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); -} +}; -/** - * Read the next master port descriptor from the EROM table. - * - * @param erom EROM read state. - * @param[out] mport On success, will be populated with the parsed - * descriptor data. - * @retval 0 success - * @retval non-zero Reading or parsing the descriptor failed. - */ -int -bcma_erom_parse_mport(struct bcma_erom *erom, - struct bcma_erom_mport *mport) -{ - uint32_t entry; - int error; - - /* Parse the master port descriptor */ - if ((error = erom_read32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, MPORT)) - return (EINVAL); - - mport->port_vid = BCMA_EROM_GET_ATTR(entry, MPORT_ID); - mport->port_num = BCMA_EROM_GET_ATTR(entry, MPORT_NUM); - - return (0); -} - -/** - * Read the next slave port region descriptor from the EROM table. - * - * @param erom EROM read state. - * @param[out] mport On success, will be populated with the parsed - * descriptor data. - * @retval 0 success - * @retval ENOENT The end of the region descriptor table was reached. - * @retval non-zero Reading or parsing the descriptor failed. - */ -int -bcma_erom_parse_sport_region(struct bcma_erom *erom, - struct bcma_erom_sport_region *region) -{ - uint32_t entry; - uint8_t size_type; - int error; - - /* Peek at the region descriptor */ - if (bcma_erom_peek32(erom, &entry)) - return (EINVAL); - - /* A non-region entry signals the end of the region table */ - if (!BCMA_EROM_ENTRY_IS(entry, REGION)) { - return (ENOENT); - } else { - erom_skip32(erom); - } - - region->base_addr = BCMA_EROM_GET_ATTR(entry, REGION_BASE); - region->region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - region->region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); - size_type = BCMA_EROM_GET_ATTR(entry, REGION_SIZE); - - /* If region address is 64-bit, fetch the high bits. */ - if (BCMA_EROM_GET_ATTR(entry, REGION_64BIT)) { - if ((error = erom_read32(erom, &entry))) - return (error); - - region->base_addr |= ((bhnd_addr_t) entry << 32); - } - - /* Parse the region size; it's either encoded as the binary logarithm - * of the number of 4K pages (i.e. log2 n), or its encoded as a - * 32-bit/64-bit literal value directly following the current entry. */ - if (size_type == BCMA_EROM_REGION_SIZE_OTHER) { - if ((error = erom_read32(erom, &entry))) - return (error); - - region->size = BCMA_EROM_GET_ATTR(entry, RSIZE_VAL); - - if (BCMA_EROM_GET_ATTR(entry, RSIZE_64BIT)) { - if ((error = erom_read32(erom, &entry))) - return (error); - region->size |= ((bhnd_size_t) entry << 32); - } - } else { - region->size = BCMA_EROM_REGION_SIZE_BASE << size_type; - } - - /* Verify that addr+size does not overflow. */ - if (region->size != 0 && - BHND_ADDR_MAX - (region->size - 1) < region->base_addr) - { - EROM_LOG(erom, "%s%u: invalid address map %llx:%llx\n", - erom_entry_type_name(region->region_type), - region->region_port, - (unsigned long long) region->base_addr, - (unsigned long long) region->size); - - return (EINVAL); - } - - return (0); -} - -/** - * Convert a bcma_erom_core record to its bhnd_core_info representation. - * - * @param core EROM core record to convert. - * @param core_idx The core index of @p core. - * @param core_unit The core unit of @p core. - * @param[out] info The populated bhnd_core_info representation. - */ -void -bcma_erom_to_core_info(const struct bcma_erom_core *core, u_int core_idx, - int core_unit, struct bhnd_core_info *info) -{ - info->vendor = core->vendor; - info->device = core->device; - info->hwrev = core->rev; - info->core_idx = core_idx; - info->unit = core_unit; -} - -/** - * Parse all cores descriptors from @p erom and return the array - * in @p cores and the count in @p num_cores. The current EROM read position - * is left unmodified. - * - * The memory allocated for the table should be freed using - * `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed - * when an error is returned. - * - * @param erom EROM read state. - * @param[out] cores the table of parsed core descriptors. - * @param[out] num_cores the number of core records in @p cores. - */ -int -bcma_erom_get_core_info(struct bcma_erom *erom, - struct bhnd_core_info **cores, +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(erom); + initial_offset = bcma_erom_tell(sc); /* Determine the core count */ - bcma_erom_reset(erom); + bcma_erom_reset(sc); for (count = 0, error = 0; !error; count++) { struct bcma_erom_core core; /* Seek to the first readable core entry */ - error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); + 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(erom, &core))) + if ((error = bcma_erom_parse_core(sc, &core))) goto cleanup; } @@ -758,17 +407,17 @@ bcma_erom_get_core_info(struct bcma_erom *erom, } /* Parse all core descriptors */ - bcma_erom_reset(erom); + bcma_erom_reset(sc); for (u_int i = 0; i < count; i++) { struct bcma_erom_core core; int unit; /* Parse the core */ - error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); + error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); if (error) goto cleanup; - error = bcma_erom_parse_core(erom, &core); + error = bcma_erom_parse_core(sc, &core); if (error) goto cleanup; @@ -794,10 +443,475 @@ bcma_erom_get_core_info(struct bcma_erom *erom, } /* Restore the initial position */ - bcma_erom_seek(erom, initial_offset); + 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. + */ +static bus_size_t +bcma_erom_tell(struct bcma_erom *erom) +{ + return (erom->offset); +} + +/** + * Seek to an absolute read position. + */ +static void +bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset) +{ + erom->offset = offset; +} + +/** + * Read a 32-bit entry value from the EROM table without advancing the + * read position. + * + * @param erom EROM read state. + * @param entry Will contain the read result on success. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +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); + } + + 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); +} + +/** + * Read a 32-bit entry value from the EROM table. + * + * @param erom EROM read state. + * @param entry Will contain the read result on success. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +static int +bcma_erom_read32(struct bcma_erom *erom, uint32_t *entry) +{ + int error; + + if ((error = bcma_erom_peek32(erom, entry)) == 0) + erom->offset += 4; + + return (error); +} + +/** + * Read and discard 32-bit entry value from the EROM table. + * + * @param erom EROM read state. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +static int +bcma_erom_skip32(struct bcma_erom *erom) +{ + uint32_t entry; + + return bcma_erom_read32(erom, &entry); +} + +/** + * Read and discard a core descriptor from the EROM table. + * + * @param erom EROM read state. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +static int +bcma_erom_skip_core(struct bcma_erom *erom) +{ + struct bcma_erom_core core; + return (bcma_erom_parse_core(erom, &core)); +} + +/** + * Read and discard a master port descriptor from the EROM table. + * + * @param erom EROM read state. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +static int +bcma_erom_skip_mport(struct bcma_erom *erom) +{ + struct bcma_erom_mport mp; + return (bcma_erom_parse_mport(erom, &mp)); +} + +/** + * Read and discard a port region descriptor from the EROM table. + * + * @param erom EROM read state. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero The read could not be completed. + */ +static int +bcma_erom_skip_sport_region(struct bcma_erom *erom) +{ + struct bcma_erom_sport_region r; + return (bcma_erom_parse_sport_region(erom, &r)); +} + +/** + * Seek to the next entry matching the given EROM entry type. + * + * @param erom EROM read state. + * @param etype One of BCMA_EROM_ENTRY_TYPE_CORE, + * BCMA_EROM_ENTRY_TYPE_MPORT, or BCMA_EROM_ENTRY_TYPE_REGION. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero Reading or parsing the descriptor failed. + */ +static int +bcma_erom_seek_next(struct bcma_erom *erom, uint8_t etype) +{ + uint32_t entry; + int error; + + /* Iterate until we hit an entry matching the requested type. */ + while (!(error = bcma_erom_peek32(erom, &entry))) { + /* Handle EOF */ + if (entry == BCMA_EROM_TABLE_EOF) + return (ENOENT); + + /* Invalid entry */ + if (!BCMA_EROM_GET_ATTR(entry, ENTRY_ISVALID)) + return (EINVAL); + + /* Entry type matches? */ + if (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE) == etype) + return (0); + + /* Skip non-matching entry types. */ + switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { + case BCMA_EROM_ENTRY_TYPE_CORE: + if ((error = bcma_erom_skip_core(erom))) + return (error); + + break; + + case BCMA_EROM_ENTRY_TYPE_MPORT: + if ((error = bcma_erom_skip_mport(erom))) + return (error); + + break; + + case BCMA_EROM_ENTRY_TYPE_REGION: + if ((error = bcma_erom_skip_sport_region(erom))) + return (error); + break; + + default: + /* Unknown entry type! */ + return (EINVAL); + } + } + + return (error); +} + +/** + * Return the read position to the start of the EROM table. + * + * @param erom EROM read state. + */ +static void +bcma_erom_reset(struct bcma_erom *erom) +{ + erom->offset = 0; +} + +/** + * Seek to the first core entry matching @p desc. + * + * @param erom EROM read state. + * @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. + */ +static int +bcma_erom_seek_matching_core(struct bcma_erom *sc, + const struct bhnd_core_match *desc, struct bhnd_core_info *core) +{ + struct bhnd_core_match imatch; + bus_size_t core_offset, next_offset; + int error; + + /* Seek to table start. */ + bcma_erom_reset(sc); + + /* 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; + + /* Seek to the next core */ + error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); + if (error) + return (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); + } + + /* Not found, or a parse error occured */ + return (error); +} + +/** + * Read the next core descriptor from the EROM table. + * + * @param erom EROM read state. + * @param[out] core On success, will be populated with the parsed core + * descriptor data. + * @retval 0 success + * @retval ENOENT The end of the EROM table was reached. + * @retval non-zero Reading or parsing the core descriptor failed. + */ +static int +bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core) +{ + uint32_t entry; + int error; + + /* Parse CoreDescA */ + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + + /* Handle EOF */ + if (entry == BCMA_EROM_TABLE_EOF) + return (ENOENT); + + if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { + EROM_LOG(erom, "Unexpected EROM entry 0x%x (type=%s)\n", + entry, bcma_erom_entry_type_name(entry)); + + return (EINVAL); + } + + core->vendor = BCMA_EROM_GET_ATTR(entry, COREA_DESIGNER); + core->device = BCMA_EROM_GET_ATTR(entry, COREA_ID); + + /* Parse CoreDescB */ + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { + return (EINVAL); + } + + core->rev = BCMA_EROM_GET_ATTR(entry, COREB_REV); + core->num_mport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_MP); + core->num_dport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_DP); + core->num_mwrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP); + core->num_swrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WSP); + + return (0); +} + +/** + * Read the next master port descriptor from the EROM table. + * + * @param erom EROM read state. + * @param[out] mport On success, will be populated with the parsed + * descriptor data. + * @retval 0 success + * @retval non-zero Reading or parsing the descriptor failed. + */ +static int +bcma_erom_parse_mport(struct bcma_erom *erom, struct bcma_erom_mport *mport) +{ + uint32_t entry; + int error; + + /* Parse the master port descriptor */ + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, MPORT)) + return (EINVAL); + + mport->port_vid = BCMA_EROM_GET_ATTR(entry, MPORT_ID); + mport->port_num = BCMA_EROM_GET_ATTR(entry, MPORT_NUM); + + return (0); +} + +/** + * Read the next slave port region descriptor from the EROM table. + * + * @param erom EROM read state. + * @param[out] mport On success, will be populated with the parsed + * descriptor data. + * @retval 0 success + * @retval ENOENT The end of the region descriptor table was reached. + * @retval non-zero Reading or parsing the descriptor failed. + */ +static int +bcma_erom_parse_sport_region(struct bcma_erom *erom, + struct bcma_erom_sport_region *region) +{ + uint32_t entry; + uint8_t size_type; + int error; + + /* Peek at the region descriptor */ + if (bcma_erom_peek32(erom, &entry)) + return (EINVAL); + + /* A non-region entry signals the end of the region table */ + if (!BCMA_EROM_ENTRY_IS(entry, REGION)) { + return (ENOENT); + } else { + bcma_erom_skip32(erom); + } + + region->base_addr = BCMA_EROM_GET_ATTR(entry, REGION_BASE); + region->region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); + region->region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); + size_type = BCMA_EROM_GET_ATTR(entry, REGION_SIZE); + + /* If region address is 64-bit, fetch the high bits. */ + if (BCMA_EROM_GET_ATTR(entry, REGION_64BIT)) { + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + + region->base_addr |= ((bhnd_addr_t) entry << 32); + } + + /* Parse the region size; it's either encoded as the binary logarithm + * of the number of 4K pages (i.e. log2 n), or its encoded as a + * 32-bit/64-bit literal value directly following the current entry. */ + if (size_type == BCMA_EROM_REGION_SIZE_OTHER) { + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + + region->size = BCMA_EROM_GET_ATTR(entry, RSIZE_VAL); + + if (BCMA_EROM_GET_ATTR(entry, RSIZE_64BIT)) { + if ((error = bcma_erom_read32(erom, &entry))) + return (error); + region->size |= ((bhnd_size_t) entry << 32); + } + } else { + region->size = BCMA_EROM_REGION_SIZE_BASE << size_type; + } + + /* Verify that addr+size does not overflow. */ + if (region->size != 0 && + BHND_ADDR_MAX - (region->size - 1) < region->base_addr) + { + EROM_LOG(erom, "%s%u: invalid address map %llx:%llx\n", + bcma_erom_entry_type_name(region->region_type), + region->region_port, + (unsigned long long) region->base_addr, + (unsigned long long) region->size); + + return (EINVAL); + } + + return (0); +} + +/** + * Convert a bcma_erom_core record to its bhnd_core_info representation. + * + * @param core EROM core record to convert. + * @param core_idx The core index of @p core. + * @param core_unit The core unit of @p core. + * @param[out] info The populated bhnd_core_info representation. + */ +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) +{ + info->vendor = core->vendor; + info->device = core->device; + info->hwrev = core->rev; + info->core_idx = core_idx; + info->unit = core_unit; +} + /** * Map an EROM region type to its corresponding port type. * @@ -805,7 +919,7 @@ bcma_erom_get_core_info(struct bcma_erom *erom, * @param[out] port_type On success, the corresponding port type. */ static int -erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type, +bcma_erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type, bhnd_port_type *port_type) { switch (region_type) { @@ -837,7 +951,7 @@ erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type, * will be updated to point to the next EROM table entry. */ static int -erom_corecfg_fill_port_regions(struct bcma_erom *erom, +bcma_erom_corecfg_fill_port_regions(struct bcma_erom *erom, struct bcma_corecfg *corecfg, bcma_pid_t port_num, uint8_t region_type) { @@ -850,7 +964,8 @@ erom_corecfg_fill_port_regions(struct bcma_erom *erom, error = 0; /* Determine the port type for this region type. */ - if ((error = erom_region_to_port_type(erom, region_type, &port_type))) + error = bcma_erom_region_to_port_type(erom, region_type, &port_type); + if (error) return (error); /* Fetch the list to be populated */ @@ -945,7 +1060,7 @@ erom_corecfg_fill_port_regions(struct bcma_erom *erom, * Parse the next core entry from the EROM table and produce a bcma_corecfg * to be owned by the caller. * - * @param erom EROM read state. + * @param erom A bcma EROM instance. * @param[out] result On success, the core's device info. The caller inherits * ownership of this allocation. * @@ -953,7 +1068,7 @@ erom_corecfg_fill_port_regions(struct bcma_erom *erom, * ENOENT will be returned. On error, returns a non-zero error value. */ int -bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) +bcma_erom_next_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) { struct bcma_corecfg *cfg; struct bcma_erom_core core; @@ -978,7 +1093,8 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) struct bcma_erom_core prev_core; /* Parse next core */ - if ((error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE))) + error = bcma_erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); + if (error) return (error); if ((error = bcma_erom_parse_core(erom, &prev_core))) @@ -992,12 +1108,13 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) } /* Seek to next core */ - if ((error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE))) + error = bcma_erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); + if (error) return (error); } /* We already parsed the core descriptor */ - if ((error = erom_skip_core(erom))) + if ((error = bcma_erom_skip_core(erom))) return (error); /* Allocate our corecfg */ @@ -1083,7 +1200,7 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) /* Device/bridge port descriptors */ for (uint8_t sp_num = 0; sp_num < core.num_dport; sp_num++) { - error = erom_corecfg_fill_port_regions(erom, cfg, sp_num, + error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, first_region_type); if (error) @@ -1092,7 +1209,7 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) /* Wrapper (aka device management) descriptors (for master ports). */ for (uint8_t sp_num = 0; sp_num < core.num_mwrap; sp_num++) { - error = erom_corecfg_fill_port_regions(erom, cfg, sp_num, + error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, BCMA_EROM_REGION_TYPE_MWRAP); if (error) @@ -1124,7 +1241,7 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) sp_num = (core.num_mwrap > 0) ? core.num_mwrap : ((core.vendor == BHND_MFGID_BCM) ? 1 : 0) + i; - error = erom_corecfg_fill_port_regions(erom, cfg, sp_num, + error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, BCMA_EROM_REGION_TYPE_SWRAP); if (error) @@ -1140,3 +1257,18 @@ bcma_erom_parse_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) return error; } + +static kobj_method_t bcma_erom_methods[] = { + 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), + KOBJMETHOD(bhnd_erom_fini, bcma_erom_fini), + KOBJMETHOD(bhnd_erom_get_core_table, bcma_erom_get_core_table), + KOBJMETHOD(bhnd_erom_free_core_table, bcma_erom_free_core_table), + KOBJMETHOD(bhnd_erom_lookup_core, bcma_erom_lookup_core), + KOBJMETHOD(bhnd_erom_lookup_core_addr, bcma_erom_lookup_core_addr), + + KOBJMETHOD_END +}; + +BHND_EROM_DEFINE_CLASS(bcma_erom, bcma_erom_parser, bcma_erom_methods, sizeof(struct bcma_erom)); diff --git a/sys/dev/bhnd/bcma/bcma_eromvar.h b/sys/dev/bhnd/bcma/bcma_eromvar.h index 292352c62199..b8fe3cb48ee3 100644 --- a/sys/dev/bhnd/bcma/bcma_eromvar.h +++ b/sys/dev/bhnd/bcma/bcma_eromvar.h @@ -33,18 +33,32 @@ #define _BCMA_BCMA_EROMVAR_H_ #include +#include #include "bcmavar.h" +struct bcma_erom; + +int bcma_erom_next_corecfg(struct bcma_erom *sc, + struct bcma_corecfg **result); + /** - * EROM read context. + * BCMA EROM per-instance state. */ struct bcma_erom { - device_t dev; /**< EROM parent device */ - 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 */ + 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. */ @@ -76,42 +90,4 @@ struct bcma_erom_sport_region { bhnd_addr_t size; /**< region size */ }; -int bcma_erom_open(struct bcma_erom *erom, struct resource *r, - bus_size_t offset); - -int bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t owner, - bus_space_tag_t bst, bus_space_handle_t bsh, - bus_size_t offset); - -int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry); -bus_size_t bcma_erom_tell(struct bcma_erom *erom); -void bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset); -void bcma_erom_reset(struct bcma_erom *erom); - -int bcma_erom_seek_next_core(struct bcma_erom *erom); -int bcma_erom_seek_core_index(struct bcma_erom *erom, - u_int core_index); -int bcma_erom_parse_core(struct bcma_erom *erom, - struct bcma_erom_core *core); - -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); - -int bcma_erom_parse_mport(struct bcma_erom *erom, - struct bcma_erom_mport *mport); - -int bcma_erom_parse_sport_region(struct bcma_erom *erom, - struct bcma_erom_sport_region *region); - -void bcma_erom_to_core_info(const struct bcma_erom_core *core, - u_int core_idx, int core_unit, struct bhnd_core_info *info); - -int bcma_erom_get_core_info(struct bcma_erom *erom, - struct bhnd_core_info **cores, - u_int *num_cores); - -int bcma_erom_parse_corecfg(struct bcma_erom *erom, - struct bcma_corecfg **result); - #endif /* _BCMA_BCMA_EROMVAR_H_ */ diff --git a/sys/dev/bhnd/bcma/bcma_nexus.c b/sys/dev/bhnd/bcma/bcma_nexus.c index 8f4e2d2f4c0c..dfe83057e51d 100644 --- a/sys/dev/bhnd/bcma/bcma_nexus.c +++ b/sys/dev/bhnd/bcma/bcma_nexus.c @@ -91,28 +91,9 @@ bcma_nexus_probe(device_t dev) static int bcma_nexus_attach(device_t dev) { - struct bcma_nexus_softc *sc; - struct resource *erom_res; - int error; - int rid; + int error; - sc = device_get_softc(dev); - - /* Map the EROM resource and enumerate the bus. */ - rid = 0; - erom_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - sc->bcma_cid.enum_addr, - sc->bcma_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); - bus_release_resource(dev, SYS_RES_MEMORY, rid, erom_res); - - if (error) + if ((error = bcma_add_children(dev))) return (error); return (bcma_attach(dev)); diff --git a/sys/dev/bhnd/bcma/bcmavar.h b/sys/dev/bhnd/bcma/bcmavar.h index baf1438fa74a..64c5da4d50f3 100644 --- a/sys/dev/bhnd/bcma/bcmavar.h +++ b/sys/dev/bhnd/bcma/bcmavar.h @@ -63,8 +63,7 @@ int bcma_probe(device_t dev); int bcma_attach(device_t dev); int bcma_detach(device_t dev); -int bcma_add_children(device_t bus, - struct resource *erom_res, bus_size_t erom_offset); +int bcma_add_children(device_t bus); struct bcma_sport_list *bcma_corecfg_get_port_list(struct bcma_corecfg *cfg, bhnd_port_type type); diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index 9b5db371359a..2f3ddcd91016 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -428,32 +428,6 @@ bhnd_get_chipid(device_t dev) { return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev)); }; -/** - * Get a list of all cores discoverable on the bhnd bus. - * - * Enumerates all cores discoverable on @p dev, returning the list in - * @p cores and the count in @p num_cores. - * - * The memory allocated for the list should be freed using - * `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed - * when an error is returned. - * - * @param dev A bhnd bus child device. - * @param[out] cores The table of core descriptors. - * @param[out] num_cores The number of core descriptors in @p cores. - * - * @retval 0 success - * @retval non-zero if an error occurs enumerating @p dev, a regular UNIX - * error code should be returned. - */ -static inline int -bhnd_get_core_table(device_t dev, struct bhnd_core_info **cores, - u_int *num_cores) -{ - return (BHND_BUS_GET_CORE_TABLE(device_get_parent(dev), dev, cores, - num_cores)); -} - /** * If supported by the chipset, return the clock source for the given clock. * diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index 2e22dcd9a12c..588d89437288 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -56,13 +56,6 @@ CODE { panic("bhnd_bus_get_chipid unimplemented"); } - static int - bhnd_bus_null_get_core_table(device_t dev, device_t child, - struct bhnd_core_info **cores, u_int *num_cores) - { - panic("bhnd_bus_get_core_table unimplemented"); - } - static bhnd_attach_type bhnd_bus_null_get_attach_type(device_t dev, device_t child) { @@ -277,32 +270,6 @@ METHOD const struct bhnd_chipid * get_chipid { device_t child; } DEFAULT bhnd_bus_null_get_chipid; -/** - * Get a list of all cores discoverable on @p dev. - * - * Enumerates all cores discoverable on @p dev, returning the list in - * @p cores and the count in @p num_cores. - * - * The memory allocated for the list should be freed using - * `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed - * when an error is returned. - * - * @param dev The bhnd bus device. - * @param child The requesting bhnd bus child. - * @param[out] cores The table of core descriptors. - * @param[out] num_cores The number of core descriptors in @p cores. - * - * @retval 0 success - * @retval non-zero if an error occurs enumerating @p dev, a regular UNIX - * error code should be returned. - */ -METHOD int get_core_table { - device_t dev; - device_t child; - struct bhnd_core_info **cores; - u_int *num_cores; -} DEFAULT bhnd_bus_null_get_core_table; - /** * Return the BHND attachment type of the parent bus. * diff --git a/sys/dev/bhnd/bhnd_erom.c b/sys/dev/bhnd/bhnd_erom.c new file mode 100644 index 000000000000..ed7f473475e0 --- /dev/null +++ b/sys/dev/bhnd/bhnd_erom.c @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include + +/** + * Allocate and return a new device enumeration table parser. + * + * @param cls The parser class for which an instance will be + * allocated. + * @param parent The parent device from which EROM resources should + * 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. + * + * @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_t *erom; + int error; + + 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))) { + printf("error initializing %s parser at %#jx with " + "rid %d: %d\n", cls->name, (uintmax_t)enum_addr, rid, + error); + + kobj_delete((kobj_t)erom, M_BHND); + return (NULL); + } + + return (erom); +} + +/** + * Perform static initialization of aa device enumeration table parser using + * the provided bus space tag and handle. + * + * This may be used to initialize a caller-allocated erom instance state + * during early boot, prior to malloc availability. + * + * @param cls The parser class for which an instance will be + * allocated. + * @param erom The erom parser instance to initialize. + * @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 bst Bus space tag. + * @param bsh Bus space handle mapping the device enumeration + * space. + * + * @retval 0 success + * @retval ENOMEM if @p esize is smaller than required by @p cls. + * @retval non-zero if an error occurs initializing the EROM parser, + * a regular unix error code will be returned. + */ +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) +{ + kobj_class_t kcls; + + kcls = (kobj_class_t)cls; + + /* Verify allocation size */ + if (kcls->size > esize) + return (ENOMEM); + + /* Perform instance initialization */ + kobj_init_static((kobj_t)erom, kcls); + return (BHND_EROM_INIT_STATIC(erom, bst, bsh)); +} + +/** + * Release any resources held by a @p erom parser previously + * initialized via bhnd_erom_init_static(). + * + * @param erom An erom parser instance previously initialized via + * bhnd_erom_init_static(). + */ +void +bhnd_erom_fini_static(bhnd_erom_t *erom) +{ + return (BHND_EROM_FINI(erom)); +} + +/** + * Release all resources held by a @p erom parser previously + * allocated via bhnd_erom_alloc(). + * + * @param erom An erom parser instance previously allocated via + * bhnd_erom_alloc(). + */ +void +bhnd_erom_free(bhnd_erom_t *erom) +{ + BHND_EROM_FINI(erom); + kobj_delete((kobj_t)erom, M_BHND); +} diff --git a/sys/dev/bhnd/bhnd_erom.h b/sys/dev/bhnd/bhnd_erom.h new file mode 100644 index 000000000000..a07e26111e63 --- /dev/null +++ b/sys/dev/bhnd/bhnd_erom.h @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_EROM_BHND_EROM_H_ +#define _BHND_EROM_BHND_EROM_H_ + +#include +#include +#include + +#include +#include + +#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); + +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); + +void bhnd_erom_fini_static(bhnd_erom_t *erom); + +void bhnd_erom_free(bhnd_erom_t *erom); + +/** + * Abstract bhnd_erom instance state. Must be first member of all subclass + * instances. + */ +struct bhnd_erom { + KOBJ_FIELDS; +}; + + +/** Number of additional bytes to reserve for statically allocated + * bhnd_erom instances. */ +#define BHND_EROM_STATIC_BYTES 64 + +/** + * A bhnd_erom instance structure large enough to statically allocate + * any known bhnd_erom subclass. + * + * The maximum size of subclasses is verified statically in + * BHND_EROM_DEFINE_CLASS(), and at runtime in bhnd_erom_init_static(). + */ +struct bhnd_erom_static { + struct bhnd_erom obj; + uint8_t idata[BHND_EROM_STATIC_BYTES]; +}; + +/** Registered EROM parser class instances. */ +SET_DECLARE(bhnd_erom_class_set, bhnd_erom_class_t); + +#define BHND_EROM_DEFINE_CLASS(name, classvar, methods, size) \ + DEFINE_CLASS_0(name, classvar, methods, size); \ + BHND_EROM_CLASS_DEF(classvar); \ + _Static_assert(size <= sizeof(struct bhnd_erom_static), \ + "cannot statically allocate instance data; " \ + "increase BHND_EROM_STATIC_BYTES"); + +#define BHND_EROM_CLASS_DEF(classvar) DATA_SET(bhnd_erom_class_set, classvar) + + +/** + * 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 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[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 lowest 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_static(bhnd_erom_class_t *cls, bus_space_tag_t bst, + bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid) +{ + return (BHND_EROM_PROBE_STATIC(cls, bst, bsh, paddr, cid)); +} + +/** + * Parse all cores descriptors in @p erom, returning the array in @p cores and + * the count in @p num_cores. + * + * The memory allocated for the table must be freed via + * bhnd_erom_free_core_table(). + * + * @param erom The erom parser to be queried. + * @param[out] cores The table of parsed core descriptors. + * @param[out] num_cores The number of core records in @p cores. + * + * @retval 0 success + * @retval non-zero if an error occurs, a regular unix error code will + * be returned. + */ +static inline int +bhnd_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, + u_int *num_cores) +{ + return (BHND_EROM_GET_CORE_TABLE(erom, cores, num_cores)); +} + +/** + * Free any memory allocated in a previous call to BHND_EROM_GET_CORE_TABLE(). + * + * @param erom The erom parser instance. + * @param cores A core table allocated by @p erom. + */ +static inline void +bhnd_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores) +{ + return (BHND_EROM_FREE_CORE_TABLE(erom, cores)); +}; + +/** + * Locate the first core table entry in @p erom that matches @p desc. + * + * @param erom The erom parser to be queried. + * @param desc A core match descriptor. + * @param[out] core On success, the matching core info record. + * + * @retval 0 success + * @retval ENOENT No core matching @p desc was found. + * @retval non-zero Reading or parsing failed. + */ +static inline int +bhnd_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + struct bhnd_core_info *core) +{ + return (BHND_EROM_LOOKUP_CORE(erom, desc, core)); +} + +/** + * Locate the first core table entry in @p erom that matches @p desc, + * and return the specified port region's base address and size. + * + * If a core matching @p desc is not found, or the requested port region + * is not mapped to the matching core, ENOENT is returned. + * + * @param erom The erom parser to be queried. + * @param desc A core match descriptor. + * @param type The port type to search for. + * @param port The port to search for. + * @param region The port region to search for. + * @param[out] core If not NULL, will be populated with the matched core + * info record on success. + * @param[out] addr On success, the base address of the port region. + * @param[out] size On success, the total size of the port region. + * + * @retval 0 success + * @retval ENOENT No core matching @p desc was found. + * @retval ENOENT No port region matching @p type, @p port, and @p region + * was found. + * @retval non-zero Reading or parsing failed. + */ +static inline int +bhnd_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + bhnd_port_type type, u_int port, u_int region, struct bhnd_core_info *core, + bhnd_addr_t *addr, bhnd_size_t *size) +{ + return (BHND_EROM_LOOKUP_CORE_ADDR(erom, desc, type, port, region, + core, addr, size)); +}; + +#endif /* _BHND_EROM_BHND_EROM_H_ */ diff --git a/sys/dev/bhnd/bhnd_erom_if.m b/sys/dev/bhnd/bhnd_erom_if.m new file mode 100644 index 000000000000..51c37855ffef --- /dev/null +++ b/sys/dev/bhnd/bhnd_erom_if.m @@ -0,0 +1,207 @@ +#- +# Copyright (c) 2016 Landon Fuller +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ + +#include +#include + +#include +#include +#include + +#include +#include + +INTERFACE bhnd_erom; + +# +# bhnd(4) device enumeration. +# +# Provides a common parser interface to the incompatible device enumeration +# tables used by bhnd(4) buses. +# + +/** + * 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 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[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_static { + bhnd_erom_class_t *cls; + bus_space_tag_t bst; + bus_space_handle_t bsh; + bus_addr_t paddr; + struct bhnd_chipid *cid; +}; + +/** + * Initialize a device enumeration table parser. + * + * @param erom The erom parser to initialize. + * @param parent The parent device from which EROM resources should + * be allocated. + * @param rid The resource id to be used when allocating the + * enumeration table. + * @param enum_addr The base address of the device enumeration table. + * + * @retval 0 success + * @retval non-zero if an error occurs initializing the EROM parser, + * a regular unix error code will be returned. + */ +METHOD int init { + bhnd_erom_t *erom; + device_t parent; + int rid; + bus_addr_t enum_addr; +}; + +/** + * Initialize an device enumeration table parser using the provided bus space + * tag and handle. + * + * @param erom The erom parser to initialize. + * @param bst Bus space tag. + * @param bsh bus space handle mapping the full bus enumeration + * space. + * + * @retval 0 success + * @retval non-zero if an error occurs initializing the EROM parser, + * a regular unix error code will be returned. + */ +METHOD int init_static { + bhnd_erom_t *erom; + bus_space_tag_t bst; + bus_space_handle_t bsh; +}; + +/** + * Release all resources held by @p erom. + * + * @param erom An erom parser instance previously initialized via + * BHND_EROM_INIT() or BHND_EROM_INIT_STATIC(). + */ +METHOD void fini { + bhnd_erom_t *erom; +}; + +/** + * Parse all cores descriptors, returning the array in @p cores and the count + * in @p num_cores. + * + * The memory allocated for the table must be freed via + * BHND_EROM_FREE_CORE_TABLE(). + * + * @param erom The erom parser to be queried. + * @param[out] cores The table of parsed core descriptors. + * @param[out] num_cores The number of core records in @p cores. + * + * @retval 0 success + * @retval non-zero if an error occurs, a regular unix error code will + * be returned. + */ +METHOD int get_core_table { + bhnd_erom_t *erom; + struct bhnd_core_info **cores; + u_int *num_cores; +}; + +/** + * Free any memory allocated in a previous call to BHND_EROM_GET_CORE_TABLE(). + * + * @param erom The erom parser instance. + * @param cores A core table allocated by @p erom. + */ +METHOD void free_core_table { + bhnd_erom_t *erom; + struct bhnd_core_info *cores; +}; + +/** + * Locate the first core table entry in @p erom that matches @p desc. + * + * @param erom The erom parser to be queried. + * @param desc A core match descriptor. + * @param[out] core On success, the matching core info record. + * + * @retval 0 success + * @retval ENOENT No core matching @p desc was found. + * @retval non-zero Reading or parsing failed. + */ +METHOD int lookup_core { + bhnd_erom_t *erom; + const struct bhnd_core_match *desc; + struct bhnd_core_info *core; +}; + +/** + * Locate the first core table entry in @p erom that matches @p desc, + * and return the specified port region's base address and size. + * + * If a core matching @p desc is not found, or the requested port region + * is not mapped to the matching core, ENOENT is returned. + * + * @param erom The erom parser to be queried. + * @param desc A core match descriptor. + * @param type The port type to search for. + * @param port The port to search for. + * @param region The port region to search for. + * @param[out] core If not NULL, will be populated with the matched core + * info record on success. + * @param[out] addr On success, the base address of the port region. + * @param[out] size On success, the total size of the port region. + * + * @retval 0 success + * @retval ENOENT No core matching @p desc was found. + * @retval ENOENT No port region matching @p type, @p port, and @p region + * was found. + * @retval non-zero Reading or parsing failed. + */ +METHOD int lookup_core_addr { + bhnd_erom_t *erom; + const struct bhnd_core_match *desc; + bhnd_port_type type; + u_int port; + u_int region; + struct bhnd_core_info *core; + bhnd_addr_t *addr; + bhnd_size_t *size; +}; diff --git a/sys/dev/bhnd/bhnd_erom_types.h b/sys/dev/bhnd/bhnd_erom_types.h new file mode 100644 index 000000000000..5e650c170f97 --- /dev/null +++ b/sys/dev/bhnd/bhnd_erom_types.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_EROM_BHND_EROM_TYPES_H_ +#define _BHND_EROM_BHND_EROM_TYPES_H_ + +#include +#include + +typedef struct kobj_class bhnd_erom_class_t; /**< bhnd_erom parser class */ +typedef struct bhnd_erom bhnd_erom_t; /**< bhnd_erom parser instance */ +typedef struct bhnd_erom_static bhnd_erom_static_t; /**< bhnd_erom parser static instance data */ + +#endif /* _BHND_EROM_BHND_EROM_TYPES_H_ */ diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index 349bc27317c2..d7051444ce73 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -944,7 +944,7 @@ bhnd_read_chipid(device_t dev, struct resource_spec *rs, } else if (chip_type == BHND_CHIPTYPE_SIBA) { /* siba(4) uses the ChipCommon base address as the enumeration * address */ - enum_addr = rman_get_start(res) + chipc_offset; + enum_addr = BHND_DEFAULT_CHIPC_ADDR; } else { device_printf(dev, "unknown chip type %hhu\n", chip_type); error = ENODEV; @@ -1578,19 +1578,41 @@ bhnd_bus_generic_release_resource(device_t dev, device_t child, int type, /** * Helper function for implementing BHND_BUS_ACTIVATE_RESOURCE(). * - * This implementation of BHND_BUS_ACTIVATE_RESOURCE() simply calls the + * This implementation of BHND_BUS_ACTIVATE_RESOURCE() first calls the * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. + * + * If this fails, and if @p dev is the direct parent of @p child, standard + * resource activation is attempted via bus_activate_resource(). This enables + * direct use of the bhnd(4) resource APIs on devices that may not be attached + * to a parent bhnd bus or bridge. */ int bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { - /* Try to delegate to the parent */ - if (device_get_parent(dev) != NULL) - return (BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), - child, type, rid, r)); + int error; + bool passthrough; - return (EINVAL); + passthrough = (device_get_parent(child) != dev); + + /* Try to delegate to the parent */ + if (device_get_parent(dev) != NULL) { + error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), + child, type, rid, r); + } else { + error = ENODEV; + } + + /* If bhnd(4) activation has failed and we're the child's direct + * parent, try falling back on standard resource activation. + */ + if (error && !passthrough) { + error = bus_activate_resource(child, type, rid, r->res); + if (!error) + r->direct = true; + } + + return (error); }; /** diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index f12c5434c811..98e1b37444e9 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -1328,6 +1328,10 @@ bhndb_retain_dynamic_window(struct bhndb_softc *sc, struct resource *r) return (NULL); } + /* Window must be large enough to map the entire resource */ + if (dwa->win->win_size < rman_get_size(r)) + return (NULL); + /* Set the window target */ error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, rman_get_start(r), rman_get_size(r)); diff --git a/sys/dev/bhnd/siba/siba.c b/sys/dev/bhnd/siba/siba.c index a8b8bc458e46..cb1d6f520cfd 100644 --- a/sys/dev/bhnd/siba/siba.c +++ b/sys/dev/bhnd/siba/siba.c @@ -335,7 +335,7 @@ siba_get_port_count(device_t dev, device_t child, bhnd_port_type type) type)); dinfo = device_get_ivars(child); - return (siba_addrspace_port_count(dinfo)); + return (siba_addrspace_port_count(dinfo->core_id.num_addrspace)); } static u_int @@ -350,10 +350,11 @@ siba_get_region_count(device_t dev, device_t child, bhnd_port_type type, type, port)); dinfo = device_get_ivars(child); - if (!siba_is_port_valid(dinfo, type, port)) + if (!siba_is_port_valid(dinfo->core_id.num_addrspace, type, port)) return (0); - return (siba_addrspace_region_count(dinfo, port)); + return (siba_addrspace_region_count(dinfo->core_id.num_addrspace, + port)); } static int @@ -441,7 +442,7 @@ siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, */ static int siba_register_addrspaces(device_t dev, struct siba_devinfo *di, - struct resource *r) + struct bhnd_resource *r) { struct siba_core_id *cid; uint32_t addr; @@ -465,7 +466,7 @@ siba_register_addrspaces(device_t dev, struct siba_devinfo *di, } /* Fetch the address match register value */ - adm = bus_read_4(r, adm_offset); + adm = bhnd_bus_read_4(r, adm_offset); /* Parse the value */ if ((error = siba_parse_admatch(adm, &addr, &size))) { @@ -504,76 +505,6 @@ siba_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo) siba_free_dinfo(dev, (struct siba_devinfo *)dinfo); } - -static int -siba_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores, - u_int *num_cores) -{ - const struct bhnd_chipid *chipid; - struct bhnd_core_info *table; - struct bhnd_resource *r; - int error; - int rid; - - /* Fetch the core count from our chip identification */ - chipid = BHND_BUS_GET_CHIPID(dev, dev); - - /* Allocate our local core table */ - table = malloc(sizeof(*table) * chipid->ncores, M_BHND, M_NOWAIT); - if (table == NULL) - return (ENOMEM); - - /* Enumerate all cores. */ - for (u_int i = 0; i < chipid->ncores; i++) { - struct siba_core_id cid; - uint32_t idhigh, idlow; - - /* Map the core's register block */ - rid = 0; - r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, - SIBA_CORE_ADDR(i), SIBA_CORE_ADDR(i) + SIBA_CORE_SIZE - 1, - SIBA_CORE_SIZE, RF_ACTIVE); - if (r == NULL) { - error = ENXIO; - goto failed; - } - - /* Read the core info */ - idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); - idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); - - cid = siba_parse_core_id(idhigh, idlow, i, 0); - table[i] = cid.core_info; - - /* Determine unit number */ - for (u_int j = 0; j < i; j++) { - if (table[j].vendor == table[i].vendor && - table[j].device == table[i].device) - table[i].unit++; - } - - /* Release our resource */ - bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); - r = NULL; - } - - /* Provide the result values (performed last to avoid modifying - * cores/num_cores if enumeration failed). */ - *cores = table; - *num_cores = chipid->ncores; - - return (0); - -failed: - if (table != NULL) - free(table, M_BHND); - - if (r != NULL) - bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); - - return (error); -} - /** * Scan the core table and add all valid discovered cores to * the bus. @@ -588,7 +519,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) struct bhnd_chipid ccid; struct bhnd_core_info *cores; struct siba_devinfo *dinfo; - struct resource *r; + struct bhnd_resource *r; int rid; int error; @@ -612,13 +543,13 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) /* Map the first core's register block. If the ChipCommon core * exists, it will always be the first core. */ rid = 0; - r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1, RF_ACTIVE); /* Identify the core */ - idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); + idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); device = SIBA_REG_GET(idhigh, IDH_DEVICE); ccrev = SIBA_IDH_CORE_REV(idhigh); @@ -632,7 +563,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) } /* Identify the chipset */ - ccreg = bus_read_4(r, CHIPC_ID); + ccreg = bhnd_bus_read_4(r, CHIPC_ID); ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR); /* Fix up the core count */ @@ -644,7 +575,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) } chipid = &ccid; - bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); } /* Allocate our temporary core table and enumerate all cores */ @@ -664,7 +595,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) r_start = SIBA_CORE_ADDR(i); r_count = SIBA_CORE_SIZE; r_end = r_start + SIBA_CORE_SIZE - 1; - r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, + r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, r_end, r_count, RF_ACTIVE); if (r == NULL) { error = ENXIO; @@ -679,8 +610,8 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) } /* Read the core info */ - idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); - idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); + idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); + idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); cid = siba_parse_core_id(idhigh, idlow, i, 0); cores[i] = cid.core_info; @@ -711,7 +642,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) device_disable(child); /* Release our resource */ - bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); r = NULL; /* Issue bus callback for fully initialized child. */ @@ -723,7 +654,7 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid) free(cores, M_BHND); if (r != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); return (error); } @@ -743,7 +674,6 @@ static device_method_t siba_methods[] = { /* BHND interface */ DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), - DEVMETHOD(bhnd_bus_get_core_table, siba_get_core_table), DEVMETHOD(bhnd_bus_alloc_devinfo, siba_alloc_bhnd_dinfo), DEVMETHOD(bhnd_bus_free_devinfo, siba_free_bhnd_dinfo), DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), diff --git a/sys/dev/bhnd/siba/siba.h b/sys/dev/bhnd/siba/siba.h index 9172525241b1..1ac0e0fc177f 100644 --- a/sys/dev/bhnd/siba/siba.h +++ b/sys/dev/bhnd/siba/siba.h @@ -45,5 +45,6 @@ */ DECLARE_CLASS(siba_driver); +DECLARE_CLASS(siba_erom_parser); -#endif /* _SIBA_SIBA_H_ */ \ No newline at end of file +#endif /* _SIBA_SIBA_H_ */ diff --git a/sys/dev/bhnd/siba/siba_erom.c b/sys/dev/bhnd/siba/siba_erom.c new file mode 100644 index 000000000000..821a6d7efad7 --- /dev/null +++ b/sys/dev/bhnd/siba/siba_erom.c @@ -0,0 +1,420 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "sibareg.h" +#include "sibavar.h" + +struct siba_erom; + +static int siba_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst, + bus_space_handle_t bsh); +static void siba_erom_fini(bhnd_erom_t *erom); + +static uint32_t siba_erom_read_4(struct siba_erom *sc, u_int core_idx, + bus_size_t offset); +static int siba_erom_read_chipid(struct siba_erom *sc, + bus_addr_t enum_addr, struct bhnd_chipid *cid); + +struct siba_erom { + struct bhnd_erom obj; + u_int ncores; /**< core count */ + + /* resource state */ + device_t dev; /**< parent dev to use for resource allocations, + or NULL if initialized with bst/bsh */ + struct bhnd_resource *res; /**< siba bus mapping, or NULL */ + int rid; /**< siba bus maping resource ID */ + + /* bus tag state */ + bus_space_tag_t bst; /**< chipc bus tag */ + bus_space_handle_t bsh; /**< chipc bus handle */ +}; + +#define EROM_LOG(sc, fmt, ...) do { \ + if (sc->dev != NULL) { \ + device_printf(sc->dev, "%s: " fmt, __FUNCTION__, \ + ##__VA_ARGS__); \ + } else { \ + printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__); \ + } \ +} while(0) + +static uint32_t +siba_erom_read_4(struct siba_erom *sc, u_int core_idx, bus_size_t offset) +{ + bus_size_t core_offset; + + /* Sanity check core index and offset */ + if (core_idx >= sc->ncores) + panic("core index %u out of range (ncores=%u)", core_idx, + sc->ncores); + + if (offset > SIBA_CORE_SIZE - sizeof(uint32_t)) + panic("invalid core offset %#jx", (uintmax_t)offset); + + /* Perform read */ + core_offset = SIBA_CORE_OFFSET(core_idx) + offset; + if (sc->res != NULL) + return (bhnd_bus_read_4(sc->res, core_offset)); + else + return (bus_space_read_4(sc->bst, sc->bsh, core_offset)); +} + +/** Fetch and parse a siba core's identification registers */ +static struct siba_core_id +siba_erom_parse_core_id(struct siba_erom *sc, u_int core_idx, int unit) +{ + uint32_t idhigh, idlow; + + idhigh = siba_erom_read_4(sc, core_idx, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); + idlow = siba_erom_read_4(sc, core_idx, SB0_REG_ABS(SIBA_CFG0_IDLOW)); + + return (siba_parse_core_id(idhigh, idlow, core_idx, unit)); +} + +/** Fetch and parse the chip identification register */ +static int +siba_erom_read_chipid(struct siba_erom *sc, bus_addr_t enum_addr, + struct bhnd_chipid *cid) +{ + struct siba_core_id ccid; + uint32_t idreg; + + /* Identify the chipcommon core */ + ccid = siba_erom_parse_core_id(sc, 0, 0); + if (ccid.core_info.vendor != BHND_MFGID_BCM || + ccid.core_info.device != BHND_COREID_CC) + { + EROM_LOG(sc, + "first core not chipcommon (vendor=%#hx, core=%#hx)\n", + ccid.core_info.vendor, ccid.core_info.device); + return (ENXIO); + } + + /* Identify the chipset */ + idreg = siba_erom_read_4(sc, 0, CHIPC_ID); + *cid = bhnd_parse_chipid(idreg, enum_addr); + + /* Fix up the core count in-place */ + return (bhnd_chipid_fixed_ncores(cid, ccid.core_info.hwrev, + &cid->ncores)); +} + +static int +siba_erom_init_common(struct siba_erom *sc) +{ + struct bhnd_chipid cid; + int error; + + /* There's always at least one core */ + sc->ncores = 1; + + /* Identify the chipset */ + if ((error = siba_erom_read_chipid(sc, SIBA_ENUM_ADDR, &cid))) + return (error); + + /* Verify the chip type */ + if (cid.chip_type != BHND_CHIPTYPE_SIBA) + return (ENXIO); + + /* + * gcc hack: ensure bhnd_chipid.ncores cannot exceed SIBA_MAX_CORES + * without triggering build failure due to -Wtype-limits + * + * if (cid.ncores > SIBA_MAX_CORES) + * return (EINVAL) + */ + _Static_assert((2^sizeof(cid.ncores)) <= SIBA_MAX_CORES, + "ncores could result in over-read of backing resource"); + + /* Update our core count */ + sc->ncores = cid.ncores; + + return (0); +} + +static int +siba_erom_init(bhnd_erom_t *erom, device_t parent, int rid, + bus_addr_t enum_addr) +{ + struct siba_erom *sc = (struct siba_erom *)erom; + + sc->dev = parent; + sc->rid = rid; + + sc->res = bhnd_alloc_resource(sc->dev, SYS_RES_MEMORY, &sc->rid, + enum_addr, enum_addr + SIBA_ENUM_SIZE -1, SIBA_ENUM_SIZE, + RF_ACTIVE|RF_SHAREABLE); + if (sc->res == NULL) + return (ENOMEM); + + return (siba_erom_init_common(sc)); +} + +static int +siba_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) +{ + struct siba_erom sc; + uint32_t idreg; + uint8_t chip_type; + int error; + + idreg = bus_space_read_4(bst, bsh, CHIPC_ID); + chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); + + if (chip_type != BHND_CHIPTYPE_SIBA) + return (ENXIO); + + /* Initialize a static EROM instance that we can use to fetch + * the chip identifier */ + if ((error = siba_erom_init_static((bhnd_erom_t *)&sc, bst, bsh))) + return (error); + + /* Try to read the chip ID, clean up the static instance */ + error = siba_erom_read_chipid(&sc, paddr, cid); + siba_erom_fini((bhnd_erom_t *)&sc); + if (error) + return (error); + + return (BUS_PROBE_DEFAULT); +} + +static int +siba_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst, + bus_space_handle_t bsh) +{ + struct siba_erom *sc = (struct siba_erom *)erom; + + sc->dev = NULL; + sc->rid = -1; + sc->res = NULL; + sc->bst = bst; + sc->bsh = bsh; + + return (siba_erom_init_common(sc)); +} + +static void +siba_erom_fini(bhnd_erom_t *erom) +{ + struct siba_erom *sc = (struct siba_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 +siba_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + struct bhnd_core_info *core) +{ + struct siba_erom *sc; + struct bhnd_core_match imatch; + + sc = (struct siba_erom *)erom; + + /* 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 < sc->ncores; i++) { + struct siba_core_id sid; + struct bhnd_core_info ci; + + /* Read the core info */ + sid = siba_erom_parse_core_id(sc, i, 0); + ci = sid.core_info; + + /* Check for initial match */ + if (!bhnd_core_matches(&ci, &imatch)) + continue; + + /* Re-scan preceding cores to determine the unit number. */ + for (u_int j = 0; j < i; j++) { + sid = siba_erom_parse_core_id(sc, i, 0); + + /* Bump the unit number? */ + if (sid.core_info.vendor == ci.vendor && + sid.core_info.device == ci.device) + ci.unit++; + } + + /* Check for full match against now-valid unit number */ + if (!bhnd_core_matches(&ci, desc)) + continue; + + /* Matching core found */ + *core = ci; + return (0); + } + + /* Not found */ + return (ENOENT); +} + +static int +siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + bhnd_port_type type, u_int port, u_int region, struct bhnd_core_info *info, + bhnd_addr_t *addr, bhnd_size_t *size) +{ + struct siba_erom *sc; + struct bhnd_core_info core; + struct siba_core_id sid; + uint32_t am, am_addr, am_size; + u_int am_offset; + u_int addrspace; + int error; + + sc = (struct siba_erom *)erom; + + /* Locate the requested core */ + if ((error = siba_erom_lookup_core(erom, desc, &core))) + return (error); + + /* Fetch full siba core ident */ + sid = siba_erom_parse_core_id(sc, core.core_idx, core.unit); + + /* Is port valid? */ + if (!siba_is_port_valid(sid.num_addrspace, type, port)) + return (ENOENT); + + /* Is region valid? */ + if (region >= siba_addrspace_region_count(sid.num_addrspace, port)) + return (ENOENT); + + /* Map the bhnd port values to a siba addrspace index */ + error = siba_addrspace_index(sid.num_addrspace, type, port, region, + &addrspace); + if (error) + return (error); + + /* Determine the register offset */ + am_offset = siba_admatch_offset(addrspace); + if (am_offset == 0) { + printf("addrspace %u is unsupported", addrspace); + return (ENODEV); + } + + /* Read and parse the address match register */ + am = siba_erom_read_4(sc, core.core_idx, am_offset); + + if ((error = siba_parse_admatch(am, &am_addr, &am_size))) { + printf("failed to decode address match register value 0x%x\n", + am); + return (error); + } + + if (info != NULL) + *info = core; + + *addr = am_addr; + *size = am_size; + + return (0); +} + +/* BHND_EROM_GET_CORE_TABLE() */ +static int +siba_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, + u_int *num_cores) +{ + struct siba_erom *sc; + struct bhnd_core_info *out; + + sc = (struct siba_erom *)erom; + + /* Allocate our core array */ + out = malloc(sizeof(*out) * sc->ncores, M_BHND, M_NOWAIT); + if (out == NULL) + return (ENOMEM); + + *cores = out; + *num_cores = sc->ncores; + + /* Enumerate all cores. */ + for (u_int i = 0; i < sc->ncores; i++) { + struct siba_core_id sid; + + /* Read the core info */ + sid = siba_erom_parse_core_id(sc, i, 0); + out[i] = sid.core_info; + + /* Determine unit number */ + for (u_int j = 0; j < i; j++) { + if (out[j].vendor == out[i].vendor && + out[j].device == out[i].device) + out[i].unit++; + } + } + + return (0); +} + +/* BHND_EROM_FREE_CORE_TABLE() */ +static void +siba_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores) +{ + free(cores, M_BHND); +} + +static kobj_method_t siba_erom_methods[] = { + KOBJMETHOD(bhnd_erom_probe_static, siba_erom_probe_static), + KOBJMETHOD(bhnd_erom_init, siba_erom_init), + KOBJMETHOD(bhnd_erom_init_static, siba_erom_init_static), + KOBJMETHOD(bhnd_erom_fini, siba_erom_fini), + KOBJMETHOD(bhnd_erom_get_core_table, siba_erom_get_core_table), + KOBJMETHOD(bhnd_erom_free_core_table, siba_erom_free_core_table), + KOBJMETHOD(bhnd_erom_lookup_core, siba_erom_lookup_core), + KOBJMETHOD(bhnd_erom_lookup_core_addr, siba_erom_lookup_core_addr), + + KOBJMETHOD_END +}; + +BHND_EROM_DEFINE_CLASS(siba_erom, siba_erom_parser, siba_erom_methods, sizeof(struct siba_erom)); diff --git a/sys/dev/bhnd/siba/siba_subr.c b/sys/dev/bhnd/siba/siba_subr.c index 81c4c63013a5..86a0bbf89607 100644 --- a/sys/dev/bhnd/siba/siba_subr.c +++ b/sys/dev/bhnd/siba/siba_subr.c @@ -184,15 +184,15 @@ siba_addrspace_region(u_int addrspace) /** * Return the number of bhnd(4) ports to advertise for the given - * @p dinfo. + * @p num_addrspace. * - * @param dinfo The device info to query. + * @param num_addrspace The number of siba address spaces. */ u_int -siba_addrspace_port_count(struct siba_devinfo *dinfo) +siba_addrspace_port_count(u_int num_addrspace) { /* 0, 1, or 2 ports */ - return min(dinfo->core_id.num_addrspace, 2); + return min(num_addrspace, 2); } /** @@ -203,10 +203,8 @@ siba_addrspace_port_count(struct siba_devinfo *dinfo) * spaces. */ u_int -siba_addrspace_region_count(struct siba_devinfo *dinfo, u_int port) +siba_addrspace_region_count(u_int num_addrspace, u_int port) { - u_int num_addrspace = dinfo->core_id.num_addrspace; - /* The first address space, if any, is mapped to device0.0 */ if (port == 0) return (min(num_addrspace, 1)); @@ -220,32 +218,33 @@ siba_addrspace_region_count(struct siba_devinfo *dinfo, u_int port) } /** - * Return true if @p port is defined on @p dinfo, false otherwise. + * Return true if @p port is defined given an address space count + * of @p num_addrspace, false otherwise. * * Refer to the siba_find_addrspace() function for information on siba's * mapping of bhnd(4) port and region identifiers. * - * @param dinfo The device info to verify the port against. + * @param num_addrspace The number of address spaces to verify the port against. * @param type The bhnd(4) port type. * @param port The bhnd(4) port number. */ bool -siba_is_port_valid(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port) +siba_is_port_valid(u_int num_addrspace, bhnd_port_type type, u_int port) { /* Only device ports are supported */ if (type != BHND_PORT_DEVICE) return (false); /* Verify the index against the port count */ - if (siba_addrspace_port_count(dinfo) <= port) + if (siba_addrspace_port_count(num_addrspace) <= port) return (false); return (true); } /** - * Map an bhnd(4) type/port/region triplet to its associated address space - * entry, if any. + * Map a bhnd(4) type/port/region triplet to its associated address space + * index, if any. * * For compatibility with bcma(4), we map address spaces to port/region * identifiers as follows: @@ -258,6 +257,46 @@ siba_is_port_valid(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port) * * The only supported port type is BHND_PORT_DEVICE. * + * @param num_addrspace The number of available siba address spaces. + * @param type The bhnd(4) port type. + * @param port The bhnd(4) port number. + * @param region The bhnd(4) port region. + * @param addridx On success, the corresponding addrspace index. + * + * @retval 0 success + * @retval ENOENT if the given type/port/region cannot be mapped to a + * siba address space. + */ +int +siba_addrspace_index(u_int num_addrspace, bhnd_port_type type, u_int port, + u_int region, u_int *addridx) +{ + u_int idx; + + if (!siba_is_port_valid(num_addrspace, type, port)) + return (ENOENT); + + if (port == 0) + idx = region; + else if (port == 1) + idx = region + 1; + else + return (ENOENT); + + if (idx >= num_addrspace) + return (ENOENT); + + /* Found */ + *addridx = idx; + return (0); +} + +/** + * Map an bhnd(4) type/port/region triplet to its associated address space + * entry, if any. + * + * The only supported port type is BHND_PORT_DEVICE. + * * @param dinfo The device info to search for a matching address space. * @param type The bhnd(4) port type. * @param port The bhnd(4) port number. @@ -267,23 +306,19 @@ struct siba_addrspace * siba_find_addrspace(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port, u_int region) { - u_int addridx; + u_int addridx; + int error; - if (!siba_is_port_valid(dinfo, type, port)) - return (NULL); - - if (port == 0) - addridx = region; - else if (port == 1) - addridx = region + 1; - else - return (NULL); - - /* Out of range? */ - if (addridx >= dinfo->core_id.num_addrspace) + /* Map to addrspace index */ + error = siba_addrspace_index(dinfo->core_id.num_addrspace, type, port, + region, &addridx); + if (error) return (NULL); /* Found */ + if (addridx >= SIBA_MAX_ADDRSPACE) + return (NULL); + return (&dinfo->addrspace[addridx]); } diff --git a/sys/dev/bhnd/siba/sibareg.h b/sys/dev/bhnd/siba/sibareg.h index be49d343499f..f1b8ae06286f 100644 --- a/sys/dev/bhnd/siba/sibareg.h +++ b/sys/dev/bhnd/siba/sibareg.h @@ -51,9 +51,11 @@ #define SIBA_MAX_CORES \ (SIBA_ENUM_SIZE/SIBA_CORE_SIZE) /**< Maximum number of cores */ -/**< Evaluates to the bus address of the @p idx core register block */ -#define SIBA_CORE_ADDR(idx) \ - (SIBA_ENUM_ADDR + ((idx) * SIBA_CORE_SIZE)) +/** Evaluates to the bus address offset of the @p idx core register block */ +#define SIBA_CORE_OFFSET(idx) ((idx) * SIBA_CORE_SIZE) + +/** Evaluates to the bus address of the @p idx core register block */ +#define SIBA_CORE_ADDR(idx) (SIBA_ENUM_ADDR + SIBA_CORE_OFFSET(idx)) /* * Sonics configuration registers are mapped to each core's enumeration diff --git a/sys/dev/bhnd/siba/sibavar.h b/sys/dev/bhnd/siba/sibavar.h index 1c29305fdfbd..81497312c7e1 100644 --- a/sys/dev/bhnd/siba/sibavar.h +++ b/sys/dev/bhnd/siba/sibavar.h @@ -70,14 +70,16 @@ int siba_init_dinfo(device_t dev, void siba_free_dinfo(device_t dev, struct siba_devinfo *dinfo); -u_int siba_addrspace_port_count(struct siba_devinfo *dinfo); -u_int siba_addrspace_region_count(struct siba_devinfo *dinfo, +u_int siba_addrspace_port_count(u_int num_addrspace); +u_int siba_addrspace_region_count(u_int num_addrspace, u_int port); u_int siba_addrspace_port(u_int addrspace); u_int siba_addrspace_region(u_int addrspace); - -bool siba_is_port_valid(struct siba_devinfo *dinfo, +int siba_addrspace_index(u_int num_addrspace, + bhnd_port_type type, u_int port, u_int region, + u_int *addridx); +bool siba_is_port_valid(u_int num_addrspace, bhnd_port_type type, u_int port); struct siba_addrspace *siba_find_addrspace(struct siba_devinfo *dinfo, diff --git a/sys/mips/broadcom/bcm_bcma.c b/sys/mips/broadcom/bcm_bcma.c deleted file mode 100644 index 08ff97a40e79..000000000000 --- a/sys/mips/broadcom/bcm_bcma.c +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * Copyright (c) 2016 Landon Fuller - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include - -#include -#include - -#include "bcm_machdep.h" - -#define BCMFC_ERR(fmt, ...) printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__) - -int -bcm_find_core_bcma(struct bhnd_chipid *chipid, bhnd_devclass_t devclass, - int unit, struct bhnd_core_info *info, uintptr_t *addr) -{ - struct bcma_erom erom; - struct bcma_erom_core core; - struct bcma_erom_sport_region region; - bhnd_devclass_t core_class; - int error; - - error = bhnd_erom_bus_space_open(&erom, NULL, mips_bus_space_generic, - (bus_space_handle_t) BCM_SOC_ADDR(chipid->enum_addr, 0), 0); - if (error) { - BCMFC_ERR("erom open failed: %d\n", error); - return (error); - } - - for (u_long core_index = 0; core_index < ULONG_MAX; core_index++) { - /* Fetch next core record */ - if ((error = bcma_erom_seek_next_core(&erom))) - return (error); - - if ((error = bcma_erom_parse_core(&erom, &core))) { - BCMFC_ERR("core parse failed: %d\n", error); - return (error); - } - - /* Check for match */ - core_class = bhnd_find_core_class(core.vendor, - core.device); - if (core_class != devclass) - continue; - - /* Provide the basic core info */ - if (info != NULL) - bcma_erom_to_core_info(&core, core_index, 0, info); - - /* Provide the core's device0.0 port address */ - error = bcma_erom_seek_core_sport_region(&erom, core_index, - BHND_PORT_DEVICE, 0, 0); - if (error) { - BCMFC_ERR("sport not found: %d\n", error); - return (error); - } - - if ((error = bcma_erom_parse_sport_region(&erom, ®ion))) { - BCMFC_ERR("sport parse failed: %d\n", error); - return (error); - } - - if (addr != NULL) - *addr = region.base_addr; - - return (0); - } - - /* Not found */ - return (ENOENT); -} diff --git a/sys/mips/broadcom/bcm_machdep.c b/sys/mips/broadcom/bcm_machdep.c index 9a241b898e04..00d4f42f310b 100644 --- a/sys/mips/broadcom/bcm_machdep.c +++ b/sys/mips/broadcom/bcm_machdep.c @@ -96,15 +96,15 @@ __FBSDID("$FreeBSD$"); #define BCM_TRACE(_fmt, ...) #endif -static int bcm_find_core(struct bhnd_chipid *chipid, - bhnd_devclass_t devclass, int unit, - struct bhnd_core_info *info, uintptr_t *addr); -static int bcm_init_platform_data(struct bcm_platform *pdata); +static int bcm_init_platform_data(struct bcm_platform *bp); -/* Allow bus-specific implementations to override bcm_find_core_(bcma|siba) - * symbols, if included in the kernel build */ -__weak_reference(bcm_find_core_default, bcm_find_core_bcma); -__weak_reference(bcm_find_core_default, bcm_find_core_siba); +static int bcm_find_core(struct bcm_platform *bp, uint16_t vendor, + uint16_t device, int unit, struct bhnd_core_info *info, + uintptr_t *addr); + +static int bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls, + kobj_ops_t erom_ops, bhnd_erom_t *erom, size_t esize, + struct bhnd_chipid *cid); extern int *edata; extern int *end; @@ -121,128 +121,213 @@ bcm_get_platform(void) return (&bcm_platform_data); } -/* Default (no-op) bcm_find_core() implementation. */ -int -bcm_find_core_default(struct bhnd_chipid *chipid, bhnd_devclass_t devclass, - int unit, struct bhnd_core_info *info, uintptr_t *addr) +static bus_addr_t +bcm_get_bus_addr(void) { - return (ENODEV); + long maddr; + + if (resource_long_value("bhnd", 0, "maddr", &maddr) == 0) + return ((u_long)maddr); + + return (BHND_DEFAULT_CHIPC_ADDR); } /** - * Search @p chipid's enumeration table for a core with @p devclass and - * @p unit. + * Search the device enumeration table for a core matching @p vendor, + * @p device, and @p unit. * - * @param chipid Chip identification data, including the address - * of the enumeration table to be searched. - * @param devclass Search for a core matching this device class. + * @param bp Platform state containing a valid EROM parser. + * @param vendor The core's required vendor. + * @param device The core's required device id. * @param unit The core's required unit number. - * @param[out] info On success, will be populated with the core + * @param[out] info If non-NULL, will be populated with the core * info. + * @param[out] addr If non-NULL, will be populated with the core's + * physical register address. */ static int -bcm_find_core(struct bhnd_chipid *chipid, bhnd_devclass_t devclass, int unit, - struct bhnd_core_info *info, uintptr_t *addr) +bcm_find_core(struct bcm_platform *bp, uint16_t vendor, uint16_t device, + int unit, struct bhnd_core_info *info, uintptr_t *addr) { - switch (chipid->chip_type) { - case BHND_CHIPTYPE_SIBA: - return (bcm_find_core_siba(chipid, devclass, unit, info, addr)); - break; - default: - if (!BHND_CHIPTYPE_HAS_EROM(chipid->chip_type)) { - printf("%s: unsupported chip type: %d\n", __FUNCTION__, - chipid->chip_type); - return (ENXIO); - } - return (bcm_find_core_bcma(chipid, devclass, unit, info, addr)); + struct bhnd_core_match md; + bhnd_addr_t b_addr; + bhnd_size_t b_size; + int error; + + md = (struct bhnd_core_match) { + BHND_MATCH_CORE_VENDOR(vendor), + BHND_MATCH_CORE_ID(BHND_COREID_CC), + BHND_MATCH_CORE_UNIT(0) + }; + + /* Fetch core info */ + error = bhnd_erom_lookup_core_addr(&bp->erom.obj, &md, BHND_PORT_DEVICE, + 0, 0, info, &b_addr, &b_size); + if (error) + return (error); + + if (addr != NULL && b_addr > UINTPTR_MAX) { + BCM_ERR("core address %#jx overflows native address width\n", + (uintmax_t)b_addr); + return (ERANGE); } + + if (addr != NULL) + *addr = b_addr; + + return (0); +} + +/** + * Probe and attach a bhnd_erom parser instance for the bhnd bus. + * + * @param[out] erom_cls The probed EROM class. + * @param[out] erom_ops The storage to be used when compiling + * @p erom_cls. + * @param[out] erom The storage to be used when initializing the + * static instance of @p erom_cls. + * @param esize The total available number of bytes allocated + * for @p erom. If this is less than is required + * by @p erom_cls ENOMEM will be returned. + * @param[out] cid On success, the probed chip identification. + */ +static int +bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls, kobj_ops_t erom_ops, + bhnd_erom_t *erom, size_t esize, struct bhnd_chipid *cid) +{ + bhnd_erom_class_t **clsp; + bus_space_tag_t bst; + bus_space_handle_t bsh; + bus_addr_t bus_addr; + int error, prio, result; + + bus_addr = bcm_get_bus_addr(); + *erom_cls = NULL; + prio = 0; + + bst = mips_bus_space_generic; + bsh = BCM_SOC_BSH(bus_addr, 0); + + SET_FOREACH(clsp, bhnd_erom_class_set) { + struct bhnd_chipid pcid; + bhnd_erom_class_t *cls; + struct kobj_ops kops; + + cls = *clsp; + + /* Compile the class' ops table */ + kobj_class_compile_static(cls, &kops); + + /* Probe the bus address */ + result = bhnd_erom_probe_static(cls, bst, bsh, bus_addr, &pcid); + + /* Drop pointer to stack allocated ops table */ + cls->ops = NULL; + + /* The parser did not match if an error was returned */ + if (result > 0) + continue; + + /* Check for a new highest priority match */ + if (*erom_cls == NULL || result > prio) { + prio = result; + + *cid = pcid; + *erom_cls = cls; + } + + /* Terminate immediately on BUS_PROBE_SPECIFIC */ + if (result == BUS_PROBE_SPECIFIC) + break; + } + + /* Valid EROM class probed? */ + if (*erom_cls == NULL) { + BCM_ERR("no erom parser found for root bus at %#jx\n", + (uintmax_t)bus_addr); + return (ENOENT); + } + + /* Using the provided storage, recompile the erom class ... */ + kobj_class_compile_static(*erom_cls, erom_ops); + + /* ... and initialize the erom parser instance */ + bsh = BCM_SOC_BSH(cid->enum_addr, 0); + error = bhnd_erom_init_static(*erom_cls, erom, esize, + mips_bus_space_generic, bsh); + + return (error); } /** * Populate platform configuration data. */ static int -bcm_init_platform_data(struct bcm_platform *pdata) +bcm_init_platform_data(struct bcm_platform *bp) { - uint32_t reg; - bhnd_addr_t enum_addr; - long maddr; - uint8_t chip_type; - bool aob, pmu; - int error; + bool aob, pmu; + int error; /* Fetch CFE console handle (if any). Must be initialized before * any calls to printf/early_putc. */ #ifdef CFE - if ((pdata->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0) - pdata->cfe_console = -1; + if ((bp->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0) + bp->cfe_console = -1; #endif - /* Fetch bhnd/chipc address */ - if (resource_long_value("bhnd", 0, "maddr", &maddr) == 0) - pdata->cc_addr = (u_long)maddr; - else - pdata->cc_addr = BHND_DEFAULT_CHIPC_ADDR; - - /* Read chip identifier from ChipCommon */ - reg = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_ID); - chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS); - - if (BHND_CHIPTYPE_HAS_EROM(chip_type)) - enum_addr = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_EROMPTR); - else - enum_addr = pdata->cc_addr; - - pdata->id = bhnd_parse_chipid(reg, enum_addr); - - /* Fetch chipc core info and capabilities */ - pdata->cc_caps = BCM_SOC_READ_4(pdata->cc_addr, CHIPC_CAPABILITIES); - - error = bcm_find_core(&pdata->id, BHND_DEVCLASS_CC, 0, &pdata->cc_id, - NULL); + /* Probe and attach device table provider, populating our + * chip identification */ + error = bcm_erom_probe_and_attach(&bp->erom_impl, &bp->erom_ops, + &bp->erom.obj, sizeof(bp->erom), &bp->cid); if (error) { - printf("%s: error locating chipc core: %d", __FUNCTION__, - error); + BCM_ERR("error attaching erom parser: %d\n", error); return (error); } - if (CHIPC_HWREV_HAS_CAP_EXT(pdata->cc_id.hwrev)) { - pdata->cc_caps_ext = BCM_SOC_READ_4(pdata->cc_addr, - CHIPC_CAPABILITIES_EXT); - } else { - pdata->cc_caps_ext = 0x0; + /* Fetch chipcommon core info */ + error = bcm_find_core(bp, BHND_MFGID_BCM, BHND_COREID_CC, 0, &bp->cc_id, + &bp->cc_addr); + if (error) { + BCM_ERR("error locating chipc core: %d\n", error); + return (error); } + /* Fetch chipc capability flags */ + bp->cc_caps = BCM_SOC_READ_4(bp->cc_addr, CHIPC_CAPABILITIES); + bp->cc_caps_ext = 0x0; + + if (CHIPC_HWREV_HAS_CAP_EXT(bp->cc_id.hwrev)) + bp->cc_caps_ext = BCM_CHIPC_READ_4(bp, CHIPC_CAPABILITIES_EXT); + /* Fetch PMU info */ - pmu = CHIPC_GET_FLAG(pdata->cc_caps, CHIPC_CAP_PMU); - aob = CHIPC_GET_FLAG(pdata->cc_caps_ext, CHIPC_CAP2_AOB); + pmu = CHIPC_GET_FLAG(bp->cc_caps, CHIPC_CAP_PMU); + aob = CHIPC_GET_FLAG(bp->cc_caps_ext, CHIPC_CAP2_AOB); if (pmu && aob) { /* PMU block mapped to a PMU core on the Always-on-Bus (aob) */ - error = bcm_find_core(&pdata->id, BHND_DEVCLASS_PMU, 0, - &pdata->pmu_id, &pdata->pmu_addr); + error = bcm_find_core(bp, BHND_MFGID_BCM, BHND_COREID_PMU, 0, + &bp->pmu_id, &bp->pmu_addr); if (error) { - printf("%s: error locating pmu core: %d", __FUNCTION__, - error); + BCM_ERR("error locating pmu core: %d\n", error); return (error); } } else if (pmu) { /* PMU block mapped to chipc */ - pdata->pmu_addr = pdata->cc_addr; - pdata->pmu_id = pdata->cc_id; + bp->pmu_addr = bp->cc_addr; + bp->pmu_id = bp->cc_id; } else { /* No PMU */ - pdata->pmu_addr = 0x0; - memset(&pdata->pmu_id, 0, sizeof(pdata->pmu_id)); + bp->pmu_addr = 0x0; + memset(&bp->pmu_id, 0, sizeof(bp->pmu_id)); } + /* Initialize PMU query state */ if (pmu) { - error = bhnd_pmu_query_init(&pdata->pmu, NULL, pdata->id, - &bcm_pmu_soc_io, pdata); + error = bhnd_pmu_query_init(&bp->pmu, NULL, bp->cid, + &bcm_pmu_soc_io, bp); if (error) { - printf("%s: bhnd_pmu_query_init() failed: %d\n", - __FUNCTION__, error); + BCM_ERR("bhnd_pmu_query_init() failed: %d\n", error); return (error); } } @@ -346,7 +431,7 @@ platform_reset(void) bcm4785war = false; /* Handle BCM4785-specific behavior */ - if (bp->id.chip_id == BHND_CHIPID_BCM4785) { + if (bp->cid.chip_id == BHND_CHIPID_BCM4785) { bcm4785war = true; /* Switch to async mode */ diff --git a/sys/mips/broadcom/bcm_machdep.h b/sys/mips/broadcom/bcm_machdep.h index d8d551f3ac1a..84aed350874f 100644 --- a/sys/mips/broadcom/bcm_machdep.h +++ b/sys/mips/broadcom/bcm_machdep.h @@ -36,29 +36,34 @@ #include #include +#include + #include extern const struct bhnd_pmu_io bcm_pmu_soc_io; -typedef int (bcm_bus_find_core)(struct bhnd_chipid *chipid, - bhnd_devclass_t devclass, int unit, struct bhnd_core_info *info, - uintptr_t *addr); - struct bcm_platform { - struct bhnd_chipid id; /**< chip id */ - struct bhnd_core_info cc_id; /**< chipc core info */ - uintptr_t cc_addr; /**< chipc core phys address */ - uint32_t cc_caps; /**< chipc capabilities */ - uint32_t cc_caps_ext; /**< chipc extended capabilies */ + struct bhnd_chipid cid; /**< chip id */ + struct bhnd_core_info cc_id; /**< chipc core info */ + uintptr_t cc_addr; /**< chipc core phys address */ + uint32_t cc_caps; /**< chipc capabilities */ + uint32_t cc_caps_ext; /**< chipc extended capabilies */ /* On non-AOB devices, the PMU register block is mapped to chipc; * the pmu_id and pmu_addr values will be copied from cc_id * and cc_addr. */ - struct bhnd_core_info pmu_id; /**< PMU core info */ - uintptr_t pmu_addr; /**< PMU core phys address, or + struct bhnd_core_info pmu_id; /**< PMU core info */ + uintptr_t pmu_addr; /**< PMU core phys address, or 0x0 if no PMU */ - struct bhnd_pmu_query pmu; /**< PMU query instance */ + struct bhnd_pmu_query pmu; /**< PMU query instance */ + + bhnd_erom_class_t *erom_impl; /**< erom parser class */ + struct kobj_ops erom_ops; /**< compiled kobj opcache */ + union { + bhnd_erom_static_t data; + bhnd_erom_t obj; + } erom; #ifdef CFE int cfe_console; /**< Console handle, or -1 */ @@ -74,9 +79,11 @@ uint64_t bcm_get_ilpfreq(struct bcm_platform *bp); u_int bcm_get_uart_rclk(struct bcm_platform *bp); -bcm_bus_find_core bcm_find_core_default; -bcm_bus_find_core bcm_find_core_bcma; -bcm_bus_find_core bcm_find_core_siba; +#define BCM_ERR(fmt, ...) \ + printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__) + +#define BCM_SOC_BSH(_addr, _offset) \ + ((bus_space_handle_t)BCM_SOC_ADDR((_addr), (_offset))) #define BCM_SOC_ADDR(_addr, _offset) \ MIPS_PHYS_TO_KSEG1((_addr) + (_offset)) diff --git a/sys/mips/broadcom/bcm_pmu.c b/sys/mips/broadcom/bcm_pmu.c index 9ded7cc3840f..46fa70da5902 100644 --- a/sys/mips/broadcom/bcm_pmu.c +++ b/sys/mips/broadcom/bcm_pmu.c @@ -239,14 +239,14 @@ bcm_get_cpufreq(struct bcm_platform *bp) * PWRCTL support */ pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL); - mreg = bhnd_pwrctl_cpu_clkreg_m(&bp->id, pll_type, &fixed_hz); + mreg = bhnd_pwrctl_cpu_clkreg_m(&bp->cid, pll_type, &fixed_hz); if (mreg == 0) return (fixed_hz); n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N); m = BCM_CHIPC_READ_4(bp, mreg); - return (bhnd_pwrctl_cpu_clock_rate(&bp->id, pll_type, n, m)); + return (bhnd_pwrctl_cpu_clock_rate(&bp->cid, pll_type, n, m)); } @@ -267,14 +267,14 @@ bcm_get_sifreq(struct bcm_platform *bp) * PWRCTL support */ pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL); - mreg = bhnd_pwrctl_si_clkreg_m(&bp->id, pll_type, &fixed_hz); + mreg = bhnd_pwrctl_si_clkreg_m(&bp->cid, pll_type, &fixed_hz); if (mreg == 0) return (fixed_hz); n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N); m = BCM_CHIPC_READ_4(bp, mreg); - return (bhnd_pwrctl_si_clock_rate(&bp->id, pll_type, n, m)); + return (bhnd_pwrctl_si_clock_rate(&bp->cid, pll_type, n, m)); } diff --git a/sys/mips/broadcom/bcm_siba.c b/sys/mips/broadcom/bcm_siba.c deleted file mode 100644 index ff8fa09a564c..000000000000 --- a/sys/mips/broadcom/bcm_siba.c +++ /dev/null @@ -1,64 +0,0 @@ -/*- - * Copyright (c) 2016 Landon Fuller - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include - -#include "bcm_machdep.h" - -int -bcm_find_core_siba(struct bhnd_chipid *chipid, bhnd_devclass_t devclass, - int unit, struct bhnd_core_info *info, uintptr_t *addr) -{ - struct siba_core_id scid; - uintptr_t cc_addr; - uint32_t idhigh, idlow; - - /* No other cores are required during early boot on siba(4) devices */ - if (devclass != BHND_DEVCLASS_CC || unit != 0) - return (ENOENT); - - cc_addr = chipid->enum_addr; - idhigh = BCM_SOC_READ_4(cc_addr, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); - idlow = BCM_SOC_READ_4(cc_addr, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); - - scid = siba_parse_core_id(idhigh, idlow, 0, 0); - - if (info != NULL) - *info = scid.core_info; - - if (addr != NULL) - *addr = cc_addr; - - return (0); -} diff --git a/sys/mips/broadcom/files.broadcom b/sys/mips/broadcom/files.broadcom index 61b120073e48..ddef0a307102 100644 --- a/sys/mips/broadcom/files.broadcom +++ b/sys/mips/broadcom/files.broadcom @@ -4,10 +4,8 @@ # for USB 1.1 OHCI, Ethernet and IPSEC cores # which are believed to be devices we have drivers for # which just need to be tweaked for attachment to an BHND system bus. -mips/broadcom/bcm_bcma.c optional bcma_nexus bcma mips/broadcom/bcm_machdep.c standard mips/broadcom/bcm_pmu.c standard -mips/broadcom/bcm_siba.c optional siba_nexus siba mips/mips/tick.c standard mips/mips/mips_pic.c standard kern/subr_intr.c standard diff --git a/sys/modules/bhnd/Makefile b/sys/modules/bhnd/Makefile index 955565934734..9c99afd6eaa2 100644 --- a/sys/modules/bhnd/Makefile +++ b/sys/modules/bhnd/Makefile @@ -10,6 +10,9 @@ KMOD= bhnd SRCS= bhnd.c bhnd_subr.c SRCS+= bhnd_bus_if.c bhnd_bus_if.h +SRCS+= bhnd_erom.c +SRCS+= bhnd_erom_if.c bhnd_erom_if.h + # ChipCommon SRCS+= chipc.c chipc_subr.c SRCS+= bhnd_sprom_chipc.c \ diff --git a/sys/modules/bhnd/bcma/Makefile b/sys/modules/bhnd/bcma/Makefile index 7071d859ab6f..59d1eb5f1413 100644 --- a/sys/modules/bhnd/bcma/Makefile +++ b/sys/modules/bhnd/bcma/Makefile @@ -5,6 +5,7 @@ KMOD= bcma SRCS= bcma.c bcma_subr.c bcma_erom.c -SRCS+= device_if.h bus_if.h bhnd_bus_if.h +SRCS+= device_if.h bus_if.h +SRCS+= bhnd_bus_if.h bhnd_erom_if.h .include diff --git a/sys/modules/bhnd/bcma_bhndb/Makefile b/sys/modules/bhnd/bcma_bhndb/Makefile index 372a7ed0f6d2..e069cb5bdc30 100644 --- a/sys/modules/bhnd/bcma_bhndb/Makefile +++ b/sys/modules/bhnd/bcma_bhndb/Makefile @@ -5,7 +5,8 @@ KMOD= bcma_bhndb SRCS= bcma_bhndb.c -SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h +SRCS+= bhnd_bus_if.h bhnd_erom_if.h +SRCS+= bhndb_bus_if.h bhndb_if.h SRCS+= device_if.h bus_if.h .include diff --git a/sys/modules/bhnd/siba/Makefile b/sys/modules/bhnd/siba/Makefile index 8ace993c04b6..0bf58e80a7c2 100644 --- a/sys/modules/bhnd/siba/Makefile +++ b/sys/modules/bhnd/siba/Makefile @@ -3,8 +3,10 @@ .PATH: ${.CURDIR}/../../../dev/bhnd/siba KMOD= siba -SRCS= siba.c siba_subr.c +SRCS= siba.c siba_subr.c \ + siba_erom.c -SRCS+= device_if.h bus_if.h bhnd_bus_if.h +SRCS+= device_if.h bus_if.h +SRCS+= bhnd_bus_if.h bhnd_erom_if.h .include diff --git a/sys/modules/bhnd/siba_bhndb/Makefile b/sys/modules/bhnd/siba_bhndb/Makefile index ba46a7f46cf4..bd9e6c28e4ce 100644 --- a/sys/modules/bhnd/siba_bhndb/Makefile +++ b/sys/modules/bhnd/siba_bhndb/Makefile @@ -5,7 +5,8 @@ KMOD= siba_bhndb SRCS= siba_bhndb.c -SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h +SRCS+= bhnd_bus_if.h bhnd_erom_if.h +SRCS+= bhndb_bus_if.h bhndb_if.h SRCS+= device_if.h bus_if.h .include