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

📄 prom.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
{	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);/* * 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);}#ifdef CONFIG_PPC_PSERIES/* * 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 (_machine == 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;}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);#endif/* * 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 */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;}/* I quickly hacked that one, check against spec ! */static inline unsigned longbus_space_to_resource_flags(unsigned int bus_space){	u8 space = (bus_space >> 24) & 0xf;	if (space == 0)		space = 0x02;	if (space == 0x02)		return IORESOURCE_MEM;	else if (space == 0x01)		return IORESOURCE_IO;	else {		printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",		    	bus_space);		return 0;	}}#ifdef CONFIG_PCIstatic struct resource *find_parent_pci_resource(struct pci_dev* pdev,						 struct address_range *range){	unsigned long mask;	int i;	/* Check this one */	mask = bus_space_to_resource_flags(range->space);	for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {		if ((pdev->resource[i].flags & mask) == mask &&			pdev->resource[i].start <= range->address &&			pdev->resource[i].end > range->address) {				if ((range->address + range->size - 1) > pdev->resource[i].end) {					/* Add better message */					printk(KERN_WARNING "PCI/OF resource overlap !\n");					return NULL;				}				break;			}	}	if (i == DEVICE_COUNT_RESOURCE)		return NULL;	return &pdev->resource[i];}/* * Request an OF device resource. Currently handles child of PCI devices, * or other nodes attached to the root node. Ultimately, put some * link to resources in the OF node. */struct resource *request_OF_resource(struct device_node* node, int index,				     const char* name_postfix){	struct pci_dev* pcidev;	u8 pci_bus, pci_devfn;	unsigned long iomask;	struct device_node* nd;	struct resource* parent;	struct resource *res = NULL;	int nlen, plen;	if (index >= node->n_addrs)		goto fail;	/* Sanity check on bus space */	iomask = bus_space_to_resource_flags(node->addrs[index].space);	if (iomask & IORESOURCE_MEM)		parent = &iomem_resource;	else if (iomask & IORESOURCE_IO)		parent = &ioport_resource;	else		goto fail;	/* Find a PCI parent if any */	nd = node;	pcidev = NULL;	while (nd) {		if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))			pcidev = pci_find_slot(pci_bus, pci_devfn);		if (pcidev) break;		nd = nd->parent;	}	if (pcidev)		parent = find_parent_pci_resource(pcidev, &node->addrs[index]);	if (!parent) {		printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",			node->name);		goto fail;	}	res = __request_region(parent, node->addrs[index].address,			       node->addrs[index].size, NULL);	if (!res)		goto fail;	nlen = strlen(node->name);	plen = name_postfix ? strlen(name_postfix) : 0;	res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);	if (res->name) {		strcpy((char *)res->name, node->name);		if (plen)			strcpy((char *)res->name+nlen, name_postfix);	}	return res;fail:	return NULL;}EXPORT_SYMBOL(request_OF_resource);int release_OF_resource(struct device_node *node, int index){	struct pci_dev* pcidev;	u8 pci_bus, pci_devfn;	unsigned long iomask, start, end;	struct device_node* nd;	struct resource* parent;	struct resource *res = NULL;	if (index >= node->n_addrs)		return -EINVAL;	/* Sanity check on bus space */	iomask = bus_space_to_resource_flags(node->addrs[index].space);	if (iomask & IORESOURCE_MEM)		parent = &iomem_resource;	else if (iomask & IORESOURCE_IO)		parent = &ioport_resource;	else		return -EINVAL;	/* Find a PCI parent if any */	nd = node;	pcidev = NULL;	while(nd) {		if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))			pcidev = pci_find_slot(pci_bus, pci_devfn);		if (pcidev) break;		nd = nd->parent;	}	if (pcidev)		parent = find_parent_pci_resource(pcidev, &node->addrs[index]);	if (!parent) {		printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",			node->name);		return -ENODEV;	}	/* Find us in the parent and its childs */	res = parent->child;	start = node->addrs[index].address;	end = start + node->addrs[index].size - 1;	while (res) {		if (res->start == start && res->end == end &&		    (res->flags & IORESOURCE_BUSY))		    	break;		if (res->start <= start && res->end >= end)			res = res->child;		else			res = res->sibling;	}	if (!res)		return -ENODEV;	if (res->name) {		kfree(res->name);		res->name = NULL;	}	release_resource(res);	kfree(res);	return 0;}EXPORT_SYMBOL(release_OF_resource);#endif /* CONFIG_PCI */

⌨️ 快捷键说明

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