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

📄 prom.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Carve out storage for the TCE table. */		base = lmb_alloc(minsize, align);		if ( !base ) {			prom_print(RELOC("ERROR, cannot find space for TCE table.\n"));			prom_exit();		}		vbase = absolute_to_virt(base);		/* Save away the TCE table attributes for later use. */		prom_tce_table[table].node = node;		prom_tce_table[table].base = vbase;		prom_tce_table[table].size = minsize;#ifdef DEBUG_PROM		prom_print(RELOC("TCE table: 0x"));		prom_print_hex(table);		prom_print_nl();		prom_print(RELOC("\tnode = 0x"));		prom_print_hex(node);		prom_print_nl();		prom_print(RELOC("\tbase = 0x"));		prom_print_hex(vbase);		prom_print_nl();		prom_print(RELOC("\tsize = 0x"));		prom_print_hex(minsize);		prom_print_nl();#endif		/* Initialize the table to have a one-to-one mapping		 * over the allocated size.		 */		tce_entryp = (unsigned long *)base;		for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {			tce_entry = (i << PAGE_SHIFT);			tce_entry |= 0x3;			*tce_entryp = tce_entry;		}		/* Call OF to setup the TCE hardware */		if (call_prom(RELOC("package-to-path"), 3, 1, node,                             path, 255) <= 0) {                        prom_print(RELOC("package-to-path failed\n"));                } else {                        prom_print(RELOC("opened "));                        prom_print(path);                        prom_print_nl();                }                phb_node = (ihandle)call_prom(RELOC("open"), 1, 1, path);                if ( (long)phb_node <= 0) {                        prom_print(RELOC("open failed\n"));                } else {                        prom_print(RELOC("open success\n"));                }                call_prom(RELOC("call-method"), 6, 0,                             RELOC("set-64-bit-addressing"),			     phb_node,			     -1,                             minsize,                              base & 0xffffffff,                             (base >> 32) & 0xffffffff);                call_prom(RELOC("close"), 1, 0, phb_node);		table++;	}	/* Flag the first invalid entry */	prom_tce_table[table].node = 0;#ifdef DEBUG_PROM	prom_print(RELOC("ending prom_initialize_tce_table\n"));#endif}/* * 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 voidprom_hold_cpus(unsigned long mem){	unsigned long i;	unsigned int reg;	phandle node;	unsigned long offset = reloc_offset();	char type[64], *path;	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     = __v2a(&__secondary_hold_spinloop);        unsigned long *acknowledge  = __v2a(&__secondary_hold_acknowledge);        unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));        struct naca_struct *_naca = RELOC(naca);        struct systemcfg *_systemcfg = RELOC(systemcfg);	struct paca_struct *_xPaca = PTRRELOC(&paca[0]);	struct prom_t *_prom = PTRRELOC(&prom);	/* Initially, we must have one active CPU. */	_systemcfg->processorCount = 1;#ifdef DEBUG_PROM	prom_print(RELOC("prom_hold_cpus: start...\n"));	prom_print(RELOC("    1) spinloop       = 0x"));	prom_print_hex(spinloop);	prom_print_nl();	prom_print(RELOC("    1) *spinloop      = 0x"));	prom_print_hex(*spinloop);	prom_print_nl();	prom_print(RELOC("    1) acknowledge    = 0x"));	prom_print_hex(acknowledge);	prom_print_nl();	prom_print(RELOC("    1) *acknowledge   = 0x"));	prom_print_hex(*acknowledge);	prom_print_nl();	prom_print(RELOC("    1) secondary_hold = 0x"));	prom_print_hex(secondary_hold);	prom_print_nl();#endif        /* 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;		call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),			  type, sizeof(type));		if (strcmp(type, RELOC("cpu")) != 0)			continue;		/* Skip non-configured cpus. */		call_prom(RELOC("getprop"), 4, 1, node, RELOC("status"),			  type, sizeof(type));		if (strcmp(type, RELOC("okay")) != 0)			continue;                reg = -1;		call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),			  &reg, sizeof(reg));		path = (char *) mem;		memset(path, 0, 256);		if ((long) call_prom(RELOC("package-to-path"), 3, 1,				     node, path, 255) < 0)			continue;#ifdef DEBUG_PROM		prom_print_nl();		prom_print(RELOC("cpuid        = 0x"));		prom_print_hex(cpuid);		prom_print_nl();		prom_print(RELOC("cpu hw idx   = 0x"));		prom_print_hex(reg);		prom_print_nl();#endif		_xPaca[cpuid].xHwProcNum = 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 = call_prom(RELOC("getprop"), 4, 1, node,				     RELOC("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_print(RELOC("SMT: too many threads!\nSMT: found "));				prom_print_hex(cpu_threads);				prom_print(RELOC(", max is "));				prom_print_hex(MAX_CPU_THREADS);				prom_print_nl();				cpu_threads = 1; /* ToDo: panic? */			}		}		hw_cpu_num = interrupt_server[0];		if (hw_cpu_num != _prom->cpu) {			/* Primary Thread of non-boot cpu */			prom_print_hex(cpuid);			prom_print(RELOC(" : starting cpu "));			prom_print(path);			prom_print(RELOC(" ... "));			call_prom(RELOC("start-cpu"), 3, 0, node,				  secondary_hold, cpuid);			for(i = 0; (i < 100000000) &&			  (*acknowledge == ((unsigned long)-1)); i++ );			if (*acknowledge == cpuid) {				prom_print(RELOC("ok\n"));				/* Set the number of active processors. */				_systemcfg->processorCount++;				_xPaca[cpuid].active = 1;				_xPaca[cpuid].available = 1;			} else {				prom_print(RELOC("failed: "));				prom_print_hex(*acknowledge);				prom_print_nl();				/* prom_panic(RELOC("cpu failed to start")); */			}		} else {			prom_print_hex(cpuid);			prom_print(RELOC(" : booting  cpu "));			prom_print(path);			prom_print_nl();		}		/* Init paca for secondary threads.   They start later. */		for (i=1; i < cpu_threads; i++) {			cpuid++;			_xPaca[cpuid].xHwProcNum = interrupt_server[i];			prom_print_hex(interrupt_server[i]);			prom_print(RELOC(" : preparing thread ... "));			if (_naca->smt_state) {				_xPaca[cpuid].available = 1;				prom_print(RELOC("available"));			} else {				prom_print(RELOC("not available"));			}			prom_print_nl();		}		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_print(RELOC("    starting secondary threads\n"));		for (i=0; i < _systemcfg->processorCount ;i++) {			unsigned long threadid = _systemcfg->processorCount*2-1-i;						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;				}			}						RELOC(hmt_thread_data)[i].threadid = threadid;#ifdef DEBUG_PROM			prom_print(RELOC("        cpuid 0x"));			prom_print_hex(i);			prom_print(RELOC(" maps to threadid 0x"));			prom_print_hex(threadid);			prom_print_nl();			prom_print(RELOC(" pir 0x"));			prom_print_hex(RELOC(hmt_thread_data)[i].pir);			prom_print_nl();#endif			_xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1;		}		_systemcfg->processorCount *= 2;	} else {		prom_print(RELOC("Processor is not HMT capable\n"));	}#endif	#ifdef DEBUG_PROM	prom_print(RELOC("prom_hold_cpus: end...\n"));#endif}static voidsmt_setup(void){	char *p, *q;	char my_smt_enabled = SMT_DYNAMIC;	unsigned long my_smt_snooze_delay;	ihandle prom_options = NULL;	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 = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));		if (prom_options != (ihandle) -1) {			call_prom(RELOC("getprop"),				4, 1, prom_options,				RELOC("ibm,smt-enabled"),				option, sizeof(option));			if (option[0] != 0) {				found = 1;				if (!strcmp(option, "off"))					my_smt_enabled = SMT_OFF;				else if (!strcmp(option, "on"))					my_smt_enabled = SMT_ON;				else					my_smt_enabled = SMT_DYNAMIC;			}		}	}	if (!found )		my_smt_enabled = SMT_DYNAMIC; /* default to on */	found = 0;	if (my_smt_enabled) {		if (strstr(RELOC(cmd_line), RELOC("smt-snooze-delay="))) {			for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-snooze-delay="))) != 0; ) {				q = p + 17;				if (p > RELOC(cmd_line) && p[-1] != ' ')					continue;				found = 1;				/* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */				my_smt_snooze_delay = 0;				while (*q >= '0' && *q <= '9') {					my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';					q++;				}			}		}		if (!found) {			prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));			if (prom_options != (ihandle) -1) {				call_prom(RELOC("getprop"),					4, 1, prom_options,					RELOC("ibm,smt-snooze-delay"),					option, sizeof(option));				if (option[0] != 0) {					found = 1;					/* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */					my_smt_snooze_delay = 0;					q = option;					while (*q >= '0' && *q <= '9') {						my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';						q++;					}				}			}		}		if (!found) {			my_smt_snooze_delay = 30000; /* default value */		}	} else {		my_smt_snooze_delay = 0; /* default value */	}	_naca->smt_snooze_delay = my_smt_snooze_delay;	_naca->smt_state = my_smt_enabled;}#ifdef CONFIG_PPCDBGextern char *trace_names[];	/* defined in udbg.c -- need a better interface */void parse_ppcdbg_optionlist(const char *cmd,				    const char *cmdend){	unsigned long offset = reloc_offset();	char **_trace_names = PTRRELOC(&trace_names[0]);	const char *all = RELOC("all");        struct naca_struct *_naca = RELOC(naca);	const char *p, *pend;	int onoff, i, cmdidx;	unsigned long mask;	char cmdbuf[30];	for (p = cmd, pend = strchr(p, ',');	     p < cmdend;	     pend = strchr(p, ',')) {		if (pend == NULL || pend > cmdend)			pend = cmdend;		onoff = 1;	/* default */		if (*p == '+' || *p == '-') {			/* explicit on or off */			onoff = (*p == '+');			p++;		}		/* parse out p..pend here */		if (pend - p < sizeof(cmdbuf)) {			strncpy(cmdbuf, p, pend - p);			cmdbuf[pend - p] = '\0';			for (cmdidx = -1, i = 0; i < PPCDBG_NUM_FLAGS; i++) {				if (_trace_names[i] &&				    (strcmp(PTRRELOC(_trace_names[i]), cmdbuf) == 0)) {					cmdidx = i;					break;				}			}			mask = 0;			if (cmdidx >= 0) {				mask = (1 << cmdidx);			} else if (strcmp(cmdbuf, all) == 0) {				mask = PPCDBG_ALL;			} else {				prom_print(RELOC("ppcdbg: unknown debug: "));				prom_print(cmdbuf);				prom_print_nl();			}			if (mask) {				if (onoff)					_naca->debug_switch |= mask;				else					_naca->debug_switch &= ~mask;			}		}		p = pend+1;	}}/* * Parse ppcdbg= cmdline option. * * Option names are listed in <asm/ppcdebug.h> in the trace_names * table.  Multiple names may be listed separated by commas (no whitespace),

⌨️ 快捷键说明

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