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

📄 cpu_mhz.c

📁 nucleus 源码包括具体的内核适合研究 nucleus
💻 C
字号:
/********************************************************
* v0.1 ???												*
* v0.2 Doug Gale										*
*		- Fixed disabling of interrupts					*
********************************************************/

#include <support.h>
#include <interrupts.h>
#include <drivers/cpu/cpu_mhz.h>
#include <drivers/cpu/msr.h>


/*
 *  $Id: MHz.c,v 1.8 2001/12/09 16:35:51 davej Exp $
 *  This file is part of x86info.
 *  (C) 2001 Dave Jones.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 * Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
 * Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
 *
 */

#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>

unsigned long calibrate_tsc(void)
{
	int ints_were_enabled = interrupts_disable();

	unsigned long startlow, starthigh;
	unsigned long endlow, endhigh;
	unsigned long count;
	
	/* Set the Gate high, disable speaker */
	outportb(0x61, (inportb(0x61) & ~0x02) | 0x01);

	/*
	 * Now let's take care of CTC channel 2
	 *
	 * Set the Gate high, program CTC channel 2 for mode 0,
	 * (interrupt on terminal count mode), binary count,
	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
	 */
	outportb(0x43, 0xB0);			/* binary, mode 0, LSB/MSB, Ch 2 */
	outportb(0x42, CALIBRATE_LATCH & 0xff);	/* LSB of count */
	outportb(0x42, CALIBRATE_LATCH >> 8);	/* MSB of count */

	rdtsc(startlow,starthigh);
	count = 0;
	do {
		count++;
	} while ((inportb(0x61) & 0x20) == 0);
	rdtsc(endlow,endhigh);

	if (ints_were_enabled)
		interrupts_enable();
	
	/* Error: ECTCNEVERSET */
	if (count <= 1)
		goto bad_ctc;
	
	/* 64-bit subtract - gcc just messes up with long longs */
	__asm__("subl %2,%0\n\t"
			"sbbl %3,%1"
			:"=a" (endlow), "=d" (endhigh)
			:"g" (startlow), "g" (starthigh),
			"0" (endlow), "1" (endhigh));
	
	/* Error: ECPUTOOFAST */
	if (endhigh)
		goto bad_ctc;
	
	/* Error: ECPUTOOSLOW */
	if (endlow <= CALIBRATE_TIME)
		goto bad_ctc;
	
	__asm__("divl %2"
			:"=a" (endlow), "=d" (endhigh)
			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
	
	return endlow;
	
	/*
	* The CTC wasn't reliable: we got a hit on the very first read,
	* or the CPU was so fast/slow that the quotient wouldn't fit in
	* 32 bits..
	*/
bad_ctc:
	return 0;
}

unsigned long get_clockrate(char tsc)
{
	unsigned long eax=0, edx=1000, cpu_khz = 0x01;
    unsigned long tsc_quotient;

	if (tsc)
	{
		tsc_quotient = calibrate_tsc();

		if (tsc_quotient)
		{
			__asm__(
				"divl %2"
				:"=a" (cpu_khz), "=d" (edx)
				:"r" (tsc_quotient),
		         "0" (eax), "1" (edx)
			);
		}
    }
	return (unsigned long)(cpu_khz / 1000);
}

⌨️ 快捷键说明

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