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

📄 cpu.c

📁 nucleus_arm.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
			{
				switch (cpu.model)
				{
					case 0x1: result = "U5D"; break;
					case 0x2: result = "U5S"; break;
				} break;
			}
			default: result = "Unknown";
		}
	}
	if (cpu.manufacturer == idRise)
	{
		switch (cpu.family)
		{
			case 0x5:
			{
				switch (cpu.model)
				{
					case 0x0: result = "mP6 iDragon (0.25鎚)"; break;
					case 0x2: result = "mP6 iDragon (0.18鎚)"; break;
					case 0x8: result = "mP6 iDragon II (0.25鎚)"; break;
					case 0x9: result = "mP6 iDragon II (0.18鎚)"; break;
				} break;
			}
			default: result = "Unknown";
		}
	}
	if (cpu.manufacturer == idSiS)
	{
		switch (cpu.family)
		{
			case 0x5:
			{
				switch (cpu.model)
				{
					case 0x0: result = "mP6 iDragon (0.25鎚)"; break;
					case 0x2: result = "mP6 iDragon (0.18鎚)"; break;
					case 0x8: result = "mP6 iDragon II (0.25鎚)"; break;
					case 0x9: result = "mP6 iDragon II (0.18鎚)"; break;
				} break;
			}
			default: result = "Unknown";
		}
	}
	if (cpu.manufacturer == idNSC)
	{
		switch (cpu.family)
		{
			case 0x5:
			{
				switch (cpu.model)
				{
					case 0x0: result = "mP6 iDragon (0.25鎚)"; break;
					case 0x2: result = "mP6 iDragon (0.18鎚)"; break;
					case 0x8: result = "mP6 iDragon II (0.25鎚)"; break;
					case 0x9: result = "mP6 iDragon II (0.18鎚)"; break;
				} break;
			}
			default: result = "Unknown";
		}
	}
	return result;
}

static int is_486(void)
{
	int result;

		asm (
	"pushf ;"			/* save EFLAGS */
	"popl	%%eax ;"		/* get EFLAGS */
	"movl	%%eax, %%ecx ;"		/* temp storage EFLAGS */
	"xorl	$0x40000, %%eax ;"	/* change AC bit in EFLAGS */
	"pushl	%%eax ;"		/* put new EFLAGS value on stack */
	"popf ;"			/* replace current EFLAGS value */
	"pushf ;"			/* get EFLAGS */
	"popl	%%eax ;"		/* save new EFLAGS in EAX */
	"cmpl	%%ecx, %%eax ;"		/* compare temp and new EFLAGS */
	"movl   $0,%%eax ;"
	"jz	0f ;"
	"incl   %%eax ;"		/* 80486 present */
	"0:"
	"pushl	%%ecx ;"		/* get original EFLAGS */
	"popf ;"			/* restore EFLAGS */
	: "=a" (result)
	:
	: "ecx" );

	return result;
}

static int is_386DX(void) /* return TRUE for 386DX, and FALSE for 386SX */
{
	int result;

		asm (
	"movl	%%cr0,%%edx ;"		/* Get CR0 */
	"pushl	%%edx ;"		/* save CR0 */
		"andb	$0xEF, %%dl ;"		/* clear bit4 */
	"movl	%%edx, %%cr0 ;" 	/* set CR0 */
	"movl	%%cr0, %%edx ;"		/* and read CR0 */
	"andb	$0x10, %%dl ;"		/* bit4 forced high? */
	"popl	%%edx ;"		/* restore reg w/ CR0 */
	"movl	%%edx, %%cr0 ;"		/* restore CR0 */
	"movl	$1, %%eax ;"		/* TRUE, 386DX */
	"jz	0f ;"
	"movl	$0, %%eax ;"		/* FALSE, 386SX */
	"0:"
	: "=a" (result)
	:
		: "%edx", "memory"
	);

	return result;
}

static int is_486DX(void) /* return TRUE for 486DX, and FALSE for 486SX */
{
	dword memory_location = 0x00;

	__asm__ (
		"fninit ;"
		"fnstsw %0 ;"
		: "=g" (memory_location)
	);
	
	return (memory_location == 0x37F) ? 1 : 0;
}

static int is_fpu(void)
{
	int result;

		asm (
	"fninit ;"
	"movl	$0x5a5a, %%eax ;"
	"fnstsw  %%eax ;"
	"cmpl	$0, %%eax ;"
	"jne	 0f ;"
	"movl	$1, %%eax ;"
	"jmp	 1f ;"

	"0:"
	"movl	$0, %%eax ;"

	"1:"
	: "=a" (result)
	:
	: "memory" );

	return result;
}

static int is_cyrix(void)
{
	int result;

	asm (
		"xorw	 %%ax, %%ax ;"		/* clear eax */
		"sahf ;"			/* clear flags, bit 1 is always 1 in flags */
		"movw	 $5, %%ax ;"
		"movw	 $2, %%bx ;"
		"div	  %%bl ;"		/* do an operation that does not change flags */
		"lahf ;"			/* get flags */
		"cmpb	 $2, %%ah ;"		/* check for change in flags */
		"movl	 $0, %%eax ;"		/* FALSE NON-Cyrix CPU */
		"jne	  0f ;"			/* flags changed not Cyrix */
		"incl	 %%eax ;"		/* TRUE Cyrix CPU */
		"0:"
		: "=a" (result)
		:
		: "ebx"
	);

	return result;
}

static void cx_w(char index, char value)
{
	int ints_were_enabled = interrupts_disable();

	outportb(0x22, index);		/* tell CPU which config. register */
	outportb(0x23, value);		/* write to CPU config. register */

	if (ints_were_enabled)
		interrupts_enable();
}

static char cx_r(char index)
{
	char value;
	int ints_were_enabled = interrupts_disable();

	outportb(0x22, index);		/* tell CPU which config. register */
	value = inportb(0x23);		/* read CPU config, register */

	if (ints_were_enabled)
		interrupts_enable();

	return value;
}

#define UNKNOWN   0xff
#define Cx486_pr  0xfd  /* ID Register not supported, software created */
#define Cx486S_a  0xfe  /* ID Register not supported, software created */
#define CR2_MASK  0x4   /* LockNW */
#define CR3_MASK  0x80  /* Resereved bit 7 */

static char cyrix_type(void)
{
	char orgc2, newc2, orgc3, newc3;
	int cr2_rw=0, cr3_rw=0, type;
	int ints_were_enabled = interrupts_disable();

	type = UNKNOWN;

	/* Test Cyrix c2 register read/writable */
	orgc2 = cx_r (0xc2);		/* get current c2 value */
	newc2 = orgc2 ^ CR2_MASK;	/* toggle test bit */
	cx_w (0xc2, newc2);		/* write test value to c2 */
	cx_r (0xc0);			/* dummy read to change bus */
	if (cx_r (0xc2) != orgc2)	/* did test bit toggle */
		cr2_rw = 1;		/* yes bit changed */
	cx_w (0xc2, orgc2);		/* return c2 to original value */
	/* end c2 read writeable test */
	/* Test Cyrix c3 register read/writable */
	orgc3 = cx_r (0xc3);		/* get current c3 value */
	newc3 = orgc3 ^ CR3_MASK;	/* toggle test bit */
	cx_w (0xc3, newc3);		/* write test value to c3 */
	cx_r (0xc0);			/* dummy read to change bus */
	if (cx_r (0xc3) != orgc3)	/* did test bit change */
		cr3_rw = 1;		/* yes it did */
		cx_w (0xc3, orgc3);		/* return c3 to original value */
	/* end c3 read writeable test */
	if ((cr2_rw && cr3_rw) || (!cr2_rw && cr3_rw)) /*DEV ID register ok */
	{
		/* <<<<<<< READ DEVICE ID Reg >>>>>>>> */
		type = cx_r (0xfe);	/* lower byte gets IDIR0 */
	}
	else if (cr2_rw && !cr3_rw)	/* Cx486S A step */
	{
		type = Cx486S_a;	/* lower byte */
	}
	else if (!cr2_rw && !cr3_rw)	/* Pre ID Regs. Cx486SLC or DLC */
	{
		type = Cx486_pr;	/* lower byte */
	}
	/* This could be broken down more, but is it needed? */
	if (type < 0x30 || type > 0xfc)
	{
		cpu.family = 4;		/* 486 class-including 5x86 */
		cpu.model = 0xFF;	/* Unknown */
	}
	else if (type < 0x50)
	{
		cpu.family = 5;		/* Pentium class-6x86 and Media GX */
		cpu.model = 0xFF;	/* Unknown */
	}
	else	
	{
		cpu.family = 6;		/* Pentium || class- 6x86MX */
		cpu.model = 0xFF;	/* Unknown */
		cpu.flags |= cpu_mmx;
	}

	if (ints_were_enabled)
		interrupts_enable();

	return type;
}

void check_cache(void)
{
	static unsigned proc_cache_l1[4] = { 0, 0, 0, 0 };
	static unsigned proc_cache_l2[4] = { 0, 0, 0, 0 };

		// query L1 cache information
	get_cpuid(0x80000005, proc_cache_l1[0], proc_cache_l1[1],
			proc_cache_l1[2], proc_cache_l1[3]);
		// query L2 cache information
	get_cpuid(0x80000006, proc_cache_l2[0], proc_cache_l2[1],
			proc_cache_l2[2], proc_cache_l2[3]);

	if (cpu.manufacturer == idAMD)
		{
			// K5/K6 supports a restricted range
			cpu.cache.CPU_L1_DTLB_ASSOC   = (proc_cache_l1[1] >> 24) & 0xff;
			cpu.cache.CPU_L1_DTLB_ENTRIES = (proc_cache_l1[1] >> 16) & 0xff;
			cpu.cache.CPU_L1_ITLB_ASSOC   = (proc_cache_l1[1] >>  8) & 0xff;
			cpu.cache.CPU_L1_ITLB_ENTRIES = (proc_cache_l1[1] >>  0) & 0xff;

			cpu.cache.CPU_L1_DCACHE_SIZE  = (proc_cache_l1[2] >> 24) & 0xff;
			cpu.cache.CPU_L1_DCACHE_ASSOC = (proc_cache_l1[2] >> 16) & 0xff;
			cpu.cache.CPU_L1_DCACHE_LINES = (proc_cache_l1[2] >>  8) & 0xff;
			cpu.cache.CPU_L1_DCACHE_LSIZE = (proc_cache_l1[2] >>  0) & 0xff;

			cpu.cache.CPU_L1_ICACHE_SIZE  = (proc_cache_l1[3] >> 24) & 0xff;
			cpu.cache.CPU_L1_ICACHE_ASSOC = (proc_cache_l1[3] >> 16) & 0xff;
			cpu.cache.CPU_L1_ICACHE_LINES = (proc_cache_l1[3] >>  8) & 0xff;
			cpu.cache.CPU_L1_ICACHE_LSIZE = (proc_cache_l1[3] >>  0) & 0xff;

			cpu.cache.CPU_L2_CACHE_SIZE   = (proc_cache_l2[2] >> 16) & 0xffff;
			cpu.cache.CPU_L2_CACHE_ASSOC  = (proc_cache_l2[2] >> 12) & 0x0f;
			cpu.cache.CPU_L2_CACHE_LINES  = (proc_cache_l2[2] >>  8) & 0x0f;
			cpu.cache.CPU_L2_CACHE_LSIZE  = (proc_cache_l2[2] >>  0) & 0xff;

			if (cpu.family == 0x06) // AMD ATHLON
			{
				// Athlon supports these additional parameters
				cpu.cache.CPU_L1_EDTLB_ASSOC   = (proc_cache_l1[0] >> 24) & 0xff;
				cpu.cache.CPU_L1_EDTLB_ENTRIES = (proc_cache_l1[0] >> 16) & 0xff;
				cpu.cache.CPU_L1_EITLB_ASSOC   = (proc_cache_l1[0] >>  8) & 0xff;
				cpu.cache.CPU_L1_EITLB_ENTRIES = (proc_cache_l1[0] >>  0) & 0xff;

				cpu.cache.CPU_L2_DTLB_ASSOC	= (proc_cache_l2[0] >> 28) & 0x0f;
				cpu.cache.CPU_L2_DTLB_ENTRIES  = (proc_cache_l2[0] >> 16) & 0xfff;
				cpu.cache.CPU_L2_UTLB_ASSOC	= (proc_cache_l2[0] >> 12) & 0x0f;
				cpu.cache.CPU_L2_UTLB_ENTRIES  = (proc_cache_l2[0] >>  0) & 0xfff;

				cpu.cache.CPU_L2_EDTLB_ASSOC   = (proc_cache_l2[1] >> 28) & 0x0f;
				cpu.cache.CPU_L2_EDTLB_ENTRIES = (proc_cache_l2[1] >> 16) & 0xfff;
				cpu.cache.CPU_L2_EUTLB_ASSOC   = (proc_cache_l2[1] >> 12) & 0x0f;
				cpu.cache.CPU_L2_EUTLB_ENTRIES = (proc_cache_l2[1] >>  0) & 0xfff;
			}
	}
}


void check_cpu(void)
{
	unsigned cpuid_levels, reg_eax, reg_ebx, reg_ecx, reg_edx, tmp;
	unsigned char b;

	if (is_cpuid_supported())
	{
		cpu.flags |= cpu_cpuid;
		get_cpuid(0, cpuid_levels, reg_ebx, reg_ecx, reg_edx);
		cpu.levels = cpuid_levels;
		cpu.vendor[ 0] = LOBYTE(LOWORD(reg_ebx));
		cpu.vendor[ 1] = HIBYTE(LOWORD(reg_ebx));
		cpu.vendor[ 2] = LOBYTE(HIWORD(reg_ebx));
		cpu.vendor[ 3] = HIBYTE(HIWORD(reg_ebx));
		cpu.vendor[ 4] = LOBYTE(LOWORD(reg_edx));
		cpu.vendor[ 5] = HIBYTE(LOWORD(reg_edx));
		cpu.vendor[ 6] = LOBYTE(HIWORD(reg_edx));
		cpu.vendor[ 7] = HIBYTE(HIWORD(reg_edx));
		cpu.vendor[ 8] = LOBYTE(LOWORD(reg_ecx));
		cpu.vendor[ 9] = HIBYTE(LOWORD(reg_ecx));
		cpu.vendor[10] = LOBYTE(HIWORD(reg_ecx));
		cpu.vendor[11] = HIBYTE(HIWORD(reg_ecx));
		cpu.vendor[12] = '\0';
		cpu.manufacturer = 0xFF;
		for (tmp=0; tmp<9; tmp++)
		{
			if (strcmp(cpu.vendor, manufacturers[tmp]) == 0)
			{
				cpu.manufacturer = tmp;
				break;
			}
		}
		if (cpuid_levels > 0)
		{
			get_cpuid (1, reg_eax, tmp, tmp, reg_edx);
			cpu.family = (reg_eax & CPUID_FAM) >> 8;
			cpu.model = (reg_eax & CPUID_MOD) >> 4;
			cpu.stepping = (reg_eax & CPUID_STEP);
			cpu.ext_family = (reg_eax & CPUID_XFAM);
			cpu.features = reg_edx;
			checkname(cpu.name);
			// fill extended info structure for intel's
			fillinfo();
			check_cache();
			if (cpu.features & HAS_FPU) cpu.flags |= cpu_fpu;
			if (cpu.features & HAS_MMX) cpu.flags |= cpu_mmx;
			if (cpu.features & HAS_SSE) cpu.flags |= cpu_isse;
		}
	}
	else
	{
		cpu.vendor[0] = 'U';
		cpu.vendor[1] = 'n';
		cpu.vendor[2] = 'k';
		cpu.vendor[3] = 'n';
		cpu.vendor[4] = 'o';
		cpu.vendor[5] = 'w';
		cpu.vendor[6] = 'n';
		cpu.vendor[7] = '\0';
		if (is_fpu())
			cpu.flags |= cpu_fpu;
		if (!is_486())
		{
			if (is_386DX())
			{
				cpu.main_family = 3;	// 386
				cpu.model = 0;			// DX
			}
			else						// It is a 386SX
			{
				cpu.main_family = 3;	// 386
				cpu.model = 1;			// SX
			}
		}
		else
		{
				if (is_cyrix())
				{
				cpu.manufacturer = idCyrix;
				b = cyrix_type();
				strcpy(cpu.name, cyrix_name[b]);
				}
				else
				if (is_486DX())
				{
					cpu.main_family = 4;	// 486
					cpu.model = 0;			// DX
				}
				else
				{
					cpu.main_family = 4;	// 486
					cpu.model = 1;			// SX
				}
		}
	}
}

void cpu_init(void)
{
	dprintf("\ncpu: Checking CPU...");
	strcpy(cpu.name, "Unknown Processor");
	check_cpu();
	dprintf("OK\n");
	if (cpu.flags & cpu_cpuid)
	{
	   	dprintf("cpu: CPUID supported (");
		dprintf(cpu.vendor);
		if (cpu.levels)
			dprintf(", %ld levels", cpu.levels);
		dprintf("), %02X/%02X/%02X\n", cpu.family, cpu.model, cpu.stepping);
		dprintf("cpu: Identified as %s %s\n", display[cpu.manufacturer], cpu.name);
		dprintf("cpu: L1 D Cache: %ldKB, L1 I Cache: %ldKB", cpu.cache.CPU_L1_DCACHE_SIZE,
			cpu.cache.CPU_L1_ICACHE_SIZE);
		if (cpu.cache.CPU_L2_CACHE_SIZE)
			dprintf(", L2 Cache: %ldKB", cpu.cache.CPU_L2_CACHE_SIZE);
		cpu.clockrate = get_clockrate(cpu.features & HAS_TSC);
		dprintf("\ncpu: Speed CPU: %ldMHz\n", cpu.clockrate);
		check_popad();
		check_pentium_f00f();
	}
	else
	{
		dprintf("cpu: %d86 ", cpu.main_family);
		if (cpu.model != 0xFF)
			dprintf("%s", (cpu.model == 0x00) ? "DX " : "SX ");
		dprintf("detected\n");
	}
}

⌨️ 快捷键说明

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