FreeBSD/sys/dev/bhnd/bhndb/bhndb.c
/**
 * Initialize the region maps and priority configuration in @p r using
 * the provided priority @p table and the set of devices attached to
 * the bridged @p bus_dev .
 * 
 * @param sc The bhndb device state.
 * @param devs All devices enumerated on the bridged bhnd bus.
 * @param ndevs The length of @p devs.
 * @param table Hardware priority table to be used to determine the relative
 * priorities of per-core port resources.
 * @param r The resource state to be configured.
 */
Initialize the region maps and priority configuration in @p r using
the provided priority @p table and the set of devices attached to
the bridged @p bus_dev .

@param sc The bhndb device state.
@param devs All devices enumerated on the bridged bhnd bus.
@param ndevs The length of @p devs.
@param table Hardware priority table to be used to determine the relative
priorities of per-core port resources.
@param r The resource state to be configured.
Initialize the region maps and priority configuration in @p r using the provided priority @p table and the set of devices attached to the bridged @p bus_dev . @param sc The bhndb device state . @param devs All devices enumerated on the bridged bhnd bus . @param ndevs The length of @p devs . @param table Hardware priority table to be used to determine the relative priorities of per - core port resources . @param r The resource state to be configured .
static int
bhndb_initialize_region_cfg(struct bhndb_softc *sc, device_t *devs, int ndevs,
    const struct bhndb_hw_priority *table, struct bhndb_resources *r)
{
	const struct bhndb_hw_priority	*hp;
	bhnd_addr_t			 addr;
	bhnd_size_t			 size;
	size_t				 prio_low, prio_default, prio_high;
	int				 error;
	prio_low = 0;
	prio_default = 0;
	prio_high = 0;
	for (int i = 0; i < ndevs; i++) {
		const struct bhndb_regwin	*regw;
		device_t			 child;
		child = devs[i];
		for (regw = r->cfg->register_windows;
		    regw->win_type != BHNDB_REGWIN_T_INVALID; regw++)
		{
			if (regw->win_type != BHNDB_REGWIN_T_CORE)
				continue;
			if (!bhndb_regwin_matches_device(regw, child))
				continue;
			error = bhnd_get_region_addr(child,
			    regw->d.core.port_type, regw->d.core.port,
			    regw->d.core.region, &addr, &size);
			if (error)
			    return (error);
			size = regw->win_size;
			error = bhndb_add_resource_region(r, addr, size,
			    BHNDB_PRIORITY_HIGH, regw);
			if (error)
				return (error);
		}
	}
	for (int i = 0; i < ndevs; i++) {
		struct bhndb_region	*region;
		device_t		 child;
		child = devs[i];
		if (bhnd_is_hw_disabled(child) || !device_is_enabled(child))
			continue;
		hp = bhndb_hw_priority_find_device(table, child);
		if (hp == NULL)
			continue;
		if (hp->priority == BHNDB_PRIORITY_NONE)
			continue;
		for (u_int i = 0; i < hp->num_ports; i++) {
			const struct bhndb_port_priority *pp;
			pp = &hp->ports[i];
			if (!bhnd_is_region_valid(child, pp->type, pp->port,
			    pp->region))
			{
				continue;
			}
			error = bhnd_get_region_addr(child, pp->type, pp->port,
			    pp->region, &addr, &size);
			if (error)
			    return (error);
			region = bhndb_find_resource_region(r, addr, size);
			if (region != NULL && region->static_regwin != NULL)
				continue;
			error = bhndb_add_resource_region(r, addr, size,
			    pp->priority, NULL);
			if (error)
				return (error);
			switch (pp->priority) {
			case BHNDB_PRIORITY_NONE:
				break;
			case BHNDB_PRIORITY_LOW:
				prio_low++;
				break;
			case BHNDB_PRIORITY_DEFAULT:
				prio_default++;
				break;
			case BHNDB_PRIORITY_HIGH:
				prio_high++;
				break;
			}
		}
	}
	size_t prio_total = prio_low + prio_default + prio_high;
	if (prio_total <= r->dwa_count) {
		r->min_prio = BHNDB_PRIORITY_LOW;
	} else if (prio_default + prio_high <= r->dwa_count) {
		r->min_prio = BHNDB_PRIORITY_DEFAULT;
	} else {
		r->min_prio = BHNDB_PRIORITY_HIGH;
	}
	if (BHNDB_DEBUG(PRIO)) {
		struct bhndb_region	*region;
		const char		*direct_msg, *type_msg;
		bhndb_priority_t	 prio, prio_min;
		prio_min = r->min_prio;
		device_printf(sc->dev, "min_prio: %d\n", prio_min);
		STAILQ_FOREACH(region, &r->bus_regions, link) {
			prio = region->priority;
			direct_msg = prio >= prio_min ? "direct" : "indirect";
			type_msg = region->static_regwin ? "static" : "dynamic";
			device_printf(sc->dev, "region 0x%llx+0x%llx priority "
			    "%u %s/%s\n",
			    (unsigned long long) region->addr, 
			    (unsigned long long) region->size,
			    region->priority,
			    direct_msg, type_msg);
		}
	}
	return (0);
}
static int bhndb_initialize_region_cfg ( struct bhndb_softc * sc , device_t * devs , int ndevs , const struct bhndb_hw_priority * table , struct bhndb_resources * r ) { const struct bhndb_hw_priority * hp ; bhnd_addr_t addr ; bhnd_size_t size ; size_t prio_low , prio_default , prio_high ; int error ; prio_low = 0 ; prio_default = 0 ; prio_high = 0 ; for ( int i = 0 ; i < ndevs ; i ++ ) { const struct bhndb_regwin * regw ; device_t child ; child = devs [ i ] ; for ( regw = r -> cfg -> register_windows ; regw -> win_type != BHNDB_REGWIN_T_INVALID ; regw ++ ) { if ( regw -> win_type != BHNDB_REGWIN_T_CORE ) continue ; if ( ! bhndb_regwin_matches_device ( regw , child ) ) continue ; error = bhnd_get_region_addr ( child , regw -> d . core . port_type , regw -> d . core . port , regw -> d . core . region , & addr , & size ) ; if ( error ) return ( error ) ; size = regw -> win_size ; error = bhndb_add_resource_region ( r , addr , size , BHNDB_PRIORITY_HIGH , regw ) ; if ( error ) return ( error ) ; } } for ( int i = 0 ; i < ndevs ; i ++ ) { struct bhndb_region * region ; device_t child ; child = devs [ i ] ; if ( bhnd_is_hw_disabled ( child ) || ! device_is_enabled ( child ) ) continue ; hp = bhndb_hw_priority_find_device ( table , child ) ; if ( hp == NULL ) continue ; if ( hp -> priority == BHNDB_PRIORITY_NONE ) continue ; for ( u_int i = 0 ; i < hp -> num_ports ; i ++ ) { const struct bhndb_port_priority * pp ; pp = & hp -> ports [ i ] ; if ( ! bhnd_is_region_valid ( child , pp -> type , pp -> port , pp -> region ) ) { continue ; } error = bhnd_get_region_addr ( child , pp -> type , pp -> port , pp -> region , & addr , & size ) ; if ( error ) return ( error ) ; region = bhndb_find_resource_region ( r , addr , size ) ; if ( region != NULL && region -> static_regwin != NULL ) continue ; error = bhndb_add_resource_region ( r , addr , size , pp -> priority , NULL ) ; if ( error ) return ( error ) ; switch ( pp -> priority ) { case BHNDB_PRIORITY_NONE : break ; case BHNDB_PRIORITY_LOW : prio_low ++ ; break ; case BHNDB_PRIORITY_DEFAULT : prio_default ++ ; break ; case BHNDB_PRIORITY_HIGH : prio_high ++ ; break ; } } } size_t prio_total = prio_low + prio_default + prio_high ; if ( prio_total <= r -> dwa_count ) { r -> min_prio = BHNDB_PRIORITY_LOW ; } else if ( prio_default + prio_high <= r -> dwa_count ) { r -> min_prio = BHNDB_PRIORITY_DEFAULT ; } else { r -> min_prio = BHNDB_PRIORITY_HIGH ; } if ( BHNDB_DEBUG ( PRIO ) ) { struct bhndb_region * region ; const char * direct_msg , * type_msg ; bhndb_priority_t prio , prio_min ; prio_min = r -> min_prio ; device_printf ( sc -> dev , " \n " , prio_min ) ; STAILQ_FOREACH ( region , & r -> bus_regions , link ) { prio = region -> priority ; direct_msg = prio >= prio_min ? " " : " " ; type_msg = region -> static_regwin ? " " : " " ; device_printf ( sc -> dev , " " " \n " , ( unsigned long long ) region -> addr , ( unsigned long long ) region -> size , region -> priority , direct_msg , type_msg ) ; } } return ( 0 ) ; }
Initialize the region maps and priority configuration in @p r using
 the provided priority @p table and the set of devices attached to
 the bridged @p bus_dev .
Initialize the region maps and priority configuration in @p r using the provided priority @p table and the set of devices attached to the bridged @p bus_dev .
/* The number of port regions per priority band that must be accessible
	 * via dynamic register windows */ /* 
	 * Register bridge regions covering all statically mapped ports.
	 */ /* Only core windows are supported */ /* Skip non-applicable register windows. */ /* Fetch the base address of the mapped port. */ /*
			 * Always defer to the register window's size.
			 * 
			 * If the port size is smaller than the window size,
			 * this ensures that we fully utilize register windows
			 * larger than the referenced port.
			 * 
			 * If the port size is larger than the window size, this
			 * ensures that we do not directly map the allocations
			 * within the region to a too-small window.
			 */ /*
			 * Add to the bus region list.
			 * 
			 * The window priority for a statically mapped
			 * region is always HIGH.
			 */ /*
	 * Perform priority accounting and register bridge regions for all
	 * ports defined in the priority table
	 */ /* 
		 * Skip priority accounting for cores that ...
		 */ /* ... do not require bridge resources */ /* ... do not have a priority table entry */ /* ... are explicitly disabled in the priority table. */ /* Determine the number of dynamic windows required and
		 * register their bus_region entries. */ /* Skip ports not defined on this device */ /* Fetch the address+size of the mapped port. */ /* Skip ports with an existing static mapping */ /* Define a dynamic region for this port */ /* Update port mapping counts */ /* Determine the minimum priority at which we'll allocate direct
	 * register windows from our dynamic pool */ /* low+default+high priority regions get windows */ /* default+high priority regions get windows */ /* high priority regions get windows */