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

📄 prom.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	of_find_node_by_name - Find a node by it's "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 = from ? from->allnext : allnodes;	for (; np != 0; np = np->allnext)		if (np->name != 0 && strcasecmp(np->name, name) == 0)			break;	if (from)		of_node_put(from);	return of_node_get(np);}/** *	of_find_node_by_type - Find a node by it's "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 = from ? from->allnext : allnodes;	for (; np != 0; np = np->allnext)		if (np->type != 0 && strcasecmp(np->type, type) == 0)			break;	if (from)		of_node_put(from);	return of_node_get(np);}/** *	of_find_compatible_node - Find a node based on type and one of the *                                tokens in it's "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 = 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))			break;	}	if (from)		of_node_put(from);	return of_node_get(np);}/** *	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;	for (; np != 0; np = np->allnext)		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)			break;	return of_node_get(np);}/** *	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){	return of_node_get(prev ? prev->allnext : allnodes);}/** *	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){	return node ? of_node_get(node->parent) : NULL;}/** *	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 = prev ? prev->sibling : node->child;	for (; next != 0; next = next->sibling)		if (of_node_get(next))			break;	if (prev)		of_node_put(prev);	return next;}/** *	of_node_get - Increment refcount of a node *	@node:	Node to inc refcount, NULL is supported to *		simplify writing of callers * *	Returns the node itself or NULL if gone. Current implementation *	does nothing as we don't yet do dynamic node allocation on ppc32 */struct device_node *of_node_get(struct device_node *node){	return node;}/** *	of_node_put - Decrement refcount of a node *	@node:	Node to dec refcount, NULL is supported to *		simplify writing of callers * *	Current implementation does nothing as we don't yet do dynamic node *	allocation on ppc32 */void  of_node_put(struct device_node *node){}/* * Find the device_node with a given phandle. */static struct device_node * __initfind_phandle(phandle ph){	struct device_node *np;	for (np = allnodes; np != 0; np = np->allnext)		if (np->node == ph)			return np;	return NULL;}/* * 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 (pp->name != NULL && strcmp(pp->name, name) == 0) {			if (lenp != 0)				*lenp = pp->length;			return pp->value;		}	return NULL;}/* * Add a property to a node */void __openfirmwareprom_add_property(struct device_node* np, struct property* prop){	struct property **next = &np->properties;	prop->next = NULL;	while (*next)		next = &(*next)->next;	*next = prop;}/* I quickly hacked that one, check against spec ! */static inline unsigned long __openfirmwarebus_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;	}}static struct resource* __openfirmwarefind_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* __openfirmwarerequest_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;}int __openfirmwarerelease_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;}#if 0void __openfirmwareprint_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);		}	}}#endifstatic spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;/* this can be called after setup -- Cort */int __openfirmwarecall_rtas(const char *service, int nargs, int nret,	  unsigned long *outputs, ...){	va_list list;	int i;	unsigned long s;	struct device_node *rtas;	int *tokp;	union {		unsigned long words[16];		double align;	} u;	rtas = find_devices("rtas");	if (rtas == NULL)		return -1;	tokp = (int *) get_property(rtas, service, NULL);	if (tokp == NULL) {		printk(KERN_ERR "No RTAS service called %s\n", service);		return -1;	}	u.words[0] = *tokp;	u.words[1] = nargs;	u.words[2] = nret;	va_start(list, outputs);	for (i = 0; i < nargs; ++i)		u.words[i+3] = va_arg(list, unsigned long);	va_end(list);	/*	 * RTAS doesn't use floating point.	 * Or at least, according to the CHRP spec we enter RTAS	 * with FP disabled, and it doesn't change the FP registers.	 *  -- paulus.	 */	spin_lock_irqsave(&rtas_lock, s);	enter_rtas((void *)__pa(&u));	spin_unlock_irqrestore(&rtas_lock, s);	if (nret > 1 && outputs != NULL)		for (i = 0; i < nret-1; ++i)			outputs[i] = u.words[i+nargs+4];	return u.words[nargs+3];}

⌨️ 快捷键说明

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