Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -1140,6 +1140,8 @@ 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_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 # Index: head/sys/dev/bhnd/bcma/bcma.h =================================================================== --- head/sys/dev/bhnd/bcma/bcma.h +++ head/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_ */ Index: head/sys/dev/bhnd/bcma/bcma.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma.c +++ head/sys/dev/bhnd/bcma/bcma.c @@ -45,6 +45,9 @@ #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_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 @@ /* 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 @@ 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), Index: head/sys/dev/bhnd/bcma/bcma_bhndb.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma_bhndb.c +++ head/sys/dev/bhnd/bcma/bcma_bhndb.c @@ -73,29 +73,12 @@ 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 */ Index: head/sys/dev/bhnd/bcma/bcma_erom.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma_erom.c +++ head/sys/dev/bhnd/bcma/bcma_erom.c @@ -39,6 +39,8 @@ #include #include +#include + #include "bcma_eromreg.h" #include "bcma_eromvar.h" @@ -56,17 +58,43 @@ * marker. */ -static const char *erom_entry_type_name (uint8_t entry); -static int erom_read32(struct bcma_erom *erom, uint32_t *entry); -static int erom_skip32(struct bcma_erom *erom); - -static int erom_skip_core(struct bcma_erom *erom); -static int erom_skip_mport(struct bcma_erom *erom); -static int erom_skip_sport_region(struct bcma_erom *erom); - -static int erom_seek_next(struct bcma_erom *erom, uint8_t etype); -static int erom_region_to_port_type(struct bcma_erom *erom, - uint8_t region_type, bhnd_port_type *port_type); +static const char *bcma_erom_entry_type_name (uint8_t entry); +static int bcma_erom_read32(struct bcma_erom *erom, + uint32_t *entry); +static int bcma_erom_skip32(struct bcma_erom *erom); + +static int bcma_erom_skip_core(struct bcma_erom *erom); +static int bcma_erom_skip_mport(struct bcma_erom *erom); +static int bcma_erom_skip_sport_region(struct bcma_erom *erom); + +static int bcma_erom_seek_next(struct bcma_erom *erom, + uint8_t etype); +static int bcma_erom_region_to_port_type(struct bcma_erom *erom, + uint8_t region_type, bhnd_port_type *port_type); + +static int bcma_erom_peek32(struct bcma_erom *erom, + uint32_t *entry); +static bus_size_t bcma_erom_tell(struct bcma_erom *erom); +static void bcma_erom_seek(struct bcma_erom *erom, + bus_size_t offset); +static void bcma_erom_reset(struct bcma_erom *erom); + +static int bcma_erom_seek_matching_core(struct bcma_erom *sc, + const struct bhnd_core_match *desc, + struct bhnd_core_info *core); + +static int bcma_erom_parse_core(struct bcma_erom *erom, + struct bcma_erom_core *core); + +static int bcma_erom_parse_mport(struct bcma_erom *erom, + struct bcma_erom_mport *mport); + +static int bcma_erom_parse_sport_region(struct bcma_erom *erom, + struct bcma_erom_sport_region *region); + +static void bcma_erom_to_core_info(const struct bcma_erom_core *core, + u_int core_idx, int core_unit, + struct bhnd_core_info *info); #define EROM_LOG(erom, fmt, ...) do { \ if (erom->dev != NULL) { \ @@ -78,58 +106,10 @@ } \ } while(0) -/** - * Open an EROM table for reading. - * - * @param[out] erom On success, will be populated with a valid EROM - * read state. - * @param r An active resource mapping the EROM core. - * @param offset Offset of the EROM core within @p resource. - * - * @retval 0 success - * @retval non-zero if the erom table could not be opened. - */ -int -bcma_erom_open(struct bcma_erom *erom, struct resource *r, - bus_size_t offset) -{ - return (bhnd_erom_bus_space_open(erom, rman_get_device(r), - rman_get_bustag(r), rman_get_bushandle(r), offset)); - - return (0); -} - -/** - * Open an EROM table for reading using the provided bus space tag and - * handle. - * - * @param[out] erom On success, will be populated with a valid EROM - * read state. - * @param dev The owning device, or NULL if none. - * @param bst EROM table bus space tag. - * @param bsh EROM table bus space handle. - * @param offset Offset of the EROM core from @p resource. - * - * @retval 0 success - * @retval non-zero if the erom table could not be opened. - */ -int -bhnd_erom_bus_space_open(struct bcma_erom *erom, device_t dev, - bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset) -{ - /* Initialize the EROM reader */ - erom->dev = dev; - erom->bst = bst; - erom->bsh = bsh; - erom->start = offset + BCMA_EROM_TABLE_START; - erom->offset = 0; - - return (0); -} /** Return the type name for an EROM entry */ static const char * -erom_entry_type_name (uint8_t entry) +bcma_erom_entry_type_name (uint8_t entry) { switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { case BCMA_EROM_ENTRY_TYPE_CORE: @@ -143,10 +123,340 @@ } } +static int +bcma_erom_init(bhnd_erom_t *erom, device_t parent, int rid, bus_addr_t enum_addr) +{ + struct bcma_erom *sc = (struct bcma_erom *)erom; + + sc->dev = parent; + + sc->rid = rid; + sc->res = bhnd_alloc_resource(parent, SYS_RES_MEMORY, &sc->rid, + enum_addr, enum_addr + BCMA_EROM_TABLE_SIZE - 1, + BCMA_EROM_TABLE_SIZE, RF_ACTIVE|RF_SHAREABLE); + if (sc->res == NULL) + return (ENOMEM); + + sc->start = BCMA_EROM_TABLE_START; + sc->offset = 0; + + return (0); +} + +static int +bcma_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst, + bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid) +{ + uint32_t idreg, eaddr; + uint8_t chip_type; + + idreg = bus_space_read_4(bst, bsh, CHIPC_ID); + chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); + + /* Fetch EROM physical address */ + if (!BHND_CHIPTYPE_HAS_EROM(chip_type)) + return (ENXIO); + + eaddr = bus_space_read_4(bst, bsh, CHIPC_EROMPTR); + + /* Parse chip identifier */ + *cid = bhnd_parse_chipid(idreg, eaddr); + + /* Verify chip type */ + switch (chip_type) { + case BHND_CHIPTYPE_BCMA: + return (BUS_PROBE_DEFAULT); + + case BHND_CHIPTYPE_BCMA_ALT: + case BHND_CHIPTYPE_UBUS: + return (BUS_PROBE_GENERIC); + + default: + return (ENXIO); + } +} + +static int +bcma_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst, + bus_space_handle_t bsh) +{ + struct bcma_erom *sc = (struct bcma_erom *)erom; + + sc->dev = NULL; + sc->rid = -1; + sc->res = NULL; + sc->bst = bst; + sc->bsh = bsh; + sc->start = BCMA_EROM_TABLE_START; + sc->offset = 0; + + return (0); +} + +static void +bcma_erom_fini(bhnd_erom_t *erom) +{ + struct bcma_erom *sc = (struct bcma_erom *)erom; + + if (sc->res != NULL) { + bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->rid, + sc->res); + + sc->res = NULL; + sc->rid = -1; + } +} + +static int +bcma_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + struct bhnd_core_info *core) +{ + struct bcma_erom *sc = (struct bcma_erom *)erom; + + /* Search for the first matching core */ + return (bcma_erom_seek_matching_core(sc, desc, core)); +} + +static int +bcma_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc, + bhnd_port_type port_type, u_int port_num, u_int region_num, + struct bhnd_core_info *core, bhnd_addr_t *addr, bhnd_size_t *size) +{ + struct bcma_erom *sc; + struct bcma_erom_core ec; + uint32_t entry; + uint8_t region_port, region_type; + bool found; + int error; + + sc = (struct bcma_erom *)erom; + + /* Seek to the first matching core and provide the core info + * to the caller */ + if ((error = bcma_erom_seek_matching_core(sc, desc, core))) + return (error); + + if ((error = bcma_erom_parse_core(sc, &ec))) + return (error); + + /* Skip master ports */ + for (u_long i = 0; i < ec.num_mport; i++) { + if ((error = bcma_erom_skip_mport(sc))) + return (error); + } + + /* Seek to the region block for the given port type */ + found = false; + while (1) { + bhnd_port_type p_type; + uint8_t r_type; + + if ((error = bcma_erom_peek32(sc, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, REGION)) + return (ENOENT); + + /* Expected region type? */ + r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); + error = bcma_erom_region_to_port_type(sc, r_type, &p_type); + if (error) + return (error); + + if (p_type == port_type) { + found = true; + break; + } + + /* Skip to next entry */ + if ((error = bcma_erom_skip_sport_region(sc))) + return (error); + } + + if (!found) + return (ENOENT); + + /* Found the appropriate port type block; now find the region records + * for the given port number */ + found = false; + for (u_int i = 0; i <= port_num; i++) { + bhnd_port_type p_type; + + if ((error = bcma_erom_peek32(sc, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, REGION)) + return (ENOENT); + + /* Fetch the type/port of the first region entry */ + region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); + region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); + + /* Have we found the region entries for the desired port? */ + if (i == port_num) { + error = bcma_erom_region_to_port_type(sc, region_type, + &p_type); + if (error) + return (error); + + if (p_type == port_type) + found = true; + + break; + } + + /* Otherwise, seek to next block of region records */ + while (1) { + uint8_t next_type, next_port; + + if ((error = bcma_erom_skip_sport_region(sc))) + return (error); + + if ((error = bcma_erom_peek32(sc, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, REGION)) + return (ENOENT); + + next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); + next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); + + if (next_type != region_type || + next_port != region_port) + break; + } + } + + if (!found) + return (ENOENT); + + /* Finally, search for the requested region number */ + for (u_int i = 0; i <= region_num; i++) { + struct bcma_erom_sport_region region; + uint8_t next_port, next_type; + + if ((error = bcma_erom_peek32(sc, &entry))) + return (error); + + if (!BCMA_EROM_ENTRY_IS(entry, REGION)) + return (ENOENT); + + /* Check for the end of the region block */ + next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); + next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); + + if (next_type != region_type || + next_port != region_port) + break; + + /* Parse the region */ + if ((error = bcma_erom_parse_sport_region(sc, ®ion))) + return (error); + + /* Is this our target region_num? */ + if (i == region_num) { + /* Found */ + *addr = region.base_addr; + *size = region.size; + return (0); + } + } + + /* Not found */ + return (ENOENT); +}; + +static int +bcma_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, + u_int *num_cores) +{ + struct bcma_erom *sc; + struct bhnd_core_info *buffer; + bus_size_t initial_offset; + u_int count; + int error; + + sc = (struct bcma_erom *)erom; + + buffer = NULL; + initial_offset = bcma_erom_tell(sc); + + /* Determine the core count */ + bcma_erom_reset(sc); + for (count = 0, error = 0; !error; count++) { + struct bcma_erom_core core; + + /* Seek to the first readable core entry */ + error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); + if (error == ENOENT) + break; + else if (error) + goto cleanup; + + /* Read past the core descriptor */ + if ((error = bcma_erom_parse_core(sc, &core))) + goto cleanup; + } + + /* Allocate our output buffer */ + buffer = malloc(sizeof(struct bhnd_core_info) * count, M_BHND, + M_NOWAIT); + if (buffer == NULL) { + error = ENOMEM; + goto cleanup; + } + + /* Parse all core descriptors */ + bcma_erom_reset(sc); + for (u_int i = 0; i < count; i++) { + struct bcma_erom_core core; + int unit; + + /* Parse the core */ + error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); + if (error) + goto cleanup; + + error = bcma_erom_parse_core(sc, &core); + if (error) + goto cleanup; + + /* Determine the unit number */ + unit = 0; + for (u_int j = 0; j < i; j++) { + if (buffer[i].vendor == buffer[j].vendor && + buffer[i].device == buffer[j].device) + unit++; + } + + /* Convert to a bhnd info record */ + bcma_erom_to_core_info(&core, i, unit, &buffer[i]); + } + +cleanup: + if (!error) { + *cores = buffer; + *num_cores = count; + } else { + if (buffer != NULL) + free(buffer, M_BHND); + } + + /* Restore the initial position */ + bcma_erom_seek(sc, initial_offset); + return (error); +} + +static void +bcma_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores) +{ + free(cores, M_BHND); +} + /** * Return the current read position. */ -bus_size_t +static bus_size_t bcma_erom_tell(struct bcma_erom *erom) { return (erom->offset); @@ -155,7 +465,7 @@ /** * Seek to an absolute read position. */ -void +static void bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset) { erom->offset = offset; @@ -171,16 +481,22 @@ * @retval ENOENT The end of the EROM table was reached. * @retval non-zero The read could not be completed. */ -int +static int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry) { + bus_size_t off; + if (erom->offset >= BCMA_EROM_TABLE_SIZE) { EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n"); return (EINVAL); } - *entry = bus_space_read_4(erom->bst, erom->bsh, - erom->start + erom->offset); + off = erom->start + erom->offset; + if (erom->res != NULL) + *entry = bhnd_bus_read_4(erom->res, off); + else + *entry = bus_space_read_4(erom->bst, erom->bsh, off); + return (0); } @@ -194,7 +510,7 @@ * @retval non-zero The read could not be completed. */ static int -erom_read32(struct bcma_erom *erom, uint32_t *entry) +bcma_erom_read32(struct bcma_erom *erom, uint32_t *entry) { int error; @@ -213,11 +529,11 @@ * @retval non-zero The read could not be completed. */ static int -erom_skip32(struct bcma_erom *erom) +bcma_erom_skip32(struct bcma_erom *erom) { uint32_t entry; - return erom_read32(erom, &entry); + return bcma_erom_read32(erom, &entry); } /** @@ -229,7 +545,7 @@ * @retval non-zero The read could not be completed. */ static int -erom_skip_core(struct bcma_erom *erom) +bcma_erom_skip_core(struct bcma_erom *erom) { struct bcma_erom_core core; return (bcma_erom_parse_core(erom, &core)); @@ -244,7 +560,7 @@ * @retval non-zero The read could not be completed. */ static int -erom_skip_mport(struct bcma_erom *erom) +bcma_erom_skip_mport(struct bcma_erom *erom) { struct bcma_erom_mport mp; return (bcma_erom_parse_mport(erom, &mp)); @@ -259,7 +575,7 @@ * @retval non-zero The read could not be completed. */ static int -erom_skip_sport_region(struct bcma_erom *erom) +bcma_erom_skip_sport_region(struct bcma_erom *erom) { struct bcma_erom_sport_region r; return (bcma_erom_parse_sport_region(erom, &r)); @@ -276,7 +592,7 @@ * @retval non-zero Reading or parsing the descriptor failed. */ static int -erom_seek_next(struct bcma_erom *erom, uint8_t etype) +bcma_erom_seek_next(struct bcma_erom *erom, uint8_t etype) { uint32_t entry; int error; @@ -298,19 +614,19 @@ /* Skip non-matching entry types. */ switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { case BCMA_EROM_ENTRY_TYPE_CORE: - if ((error = erom_skip_core(erom))) + if ((error = bcma_erom_skip_core(erom))) return (error); break; case BCMA_EROM_ENTRY_TYPE_MPORT: - if ((error = erom_skip_mport(erom))) + if ((error = bcma_erom_skip_mport(erom))) return (error); break; case BCMA_EROM_ENTRY_TYPE_REGION: - if ((error = erom_skip_sport_region(erom))) + if ((error = bcma_erom_skip_sport_region(erom))) return (error); break; @@ -328,62 +644,100 @@ * * @param erom EROM read state. */ -void +static void bcma_erom_reset(struct bcma_erom *erom) { erom->offset = 0; } /** - * Seek to the next core entry. - * - * @param erom EROM read state. - * @retval 0 success - * @retval ENOENT The end of the EROM table was reached. - * @retval non-zero Reading or parsing failed. - */ -int -bcma_erom_seek_next_core(struct bcma_erom *erom) -{ - return (erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE)); -} - -/** - * Seek to the requested core entry. + * Seek to the first core entry matching @p desc. * * @param erom EROM read state. - * @param core_index Index of the core to seek to. + * @param desc The core match descriptor. + * @param[out] core On success, the matching core info. If the core info + * is not desired, a NULL pointer may be provided. * @retval 0 success * @retval ENOENT The end of the EROM table was reached before @p index was * found. * @retval non-zero Reading or parsing failed. */ -int -bcma_erom_seek_core_index(struct bcma_erom *erom, u_int core_index) +static int +bcma_erom_seek_matching_core(struct bcma_erom *sc, + const struct bhnd_core_match *desc, struct bhnd_core_info *core) { - int error; + struct bhnd_core_match imatch; + bus_size_t core_offset, next_offset; + int error; - /* Start search at top of EROM */ - bcma_erom_reset(erom); + /* Seek to table start. */ + bcma_erom_reset(sc); - /* Skip core descriptors till we hit the requested entry */ - for (u_int i = 0; i < core_index; i++) { - struct bcma_erom_core core; + /* We can't determine a core's unit number during the initial scan. */ + imatch = *desc; + imatch.m.match.core_unit = 0; + + /* Locate the first matching core */ + for (u_int i = 0; i < UINT_MAX; i++) { + struct bcma_erom_core ec; + struct bhnd_core_info ci; - /* Read past the core descriptor */ - if ((error = bcma_erom_parse_core(erom, &core))) + /* Seek to the next core */ + error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); + if (error) return (error); - /* Seek to the next readable core entry */ - error = erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); - if (error) + /* Save the core offset */ + core_offset = bcma_erom_tell(sc); + + /* Parse the core */ + if ((error = bcma_erom_parse_core(sc, &ec))) return (error); + + bcma_erom_to_core_info(&ec, i, 0, &ci); + + /* Check for initial match */ + if (!bhnd_core_matches(&ci, &imatch)) + continue; + + /* Re-scan preceding cores to determine the unit number. */ + next_offset = bcma_erom_tell(sc); + bcma_erom_reset(sc); + for (u_int j = 0; j < i; j++) { + /* Parse the core */ + error = bcma_erom_seek_next(sc, + BCMA_EROM_ENTRY_TYPE_CORE); + if (error) + return (error); + + if ((error = bcma_erom_parse_core(sc, &ec))) + return (error); + + /* Bump the unit number? */ + if (ec.vendor == ci.vendor && ec.device == ci.device) + ci.unit++; + } + + /* Check for full match against now-valid unit number */ + if (!bhnd_core_matches(&ci, desc)) { + /* Reposition to allow reading the next core */ + bcma_erom_seek(sc, next_offset); + continue; + } + + /* Found; seek to the core's initial offset and provide + * the core info to the caller */ + bcma_erom_seek(sc, core_offset); + if (core != NULL) + *core = ci; + + return (0); } - return (0); + /* Not found, or a parse error occured */ + return (error); } - /** * Read the next core descriptor from the EROM table. * @@ -394,14 +748,14 @@ * @retval ENOENT The end of the EROM table was reached. * @retval non-zero Reading or parsing the core descriptor failed. */ -int +static int bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core) { uint32_t entry; int error; /* Parse CoreDescA */ - if ((error = erom_read32(erom, &entry))) + if ((error = bcma_erom_read32(erom, &entry))) return (error); /* Handle EOF */ @@ -410,7 +764,7 @@ if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { EROM_LOG(erom, "Unexpected EROM entry 0x%x (type=%s)\n", - entry, erom_entry_type_name(entry)); + entry, bcma_erom_entry_type_name(entry)); return (EINVAL); } @@ -419,7 +773,7 @@ core->device = BCMA_EROM_GET_ATTR(entry, COREA_ID); /* Parse CoreDescB */ - if ((error = erom_read32(erom, &entry))) + if ((error = bcma_erom_read32(erom, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { @@ -436,153 +790,6 @@ } /** - * Seek to a region record associated with @p core_index. - * - * @param erom EROM read state. - * @param core_index The index of the core record to be searched. - * @param port_type The port type to search for. - * @param port_num The port number to search for. - * @param region_num The region number to search for. - * @retval 0 success - * @retval ENOENT The requested region was not found. - * @retval non-zero Reading or parsing failed. - */ -int -bcma_erom_seek_core_sport_region(struct bcma_erom *erom, u_int core_index, - bhnd_port_type port_type, u_int port_num, u_int region_num) -{ - struct bcma_erom_core core; - uint32_t entry; - uint8_t region_port, region_type; - bool found; - int error; - - if ((error = bcma_erom_seek_core_index(erom, core_index))) - return (error); - - if ((error = bcma_erom_parse_core(erom, &core))) - return (error); - - /* Skip master ports */ - for (u_long i = 0; i < core.num_mport; i++) { - if ((error = erom_skip_mport(erom))) - return (error); - } - - /* Seek to the region block for the given port type */ - found = false; - while (1) { - bhnd_port_type p_type; - uint8_t r_type; - - if ((error = bcma_erom_peek32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, REGION)) - return (ENOENT); - - /* Expected region type? */ - r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - if ((error = erom_region_to_port_type(erom, r_type, &p_type))) - return (error); - - if (p_type == port_type) { - found = true; - break; - } - - /* Skip to next entry */ - if ((error = erom_skip_sport_region(erom))) - return (error); - } - - if (!found) - return (ENOENT); - - /* Found the appropriate port type block; now find the region records - * for the given port number */ - found = false; - for (u_int i = 0; i <= port_num; i++) { - bhnd_port_type p_type; - - if ((error = bcma_erom_peek32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, REGION)) - return (ENOENT); - - /* Fetch the type/port of the first region entry */ - region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); - - /* Have we found the region entries for the desired port? */ - if (i == port_num) { - error = erom_region_to_port_type(erom, region_type, - &p_type); - if (error) - return (error); - - if (p_type == port_type) - found = true; - - break; - } - - /* Otherwise, seek to next block of region records */ - while (1) { - uint8_t next_type, next_port; - - if ((error = erom_skip_sport_region(erom))) - return (error); - - if ((error = bcma_erom_peek32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, REGION)) - return (ENOENT); - - next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); - - if (next_type != region_type || - next_port != region_port) - break; - } - } - - if (!found) - return (ENOENT); - - /* Finally, search for the requested region number */ - for (u_int i = 0; i <= region_num; i++) { - uint8_t next_port, next_type; - - if ((error = bcma_erom_peek32(erom, &entry))) - return (error); - - if (!BCMA_EROM_ENTRY_IS(entry, REGION)) - return (ENOENT); - - /* Check for the end of the region block */ - next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); - next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); - - if (next_type != region_type || - next_port != region_port) - break; - - if (i == region_num) - return (0); - - if ((error = erom_skip_sport_region(erom))) - return (error); - } - - /* Not found */ - return (ENOENT); -} - -/** * Read the next master port descriptor from the EROM table. * * @param erom EROM read state. @@ -591,15 +798,14 @@ * @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) +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 = erom_read32(erom, &entry))) + if ((error = bcma_erom_read32(erom, &entry))) return (error); if (!BCMA_EROM_ENTRY_IS(entry, MPORT)) @@ -621,7 +827,7 @@ * @retval ENOENT The end of the region descriptor table was reached. * @retval non-zero Reading or parsing the descriptor failed. */ -int +static int bcma_erom_parse_sport_region(struct bcma_erom *erom, struct bcma_erom_sport_region *region) { @@ -637,7 +843,7 @@ if (!BCMA_EROM_ENTRY_IS(entry, REGION)) { return (ENOENT); } else { - erom_skip32(erom); + bcma_erom_skip32(erom); } region->base_addr = BCMA_EROM_GET_ATTR(entry, REGION_BASE); @@ -647,7 +853,7 @@ /* If region address is 64-bit, fetch the high bits. */ if (BCMA_EROM_GET_ATTR(entry, REGION_64BIT)) { - if ((error = erom_read32(erom, &entry))) + if ((error = bcma_erom_read32(erom, &entry))) return (error); region->base_addr |= ((bhnd_addr_t) entry << 32); @@ -657,13 +863,13 @@ * 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))) + 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 = erom_read32(erom, &entry))) + if ((error = bcma_erom_read32(erom, &entry))) return (error); region->size |= ((bhnd_size_t) entry << 32); } @@ -676,7 +882,7 @@ 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), + bcma_erom_entry_type_name(region->region_type), region->region_port, (unsigned long long) region->base_addr, (unsigned long long) region->size); @@ -695,7 +901,7 @@ * @param core_unit The core unit of @p core. * @param[out] info The populated bhnd_core_info representation. */ -void +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) { @@ -707,105 +913,13 @@ } /** - * 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, - u_int *num_cores) -{ - struct bhnd_core_info *buffer; - bus_size_t initial_offset; - u_int count; - int error; - - buffer = NULL; - initial_offset = bcma_erom_tell(erom); - - /* Determine the core count */ - bcma_erom_reset(erom); - 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); - if (error == ENOENT) - break; - else if (error) - goto cleanup; - - /* Read past the core descriptor */ - if ((error = bcma_erom_parse_core(erom, &core))) - goto cleanup; - } - - /* Allocate our output buffer */ - buffer = malloc(sizeof(struct bhnd_core_info) * count, M_BHND, - M_NOWAIT); - if (buffer == NULL) { - error = ENOMEM; - goto cleanup; - } - - /* Parse all core descriptors */ - bcma_erom_reset(erom); - 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); - if (error) - goto cleanup; - - error = bcma_erom_parse_core(erom, &core); - if (error) - goto cleanup; - - /* Determine the unit number */ - unit = 0; - for (u_int j = 0; j < i; j++) { - if (buffer[i].vendor == buffer[j].vendor && - buffer[i].device == buffer[j].device) - unit++; - } - - /* Convert to a bhnd info record */ - bcma_erom_to_core_info(&core, i, unit, &buffer[i]); - } - -cleanup: - if (!error) { - *cores = buffer; - *num_cores = count; - } else { - if (buffer != NULL) - free(buffer, M_BHND); - } - - /* Restore the initial position */ - bcma_erom_seek(erom, initial_offset); - return (error); -} - -/** * Map an EROM region type to its corresponding port type. * * @param region_type Region type value. * @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 @@ * 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 @@ 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 @@ * 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 @@ * 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 @@ 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 @@ } /* 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 @@ /* 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 @@ /* 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 @@ 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 @@ 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)); Index: head/sys/dev/bhnd/bcma/bcma_eromvar.h =================================================================== --- head/sys/dev/bhnd/bcma/bcma_eromvar.h +++ head/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 @@ 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_ */ Index: head/sys/dev/bhnd/bcma/bcma_nexus.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma_nexus.c +++ head/sys/dev/bhnd/bcma/bcma_nexus.c @@ -91,28 +91,9 @@ static int bcma_nexus_attach(device_t dev) { - struct bcma_nexus_softc *sc; - struct resource *erom_res; - int error; - int rid; - - 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); + int error; - if (error) + if ((error = bcma_add_children(dev))) return (error); return (bcma_attach(dev)); Index: head/sys/dev/bhnd/bcma/bcmavar.h =================================================================== --- head/sys/dev/bhnd/bcma/bcmavar.h +++ head/sys/dev/bhnd/bcma/bcmavar.h @@ -63,8 +63,7 @@ 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); Index: head/sys/dev/bhnd/bhnd.h =================================================================== --- head/sys/dev/bhnd/bhnd.h +++ head/sys/dev/bhnd/bhnd.h @@ -429,32 +429,6 @@ }; /** - * 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. * * This function is only supported on early PWRCTL-equipped chipsets Index: head/sys/dev/bhnd/bhnd_bus_if.m =================================================================== --- head/sys/dev/bhnd/bhnd_bus_if.m +++ head/sys/dev/bhnd/bhnd_bus_if.m @@ -56,13 +56,6 @@ 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) { @@ -278,32 +271,6 @@ } 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. * * @param dev The device whose child is being examined. Index: head/sys/dev/bhnd/bhnd_erom.h =================================================================== --- head/sys/dev/bhnd/bhnd_erom.h +++ head/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_ */ Index: head/sys/dev/bhnd/bhnd_erom.c =================================================================== --- head/sys/dev/bhnd/bhnd_erom.c +++ head/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); +} Index: head/sys/dev/bhnd/bhnd_erom_if.m =================================================================== --- head/sys/dev/bhnd/bhnd_erom_if.m +++ head/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; +}; Index: head/sys/dev/bhnd/bhnd_erom_types.h =================================================================== --- head/sys/dev/bhnd/bhnd_erom_types.h +++ head/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_ */ Index: head/sys/dev/bhnd/bhnd_subr.c =================================================================== --- head/sys/dev/bhnd/bhnd_subr.c +++ head/sys/dev/bhnd/bhnd_subr.c @@ -944,7 +944,7 @@ } 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 @@ /** * 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) { + int error; + bool passthrough; + + passthrough = (device_get_parent(child) != dev); + /* 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)); + if (device_get_parent(dev) != NULL) { + error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), + child, type, rid, r); + } else { + error = ENODEV; + } - return (EINVAL); + /* 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); }; /** Index: head/sys/dev/bhnd/bhndb/bhndb.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb.c +++ head/sys/dev/bhnd/bhndb/bhndb.c @@ -1328,6 +1328,10 @@ 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)); Index: head/sys/dev/bhnd/siba/siba.h =================================================================== --- head/sys/dev/bhnd/siba/siba.h +++ head/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_ */ Index: head/sys/dev/bhnd/siba/siba.c =================================================================== --- head/sys/dev/bhnd/siba/siba.c +++ head/sys/dev/bhnd/siba/siba.c @@ -335,7 +335,7 @@ 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 @@ 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 @@ */ 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 @@ } /* 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_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 @@ 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 @@ /* 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 @@ } /* 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 @@ } 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 @@ 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 @@ } /* 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 @@ 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 @@ 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 @@ /* 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), Index: head/sys/dev/bhnd/siba/siba_erom.c =================================================================== --- head/sys/dev/bhnd/siba/siba_erom.c +++ head/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)); Index: head/sys/dev/bhnd/siba/siba_subr.c =================================================================== --- head/sys/dev/bhnd/siba/siba_subr.c +++ head/sys/dev/bhnd/siba/siba_subr.c @@ -184,15 +184,15 @@ /** * 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 @@ * 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 @@ } /** - * 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 @@ * * 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 @@ siba_find_addrspace(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port, u_int region) { - u_int addridx; - - if (!siba_is_port_valid(dinfo, type, port)) - return (NULL); + u_int addridx; + int error; - if (port == 0) - addridx = region; - else if (port == 1) - addridx = region + 1; - else + /* Map to addrspace index */ + error = siba_addrspace_index(dinfo->core_id.num_addrspace, type, port, + region, &addridx); + if (error) return (NULL); - /* Out of range? */ - if (addridx >= dinfo->core_id.num_addrspace) + /* Found */ + if (addridx >= SIBA_MAX_ADDRSPACE) return (NULL); - /* Found */ return (&dinfo->addrspace[addridx]); } Index: head/sys/dev/bhnd/siba/sibareg.h =================================================================== --- head/sys/dev/bhnd/siba/sibareg.h +++ head/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 Index: head/sys/dev/bhnd/siba/sibavar.h =================================================================== --- head/sys/dev/bhnd/siba/sibavar.h +++ head/sys/dev/bhnd/siba/sibavar.h @@ -70,14 +70,16 @@ 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, Index: head/sys/mips/broadcom/bcm_bcma.c =================================================================== --- head/sys/mips/broadcom/bcm_bcma.c +++ head/sys/mips/broadcom/bcm_bcma.c @@ -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); -} Index: head/sys/mips/broadcom/bcm_machdep.h =================================================================== --- head/sys/mips/broadcom/bcm_machdep.h +++ head/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 @@ 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)) Index: head/sys/mips/broadcom/bcm_machdep.c =================================================================== --- head/sys/mips/broadcom/bcm_machdep.c +++ head/sys/mips/broadcom/bcm_machdep.c @@ -96,15 +96,15 @@ #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); - -/* 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_init_platform_data(struct bcm_platform *bp); + +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 @@ 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); + 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; } - return (bcm_find_core_bcma(chipid, devclass, unit, info, addr)); + + /* 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 @@ 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 */ Index: head/sys/mips/broadcom/bcm_pmu.c =================================================================== --- head/sys/mips/broadcom/bcm_pmu.c +++ head/sys/mips/broadcom/bcm_pmu.c @@ -239,14 +239,14 @@ * 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 @@ * 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)); } Index: head/sys/mips/broadcom/bcm_siba.c =================================================================== --- head/sys/mips/broadcom/bcm_siba.c +++ head/sys/mips/broadcom/bcm_siba.c @@ -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); -} Index: head/sys/mips/broadcom/files.broadcom =================================================================== --- head/sys/mips/broadcom/files.broadcom +++ head/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 Index: head/sys/modules/bhnd/Makefile =================================================================== --- head/sys/modules/bhnd/Makefile +++ head/sys/modules/bhnd/Makefile @@ -10,6 +10,9 @@ 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 \ Index: head/sys/modules/bhnd/bcma/Makefile =================================================================== --- head/sys/modules/bhnd/bcma/Makefile +++ head/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 Index: head/sys/modules/bhnd/bcma_bhndb/Makefile =================================================================== --- head/sys/modules/bhnd/bcma_bhndb/Makefile +++ head/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 Index: head/sys/modules/bhnd/siba/Makefile =================================================================== --- head/sys/modules/bhnd/siba/Makefile +++ head/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 Index: head/sys/modules/bhnd/siba_bhndb/Makefile =================================================================== --- head/sys/modules/bhnd/siba_bhndb/Makefile +++ head/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