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

📄 prom.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		pp = (struct property *) mem_start;		namep = (char *) (pp + 1);		pp->name = PTRUNRELOC(namep);		if ((long) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,				    namep) <= 0)			break;		mem_start = DOUBLEWORD_ALIGN((unsigned long)namep + strlen(namep) + 1);		prev_name = namep;		valp = (unsigned char *) mem_start;		pp->value = PTRUNRELOC(valp);		pp->length = (int)(long)			call_prom(RELOC("getprop"), 4, 1, node, namep,				  valp, mem_end - mem_start);		if (pp->length < 0)			continue;		mem_start = DOUBLEWORD_ALIGN(mem_start + pp->length);		*prev_propp = PTRUNRELOC(pp);		prev_propp = &pp->next;	}	/* Add a "linux_phandle" value */	if (np->node != NULL) {		u32 ibm_phandle = 0;		int len;		/* First see if "ibm,phandle" exists and use its value */		len = (int) call_prom(RELOC("getprop"), 4, 1, node,				      RELOC("ibm,phandle"),				      &ibm_phandle, sizeof(ibm_phandle));		if (len < 0) {			np->linux_phandle = np->node;		} else {			np->linux_phandle = ibm_phandle;		}	}	*prev_propp = 0;	/* get the node's full name */	l = (long) call_prom(RELOC("package-to-path"), 3, 1, node,			    (char *) mem_start, mem_end - mem_start);	if (l >= 0) {		np->full_name = PTRUNRELOC((char *) mem_start);		*(char *)(mem_start + l) = 0;		mem_start = DOUBLEWORD_ALIGN(mem_start + l + 1);	}	/* do all our children */	child = call_prom(RELOC("child"), 1, 1, node);	while (child != (phandle)0) {		mem_start = inspect_node(child, np, mem_start, mem_end,					 allnextpp);		child = call_prom(RELOC("peer"), 1, 1, child);	}	return mem_start;}/* * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). * It traverses the device tree and fills in the name, type, * {n_}addrs and {n_}intrs fields of each node. */void __initfinish_device_tree(void){	unsigned long mem = klimit;	mem = finish_node(allnodes, mem, NULL, 0, 0);	dev_tree_size = mem - (unsigned long) allnodes;	mem = _ALIGN(mem, PAGE_SIZE);	lmb_reserve(__pa(klimit), mem-klimit);	klimit = mem;	rtas.dev = find_devices("rtas");}static unsigned long __initfinish_node(struct device_node *np, unsigned long mem_start,	    interpret_func *ifunc, int naddrc, int nsizec){	struct device_node *child;	int *ip;	np->name = get_property(np, "name", 0);	np->type = get_property(np, "device_type", 0);	/* get the device addresses and interrupts */	if (ifunc != NULL) {	  mem_start = ifunc(np, mem_start, naddrc, nsizec);	}	mem_start = finish_node_interrupts(np, mem_start);	/* Look for #address-cells and #size-cells properties. */	ip = (int *) get_property(np, "#address-cells", 0);	if (ip != NULL)		naddrc = *ip;	ip = (int *) get_property(np, "#size-cells", 0);	if (ip != NULL)		nsizec = *ip;	/* the f50 sets the name to 'display' and 'compatible' to what we	 * expect for the name -- Cort	 */	ifunc = NULL;	if (!strcmp(np->name, "display"))		np->name = get_property(np, "compatible", 0);	if (!strcmp(np->name, "device-tree") || np->parent == NULL)		ifunc = interpret_root_props;	else if (np->type == 0)		ifunc = NULL;	else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))		ifunc = interpret_pci_props;	else if (!strcmp(np->type, "isa"))		ifunc = interpret_isa_props;	for (child = np->child; child != NULL; child = child->sibling)		mem_start = finish_node(child, mem_start, ifunc,					naddrc, nsizec);	return mem_start;}/* This routine walks the interrupt tree for a given device node and gather  * all necessary informations according to the draft interrupt mapping * for CHRP. The current version was only tested on Apple "Core99" machines * and may not handle cascaded controllers correctly. */__initstatic unsigned longfinish_node_interrupts(struct device_node *np, unsigned long mem_start){	/* Finish this node */	unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;	phandle *parent, map_parent;	struct device_node *node, *parent_node;	int l, isize, ipsize, asize, map_size, regpsize;	/* Currently, we don't look at all nodes with no "interrupts" property */	interrupts = (unsigned int *)get_property(np, "interrupts", &l);	if (interrupts == NULL)		return mem_start;	ipsize = l>>2;	reg = (unsigned int *)get_property(np, "reg", &l);	regpsize = l>>2;	/* We assume default interrupt cell size is 1 (bugus ?) */	isize = 1;	node = np;		do {	    /* We adjust the cell size if the current parent contains an #interrupt-cells	     * property */	    isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);	    if (isizep)	    	isize = *isizep;	    /* We don't do interrupt cascade (ISA) for now, we stop on the first 	     * controller found	     */	    if (get_property(node, "interrupt-controller", &l)) {	    	int i,j;	    	np->intrs = (struct interrupt_info *) mem_start;		np->n_intrs = ipsize / isize;		mem_start += np->n_intrs * sizeof(struct interrupt_info);		for (i = 0; i < np->n_intrs; ++i) {		    np->intrs[i].line = irq_offset_up(*interrupts++);		    np->intrs[i].sense = 1;		    if (isize > 1)		        np->intrs[i].sense = *interrupts++;		    for (j=2; j<isize; j++)		    	interrupts++;		}		return mem_start;	    }	    /* We lookup for an interrupt-map. This code can only handle one interrupt	     * per device in the map. We also don't handle #address-cells in the parent	     * I skip the pci node itself here, may not be necessary but I don't like it's	     * reg property.	     */	    if (np != node)	        map = (unsigned int *)get_property(node, "interrupt-map", &l);	     else	     	map = NULL;	    if (map && l) {	    	int i, found, temp_isize, temp_asize;	        map_size = l>>2;	        map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);	        asizep = (unsigned int *)get_property(node, "#address-cells", &l);	        if (asizep && l == sizeof(unsigned int))	            asize = *asizep;	        else	            asize = 0;	        found = 0;	        while (map_size>0 && !found) {	            found = 1;	            for (i=0; i<asize; i++) {	            	unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;	            	if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))	           	    found = 0;	           	map++;	           	map_size--;	            }	            for (i=0; i<isize; i++) {	            	unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;	            	if ((mask & *map) != (mask & interrupts[i]))	            	    found = 0;	            	map++;	            	map_size--;	            }	            map_parent = *((phandle *)map);	            map+=1; map_size-=1;	            parent_node = find_phandle(map_parent);	            temp_isize = isize;		    temp_asize = 0;	            if (parent_node) {			isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);	    		if (isizep)	    		    temp_isize = *isizep;			asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l);			if (asizep && l == sizeof(unsigned int))				temp_asize = *asizep;	            }	            if (!found) {			map += temp_isize + temp_asize;			map_size -= temp_isize + temp_asize;	            }	        }	        if (found) {		    /* Mapped to a new parent.  Use the reg and interrupts specified in		     * the map as the new search parameters.  Then search from the parent.		     */	            node = parent_node;		    reg = map;		    regpsize = temp_asize;		    interrupts = map + temp_asize;		    ipsize = temp_isize;		    continue;	        }	    }	    /* We look for an explicit interrupt-parent.	     */	    parent = (phandle *)get_property(node, "interrupt-parent", &l);	    if (parent && (l == sizeof(phandle)) &&	    	(parent_node = find_phandle(*parent))) {	    	node = parent_node;	    	continue;	    }	    /* Default, get real parent */	    node = node->parent;	} while (node);	return mem_start;}intprom_n_addr_cells(struct device_node* np){	int* ip;	do {		if (np->parent)			np = np->parent;		ip = (int *) get_property(np, "#address-cells", 0);		if (ip != NULL)			return *ip;	} while (np->parent);	/* No #address-cells property for the root node, default to 1 */	return 1;}intprom_n_size_cells(struct device_node* np){	int* ip;	do {		if (np->parent)			np = np->parent;		ip = (int *) get_property(np, "#size-cells", 0);		if (ip != NULL)			return *ip;	} while (np->parent);	/* No #size-cells property for the root node, default to 1 */	return 1;}static unsigned long __initinterpret_pci_props(struct device_node *np, unsigned long mem_start,		    int naddrc, int nsizec){	struct address_range *adr;	struct pci_reg_property *pci_addrs;	int i, l;	pci_addrs = (struct pci_reg_property *)		get_property(np, "assigned-addresses", &l);	if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct pci_reg_property)) >= 0) {			adr[i].space = pci_addrs[i].addr.a_hi;			adr[i].address = pci_addrs[i].addr.a_lo;			adr[i].size = pci_addrs[i].size_lo;			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	return mem_start;}static unsigned long __initinterpret_isa_props(struct device_node *np, unsigned long mem_start,		    int naddrc, int nsizec){	struct isa_reg_property *rp;	struct address_range *adr;	int i, l;	rp = (struct isa_reg_property *) get_property(np, "reg", &l);	if (rp != 0 && l >= sizeof(struct isa_reg_property)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct reg_property)) >= 0) {			adr[i].space = rp[i].space;			adr[i].address = rp[i].address				+ (adr[i].space? 0: _ISA_MEM_BASE);			adr[i].size = rp[i].size;			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	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;	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 = 0;			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);	}	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);	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;	

⌨️ 快捷键说明

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