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

prom_init.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
		for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {			tce_entry = (i << PAGE_SHIFT);			tce_entry |= 0x3;			*tce_entryp = tce_entry;		}		prom_printf("opening PHB %s", path);		phb_node = call_prom("open", 1, 1, path);		if ( (long)phb_node <= 0)			prom_printf("... failed\n");		else			prom_printf("... done\n");		call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),			  phb_node, -1, minsize,			  (u32) base, (u32) (base >> 32));		call_prom("close", 1, 0, phb_node);	}	reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);	/* Flag the first invalid entry */	prom_debug("ending prom_initialize_tce_table\n");}/* * With CHRP SMP we need to use the OF to start the other * processors so we can't wait until smp_boot_cpus (the OF is * trashed by then) so we have to put the processors into * a holding pattern controlled by the kernel (not OF) before * we destroy the OF. * * This uses a chunk of low memory, puts some holding pattern * code there and sends the other processors off to there until * smp_boot_cpus tells them to do something.  The holding pattern * checks that address until its cpu # is there, when it is that * cpu jumps to __secondary_start().  smp_boot_cpus() takes care * of setting those values. * * We also use physical address 0x4 here to tell when a cpu * is in its holding pattern code. * * Fixup comment... DRENG / PPPBBB - Peter * * -- Cort */static void __init prom_hold_cpus(void){	unsigned long i;	unsigned int reg;	phandle node;	unsigned long offset = reloc_offset();	char type[64];	int cpuid = 0;	unsigned int interrupt_server[MAX_CPU_THREADS];	unsigned int cpu_threads, hw_cpu_num;	int propsize;	extern void __secondary_hold(void);	extern unsigned long __secondary_hold_spinloop;	extern unsigned long __secondary_hold_acknowledge;	unsigned long *spinloop		= (void *)virt_to_abs(&__secondary_hold_spinloop);	unsigned long *acknowledge		= (void *)virt_to_abs(&__secondary_hold_acknowledge);	unsigned long secondary_hold		= virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));	struct prom_t *_prom = PTRRELOC(&prom);	prom_debug("prom_hold_cpus: start...\n");	prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);	prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);	prom_debug("    1) acknowledge    = 0x%x\n",		   (unsigned long)acknowledge);	prom_debug("    1) *acknowledge   = 0x%x\n", *acknowledge);	prom_debug("    1) secondary_hold = 0x%x\n", secondary_hold);	/* Set the common spinloop variable, so all of the secondary cpus	 * will block when they are awakened from their OF spinloop.	 * This must occur for both SMP and non SMP kernels, since OF will	 * be trashed when we move the kernel.	 */	*spinloop = 0;#ifdef CONFIG_HMT	for (i=0; i < NR_CPUS; i++) {		RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;	}#endif	/* look for cpus */	for (node = 0; prom_next_node(&node); ) {		type[0] = 0;		prom_getprop(node, "device_type", type, sizeof(type));		if (strcmp(type, RELOC("cpu")) != 0)			continue;		/* Skip non-configured cpus. */		prom_getprop(node, "status", type, sizeof(type));		if (strcmp(type, RELOC("okay")) != 0)			continue;		reg = -1;		prom_getprop(node, "reg", &reg, sizeof(reg));		prom_debug("\ncpuid        = 0x%x\n", cpuid);		prom_debug("cpu hw idx   = 0x%x\n", reg);		/* Init the acknowledge var which will be reset by		 * the secondary cpu when it awakens from its OF		 * spinloop.		 */		*acknowledge = (unsigned long)-1;		propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",					&interrupt_server,					sizeof(interrupt_server));		if (propsize < 0) {			/* no property.  old hardware has no SMT */			cpu_threads = 1;			interrupt_server[0] = reg; /* fake it with phys id */		} else {			/* We have a threaded processor */			cpu_threads = propsize / sizeof(u32);			if (cpu_threads > MAX_CPU_THREADS) {				prom_printf("SMT: too many threads!\n"					    "SMT: found %x, max is %x\n",					    cpu_threads, MAX_CPU_THREADS);				cpu_threads = 1; /* ToDo: panic? */			}		}		hw_cpu_num = interrupt_server[0];		if (hw_cpu_num != _prom->cpu) {			/* Primary Thread of non-boot cpu */			prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);			call_prom("start-cpu", 3, 0, node,				  secondary_hold, cpuid);			for ( i = 0 ; (i < 100000000) && 			      (*acknowledge == ((unsigned long)-1)); i++ ) ;			if (*acknowledge == cpuid) {				prom_printf("done\n");				/* We have to get every CPU out of OF,				 * even if we never start it. */				if (cpuid >= NR_CPUS)					goto next;			} else {				prom_printf("failed: %x\n", *acknowledge);			}		}#ifdef CONFIG_SMP		else			prom_printf("%x : boot cpu     %x\n", cpuid, reg);#endifnext:#ifdef CONFIG_SMP		/* Init paca for secondary threads.   They start later. */		for (i=1; i < cpu_threads; i++) {			cpuid++;			if (cpuid >= NR_CPUS)				continue;		}#endif /* CONFIG_SMP */		cpuid++;	}#ifdef CONFIG_HMT	/* Only enable HMT on processors that provide support. */	if (__is_processor(PV_PULSAR) || 	    __is_processor(PV_ICESTAR) ||	    __is_processor(PV_SSTAR)) {		prom_printf("    starting secondary threads\n");		for (i = 0; i < NR_CPUS; i += 2) {			if (!cpu_online(i))				continue;			if (i == 0) {				unsigned long pir = mfspr(SPRN_PIR);				if (__is_processor(PV_PULSAR)) {					RELOC(hmt_thread_data)[i].pir = 						pir & 0x1f;				} else {					RELOC(hmt_thread_data)[i].pir = 						pir & 0x3ff;				}			}		}	} else {		prom_printf("Processor is not HMT capable\n");	}#endif	if (cpuid > NR_CPUS)		prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)			    ") exceeded: ignoring extras\n");	prom_debug("prom_hold_cpus: end...\n");}static void __init prom_init_client_services(unsigned long pp){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	/* Get a handle to the prom entry point before anything else */	_prom->entry = pp;	/* Init default value for phys size */	_prom->root_size_cells = 1;	_prom->root_addr_cells = 2;	/* get a handle for the stdout device */	_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));	if ((long)_prom->chosen <= 0)		prom_panic("cannot find chosen"); /* msg won't be printed :( */	/* get device tree root */	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));	if ((long)_prom->root <= 0)		prom_panic("cannot find device tree root"); /* msg won't be printed :( */}static void __init prom_init_stdout(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	char *path = RELOC(of_stdout_device);	char type[16];	u32 val;	if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)		prom_panic("cannot find stdout");	_prom->stdout = val;	/* Get the full OF pathname of the stdout device */	memset(path, 0, 256);	call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);	val = call_prom("instance-to-package", 1, 1, _prom->stdout);	prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));	prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));	prom_setprop(_prom->chosen, "linux,stdout-path",		     RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);	/* If it's a display, note it */	memset(type, 0, sizeof(type));	prom_getprop(val, "device_type", type, sizeof(type));	if (strcmp(type, RELOC("display")) == 0) {		_prom->disp_node = val;		prom_setprop(val, "linux,boot-display", NULL, 0);	}}static int __init prom_find_machine_type(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	char compat[256];	int len, i = 0;	phandle rtas;	len = prom_getprop(_prom->root, "compatible",			   compat, sizeof(compat)-1);	if (len > 0) {		compat[len] = 0;		while (i < len) {			char *p = &compat[i];			int sl = strlen(p);			if (sl == 0)				break;			if (strstr(p, RELOC("Power Macintosh")) ||			    strstr(p, RELOC("MacRISC4")))				return PLATFORM_POWERMAC;			i += sl + 1;		}	}	/* Default to pSeries. We need to know if we are running LPAR */	rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));	if (rtas != (phandle) -1) {		unsigned long x;		x = prom_getproplen(rtas, "ibm,hypertas-functions");		if (x != PROM_ERROR) {			prom_printf("Hypertas detected, assuming LPAR !\n");			return PLATFORM_PSERIES_LPAR;		}	}	return PLATFORM_PSERIES;}static int __init prom_set_color(ihandle ih, int i, int r, int g, int b){	unsigned long offset = reloc_offset();	return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);}/* * If we have a display that we don't know how to drive, * we will want to try to execute OF's open method for it * later.  However, OF will probably fall over if we do that * we've taken over the MMU. * So we check whether we will need to open the display, * and if so, open it now. */static unsigned long __init prom_check_displays(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	char type[16], *path;	phandle node;	ihandle ih;	int i;	static unsigned char default_colors[] = {		0x00, 0x00, 0x00,		0x00, 0x00, 0xaa,		0x00, 0xaa, 0x00,		0x00, 0xaa, 0xaa,		0xaa, 0x00, 0x00,		0xaa, 0x00, 0xaa,		0xaa, 0xaa, 0x00,		0xaa, 0xaa, 0xaa,		0x55, 0x55, 0x55,		0x55, 0x55, 0xff,		0x55, 0xff, 0x55,		0x55, 0xff, 0xff,		0xff, 0x55, 0x55,		0xff, 0x55, 0xff,		0xff, 0xff, 0x55,		0xff, 0xff, 0xff	};	const unsigned char *clut;	prom_printf("Looking for displays\n");	for (node = 0; prom_next_node(&node); ) {		memset(type, 0, sizeof(type));		prom_getprop(node, "device_type", type, sizeof(type));		if (strcmp(type, RELOC("display")) != 0)			continue;		/* It seems OF doesn't null-terminate the path :-( */		path = RELOC(prom_scratch);		memset(path, 0, PROM_SCRATCH_SIZE);		/*		 * leave some room at the end of the path for appending extra		 * arguments		 */		if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)			continue;		prom_printf("found display   : %s, opening ... ", path);				ih = call_prom("open", 1, 1, path);		if (ih == (ihandle)0 || ih == (ihandle)-1) {			prom_printf("failed\n");			continue;		}		/* Success */		prom_printf("done\n");		prom_setprop(node, "linux,opened", NULL, 0);		/*		 * stdout wasn't a display node, pick the first we can find		 * for btext		 */		if (_prom->disp_node == 0)			_prom->disp_node = node;		/* Setup a useable color table when the appropriate		 * method is available. Should update this to set-colors */		clut = RELOC(default_colors);		for (i = 0; i < 32; i++, clut += 3)			if (prom_set_color(ih, i, clut[0], clut[1],					   clut[2]) != 0)				break;#ifdef CONFIG_LOGO_LINUX_CLUT224		clut = PTRRELOC(RELOC(logo_linux_clut224.clut));		for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)			if (prom_set_color(ih, i + 32, clut[0], clut[1],					   clut[2]) != 0)				break;#endif /* CONFIG_LOGO_LINUX_CLUT224 */	}}/* Return (relocated) pointer to this much memory: moves initrd if reqd. */static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,			      unsigned long needed, unsigned long align){	unsigned long offset = reloc_offset();	void *ret;	*mem_start = _ALIGN(*mem_start, align);	while ((*mem_start + needed) > *mem_end) {		unsigned long room, chunk;		prom_debug("Chunk exhausted, claiming more at %x...\n",			   RELOC(alloc_bottom));		room = RELOC(alloc_top) - RELOC(alloc_bottom);		if (room > DEVTREE_CHUNK_SIZE)			room = DEVTREE_CHUNK_SIZE;		if (room < PAGE_SIZE)			prom_panic("No memory for flatten_device_tree (no room)");		chunk = alloc_up(room, 0);		if (chunk == 0)			prom_panic("No memory for flatten_device_tree (claim failed)");		*mem_end = RELOC(alloc_top);	}	ret = (void *)*mem_start;	*mem_start += needed;	return ret;}#define dt_push_token(token, mem_start, mem_end) \	do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)static unsigned long __init dt_find_string(char *str){	unsigned long offset = reloc_offset();	char *s, *os;	s = os = (char *)RELOC(dt_string_start);	s += 4;

⌨️ 快捷键说明

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