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

prom.c

优龙2410linux2.6.8内核源代码
C
第 1 页 / 共 5 页
字号:
	__make_room(startp, endp, sizeof(type), __alignof__(type))static void __initinspect_node(phandle node, struct device_node *dad,	     unsigned long *mem_start, unsigned long *mem_end,	     struct device_node ***allnextpp){	int l;	phandle child;	struct device_node *np;	struct property *pp, **prev_propp;	char *prev_name, *namep;	unsigned char *valp;	unsigned long offset = reloc_offset();	phandle ibm_phandle;	np = make_room(mem_start, mem_end, struct device_node);	memset(np, 0, sizeof(*np));	np->node = node;	**allnextpp = PTRUNRELOC(np);	*allnextpp = &np->allnext;	if (dad != 0) {		np->parent = PTRUNRELOC(dad);		/* we temporarily use the `next' field as `last_child'. */		if (dad->next == 0)			dad->child = PTRUNRELOC(np);		else			dad->next->sibling = PTRUNRELOC(np);		dad->next = np;	}	/* get and store all properties */	prev_propp = &np->properties;	prev_name = RELOC("");	for (;;) {		/* 32 is max len of name including nul. */		namep = make_room(mem_start, mem_end, char[32]);		if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {			/* No more nodes: unwind alloc */			*mem_start = (unsigned long)namep;			break;		}		/* Trim off some if we can */		*mem_start = DOUBLEWORD_ALIGN((unsigned long)namep					     + strlen(namep) + 1);		pp = make_room(mem_start, mem_end, struct property);		pp->name = PTRUNRELOC(namep);		prev_name = namep;		pp->length = call_prom("getproplen", 2, 1, node, namep);		if (pp->length < 0)			continue;		if (pp->length > MAX_PROPERTY_LENGTH) {			char path[128];			prom_printf("WARNING: ignoring large property ");			/* It seems OF doesn't null-terminate the path :-( */			memset(path, 0, sizeof(path));			if (call_prom("package-to-path", 3, 1, node,				      path, sizeof(path)-1) > 0)				prom_printf("[%s] ", path);			prom_printf("%s length 0x%x\n", namep, pp->length);			continue;		}		valp = __make_room(mem_start, mem_end, pp->length, 1);		pp->value = PTRUNRELOC(valp);		call_prom("getprop", 4, 1, node, namep, valp, pp->length);		*prev_propp = PTRUNRELOC(pp);		prev_propp = &pp->next;	}	/* Add a "linux,phandle" property. */	namep = make_room(mem_start, mem_end, char[16]);	strcpy(namep, RELOC("linux,phandle"));	pp = make_room(mem_start, mem_end, struct property);	pp->name = PTRUNRELOC(namep);	pp->length = sizeof(phandle);	valp = make_room(mem_start, mem_end, phandle);	pp->value = PTRUNRELOC(valp);	*(phandle *)valp = node;	*prev_propp = PTRUNRELOC(pp);	pp->next = NULL;	/* Set np->linux_phandle to the value of the ibm,phandle property	   if it exists, otherwise to the phandle for this node. */	np->linux_phandle = node;	if (prom_getprop(node, "ibm,phandle",			 &ibm_phandle, sizeof(ibm_phandle)) > 0)		np->linux_phandle = ibm_phandle;	/* get the node's full name */	namep = (char *)*mem_start;	l = call_prom("package-to-path", 3, 1, node,		      namep, *mem_end - *mem_start);	if (l >= 0) {		/* Didn't fit?  Get more room. */		if (l+1 > *mem_end - *mem_start) {			namep = __make_room(mem_start, mem_end, l+1, 1);			call_prom("package-to-path", 3, 1, node, namep, l);		}		np->full_name = PTRUNRELOC(namep);		namep[l] = '\0';		*mem_start = DOUBLEWORD_ALIGN(*mem_start + l + 1);	}	/* do all our children */	child = call_prom("child", 1, 1, node);	while (child != (phandle)0) {		inspect_node(child, np, mem_start, mem_end,					 allnextpp);		child = call_prom("peer", 1, 1, child);	}}/* * Make a copy of the device tree from the PROM. */static unsigned long __initcopy_device_tree(unsigned long mem_start){	phandle root;	struct device_node **allnextp;	unsigned long offset = reloc_offset();	unsigned long mem_end;	/* We pass mem_end-mem_start to OF: keep it well under 32-bit */	mem_end = mem_start + 1024*1024*1024;#ifdef CONFIG_BLK_DEV_INITRD	if (RELOC(initrd_start) && RELOC(initrd_start) > mem_start)		mem_end = RELOC(initrd_start);#endif /* CONFIG_BLK_DEV_INITRD */	root = call_prom("peer", 1, 1, (phandle)0);	if (root == (phandle)0) {		prom_panic("couldn't get device tree root\n");	}	allnextp = &RELOC(allnodes);	inspect_node(root, NULL, &mem_start, &mem_end, &allnextp);	*allnextp = NULL;	return mem_start;}/* Verify bi_recs are good */static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs){	struct bi_record *first, *last;	prom_debug("birec_verify: r6=0x%x\n", (unsigned long)bi_recs);	if (bi_recs != NULL)		prom_debug("  tag=0x%x\n", bi_recs->tag);	if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )		return NULL;	last = (struct bi_record *)(long)bi_recs->data[0];	prom_debug("  last=0x%x\n", (unsigned long)last);	if (last != NULL)		prom_debug("  last_tag=0x%x\n", last->tag);	if ( last == NULL || last->tag != BI_LAST )		return NULL;	first = (struct bi_record *)(long)last->data[0];	prom_debug("  first=0x%x\n", (unsigned long)first);	if ( first == NULL || first != bi_recs )		return NULL;	return bi_recs;}static void __init prom_bi_rec_reserve(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	struct bi_record *rec;	if ( _prom->bi_recs != NULL) {		for ( rec=_prom->bi_recs;		      rec->tag != BI_LAST;		      rec=bi_rec_next(rec) ) {			prom_debug("bi: 0x%x\n", rec->tag);			switch (rec->tag) {#ifdef CONFIG_BLK_DEV_INITRD			case BI_INITRD:				RELOC(initrd_start) = (unsigned long)(rec->data[0]);				RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1];				break;#endif /* CONFIG_BLK_DEV_INITRD */			}		}		/* The next use of this field will be after relocation	 	 * is enabled, so convert this physical address into a	 	 * virtual address.	 	 */		_prom->bi_recs = PTRUNRELOC(_prom->bi_recs);	}}/* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. */unsigned long __initprom_init(unsigned long r3, unsigned long r4, unsigned long pp,	  unsigned long r6, unsigned long r7){	unsigned long mem;	ihandle prom_cpu;	phandle cpu_pkg;	unsigned long offset = reloc_offset();	long l;	char *p, *d;	unsigned long phys;	u32 getprop_rval;	struct systemcfg *_systemcfg;	struct paca_struct *lpaca = PTRRELOC(&paca[0]);	struct prom_t *_prom = PTRRELOC(&prom);	/* First zero the BSS -- use memset, some arches don't have	 * caches on yet */	memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);	/* Setup systemcfg and NACA pointers now */	RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset);	RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset);	/* Init interface to Open Firmware and pickup bi-recs */	prom_init_client_services(pp);	/* Init prom stdout device */	prom_init_stdout();	prom_debug("klimit=0x%x\n", RELOC(klimit));	prom_debug("offset=0x%x\n", offset);	prom_debug("->mem=0x%x\n", RELOC(klimit) - offset);	/* check out if we have bi_recs */	_prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);	if ( _prom->bi_recs != NULL ) {		RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +					   _prom->bi_recs->data[1]);		prom_debug("bi_recs=0x%x\n", (unsigned long)_prom->bi_recs);		prom_debug("new mem=0x%x\n", RELOC(klimit) - offset);	}	/* If we don't have birec's or didn't find them, check for an initrd	 * using the "yaboot" way	 */#ifdef CONFIG_BLK_DEV_INITRD	if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;		RELOC(initrd_end) = RELOC(initrd_start) + r4;		RELOC(initrd_below_start_ok) = 1;	}#endif /* CONFIG_BLK_DEV_INITRD */	/* Default machine type. */	_systemcfg->platform = prom_find_machine_type();	/* On pSeries, copy the CPU hold code */	if (_systemcfg->platform == PLATFORM_PSERIES)		copy_and_flush(0, KERNELBASE - offset, 0x100, 0);	/* Start storing things at klimit */	mem = RELOC(klimit) - offset;	/* Get the full OF pathname of the stdout device */	p = (char *) mem;	memset(p, 0, 256);	call_prom("instance-to-path", 3, 1, _prom->stdout, p, 255);	RELOC(of_stdout_device) = PTRUNRELOC(p);	mem += strlen(p) + 1;	getprop_rval = 1;	prom_getprop(_prom->root, "#size-cells",		     &getprop_rval, sizeof(getprop_rval));	_prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64;	/* Determine which cpu is actually running right _now_ */	if (prom_getprop(_prom->chosen, "cpu",			 &prom_cpu, sizeof(prom_cpu)) <= 0)		prom_panic("cannot find boot cpu");	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));	_prom->cpu = getprop_rval;	lpaca[0].hw_cpu_id = _prom->cpu;	RELOC(boot_cpuid) = 0;	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);	/* Get the boot device and translate it to a full OF pathname. */	p = (char *) mem;	l = prom_getprop(_prom->chosen, "bootpath", p, 1<<20);	if (l > 0) {		p[l] = 0;	/* should already be null-terminated */		RELOC(bootpath) = PTRUNRELOC(p);		mem += l + 1;		d = (char *) mem;		*d = 0;		call_prom("canon", 3, 1, p, d, 1<<20);		RELOC(bootdevice) = PTRUNRELOC(d);		mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);	}	RELOC(cmd_line[0]) = 0;	if ((long)_prom->chosen > 0) {		prom_getprop(_prom->chosen, "bootargs", p, sizeof(cmd_line));		if (p != NULL && p[0] != 0)			strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));	}	early_cmdline_parse();	prom_initialize_lmb();	prom_bi_rec_reserve();	mem = check_display(mem);	if (_systemcfg->platform != PLATFORM_POWERMAC)		prom_instantiate_rtas();	/* Initialize some system info into the Naca early... */	prom_initialize_naca();	smt_setup();	/* If we are on an SMP machine, then we *MUST* do the	 * following, regardless of whether we have an SMP	 * kernel or not.	 */	prom_hold_cpus(mem);	prom_debug("after basic inits, mem=0x%x\n", mem);#ifdef CONFIG_BLK_DEV_INITRD	prom_debug("initrd_start=0x%x\n", RELOC(initrd_start));	prom_debug("initrd_end=0x%x\n", RELOC(initrd_end));#endif /* CONFIG_BLK_DEV_INITRD */	prom_debug("copying OF device tree...\n");	mem = copy_device_tree(mem);	RELOC(klimit) = mem + offset;	prom_debug("new klimit is\n");	prom_debug("klimit=0x%x\n", RELOC(klimit));	prom_debug(" ->mem=0x%x\n", mem);	lmb_reserve(0, __pa(RELOC(klimit)));#ifdef CONFIG_BLK_DEV_INITRD	if (RELOC(initrd_start)) {		unsigned long initrd_len;		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);		/* Move initrd if it's where we're going to copy kernel. */		if (RELOC(initrd_start) < __pa(RELOC(klimit))) {			memmove((void *)mem, (void *)RELOC(initrd_start),				initrd_len);			RELOC(initrd_start) = mem;			RELOC(initrd_end) = mem + initrd_len;		}		lmb_reserve(RELOC(initrd_start), initrd_len);	}#endif /* CONFIG_BLK_DEV_INITRD */	if (_systemcfg->platform == PLATFORM_PSERIES)		prom_initialize_tce_table();#ifdef CONFIG_PMAC_DART	if (_systemcfg->platform == PLATFORM_POWERMAC)		prom_initialize_dart_table();#endif#ifdef CONFIG_BOOTX_TEXT	if (_prom->disp_node) {		prom_printf("Setting up bi display...\n");		setup_disp_fake_bi(_prom->disp_node);	}#endif /* CONFIG_BOOTX_TEXT */	prom_printf("Calling quiesce ...\n");	call_prom("quiesce", 0, 0);	phys = KERNELBASE - offset;#ifdef CONFIG_BLK_DEV_INITRD	/* If we had an initrd, we convert its address to virtual */	if (RELOC(initrd_start)) {		RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));		RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));	}#endif /* CONFIG_BLK_DEV_INITRD */	prom_printf("returning from prom_init\n");	return phys;}/* * Find the device_node with a given phandle. */static struct device_node * __devinitfind_phandle(phandle ph){	struct device_node *np;	for (np = allnodes; np != 0; np = np->allnext)		if (np->linux_phandle == ph)			return np;	return NULL;}/* * Find the interrupt parent of a node. */static struct device_node * __devinitintr_parent(struct device_node *p){	phandle *parp;	parp = (phandle *) get_property(p, "interrupt-parent", NULL);	if (parp == NULL)		return p->parent;	return find_phandle(*parp);}/* * Find out the size of each entry of the interrupts property * for a node. */int __devinit prom_n_intr_cells(struct device_node *np){	struct device_node *p;	unsigned int *icp;	for (p = np; (p = intr_parent(p)) != NULL; ) {		icp = (unsigned int *)			get_property(p, "#interrupt-cells", NULL);		if (icp != NULL)			return *icp;		if (get_property(p, "interrupt-controller", NULL) != NULL		    || get_property(p, "interrupt-map", NULL) != NULL) {			printk("oops, node %s doesn't have #interrupt-cells\n",			       p->full_name);			return 1;		}	}#ifdef DEBUG_IRQ	printk("prom_n_intr_cells failed for %s\n", np->full_name);#endif	return 1;}/* * Map an interrupt from a device up to the platform interrupt * descriptor. */static int __devinitmap_interrupt(unsigned int **irq, struct device_node **ictrler,	      struct device_node *np, unsigned int *ints, int nintrc){	struct device_node *p, *ipar;	unsigned int *imap, *imask, *ip;	int i, imaplen, match;	int newintrc, newaddrc;	unsigned int *reg;	int naddrc;	reg = (unsigned int *) get_property(np, "reg", NULL);	naddrc = prom_n_addr_cells(np);	p = intr_parent(np);	while (p != NULL) {		if (get_property(p, "interrupt-controller", NULL) != NULL)			/* this node is an interrupt controller, stop here */			break;

⌨️ 快捷键说明

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