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

prom.c

优龙2410linux2.6.8内核源代码
C
第 1 页 / 共 5 页
字号:
	/* 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));		path = (char *) mem;		memset(path, 0, 256);		if (call_prom("package-to-path", 3, 1,			      node, path, 255) == PROM_ERROR)			continue;		prom_debug("\ncpuid        = 0x%x\n", cpuid);		prom_debug("cpu hw idx   = 0x%x\n", reg);		lpaca[cpuid].hw_cpu_id = 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 %s... ", cpuid, path);			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;#ifdef CONFIG_SMP				/* Set the number of active processors. */				_systemcfg->processorCount++;				cpu_set(cpuid, RELOC(cpu_available_map));				cpu_set(cpuid, RELOC(cpu_possible_map));				cpu_set(cpuid, RELOC(cpu_present_at_boot));#endif			} else {				prom_printf("... failed: %x\n", *acknowledge);			}		}#ifdef CONFIG_SMP		else {			prom_printf("%x : booting  cpu %s\n", cpuid, path);			cpu_set(cpuid, RELOC(cpu_available_map));			cpu_set(cpuid, RELOC(cpu_possible_map));			cpu_set(cpuid, RELOC(cpu_online_map));			cpu_set(cpuid, RELOC(cpu_present_at_boot));		}#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;			lpaca[cpuid].hw_cpu_id = interrupt_server[i];			prom_printf("%x : preparing thread ... ",				    interrupt_server[i]);			if (_naca->smt_state) {				cpu_set(cpuid, RELOC(cpu_available_map));				cpu_set(cpuid, RELOC(cpu_present_at_boot));				prom_printf("available\n");			} else {				prom_printf("not available\n");			}		}#endif		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 = _get_PIR();				if (__is_processor(PV_PULSAR)) {					RELOC(hmt_thread_data)[i].pir = 						pir & 0x1f;				} else {					RELOC(hmt_thread_data)[i].pir = 						pir & 0x3ff;				}			}/* 			cpu_set(i+1, cpu_online_map); */			cpu_set(i+1, RELOC(cpu_possible_map));		}		_systemcfg->processorCount *= 2;	} 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 smt_setup(void){	char *p, *q;	char my_smt_enabled = SMT_DYNAMIC;	ihandle prom_options = 0;	char option[9];	unsigned long offset = reloc_offset();	struct naca_struct *_naca = RELOC(naca);	char found = 0;	if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {		for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {			q = p + 12;			if (p > RELOC(cmd_line) && p[-1] != ' ')				continue;			found = 1;			if (q[0] == 'o' && q[1] == 'f' && 			    q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {				my_smt_enabled = SMT_OFF;			} else if (q[0]=='o' && q[1] == 'n' && 				   (q[2] == ' ' || q[2] == '\0')) {				my_smt_enabled = SMT_ON;			} else {				my_smt_enabled = SMT_DYNAMIC;			} 		}	}	if (!found) {		prom_options = call_prom("finddevice", 1, 1, ADDR("/options"));		if (prom_options != (ihandle) -1) {			prom_getprop(prom_options, "ibm,smt-enabled",				     option, sizeof(option));			if (option[0] != 0) {				found = 1;				if (!strcmp(option, RELOC("off")))					my_smt_enabled = SMT_OFF;				else if (!strcmp(option, RELOC("on")))					my_smt_enabled = SMT_ON;				else					my_smt_enabled = SMT_DYNAMIC;			}		}	}	if (!found )		my_smt_enabled = SMT_DYNAMIC; /* default to on */	_naca->smt_state = my_smt_enabled;}#ifdef CONFIG_BOOTX_TEXT/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */static void __init setup_disp_fake_bi(ihandle dp){	int width = 640, height = 480, depth = 8, pitch;	unsigned address;	struct pci_reg_property addrs[8];	int i, naddrs;	char name[64];	unsigned long offset = reloc_offset();	memset(name, 0, sizeof(name));	prom_getprop(dp, "name", name, sizeof(name));	name[sizeof(name)-1] = 0;	prom_printf("Initializing fake screen: %s\n", name);	prom_getprop(dp, "width", &width, sizeof(width));	prom_getprop(dp, "height", &height, sizeof(height));	prom_getprop(dp, "depth", &depth, sizeof(depth));	pitch = width * ((depth + 7) / 8);	prom_getprop(dp, "linebytes", &pitch, sizeof(pitch));	if (pitch == 1)		pitch = 0x1000;		/* for strange IBM display */	address = 0;	prom_printf("width %x height %x depth %x linebytes %x\n",		    width, height, depth, depth);	prom_getprop(dp, "address", &address, sizeof(address));	if (address == 0) {		/* look for an assigned address with a size of >= 1MB */		naddrs = prom_getprop(dp, "assigned-addresses",				      addrs, sizeof(addrs));		naddrs /= sizeof(struct pci_reg_property);		for (i = 0; i < naddrs; ++i) {			if (addrs[i].size_lo >= (1 << 20)) {				address = addrs[i].addr.a_lo;				/* use the BE aperture if possible */				if (addrs[i].size_lo >= (16 << 20))					address += (8 << 20);				break;			}		}		if (address == 0) {			prom_printf("Failed to get address of frame buffer\n");			return;		}	}	btext_setup_display(width, height, depth, pitch, address);	prom_printf("Addr of fb: %x\n", address);	RELOC(boot_text_mapped) = 0;}#endif /* CONFIG_BOOTX_TEXT */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->encode_phys_size = 32;	/* 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);	u32 val;	if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)		prom_panic("cannot find stdout");	_prom->stdout = val;}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;	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 */	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 check_display(unsigned long mem){	phandle node;	ihandle ih;	int i, j;	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	char type[16], *path;	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->disp_node = 0;	prom_printf("Looking for displays\n");	if (RELOC(of_stdout_device) != 0)		prom_printf("OF stdout is    : %s\n",			    PTRRELOC(RELOC(of_stdout_device)));	for (node = 0; prom_next_node(&node); ) {		type[0] = 0;		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 = (char *) mem;		memset(path, 0, 256);		/*		 * leave some room at the end of the path for appending extra		 * arguments		 */		if (call_prom("package-to-path", 3, 1, node, path, 250) < 0)			continue;		prom_printf("found display   : %s\n", path);				/*		 * If this display is the device that OF is using for stdout,		 * move it to the front of the list.		 */		mem += strlen(path) + 1;		i = RELOC(prom_num_displays);		RELOC(prom_num_displays) = i + 1;		if (RELOC(of_stdout_device) != 0 && i > 0		    && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {			for (; i > 0; --i) {				RELOC(prom_display_paths[i])					= RELOC(prom_display_paths[i-1]);				RELOC(prom_display_nodes[i])					= RELOC(prom_display_nodes[i-1]);			}			_prom->disp_node = node;		}		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);		RELOC(prom_display_nodes[i]) = node;		if (_prom->disp_node == 0)			_prom->disp_node = node;		if (RELOC(prom_num_displays) >= FB_MAX)			break;	}	prom_printf("Opening displays...\n");	for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) {		path = PTRRELOC(RELOC(prom_display_paths[j]));		prom_printf("opening display : %s", path);		ih = call_prom("open", 1, 1, path);		if (ih == (ihandle)0 || ih == (ihandle)-1) {			prom_printf("... failed\n");			continue;		}		prom_printf("... done\n");		/* 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 DOUBLEWORD_ALIGN(mem);}/* 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){	void *ret;	*mem_start = ALIGN(*mem_start, align);	if (*mem_start + needed > *mem_end) {#ifdef CONFIG_BLK_DEV_INITRD		unsigned long offset = reloc_offset();		/* FIXME: Apple OF doesn't map unclaimed mem.  If this		 * ever happened on G5, we'd need to fix. */		unsigned long initrd_len;		if (*mem_end != RELOC(initrd_start))			prom_panic("No memory for copy_device_tree");		prom_printf("Huge device_tree: moving initrd\n");		/* Move by 4M. */		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);		*mem_end = RELOC(initrd_start) + 4 * 1024 * 1024;		memmove((void *)*mem_end, (void *)RELOC(initrd_start),			initrd_len);		RELOC(initrd_start) = *mem_end;		RELOC(initrd_end) = RELOC(initrd_start) + initrd_len;#else		prom_panic("No memory for copy_device_tree");#endif	}	ret = (void *)*mem_start;	*mem_start += needed;	return ret;}#define make_room(startp, endp, type) \

⌨️ 快捷键说明

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