FreeBSD/sys/dev/bhnd/siba/siba.c
/**
 * Scan the core table and add all valid discovered cores to
 * the bus.
 * 
 * @param dev The siba bus device.
 * @param chipid The chip identifier, if the device does not provide a
 * ChipCommon core. Should o NULL otherwise.
 */
Scan the core table and add all valid discovered cores to
the bus.

@param dev The siba bus device.
@param chipid The chip identifier, if the device does not provide a
ChipCommon core. Should o NULL otherwise.
Scan the core table and add all valid discovered cores to the bus . @param dev The siba bus device . @param chipid The chip identifier if the device does not provide a ChipCommon core . Should o NULL otherwise .
int
siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
{
	struct bhnd_chipid	 ccid;
	struct bhnd_core_info	*cores;
	struct siba_devinfo	*dinfo;
	struct resource		*r;
	int			 rid;
	int			 error;
	dinfo = NULL;
	cores = NULL;
	r = NULL;
	if (chipid == NULL) {
		uint32_t	idhigh, ccreg;
		uint16_t	vendor, device;
		uint8_t		ccrev;
		rid = 0;
		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
		    SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, 
		    SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1,
		    RF_ACTIVE);
		idhigh = 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);
		if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) {
			device_printf(dev,
			    "cannot identify device: no chipcommon core "
			    "found\n");
			error = ENXIO;
			goto cleanup;
		}
		ccreg = bus_read_4(r, CHIPC_ID);
		ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR);
		if (!CHIPC_NCORES_MIN_HWREV(ccrev)) {
			switch (ccid.chip_id) {
			case BHND_CHIPID_BCM4306:
				ccid.ncores = 6;
				break;
			case BHND_CHIPID_BCM4704:
				ccid.ncores = 9;
				break;
			case BHND_CHIPID_BCM5365:
				ccid.ncores = 7;
				break;
			default:
				device_printf(dev, "unable to determine core "
				    "count for unrecognized chipset 0x%hx\n",
				    ccid.chip_id);
				error = ENXIO;
				goto cleanup;
			}
		}
		chipid = &ccid;
		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
	}
	cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
	if (cores == NULL)
		return (ENOMEM);
	for (u_int i = 0; i < chipid->ncores; i++) {
		struct siba_core_id	 cid;
		device_t		 child;
		uint32_t		 idhigh, idlow;
		rman_res_t		 r_count, r_end, r_start;
		rid = 0;
		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_end, r_count, RF_ACTIVE);
		if (r == NULL) {
			error = ENXIO;
			goto cleanup;
		}
		child = BUS_ADD_CHILD(dev, 0, NULL, -1);
		if (child == NULL) {
			error = ENXIO;
			goto cleanup;
		}
		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
		idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
		cid = siba_parse_core_id(idhigh, idlow, i, 0);
		cores[i] = cid.core_info;
		for (u_int j = 0; j < i; j++) {
			if (cores[j].vendor == cores[i].vendor &&
			    cores[j].device == cores[i].device)
				cores[i].unit++;
		}
		if ((dinfo = device_get_ivars(child)) == NULL) {
			error = ENXIO;
			goto cleanup;
		}
		if ((error = siba_init_dinfo(dev, dinfo, &cid)))
			goto cleanup;
		if ((error = siba_register_addrspaces(dev, dinfo, r)))
			goto cleanup;
		if (bhnd_is_hw_disabled(child))
			device_disable(child);
		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
		r = NULL;
	}
cleanup:
	if (cores != NULL)
		free(cores, M_BHND);
	if (r != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
	return (error);
}
int siba_add_children ( device_t dev , const struct bhnd_chipid * chipid ) { struct bhnd_chipid ccid ; struct bhnd_core_info * cores ; struct siba_devinfo * dinfo ; struct resource * r ; int rid ; int error ; dinfo = NULL ; cores = NULL ; r = NULL ; if ( chipid == NULL ) { uint32_t idhigh , ccreg ; uint16_t vendor , device ; uint8_t ccrev ; rid = 0 ; r = bus_alloc_resource ( dev , SYS_RES_MEMORY , & rid , SIBA_CORE_ADDR ( 0 ) , SIBA_CORE_SIZE , SIBA_CORE_ADDR ( 0 ) + SIBA_CORE_SIZE - 1 , RF_ACTIVE ) ; idhigh = 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 ) ; if ( vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC ) { device_printf ( dev , " " " \n " ) ; error = ENXIO ; goto cleanup ; } ccreg = bus_read_4 ( r , CHIPC_ID ) ; ccid = bhnd_parse_chipid ( ccreg , SIBA_ENUM_ADDR ) ; if ( ! CHIPC_NCORES_MIN_HWREV ( ccrev ) ) { switch ( ccid . chip_id ) { case BHND_CHIPID_BCM4306 : ccid . ncores = 6 ; break ; case BHND_CHIPID_BCM4704 : ccid . ncores = 9 ; break ; case BHND_CHIPID_BCM5365 : ccid . ncores = 7 ; break ; default : device_printf ( dev , " " " \n " , ccid . chip_id ) ; error = ENXIO ; goto cleanup ; } } chipid = & ccid ; bus_release_resource ( dev , SYS_RES_MEMORY , rid , r ) ; } cores = malloc ( sizeof ( * cores ) * chipid -> ncores , M_BHND , M_NOWAIT ) ; if ( cores == NULL ) return ( ENOMEM ) ; for ( u_int i = 0 ; i < chipid -> ncores ; i ++ ) { struct siba_core_id cid ; device_t child ; uint32_t idhigh , idlow ; rman_res_t r_count , r_end , r_start ; rid = 0 ; 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_end , r_count , RF_ACTIVE ) ; if ( r == NULL ) { error = ENXIO ; goto cleanup ; } child = BUS_ADD_CHILD ( dev , 0 , NULL , -1 ) ; if ( child == NULL ) { error = ENXIO ; goto cleanup ; } idhigh = bus_read_4 ( r , SB0_REG_ABS ( SIBA_CFG0_IDHIGH ) ) ; idlow = bus_read_4 ( r , SB0_REG_ABS ( SIBA_CFG0_IDLOW ) ) ; cid = siba_parse_core_id ( idhigh , idlow , i , 0 ) ; cores [ i ] = cid . core_info ; for ( u_int j = 0 ; j < i ; j ++ ) { if ( cores [ j ] . vendor == cores [ i ] . vendor && cores [ j ] . device == cores [ i ] . device ) cores [ i ] . unit ++ ; } if ( ( dinfo = device_get_ivars ( child ) ) == NULL ) { error = ENXIO ; goto cleanup ; } if ( ( error = siba_init_dinfo ( dev , dinfo , & cid ) ) ) goto cleanup ; if ( ( error = siba_register_addrspaces ( dev , dinfo , r ) ) ) goto cleanup ; if ( bhnd_is_hw_disabled ( child ) ) device_disable ( child ) ; bus_release_resource ( dev , SYS_RES_MEMORY , rid , r ) ; r = NULL ; } cleanup : if ( cores != NULL ) free ( cores , M_BHND ) ; if ( r != NULL ) bus_release_resource ( dev , SYS_RES_MEMORY , rid , r ) ; return ( error ) ; }
Scan the core table and add all valid discovered cores to
 the bus.
Scan the core table and add all valid discovered cores to the bus .
/*
	 * Try to determine the number of device cores via the ChipCommon
	 * identification registers.
	 * 
	 * A small number of very early devices do not include a ChipCommon
	 * core, in which case our caller must supply the chip identification
	 * information via a non-NULL chipid parameter.
	 */ /* Map the first core's register block. If the ChipCommon core
		 * exists, it will always be the first core. */ /* Identify the core */ /* Identify the chipset */ /*
				* BCM5365 does support ID_NUMCORE in at least
				* some of its revisions, but for unknown
				* reasons, Broadcom's drivers always exclude
				* the ChipCommon revision (0x5) used by BCM5365
				* from the set of revisions supporting
				* ID_NUMCORE, and instead supply a fixed value.
				* 
				* Presumably, at least some of these devices
				* shipped with a broken ID_NUMCORE value.
				*/ /* Allocate our temporary core table and enumerate all cores */ /* Add all cores. */ /* Map the core's register block */ /* Add the child device */ /* Read the core info */ /* Determine unit number */ /* Initialize per-device bus info */ /* Register the core's address space(s). */ /* If pins are floating or the hardware is otherwise
		 * unpopulated, the device shouldn't be used. */ /* Release our resource */