prom.c

来自「linux2.6.16版本」· C语言 代码 · 共 1,974 行 · 第 1/4 页

C
1,974
字号
       lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL);       if (lprop)               crashk_res.end = crashk_res.start + *lprop - 1;#endif	/* Retreive command line */ 	p = of_get_flat_dt_prop(node, "bootargs", &l);	if (p != NULL && l > 0)		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));#ifdef CONFIG_CMDLINE	if (l == 0 || (l == 1 && (*p) == 0))		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);#endif /* CONFIG_CMDLINE */	DBG("Command line is: %s\n", cmd_line);	if (strstr(cmd_line, "mem=")) {		char *p, *q;		unsigned long maxmem = 0;		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {			q = p + 4;			if (p > cmd_line && p[-1] != ' ')				continue;			maxmem = simple_strtoul(q, &q, 0);			if (*q == 'k' || *q == 'K') {				maxmem <<= 10;				++q;			} else if (*q == 'm' || *q == 'M') {				maxmem <<= 20;				++q;			} else if (*q == 'g' || *q == 'G') {				maxmem <<= 30;				++q;			}		}		memory_limit = maxmem;	}	/* break now */	return 1;}static int __init early_init_dt_scan_root(unsigned long node,					  const char *uname, int depth, void *data){	u32 *prop;	if (depth != 0)		return 0;	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);	dt_root_size_cells = (prop == NULL) ? 1 : *prop;	DBG("dt_root_size_cells = %x\n", dt_root_size_cells);	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;	DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);		/* break now */	return 1;}static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp){	cell_t *p = *cellp;	unsigned long r;	/* Ignore more than 2 cells */	while (s > sizeof(unsigned long) / 4) {		p++;		s--;	}	r = *p++;#ifdef CONFIG_PPC64	if (s > 1) {		r <<= 32;		r |= *(p++);		s--;	}#endif	*cellp = p;	return r;}static int __init early_init_dt_scan_memory(unsigned long node,					    const char *uname, int depth, void *data){	char *type = of_get_flat_dt_prop(node, "device_type", NULL);	cell_t *reg, *endp;	unsigned long l;	/* We are scanning "memory" nodes only */	if (type == NULL) {		/*		 * The longtrail doesn't have a device_type on the		 * /memory node, so look for the node called /memory@0.		 */		if (depth != 1 || strcmp(uname, "memory@0") != 0)			return 0;	} else if (strcmp(type, "memory") != 0)		return 0;	reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);	if (reg == NULL)		reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);	if (reg == NULL)		return 0;	endp = reg + (l / sizeof(cell_t));	DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",	    uname, l, reg[0], reg[1], reg[2], reg[3]);	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {		unsigned long base, size;		base = dt_mem_next_cell(dt_root_addr_cells, &reg);		size = dt_mem_next_cell(dt_root_size_cells, &reg);		if (size == 0)			continue;		DBG(" - %lx ,  %lx\n", base, size);#ifdef CONFIG_PPC64		if (iommu_is_off) {			if (base >= 0x80000000ul)				continue;			if ((base + size) > 0x80000000ul)				size = 0x80000000ul - base;		}#endif		lmb_add(base, size);	}	return 0;}static void __init early_reserve_mem(void){	u64 base, size;	u64 *reserve_map;	reserve_map = (u64 *)(((unsigned long)initial_boot_params) +					initial_boot_params->off_mem_rsvmap);#ifdef CONFIG_PPC32	/* 	 * Handle the case where we might be booting from an old kexec	 * image that setup the mem_rsvmap as pairs of 32-bit values	 */	if (*reserve_map > 0xffffffffull) {		u32 base_32, size_32;		u32 *reserve_map_32 = (u32 *)reserve_map;		while (1) {			base_32 = *(reserve_map_32++);			size_32 = *(reserve_map_32++);			if (size_32 == 0)				break;			DBG("reserving: %x -> %x\n", base_32, size_32);			lmb_reserve(base_32, size_32);		}		return;	}#endif	while (1) {		base = *(reserve_map++);		size = *(reserve_map++);		if (size == 0)			break;		DBG("reserving: %llx -> %llx\n", base, size);		lmb_reserve(base, size);	}#if 0	DBG("memory reserved, lmbs :\n");      	lmb_dump_all();#endif}void __init early_init_devtree(void *params){	DBG(" -> early_init_devtree()\n");	/* Setup flat device-tree pointer */	initial_boot_params = params;	/* Retrieve various informations from the /chosen node of the	 * device-tree, including the platform type, initrd location and	 * size, TCE reserve, and more ...	 */	of_scan_flat_dt(early_init_dt_scan_chosen, NULL);	/* Scan memory nodes and rebuild LMBs */	lmb_init();	of_scan_flat_dt(early_init_dt_scan_root, NULL);	of_scan_flat_dt(early_init_dt_scan_memory, NULL);	lmb_enforce_memory_limit(memory_limit);	lmb_analyze();	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());	/* Reserve LMB regions used by kernel, initrd, dt, etc... */	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);#ifdef CONFIG_CRASH_DUMP	lmb_reserve(0, KDUMP_RESERVE_LIMIT);#endif	early_reserve_mem();	DBG("Scanning CPUs ...\n");	/* Retreive CPU related informations from the flat tree	 * (altivec support, boot CPU ID, ...)	 */	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);	DBG(" <- early_init_devtree()\n");}#undef printkintprom_n_addr_cells(struct device_node* np){	int* ip;	do {		if (np->parent)			np = np->parent;		ip = (int *) get_property(np, "#address-cells", NULL);		if (ip != NULL)			return *ip;	} while (np->parent);	/* No #address-cells property for the root node, default to 1 */	return 1;}EXPORT_SYMBOL(prom_n_addr_cells);intprom_n_size_cells(struct device_node* np){	int* ip;	do {		if (np->parent)			np = np->parent;		ip = (int *) get_property(np, "#size-cells", NULL);		if (ip != NULL)			return *ip;	} while (np->parent);	/* No #size-cells property for the root node, default to 1 */	return 1;}EXPORT_SYMBOL(prom_n_size_cells);/** * Work out the sense (active-low level / active-high edge) * of each interrupt from the device tree. */void __init prom_get_irq_senses(unsigned char *senses, int off, int max){	struct device_node *np;	int i, j;	/* default to level-triggered */	memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);	for (np = allnodes; np != 0; np = np->allnext) {		for (j = 0; j < np->n_intrs; j++) {			i = np->intrs[j].line;			if (i >= off && i < max)				senses[i-off] = np->intrs[j].sense;		}	}}/** * Construct and return a list of the device_nodes with a given name. */struct device_node *find_devices(const char *name){	struct device_node *head, **prevp, *np;	prevp = &head;	for (np = allnodes; np != 0; np = np->allnext) {		if (np->name != 0 && strcasecmp(np->name, name) == 0) {			*prevp = np;			prevp = &np->next;		}	}	*prevp = NULL;	return head;}EXPORT_SYMBOL(find_devices);/** * Construct and return a list of the device_nodes with a given type. */struct device_node *find_type_devices(const char *type){	struct device_node *head, **prevp, *np;	prevp = &head;	for (np = allnodes; np != 0; np = np->allnext) {		if (np->type != 0 && strcasecmp(np->type, type) == 0) {			*prevp = np;			prevp = &np->next;		}	}	*prevp = NULL;	return head;}EXPORT_SYMBOL(find_type_devices);/** * Returns all nodes linked together */struct device_node *find_all_nodes(void){	struct device_node *head, **prevp, *np;	prevp = &head;	for (np = allnodes; np != 0; np = np->allnext) {		*prevp = np;		prevp = &np->next;	}	*prevp = NULL;	return head;}EXPORT_SYMBOL(find_all_nodes);/** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */int device_is_compatible(struct device_node *device, const char *compat){	const char* cp;	int cplen, l;	cp = (char *) get_property(device, "compatible", &cplen);	if (cp == NULL)		return 0;	while (cplen > 0) {		if (strncasecmp(cp, compat, strlen(compat)) == 0)			return 1;		l = strlen(cp) + 1;		cp += l;		cplen -= l;	}	return 0;}EXPORT_SYMBOL(device_is_compatible);/** * Indicates whether the root node has a given value in its * compatible property. */int machine_is_compatible(const char *compat){	struct device_node *root;	int rc = 0;	root = of_find_node_by_path("/");	if (root) {		rc = device_is_compatible(root, compat);		of_node_put(root);	}	return rc;}EXPORT_SYMBOL(machine_is_compatible);/** * Construct and return a list of the device_nodes with a given type * and compatible property. */struct device_node *find_compatible_devices(const char *type,					    const char *compat){	struct device_node *head, **prevp, *np;	prevp = &head;	for (np = allnodes; np != 0; np = np->allnext) {		if (type != NULL		    && !(np->type != 0 && strcasecmp(np->type, type) == 0))			continue;		if (device_is_compatible(np, compat)) {			*prevp = np;			prevp = &np->next;		}	}	*prevp = NULL;	return head;}EXPORT_SYMBOL(find_compatible_devices);/** * Find the device_node with a given full_name. */struct device_node *find_path_device(const char *path){	struct device_node *np;	for (np = allnodes; np != 0; np = np->allnext)		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)			return np;	return NULL;}EXPORT_SYMBOL(find_path_device);/******* * * New implementation of the OF "find" APIs, return a refcounted * object, call of_node_put() when done.  The device tree and list * are protected by a rw_lock. * * Note that property management will need some locking as well, * this isn't dealt with yet. * *******//** *	of_find_node_by_name - Find a node by its "name" property *	@from:	The node to start searching from or NULL, the node *		you pass will not be searched, only the next one *		will; typically, you pass what the previous call *		returned. of_node_put() will be called on it *	@name:	The name string to match against * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_name(struct device_node *from,	const char *name){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np != NULL; np = np->allnext)		if (np->name != NULL && strcasecmp(np->name, name) == 0		    && of_node_get(np))			break;	if (from)		of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_name);/** *	of_find_node_by_type - Find a node by its "device_type" property *	@from:	The node to start searching from or NULL, the node *		you pass will not be searched, only the next one *		will; typically, you pass what the previous call *		returned. of_node_put() will be called on it *	@name:	The type string to match against * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_type(struct device_node *from,	const char *type){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np != 0; np = np->allnext)		if (np->type != 0 && strcasecmp(np->type, type) == 0		    && of_node_get(np))			break;	if (from)		of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_type);/** *	of_find_compatible_node - Find a node based on type and one of the *                                tokens in its "compatible" property *	@from:		The node to start searching from or NULL, the node *			you pass will not be searched, only the next one *			will; typically, you pass what the previous call *			returned. of_node_put() will be called on it *	@type:		The type string to match "device_type" or NULL to ignore *	@compatible:	The string to match to one of the tokens in the device *			"compatible" list. * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_compatible_node(struct device_node *from,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?