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

prom.c

优龙2410linux2.6.8内核源代码
C
第 1 页 / 共 5 页
字号:
		pteg_count = (rnd_mem_size >> (12 + 1));		_naca->pftSize = __ilog2(pteg_count << 7);	}	if (_naca->pftSize == 0) {		prom_printf("prom: failed to compute pftSize!\n");		PROM_BUG();	}	/* Add an eye catcher and the systemcfg layout version number */	strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));	_systemcfg->version.major = SYSTEMCFG_MAJOR;	_systemcfg->version.minor = SYSTEMCFG_MINOR;	_systemcfg->processor = _get_PVR();	prom_debug("systemcfg->processorCount       = 0x%x\n",		   _systemcfg->processorCount);	prom_debug("systemcfg->physicalMemorySize   = 0x%x\n",		   _systemcfg->physicalMemorySize);	prom_debug("naca->pftSize                   = 0x%x\n",		   _naca->pftSize);	prom_debug("systemcfg->dCacheL1LineSize     = 0x%x\n",		   _systemcfg->dCacheL1LineSize);	prom_debug("systemcfg->iCacheL1LineSize     = 0x%x\n",		   _systemcfg->iCacheL1LineSize);	prom_debug("naca->serialPortAddr            = 0x%x\n",		   _naca->serialPortAddr);	prom_debug("naca->interrupt_controller      = 0x%x\n",		   _naca->interrupt_controller);	prom_debug("systemcfg->platform             = 0x%x\n",		   _systemcfg->platform);	prom_debug("prom_initialize_naca: end...\n");}static void __init early_cmdline_parse(void){	unsigned long offset = reloc_offset();	char *opt;#ifndef CONFIG_PMAC_DART	struct systemcfg *_systemcfg = RELOC(systemcfg);#endif	opt = strstr(RELOC(cmd_line), RELOC("iommu="));	if (opt) {		prom_printf("opt is:%s\n", opt);		opt += 6;		while (*opt && *opt == ' ')			opt++;		if (!strncmp(opt, RELOC("off"), 3))			RELOC(ppc64_iommu_off) = 1;		else if (!strncmp(opt, RELOC("force"), 5))			RELOC(iommu_force_on) = 1;	}#ifndef CONFIG_PMAC_DART	if (_systemcfg->platform == PLATFORM_POWERMAC) {		RELOC(ppc64_iommu_off) = 1;		prom_printf("DART disabled on PowerMac !\n");	}#endif}#ifdef DEBUG_PROMvoid prom_dump_lmb(void){	unsigned long i;	unsigned long offset = reloc_offset();	struct lmb *_lmb  = PTRRELOC(&lmb);	prom_printf("\nprom_dump_lmb:\n");	prom_printf("    memory.cnt		  = 0x%x\n",		    _lmb->memory.cnt);	prom_printf("    memory.size		 = 0x%x\n",		    _lmb->memory.size);	for (i=0; i < _lmb->memory.cnt ;i++) {		prom_printf("    memory.region[0x%x].base       = 0x%x\n",			    i, _lmb->memory.region[i].base);		prom_printf("		      .physbase = 0x%x\n",			    _lmb->memory.region[i].physbase);		prom_printf("		      .size     = 0x%x\n",			    _lmb->memory.region[i].size);	}	prom_printf("\n    reserved.cnt		  = 0x%x\n",		    _lmb->reserved.cnt);	prom_printf("    reserved.size		 = 0x%x\n",		    _lmb->reserved.size);	for (i=0; i < _lmb->reserved.cnt ;i++) {		prom_printf("    reserved.region[0x%x\n].base       = 0x%x\n",			    i, _lmb->reserved.region[i].base);		prom_printf("		      .physbase = 0x%x\n",			    _lmb->reserved.region[i].physbase);		prom_printf("		      .size     = 0x%x\n",			    _lmb->reserved.region[i].size);	}}#endif /* DEBUG_PROM */static void __init prom_initialize_lmb(void){	phandle node;	char type[64];	unsigned long i, offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	struct systemcfg *_systemcfg = RELOC(systemcfg);	union lmb_reg_property reg;	unsigned long lmb_base, lmb_size;	unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;	lmb_init();	/* XXX Quick HACK. Proper fix is to drop those structures and properly use	 * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2	 */	if (_systemcfg->platform == PLATFORM_POWERMAC)		bytes_per_reg = 12;	for (node = 0; prom_next_node(&node); ) {		type[0] = 0;		prom_getprop(node, "device_type", type, sizeof(type));		if (strcmp(type, RELOC("memory")))			continue;		num_regs = prom_getprop(node, "reg", &reg, sizeof(reg))			/ bytes_per_reg;		for (i=0; i < num_regs ;i++) {			if (_systemcfg->platform == PLATFORM_POWERMAC) {				lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;				lmb_base |= (unsigned long)reg.addrPM[i].address_lo;				lmb_size = reg.addrPM[i].size;			} else if (_prom->encode_phys_size == 32) {				lmb_base = reg.addr32[i].address;				lmb_size = reg.addr32[i].size;			} else {				lmb_base = reg.addr64[i].address;				lmb_size = reg.addr64[i].size;			}			/* We limit memory to 2GB if the IOMMU is off */			if (RELOC(ppc64_iommu_off)) {				if (lmb_base >= 0x80000000UL)					continue;				if ((lmb_base + lmb_size) > 0x80000000UL)					lmb_size = 0x80000000UL - lmb_base;			}			if (lmb_add(lmb_base, lmb_size) < 0)				prom_printf("Too many LMB's, discarding this one...\n");		}	}	lmb_analyze();#ifdef DEBUG_PROM	prom_dump_lmb();#endif /* DEBUG_PROM */}static void __initprom_instantiate_rtas(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	struct rtas_t *_rtas = PTRRELOC(&rtas);	struct systemcfg *_systemcfg = RELOC(systemcfg);	ihandle prom_rtas;	u32 getprop_rval;	char hypertas_funcs[4];	prom_debug("prom_instantiate_rtas: start...\n");	prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));	if (prom_rtas != (ihandle) -1) {		unsigned long x;		x = prom_getprop(prom_rtas, "ibm,hypertas-functions",				 hypertas_funcs, sizeof(hypertas_funcs));		if (x != PROM_ERROR) {			prom_printf("Hypertas detected, assuming LPAR !\n");			_systemcfg->platform = PLATFORM_PSERIES_LPAR;		}		prom_getprop(prom_rtas, "rtas-size",			     &getprop_rval, sizeof(getprop_rval));		_rtas->size = getprop_rval;		prom_printf("instantiating rtas");		if (_rtas->size != 0) {			unsigned long rtas_region = RTAS_INSTANTIATE_MAX;			/* Grab some space within the first RTAS_INSTANTIATE_MAX bytes			 * of physical memory (or within the RMO region) because RTAS			 * runs in 32-bit mode and relocate off.			 */			if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {				struct lmb *_lmb  = PTRRELOC(&lmb);				rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);			}			_rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);			prom_printf(" at 0x%x", _rtas->base);			prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));			prom_printf("...");			if (call_prom("call-method", 3, 2,				      ADDR("instantiate-rtas"),				      prom_rtas,				      _rtas->base) != PROM_ERROR) {				_rtas->entry = (long)_prom->args.rets[1];			}			RELOC(rtas_rmo_buf)				= lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,							rtas_region);		}		if (_rtas->entry <= 0) {			prom_printf(" failed\n");		} else {			prom_printf(" done\n");		}		prom_debug("rtas->base		= 0x%x\n", _rtas->base);		prom_debug("rtas->entry	       = 0x%x\n", _rtas->entry);		prom_debug("rtas->size		= 0x%x\n", _rtas->size);	}	prom_debug("prom_instantiate_rtas: end...\n");}#ifdef CONFIG_PMAC_DARTstatic void __init prom_initialize_dart_table(void){	unsigned long offset = reloc_offset();	extern unsigned long dart_tablebase;	extern unsigned long dart_tablesize;	/* Only reserve DART space if machine has more than 2GB of RAM	 * or if requested with iommu=on on cmdline.	 */	if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on))		return;	/* 512 pages (2MB) is max DART tablesize. */	RELOC(dart_tablesize) = 1UL << 21;	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we	 * will blow up an entire large page anyway in the kernel mapping	 */	RELOC(dart_tablebase) = (unsigned long)		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));	prom_printf("Dart at: %x\n", RELOC(dart_tablebase));}#endif /* CONFIG_PMAC_DART */static void __init prom_initialize_tce_table(void){	phandle node;	ihandle phb_node;	unsigned long offset = reloc_offset();	char compatible[64], path[64], type[64], model[64];	unsigned long i, table = 0;	unsigned long base, vbase, align;	unsigned int minalign, minsize;	struct of_tce_table *prom_tce_table = RELOC(of_tce_table);	unsigned long tce_entry, *tce_entryp;	if (RELOC(ppc64_iommu_off))		return;	prom_debug("starting prom_initialize_tce_table\n");	/* Search all nodes looking for PHBs. */	for (node = 0; prom_next_node(&node); ) {		if (table == MAX_PHB) {			prom_printf("WARNING: PCI host bridge ignored, "				    "need to increase MAX_PHB\n");			continue;		}		compatible[0] = 0;		type[0] = 0;		model[0] = 0;		prom_getprop(node, "compatible",			     compatible, sizeof(compatible));		prom_getprop(node, "device_type", type, sizeof(type));		prom_getprop(node, "model", model, sizeof(model));		/* Keep the old logic in tack to avoid regression. */		if (compatible[0] != 0) {			if ((strstr(compatible, RELOC("python")) == NULL) &&			    (strstr(compatible, RELOC("Speedwagon")) == NULL) &&			    (strstr(compatible, RELOC("Winnipeg")) == NULL))				continue;		} else if (model[0] != 0) {			if ((strstr(model, RELOC("ython")) == NULL) &&			    (strstr(model, RELOC("peedwagon")) == NULL) &&			    (strstr(model, RELOC("innipeg")) == NULL))				continue;		}		if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {			continue;		}		if (prom_getprop(node, "tce-table-minalign", &minalign,				 sizeof(minalign)) == PROM_ERROR) {			minalign = 0;		}		if (prom_getprop(node, "tce-table-minsize", &minsize,				 sizeof(minsize)) == PROM_ERROR) {			minsize = 4UL << 20;		}		/*		 * Even though we read what OF wants, we just set the table		 * size to 4 MB.  This is enough to map 2GB of PCI DMA space.		 * By doing this, we avoid the pitfalls of trying to DMA to		 * MMIO space and the DMA alias hole.		 *		 * On POWER4, firmware sets the TCE region by assuming		 * each TCE table is 8MB. Using this memory for anything		 * else will impact performance, so we always allocate 8MB.		 * Anton		 */		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))			minsize = 8UL << 20;		else			minsize = 4UL << 20;		/* Align to the greater of the align or size */		align = max(minalign, minsize);		/* Carve out storage for the TCE table. */		base = lmb_alloc(minsize, align);		if ( !base ) {			prom_panic("ERROR, cannot find space for TCE table.\n");		}		vbase = (unsigned long)abs_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;		prom_debug("TCE table: 0x%x\n", table);		prom_debug("\tnode = 0x%x\n", node);		prom_debug("\tbase = 0x%x\n", vbase);		prom_debug("\tsize = 0x%x\n", minsize);		/* 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;		}		/* It seems OF doesn't null-terminate the path :-( */		memset(path, 0, sizeof(path));		/* Call OF to setup the TCE hardware */		if (call_prom("package-to-path", 3, 1, node,			      path, sizeof(path)-1) == PROM_ERROR) {			prom_printf("package-to-path failed\n");		} else {			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);		table++;	}	/* Flag the first invalid entry */	prom_tce_table[table].node = 0;	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(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		= (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 systemcfg *_systemcfg = RELOC(systemcfg);	struct paca_struct *lpaca = PTRRELOC(&paca[0]);	struct prom_t *_prom = PTRRELOC(&prom);#ifdef CONFIG_SMP	struct naca_struct *_naca = RELOC(naca);#endif	/* On pmac, we just fill out the various global bitmasks and	 * arrays indicating our CPUs are here, they are actually started	 * later on from pmac_smp	 */	if (_systemcfg->platform == PLATFORM_POWERMAC) {		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;			reg = -1;			prom_getprop(node, "reg", &reg, sizeof(reg));			lpaca[cpuid].hw_cpu_id = reg;#ifdef CONFIG_SMP			cpu_set(cpuid, RELOC(cpu_available_map));			cpu_set(cpuid, RELOC(cpu_possible_map));			cpu_set(cpuid, RELOC(cpu_present_at_boot));			if (reg == 0)				cpu_set(cpuid, RELOC(cpu_online_map));#endif /* CONFIG_SMP */			cpuid++;		}		return;	}	/* Initially, we must have one active CPU. */	_systemcfg->processorCount = 1;	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);

⌨️ 快捷键说明

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