예제 #1
0
파일: chipc.c 프로젝트: wulf7/freebsd
/* Initialize memory state for all chipc port regions */
static int
chipc_init_rman(struct chipc_softc *sc)
{
	u_int	num_ports;
	int	error;

	/* Port types for which we'll register chipc_region mappings */
	bhnd_port_type types[] = {
	    BHND_PORT_DEVICE
	};

	/* Initialize resource manager */
	sc->mem_rman.rm_start = 0;
	sc->mem_rman.rm_end = BUS_SPACE_MAXADDR;
	sc->mem_rman.rm_type = RMAN_ARRAY;
	sc->mem_rman.rm_descr = "ChipCommon Device Memory";
	if ((error = rman_init(&sc->mem_rman))) {
		device_printf(sc->dev, "could not initialize mem_rman: %d\n",
		    error);
		return (error);
	}

	/* Populate per-port-region state */
	for (u_int i = 0; i < nitems(types); i++) {
		num_ports = bhnd_get_port_count(sc->dev, types[i]);
		for (u_int port = 0; port < num_ports; port++) {
			error = chipc_rman_init_regions(sc, types[i], port);
			if (error) {
				device_printf(sc->dev,
				    "region init failed for %s%u: %d\n",
				     bhnd_port_type_name(types[i]), port,
				     error);

				goto failed;
			}
		}
	}

	return (0);

failed:
	chipc_free_rman(sc);
	return (error);
}
예제 #2
0
파일: chipc.c 프로젝트: wulf7/freebsd
/* Allocate region records for the given port, and add the port's memory
 * range to the mem_rman */
static int
chipc_rman_init_regions (struct chipc_softc *sc, bhnd_port_type type,
    u_int port)
{
	struct	chipc_region	*cr;
	rman_res_t		 start, end;
	u_int			 num_regions;
	int			 error;

	num_regions = bhnd_get_region_count(sc->dev, type, port);
	for (u_int region = 0; region < num_regions; region++) {
		/* Allocate new region record */
		cr = chipc_alloc_region(sc, type, port, region);
		if (cr == NULL)
			return (ENODEV);

		/* Can't manage regions that cannot be allocated */
		if (cr->cr_rid < 0) {
			BHND_DEBUG_DEV(sc->dev, "no rid for chipc region "
			    "%s%u.%u", bhnd_port_type_name(type), port, region);
			chipc_free_region(sc, cr);
			continue;
		}

		/* Add to rman's managed range */
		start = cr->cr_addr;
		end = cr->cr_end;
		if ((error = rman_manage_region(&sc->mem_rman, start, end))) {
			chipc_free_region(sc, cr);
			return (error);
		}

		/* Add to region list */
		STAILQ_INSERT_TAIL(&sc->mem_regions, cr, cr_link);
	}

	return (0);
}
예제 #3
0
파일: bcma_erom.c 프로젝트: 2asoft/freebsd
/**
 * Register all MMIO region descriptors for the given slave port.
 * 
 * @param erom EROM read state.
 * @param corecfg Core info to be populated with the scanned port regions.
 * @param port_num Port index for which regions will be parsed.
 * @param region_type The region type to be parsed.
 * @param[out] offset The offset at which to perform parsing. On success, this
 * will be updated to point to the next EROM table entry.
 */
static int 
erom_corecfg_fill_port_regions(struct bcma_erom *erom,
    struct bcma_corecfg *corecfg, bcma_pid_t port_num,
    uint8_t region_type)
{
	struct bcma_sport	*sport;
	struct bcma_sport_list	*sports;
	bus_size_t		 entry_offset;
	int			 error;
	bhnd_port_type		 port_type;

	error = 0;
	
	/* Determine the port type for this region type. */
	switch (region_type) {
		case BCMA_EROM_REGION_TYPE_DEVICE:
			port_type = BHND_PORT_DEVICE;
			break;
		case BCMA_EROM_REGION_TYPE_BRIDGE:
			port_type = BHND_PORT_BRIDGE;
			break;
		case BCMA_EROM_REGION_TYPE_MWRAP:
		case BCMA_EROM_REGION_TYPE_SWRAP:
			port_type = BHND_PORT_AGENT;
			break;
		default:
			EROM_LOG(erom, "unsupported region type %hhx\n",
			    region_type);
			return (EINVAL);
	}

	/* Fetch the list to be populated */
	sports = bcma_corecfg_get_port_list(corecfg, port_type);
	
	/* Allocate a new port descriptor */
	sport = bcma_alloc_sport(port_num, port_type);
	if (sport == NULL)
		return (ENOMEM);

	/* Read all address regions defined for this port */
	for (bcma_rmid_t region_num = 0;; region_num++) {
		struct bcma_map			*map;
		struct bcma_erom_sport_region	 spr;

		/* No valid port definition should come anywhere near
		 * BCMA_RMID_MAX. */
		if (region_num == BCMA_RMID_MAX) {
			EROM_LOG(erom, "core%u %s%u: region count reached "
			    "upper limit of %u\n",
			    corecfg->core_info.core_idx,
			    bhnd_port_type_name(port_type),
			    port_num, BCMA_RMID_MAX);

			error = EINVAL;
			goto cleanup;
		}

		/* Parse the next region entry. */
		entry_offset = bcma_erom_tell(erom);
		error = bcma_erom_parse_sport_region(erom, &spr);
		if (error && error != ENOENT) {
			EROM_LOG(erom, "core%u %s%u.%u: invalid slave port "
			    "address region\n",
			    corecfg->core_info.core_idx,
			    bhnd_port_type_name(port_type),
			    port_num, region_num);
			goto cleanup;
		}

		/* ENOENT signals no further region entries */
		if (error == ENOENT) {
			/* No further entries */
			error = 0;
			break;
		} 
		
		/* A region or type mismatch also signals no further region
		 * entries */
		if (spr.region_port != port_num ||
		    spr.region_type != region_type)
		{
			/* We don't want to consume this entry */
			bcma_erom_seek(erom, entry_offset);

			error = 0;
			goto cleanup;
		}

		/*
		 * Create the map entry. 
		 */
		map = malloc(sizeof(struct bcma_map), M_BHND, M_NOWAIT);
		if (map == NULL) {
			error = ENOMEM;
			goto cleanup;
		}

		map->m_region_num = region_num;
		map->m_base = spr.base_addr;
		map->m_size = spr.size;
		map->m_rid = -1;

		/* Add the region map to the port */
		STAILQ_INSERT_TAIL(&sport->sp_maps, map, m_link);
		sport->sp_num_maps++;
	}

cleanup:
	/* Append the new port descriptor on success, or deallocate the
	 * partially parsed descriptor on failure. */
	if (error == 0) {
		STAILQ_INSERT_TAIL(sports, sport, sp_link);
	} else if (sport != NULL) {
		bcma_free_sport(sport);
	}

	return error;
}