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

📄 setup.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		cli();		ccr3 = getCx86(CX86_CCR3);		setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */		ccr5 = getCx86(CX86_CCR5);		if (ccr5 & 2)			setCx86(CX86_CCR5, ccr5 & 0xfd);  /* reset SLOP */		setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */		sti();		if (ccr5 & 2) { /* possible wrong calibration done */			printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");			calibrate_delay();			c->loops_per_jiffy = loops_per_jiffy;		}	}}static void __init init_cyrix(struct cpuinfo_x86 *c){	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;	char *buf = c->x86_model_id;	const char *p = NULL;	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */	clear_bit(0*32+31, &c->x86_capability);	/* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */	if ( test_bit(1*32+24, &c->x86_capability) ) {		clear_bit(1*32+24, &c->x86_capability);		set_bit(X86_FEATURE_CXMMX, &c->x86_capability);	}	do_cyrix_devid(&dir0, &dir1);	check_cx686_slop(c);	Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family"   */	dir0_lsn = dir0 & 0xf;                /* model or clock multiplier */	/* common case step number/rev -- exceptions handled below */	c->x86_model = (dir1 >> 4) + 1;	c->x86_mask = dir1 & 0xf;	/* Now cook; the original recipe is by Channing Corn, from Cyrix.	 * We do the same thing for each generation: we work out	 * the model, multiplier and stepping.  Black magic included,	 * to make the silicon step/rev numbers match the printed ones.	 */	 	switch (dir0_msn) {		unsigned char tmp;	case 0: /* Cx486SLC/DLC/SRx/DRx */		p = Cx486_name[dir0_lsn & 7];		break;	case 1: /* Cx486S/DX/DX2/DX4 */		p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]			: Cx486S_name[dir0_lsn & 3];		break;	case 2: /* 5x86 */		Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];		p = Cx86_cb+2;		break;	case 3: /* 6x86/6x86L */		Cx86_cb[1] = ' ';		Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];		if (dir1 > 0x21) { /* 686L */			Cx86_cb[0] = 'L';			p = Cx86_cb;			(c->x86_model)++;		} else             /* 686 */			p = Cx86_cb+1;		/* Emulate MTRRs using Cyrix's ARRs. */		set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);		/* 6x86's contain this bug */		c->coma_bug = 1;		break;	case 4: /* MediaGX/GXm */		/*		 *	Life sometimes gets weiiiiiiiird if we use this		 *	on the MediaGX. So we turn it off for now. 		 */		#ifdef CONFIG_PCI		/* It isnt really a PCI quirk directly, but the cure is the		   same. The MediaGX has deep magic SMM stuff that handles the		   SB emulation. It thows away the fifo on disable_dma() which		   is wrong and ruins the audio.                    		   Bug2: VSA1 has a wrap bug so that using maximum sized DMA 		   causes bad things. According to NatSemi VSA2 has another		   bug to do with 'hlt'. I've not seen any boards using VSA2		   and X doesn't seem to support it either so who cares 8).		   VSA1 we work around however.		*/		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");		isa_dma_bridge_buggy = 2;#endif				c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */		/* GXm supports extended cpuid levels 'ala' AMD */		if (c->cpuid_level == 2) {			get_model_name(c);  /* get CPU marketing name */			clear_bit(X86_FEATURE_TSC, c->x86_capability);			return;		}		else {  /* MediaGX */			Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';			p = Cx86_cb+2;			c->x86_model = (dir1 & 0x20) ? 1 : 2;			clear_bit(X86_FEATURE_TSC, &c->x86_capability);		}		break;        case 5: /* 6x86MX/M II */		if (dir1 > 7) dir0_msn++;  /* M II */		else c->coma_bug = 1;      /* 6x86MX, it has the bug. */		tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;		Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];		p = Cx86_cb+tmp;        	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))			(c->x86_model)++;		/* Emulate MTRRs using Cyrix's ARRs. */		set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);		break;	case 0xf:  /* Cyrix 486 without DEVID registers */		switch (dir0_lsn) {		case 0xd:  /* either a 486SLC or DLC w/o DEVID */			dir0_msn = 0;			p = Cx486_name[(c->hard_math) ? 1 : 0];			break;		case 0xe:  /* a 486S A step */			dir0_msn = 0;			p = Cx486S_name[0];			break;		}		break;	default:  /* unknown (shouldn't happen, we know everyone ;-) */		dir0_msn = 7;		break;	}	strcpy(buf, Cx86_model[dir0_msn & 7]);	if (p) strcat(buf, p);	return;}static void __init init_centaur(struct cpuinfo_x86 *c){	enum {		ECX8=1<<1,		EIERRINT=1<<2,		DPM=1<<3,		DMCE=1<<4,		DSTPCLK=1<<5,		ELINEAR=1<<6,		DSMC=1<<7,		DTLOCK=1<<8,		EDCTLB=1<<8,		EMMX=1<<9,		DPDC=1<<11,		EBRPRED=1<<12,		DIC=1<<13,		DDC=1<<14,		DNA=1<<15,		ERETSTK=1<<16,		E2MMX=1<<19,		EAMD3D=1<<20,	};	char *name;	u32  fcr_set=0;	u32  fcr_clr=0;	u32  lo,hi,newlo;	u32  aa,bb,cc,dd;	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */	clear_bit(0*32+31, &c->x86_capability);	switch (c->x86) {		case 5:			switch(c->x86_model) {			case 4:				name="C6";				fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;				fcr_clr=DPDC;				printk("Disabling bugged TSC.\n");				clear_bit(X86_FEATURE_TSC, &c->x86_capability);				break;			case 8:				switch(c->x86_mask) {				default:					name="2";					break;				case 7 ... 9:					name="2A";					break;				case 10 ... 15:					name="2B";					break;				}				fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;				fcr_clr=DPDC;				break;			case 9:				name="3";				fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;				fcr_clr=DPDC;				break;			case 10:				name="4";				/* no info on the WC4 yet */				break;			default:				name="??";			}			/* get FCR  */			rdmsr(0x107, lo, hi);			newlo=(lo|fcr_set) & (~fcr_clr);			if (newlo!=lo) {				printk("Centaur FCR was 0x%X now 0x%X\n", lo, newlo );				wrmsr(0x107, newlo, hi );			} else {				printk("Centaur FCR is 0x%X\n",lo);			}			/* Emulate MTRRs using Centaur's MCR. */			set_bit(X86_FEATURE_CENTAUR_MCR, &c->x86_capability);			/* Report CX8 */			set_bit(X86_FEATURE_CX8, &c->x86_capability);			/* Set 3DNow! on Winchip 2 and above. */			if (c->x86_model >=8)				set_bit(X86_FEATURE_3DNOW, &c->x86_capability);			/* See if we can find out some more. */			if ( cpuid_eax(0x80000000) >= 0x80000005 ) {				/* Yes, we can. */				cpuid(0x80000005,&aa,&bb,&cc,&dd);				/* Add L1 data and code cache sizes. */				c->x86_cache_size = (cc>>24)+(dd>>24);			}			sprintf( c->x86_model_id, "WinChip %s", name );			break;		case 6:			switch (c->x86_model) {				case 6:	/* Cyrix III */					rdmsr (0x1107, lo, hi);					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */					wrmsr (0x1107, lo, hi);					set_bit(X86_FEATURE_CX8, &c->x86_capability);					rdmsr (0x80000001, lo, hi);					if (hi & (1<<31))						set_bit(X86_FEATURE_3DNOW, &c->x86_capability);					get_model_name(c);					display_cacheinfo(c);					break;			}			break;	}}static void __init init_transmeta(struct cpuinfo_x86 *c){	unsigned int cap_mask, uk, max, dummy;	unsigned int cms_rev1, cms_rev2;	unsigned int cpu_rev, cpu_freq, cpu_flags;	char cpu_info[65];	get_model_name(c);	/* Same as AMD/Cyrix */	display_cacheinfo(c);	/* Print CMS and CPU revision */	max = cpuid_eax(0x80860000);	if ( max >= 0x80860001 ) {		cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); 		printk("CPU: Processor revision %u.%u.%u.%u, %u MHz\n",		       (cpu_rev >> 24) & 0xff,		       (cpu_rev >> 16) & 0xff,		       (cpu_rev >> 8) & 0xff,		       cpu_rev & 0xff,		       cpu_freq);	}	if ( max >= 0x80860002 ) {		cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy);		printk("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",		       (cms_rev1 >> 24) & 0xff,		       (cms_rev1 >> 16) & 0xff,		       (cms_rev1 >> 8) & 0xff,		       cms_rev1 & 0xff,		       cms_rev2);	}	if ( max >= 0x80860006 ) {		cpuid(0x80860003,		      (void *)&cpu_info[0],		      (void *)&cpu_info[4],		      (void *)&cpu_info[8],		      (void *)&cpu_info[12]);		cpuid(0x80860004,		      (void *)&cpu_info[16],		      (void *)&cpu_info[20],		      (void *)&cpu_info[24],		      (void *)&cpu_info[28]);		cpuid(0x80860005,		      (void *)&cpu_info[32],		      (void *)&cpu_info[36],		      (void *)&cpu_info[40],		      (void *)&cpu_info[44]);		cpuid(0x80860006,		      (void *)&cpu_info[48],		      (void *)&cpu_info[52],		      (void *)&cpu_info[56],		      (void *)&cpu_info[60]);		cpu_info[64] = '\0';		printk("CPU: %s\n", cpu_info);	}	/* Unhide possibly hidden capability flags */	rdmsr(0x80860004, cap_mask, uk);	wrmsr(0x80860004, ~0, uk);	c->x86_capability[0] = cpuid_edx(0x00000001);	wrmsr(0x80860004, cap_mask, uk);}extern void trap_init_f00f_bug(void);static void __init init_intel(struct cpuinfo_x86 *c){#ifndef CONFIG_M686	static int f00f_workaround_enabled = 0;#endif	extern void mcheck_init(struct cpuinfo_x86 *c);	char *p = NULL;	unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */#ifndef CONFIG_M686	/*	 * All current models of Pentium and Pentium with MMX technology CPUs	 * have the F0 0F bug, which lets nonpriviledged users lock up the system.	 * Note that the workaround only should be initialized once...	 */	c->f00f_bug = 0;	if ( c->x86 == 5 ) {		c->f00f_bug = 1;		if ( !f00f_workaround_enabled ) {			trap_init_f00f_bug();			printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n");			f00f_workaround_enabled = 1;		}	}#endif	if (c->cpuid_level > 1) {		/* supports eax=2  call */		int i, j, n;		int regs[4];		unsigned char *dp = (unsigned char *)regs;		/* Number of times to iterate */		n = cpuid_eax(2) & 0xFF;		for ( i = 0 ; i < n ; i++ ) {			cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);						/* If bit 31 is set, this is an unknown format */			for ( j = 0 ; j < 3 ; j++ ) {				if ( regs[j] < 0 ) regs[j] = 0;			}			/* Byte 0 is level count, not a descriptor */			for ( j = 1 ; j < 16 ; j++ ) {				unsigned char des = dp[j];				unsigned char dl, dh;				unsigned int cs;				dh = des >> 4;				dl = des & 0x0F;				/* Black magic... */				switch ( dh )				{				case 0:					switch ( dl ) {					case 6:						/* L1 I cache */						l1i += 8;						break;					case 8:						/* L1 I cache */						l1i += 16;						break;					case 10:						/* L1 D cache */						l1d += 8;						break;					case 12:						/* L1 D cache */						l1d += 16;						break;					default:;						/* TLB, or unknown */					}					break;				case 2:					if ( dl ) {						/* L3 cache */						cs = (dl-1) << 9;						l3 += cs;					}					break;				case 4:					if ( c->x86 > 6 && dl ) {						/* P4 family */						if ( dl ) {							/* L3 cache */							cs = 128 << (dl-1);							l3 += cs;							break;						}					}					/* else same as 8 - fall through */				case 8:					if ( dl ) {						/* L2 cache */						cs = 128 << (dl-1);						l2 += cs;					}					break;				case 6:					if (dl > 5) {						/* L1 D cache */						cs = 8<<(dl-6);						l1d += cs;					}					break;				case 7:					if ( dl >= 8 ) 					{						/* L2 cache */						cs = 64<<(dl-8);						l2 += cs;					} else {						/* L0 I cache, count as L1 */						cs = dl ? (16 << (dl-1)) : 12;						l1i += cs;					}					break;				default:					/* TLB, or something else we don't know about */					break;				}			}		}		if ( l1i || l1d )			printk("CPU: L1 I cache: %dK, L1 D cache: %dK\n",			       l1i, l1d);		if ( l2 )			printk("CPU: L2 cache: %dK\n", l2);		if ( l3 )			printk("CPU: L3 cache: %dK\n", l3);		/*		 * This assumes the L3 cache is shared; it typically lives in		 * the northbridge.  The L1 caches are included by the L2		 * cache, and so should not be included for the purpose of		 * SMP switching weights.		 */		c->x86_cache_size = l2 ? l2 : (l1i+l1d);	}	/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */	if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 )		clear_bit(X86_FEATURE_SEP, &c->x86_capability);		/* Names for the Pentium II/Celeron processors 	   detectable only by also checking the cache size.	   Dixon is NOT a Celeron. */	if (c->x86 == 6) {		switch (c->x86_model) {		case 5:			if (l2 == 0)				p = "Celeron (Covington)";			if (l2 == 256)				p = "Mobile Pentium II (Dixon)";			break;					case 6:			if (l2 == 128)				p = "Celeron (Mendocino)";			break;					case 8:			if (l2 == 128)				p = "Celeron (Coppermine)";			break;		}	}	if ( p )		strcpy(c->x86_model_id, p);	/* Enable MCA if available */	mcheck_init(c);}void __init get_cpu_vendor(struct cpuinfo_x86 *c){	char *v = c->x86_vendor_id;	if (!strcmp(v, "GenuineIntel"))		c->x86_vendor = X86_VENDOR_INTEL;	else if (!strcmp(v, "AuthenticAMD"))		c->x86_vendor = X86_VENDOR_AMD;	else if (!strcmp(v, "CyrixInstead"))		c->x86_vendor = X86_VENDOR_CYRIX;	else if (!strcmp(v, "UMC UMC UMC "))		c->x86_vendor = X86_VENDOR_UMC;	else if (!strcmp(v, "CentaurHauls"))		c->x86_vendor = X86_VENDOR_CENTAUR;	else if (!strcmp(v, "NexGenDriven"))		c->x86_vendor = X86_VENDOR_NEXGEN;	else if (!strcmp(v, "RiseRiseRise"))		c->x86_vendor = X86_VENDOR_RISE;	else if (!strcmp(v, "GenuineTMx86") ||		 !strcmp(v, "TransmetaCPU"))		c->x86_vendor = X86_VENDOR_TRANSMETA;	else		c->x86_vendor = X86_VENDOR_UNKNOWN;}struct cpu_model_info {	int vendor;	int family;	char *model_names[16];};/* Naming convention should be: <Name> [(<Codename>)] *//* This table only is used unless init_<vendor>() below doesn't set it; *//* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */static struct cpu_model_info cpu_models[] __initdata = {	{ X86_VENDOR_INTEL,	4,	  { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", 	    "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, 	    NULL, NULL, NULL, NULL, NULL }},	{ X86_VENDOR_INTEL,	5,	  { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75 - 200",	    "OverDrive PODP5V83", "Pentium MMX", NULL, NULL,	    "Mobile Pentium 75 - 200", "Mobile Pentium MMX", NULL, NULL, NULL,	    NULL, NULL, NULL, NULL }},	{ X86_VENDOR_INTEL,	6,	  { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", 

⌨️ 快捷键说明

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