⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prom.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif}void __init early_init_devtree(void *params){	DBG(" -> early_init_devtree(%p)\n", params);	/* Setup flat device-tree pointer */	initial_boot_params = params;#ifdef CONFIG_PPC_RTAS	/* Some machines might need RTAS info for debugging, grab it now. */	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);#endif	/* 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);	/* Save command line for /proc/cmdline and then parse parameters */	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);	parse_early_param();	/* Reserve LMB regions used by kernel, initrd, dt, etc... */	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);	reserve_kdump_trampoline();	reserve_crashkernel();	early_reserve_mem();	lmb_enforce_memory_limit(memory_limit);	lmb_analyze();	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());	/* We may need to relocate the flat tree, do it now.	 * FIXME .. and the initrd too? */	move_device_tree();	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");}/** * 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 = of_device_is_compatible(root, compat);		of_node_put(root);	}	return rc;}EXPORT_SYMBOL(machine_is_compatible);/******* * * 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_phandle - Find a node given a phandle *	@handle:	phandle of the node to find * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_phandle(phandle handle){	struct device_node *np;	read_lock(&devtree_lock);	for (np = allnodes; np != 0; np = np->allnext)		if (np->linux_phandle == handle)			break;	of_node_get(np);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_phandle);/** *	of_find_all_nodes - Get next node in global list *	@prev:	Previous node or NULL to start iteration *		of_node_put() will be called on it * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_all_nodes(struct device_node *prev){	struct device_node *np;	read_lock(&devtree_lock);	np = prev ? prev->allnext : allnodes;	for (; np != 0; np = np->allnext)		if (of_node_get(np))			break;	of_node_put(prev);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_all_nodes);/** *	of_node_get - Increment refcount of a node *	@node:	Node to inc refcount, NULL is supported to *		simplify writing of callers * *	Returns node. */struct device_node *of_node_get(struct device_node *node){	if (node)		kref_get(&node->kref);	return node;}EXPORT_SYMBOL(of_node_get);static inline struct device_node * kref_to_device_node(struct kref *kref){	return container_of(kref, struct device_node, kref);}/** *	of_node_release - release a dynamically allocated node *	@kref:  kref element of the node to be released * *	In of_node_put() this function is passed to kref_put() *	as the destructor. */static void of_node_release(struct kref *kref){	struct device_node *node = kref_to_device_node(kref);	struct property *prop = node->properties;	/* We should never be releasing nodes that haven't been detached. */	if (!of_node_check_flag(node, OF_DETACHED)) {		printk("WARNING: Bad of_node_put() on %s\n", node->full_name);		dump_stack();		kref_init(&node->kref);		return;	}	if (!of_node_check_flag(node, OF_DYNAMIC))		return;	while (prop) {		struct property *next = prop->next;		kfree(prop->name);		kfree(prop->value);		kfree(prop);		prop = next;		if (!prop) {			prop = node->deadprops;			node->deadprops = NULL;		}	}	kfree(node->full_name);	kfree(node->data);	kfree(node);}/** *	of_node_put - Decrement refcount of a node *	@node:	Node to dec refcount, NULL is supported to *		simplify writing of callers * */void of_node_put(struct device_node *node){	if (node)		kref_put(&node->kref, of_node_release);}EXPORT_SYMBOL(of_node_put);/* * Plug a device node into the tree and global list. */void of_attach_node(struct device_node *np){	write_lock(&devtree_lock);	np->sibling = np->parent->child;	np->allnext = allnodes;	np->parent->child = np;	allnodes = np;	write_unlock(&devtree_lock);}/* * "Unplug" a node from the device tree.  The caller must hold * a reference to the node.  The memory associated with the node * is not freed until its refcount goes to zero. */void of_detach_node(struct device_node *np){	struct device_node *parent;	write_lock(&devtree_lock);	parent = np->parent;	if (!parent)		goto out_unlock;	if (allnodes == np)		allnodes = np->allnext;	else {		struct device_node *prev;		for (prev = allnodes;		     prev->allnext != np;		     prev = prev->allnext)			;		prev->allnext = np->allnext;	}	if (parent->child == np)		parent->child = np->sibling;	else {		struct device_node *prevsib;		for (prevsib = np->parent->child;		     prevsib->sibling != np;		     prevsib = prevsib->sibling)			;		prevsib->sibling = np->sibling;	}	of_node_set_flag(np, OF_DETACHED);out_unlock:	write_unlock(&devtree_lock);}#ifdef CONFIG_PPC_PSERIES/* * Fix up the uninitialized fields in a new device node: * name, type and pci-specific fields */static int of_finish_dynamic_node(struct device_node *node){	struct device_node *parent = of_get_parent(node);	int err = 0;	const phandle *ibm_phandle;	node->name = of_get_property(node, "name", NULL);	node->type = of_get_property(node, "device_type", NULL);	if (!node->name)		node->name = "<NULL>";	if (!node->type)		node->type = "<NULL>";	if (!parent) {		err = -ENODEV;		goto out;	}	/* We don't support that function on PowerMac, at least	 * not yet	 */	if (machine_is(powermac))		return -ENODEV;	/* fix up new node's linux_phandle field */	if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))		node->linux_phandle = *ibm_phandle;out:	of_node_put(parent);	return err;}static int prom_reconfig_notifier(struct notifier_block *nb,				  unsigned long action, void *node){	int err;	switch (action) {	case PSERIES_RECONFIG_ADD:		err = of_finish_dynamic_node(node);		if (err < 0) {			printk(KERN_ERR "finish_node returned %d\n", err);			err = NOTIFY_BAD;		}		break;	default:		err = NOTIFY_DONE;		break;	}	return err;}static struct notifier_block prom_reconfig_nb = {	.notifier_call = prom_reconfig_notifier,	.priority = 10, /* This one needs to run first */};static int __init prom_reconfig_setup(void){	return pSeries_reconfig_notifier_register(&prom_reconfig_nb);}__initcall(prom_reconfig_setup);#endif/* * Add a property to a node */int prom_add_property(struct device_node* np, struct property* prop){	struct property **next;	prop->next = NULL;		write_lock(&devtree_lock);	next = &np->properties;	while (*next) {		if (strcmp(prop->name, (*next)->name) == 0) {			/* duplicate ! don't insert it */			write_unlock(&devtree_lock);			return -1;		}		next = &(*next)->next;	}	*next = prop;	write_unlock(&devtree_lock);#ifdef CONFIG_PROC_DEVICETREE	/* try to add to proc as well if it was initialized */	if (np->pde)		proc_device_tree_add_prop(np->pde, prop);#endif /* CONFIG_PROC_DEVICETREE */	return 0;}/* * Remove a property from a node.  Note that we don't actually * remove it, since we have given out who-knows-how-many pointers * to the data using get-property.  Instead we just move the property * to the "dead properties" list, so it won't be found any more. */int prom_remove_property(struct device_node *np, struct property *prop){	struct property **next;	int found = 0;	write_lock(&devtree_lock);	next = &np->properties;	while (*next) {		if (*next == prop) {			/* found the node */			*next = prop->next;			prop->next = np->deadprops;			np->deadprops = prop;			found = 1;			break;		}		next = &(*next)->next;	}	write_unlock(&devtree_lock);	if (!found)		return -ENODEV;#ifdef CONFIG_PROC_DEVICETREE	/* try to remove the proc node as well */	if (np->pde)		proc_device_tree_remove_prop(np->pde, prop);#endif /* CONFIG_PROC_DEVICETREE */	return 0;}/* * Update a property in a node.  Note that we don't actually * remove it, since we have given out who-knows-how-many pointers * to the data using get-property.  Instead we just move the property * to the "dead properties" list, and add the new property to the * property list */int prom_update_property(struct device_node *np,			 struct property *newprop,			 struct property *oldprop){	struct property **next;	int found = 0;	write_lock(&devtree_lock);	next = &np->properties;	while (*next) {		if (*next == oldprop) {			/* found the node */			newprop->next = oldprop->next;			*next = newprop;			oldprop->next = np->deadprops;			np->deadprops = oldprop;			found = 1;			break;		}		next = &(*next)->next;	}	write_unlock(&devtree_lock);	if (!found)		return -ENODEV;#ifdef CONFIG_PROC_DEVICETREE	/* try to add to proc as well if it was initialized */	if (np->pde)		proc_device_tree_update_prop(np->pde, newprop, oldprop);#endif /* CONFIG_PROC_DEVICETREE */	return 0;}/* Find the device node for a given logical cpu number, also returns the cpu * local thread number (index in ibm,interrupt-server#s) if relevant and * asked for (non NULL) */struct device_node *of_get_cpu_node(int cpu, unsigned int *thread){	int hardid;	struct device_node *np;	hardid = get_hard_smp_processor_id(cpu);	for_each_node_by_type(np, "cpu") {		const u32 *intserv;		unsigned int plen, t;		/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist		 * fallback to "reg" property and assume no threads		 */		intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",				&plen);		if (intserv == NULL) {			const u32 *reg = of_get_property(np, "reg", NULL);			if (reg == NULL)				continue;			if (*reg == hardid) {				if (thread)					*thread = 0;				return np;			}		} else {			plen /= sizeof(u32);			for (t = 0; t < plen; t++) {				if (hardid == intserv[t]) {					if (thread)						*thread = t;					return np;				}			}		}	}	return NULL;}EXPORT_SYMBOL(of_get_cpu_node);#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)static struct debugfs_blob_wrapper flat_dt_blob;static int __init export_flat_device_tree(void){	struct dentry *d;	flat_dt_blob.data = initial_boot_params;	flat_dt_blob.size = initial_boot_params->totalsize;	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,				powerpc_debugfs_root, &flat_dt_blob);	if (!d)		return 1;	return 0;}__initcall(export_flat_device_tree);#endif

⌨️ 快捷键说明

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