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

📄 prom.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	if (use_of_interrupt_tree)		return mem_start;	ip = (int *) get_property(np, "interrupts", &l);	if (ip != 0) {		np->intrs = (struct interrupt_info *) mem_start;		np->n_intrs = l / (2 * sizeof(int));		mem_start += np->n_intrs * sizeof(struct interrupt_info);		for (i = 0; i < np->n_intrs; ++i) {			np->intrs[i].line = *ip++;			np->intrs[i].sense = *ip++;		}	}	return mem_start;}static unsigned long __initinterpret_root_props(struct device_node *np, unsigned long mem_start,		     int naddrc, int nsizec){	struct address_range *adr;	int i, l, *ip;	unsigned int *rp;	int rpsize = (naddrc + nsizec) * sizeof(unsigned int);	rp = (unsigned int *) get_property(np, "reg", &l);	if (rp != 0 && l >= rpsize) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= rpsize) >= 0) {			adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);			adr[i].address = rp[naddrc - 1];			adr[i].size = rp[naddrc + nsizec - 1];			++i;			rp += naddrc + nsizec;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	if (use_of_interrupt_tree)		return mem_start;	ip = (int *) get_property(np, "AAPL,interrupts", &l);	if (ip == 0)		ip = (int *) get_property(np, "interrupts", &l);	if (ip != 0) {		np->intrs = (struct interrupt_info *) mem_start;		np->n_intrs = l / sizeof(int);		mem_start += np->n_intrs * sizeof(struct interrupt_info);		for (i = 0; i < np->n_intrs; ++i) {			np->intrs[i].line = *ip++;			np->intrs[i].sense = 1;		}	}	return mem_start;}/* * Work out the sense (active-low level / active-high edge) * of each interrupt from the device tree. */void __initprom_get_irq_senses(unsigned char *senses, int off, int max){	struct device_node *np;	int i, j;	/* default to level-triggered */	memset(senses, 1, max - off);	if (!use_of_interrupt_tree)		return;	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 = 0;	return head;}/* * 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 = 0;	return head;}/* * Returns all nodes linked together */struct device_node * __openfirmwarefind_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 = 0;	return head;}/* Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */intdevice_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;}/* * Indicates whether the root node has a given value in its * compatible property. */intmachine_is_compatible(const char *compat){	struct device_node *root;	root = find_path_device("/");	if (root == 0)		return 0;	return device_is_compatible(root, compat);}/* * 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 = 0;	return head;}/* * 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;}/* * 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 0;}/* * 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. * WARNING: out_resource->name should be initialized before calling this * function. */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;	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 "request_OF_resource(%s), parent not found\n",			node->name);		return -ENODEV;	}	/* Find us in the parent */	res = parent->child;	while (res) {		if (res->start == node->addrs[index].address &&		    res->end == (res->start + node->addrs[index].size - 1))		    	break;		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);	/* Shouldn't we enable kernel FP here ? enter_rtas will play	 * with MSR_FE0|MSR_FE1|MSR_FP so I assume rtas might use	 * floating points. If that's the case, then we need to make	 * sure any lazy FP context is backed up	 * --BenH	 */	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];}void __initabort(){#ifdef CONFIG_XMON	xmon(NULL);#endif	for (;;)		prom_exit();}

⌨️ 快捷键说明

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