欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

prom.c

底层驱动开发
C
第 1 页 / 共 4 页
字号:
 * 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 != 0; np = np->allnext)		if (np->name != 0 && 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,	const char *type, const char *compatible){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np != 0; np = np->allnext) {		if (type != NULL		    && !(np->type != 0 && strcasecmp(np->type, type) == 0))			continue;		if (device_is_compatible(np, compatible) && of_node_get(np))			break;	}	if (from)		of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_compatible_node);/** *	of_find_node_by_path - Find a node matching a full OF path *	@path:	The full path to match * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_path(const char *path){	struct device_node *np = allnodes;	read_lock(&devtree_lock);	for (; np != 0; np = np->allnext) {		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0		    && of_node_get(np))			break;	}	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_path);/** *	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;	if (np)		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;	if (prev)		of_node_put(prev);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_all_nodes);/** *	of_get_parent - Get a node's parent if any *	@node:	Node to get parent * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_get_parent(const struct device_node *node){	struct device_node *np;	if (!node)		return NULL;	read_lock(&devtree_lock);	np = of_node_get(node->parent);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_get_parent);/** *	of_get_next_child - Iterate a node childs *	@node:	parent node *	@prev:	previous child of the parent node, or NULL to get first * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_get_next_child(const struct device_node *node,	struct device_node *prev){	struct device_node *next;	read_lock(&devtree_lock);	next = prev ? prev->sibling : node->child;	for (; next != 0; next = next->sibling)		if (of_node_get(next))			break;	if (prev)		of_node_put(prev);	read_unlock(&devtree_lock);	return next;}EXPORT_SYMBOL(of_get_next_child);/** *	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;	if (!OF_IS_DYNAMIC(node))		return;	while (prop) {		struct property *next = prop->next;		kfree(prop->name);		kfree(prop->value);		kfree(prop);		prop = next;	}	kfree(node->intrs);	kfree(node->addrs);	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);/* * Fix up the uninitialized fields in a new device node: * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields * * A lot of boot-time code is duplicated here, because functions such * as finish_node_interrupts, interpret_pci_props, etc. cannot use the * slab allocator. * * This should probably be split up into smaller chunks. */static int of_finish_dynamic_node(struct device_node *node,				  unsigned long *unused1, int unused2,				  int unused3, int unused4){	struct device_node *parent = of_get_parent(node);	int err = 0;	phandle *ibm_phandle;	node->name = get_property(node, "name", NULL);	node->type = get_property(node, "device_type", NULL);	if (!parent) {		err = -ENODEV;		goto out;	}	/* We don't support that function on PowerMac, at least	 * not yet	 */	if (systemcfg->platform == PLATFORM_POWERMAC)		return -ENODEV;	/* fix up new node's linux_phandle field */	if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL)))		node->linux_phandle = *ibm_phandle;out:	of_node_put(parent);	return err;}/* * 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(const struct device_node *np){	struct device_node *parent;	write_lock(&devtree_lock);	parent = np->parent;	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;	}	write_unlock(&devtree_lock);}static int prom_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node){	int err;	switch (action) {	case PSERIES_RECONFIG_ADD:		err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0);		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);/* * Find a property with a given name for a given node * and return the value. */unsigned char *get_property(struct device_node *np, const char *name, int *lenp){	struct property *pp;	for (pp = np->properties; pp != 0; pp = pp->next)		if (strcmp(pp->name, name) == 0) {			if (lenp != 0)				*lenp = pp->length;			return pp->value;		}	return NULL;}EXPORT_SYMBOL(get_property);/* * Add a property to a node */voidprom_add_property(struct device_node* np, struct property* prop){	struct property **next = &np->properties;	prop->next = NULL;		while (*next)		next = &(*next)->next;	*next = prop;}#if 0voidprint_properties(struct device_node *np){	struct property *pp;	char *cp;	int i, n;	for (pp = np->properties; pp != 0; pp = pp->next) {		printk(KERN_INFO "%s", pp->name);		for (i = strlen(pp->name); i < 16; ++i)			printk(" ");		cp = (char *) pp->value;		for (i = pp->length; i > 0; --i, ++cp)			if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))			    || (i == 1 && *cp != 0))				break;		if (i == 0 && pp->length > 1) {			/* looks like a string */			printk(" %s\n", (char *) pp->value);		} else {			/* dump it in hex */			n = pp->length;			if (n > 64)				n = 64;			if (pp->length % 4 == 0) {				unsigned int *p = (unsigned int *) pp->value;				n /= 4;				for (i = 0; i < n; ++i) {					if (i != 0 && (i % 4) == 0)						printk("\n                ");					printk(" %08x", *p++);				}			} else {				unsigned char *bp = pp->value;				for (i = 0; i < n; ++i) {					if (i != 0 && (i % 16) == 0)						printk("\n                ");					printk(" %02x", *bp++);				}			}			printk("\n");			if (pp->length > 64)				printk("                 ... (length = %d)\n",				       pp->length);		}	}}#endif

⌨️ 快捷键说明

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