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

📄 speedstep.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  $Id: speedstep.c,v 1.64 2003/01/02 22:16:26 db Exp $ * * (C) 2001  Dave Jones, Arjan van de ven. * (C) 2002  Dominik Brodowski <linux@brodo.de> * *  Licensed under the terms of the GNU GPL License version 2. *  Based upon reverse engineered information, and on Intel documentation *  for chipsets ICH2-M and ICH3-M. * *  Many thanks to Ducrot Bruno for finding and fixing the last *  "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler  *  for extensive testing. * *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* *//********************************************************************* *                        SPEEDSTEP - DEFINITIONS                    * *********************************************************************/#include <linux/kernel.h>#include <linux/module.h> #include <linux/init.h>#include <linux/cpufreq.h>#include <linux/pci.h>#include <linux/slab.h>#include <asm/msr.h>static struct cpufreq_driver		*speedstep_driver;/* speedstep_chipset: *   It is necessary to know which chipset is used. As accesses to  * this device occur at various places in this module, we need a  * static struct pci_dev * pointing to that device. */static unsigned int                     speedstep_chipset;static struct pci_dev                   *speedstep_chipset_dev;#define SPEEDSTEP_CHIPSET_ICH2M         0x00000002#define SPEEDSTEP_CHIPSET_ICH3M         0x00000003/* speedstep_processor */static unsigned int                     speedstep_processor = 0;static int                              speedstep_coppermine = 0;#define SPEEDSTEP_PROCESSOR_PIII_C      0x00000001  /* Coppermine core */#define SPEEDSTEP_PROCESSOR_PIII_T      0x00000002  /* Tualatin core */#define SPEEDSTEP_PROCESSOR_P4M         0x00000003  /* P4-M with 100 MHz FSB *//* speedstep_[low,high]_freq *   There are only two frequency states for each processor. Values * are in kHz for the time being. */#define SPEEDSTEP_HIGH                  0x00000000#define SPEEDSTEP_LOW                   0x00000001static struct cpufreq_frequency_table speedstep_freqs[] = {	{SPEEDSTEP_HIGH, 	0},	{SPEEDSTEP_LOW,		0},	{0,			CPUFREQ_TABLE_END},};#define speedstep_low_freq	speedstep_freqs[SPEEDSTEP_LOW].frequency#define speedstep_high_freq	speedstep_freqs[SPEEDSTEP_HIGH].frequency/* DEBUG *   Define it if you want verbose debug output, e.g. for bug reporting *///#define SPEEDSTEP_DEBUG#ifdef SPEEDSTEP_DEBUG#define dprintk(msg...) printk(msg)#else#define dprintk(msg...) do { } while(0)#endif/********************************************************************* *                    LOW LEVEL CHIPSET INTERFACE                    * *********************************************************************//** * speedstep_get_state - read the current SpeedStep state * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * *   Tries to read the SpeedStep state. Returns -EIO when there has been * trouble to read the status or write to the control register, -EINVAL * on an unsupported chipset, and zero on success. */static int speedstep_get_state (unsigned int *state){	unsigned long   flags;	u32             pmbase;	u8              value;	if (!speedstep_chipset_dev || !state)		return -EINVAL;	switch (speedstep_chipset) {	case SPEEDSTEP_CHIPSET_ICH2M:	case SPEEDSTEP_CHIPSET_ICH3M:		/* get PMBASE */		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);		if (!(pmbase & 0x01))			return -EIO;		pmbase &= 0xFFFFFFFE;		if (!pmbase) 			return -EIO;		/* read state */		local_irq_save(flags);		value = inb(pmbase + 0x50);		local_irq_restore(flags);		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);		*state = value & 0x01;		return 0;	}	printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n");	return -EINVAL;}/** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * *   Tries to change the SpeedStep state.  */static void speedstep_set_state (unsigned int state, int notify){	u32                     pmbase;	u8	                pm2_blk;	u8                      value;	unsigned long           flags;	unsigned int            oldstate;	struct cpufreq_freqs    freqs;	if (!speedstep_chipset_dev || (state > 0x1))		return;	if (speedstep_get_state(&oldstate))		return;	if (oldstate == state)		return;	freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq;	freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq;	freqs.cpu = 0; /* speedstep.c is UP only driver */		if (notify)		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);	switch (speedstep_chipset) {	case SPEEDSTEP_CHIPSET_ICH2M:	case SPEEDSTEP_CHIPSET_ICH3M:		/* get PMBASE */		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);		if (!(pmbase & 0x01))		{			printk(KERN_ERR "cpufreq: could not find speedstep register\n");			return;		}		pmbase &= 0xFFFFFFFE;		if (!pmbase) {			printk(KERN_ERR "cpufreq: could not find speedstep register\n");			return;		}		/* Disable IRQs */		local_irq_save(flags);		/* read state */		value = inb(pmbase + 0x50);		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);		/* write new state */		value &= 0xFE;		value |= state;		dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);		/* Disable bus master arbitration */		pm2_blk = inb(pmbase + 0x20);		pm2_blk |= 0x01;		outb(pm2_blk, (pmbase + 0x20));		/* Actual transition */		outb(value, (pmbase + 0x50));		/* Restore bus master arbitration */		pm2_blk &= 0xfe;		outb(pm2_blk, (pmbase + 0x20));		/* check if transition was sucessful */		value = inb(pmbase + 0x50);		/* Enable IRQs */		local_irq_restore(flags);		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);		if (state == (value & 0x1)) {			dprintk (KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000));		} else {			printk (KERN_ERR "cpufreq: change failed - I/O error\n");		}		break;	default:		printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n");	}	if (notify)		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);	return;}/** * speedstep_activate - activate SpeedStep control in the chipset * *   Tries to activate the SpeedStep status and control registers. * Returns -EINVAL on an unsupported chipset, and zero on success. */static int speedstep_activate (void){	if (!speedstep_chipset_dev)		return -EINVAL;	switch (speedstep_chipset) {	case SPEEDSTEP_CHIPSET_ICH2M:	case SPEEDSTEP_CHIPSET_ICH3M:	{		u16             value = 0;		pci_read_config_word(speedstep_chipset_dev, 				     0x00A0, &value);		if (!(value & 0x08)) {			value |= 0x08;			dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");			pci_write_config_word(speedstep_chipset_dev, 					      0x00A0, value);		}		return 0;	}	}		printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n");	return -EINVAL;}/** * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic * *   Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to  * the LPC bridge / PM module which contains all power-management  * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected * chipset, or zero on failure. */static unsigned int speedstep_detect_chipset (void){	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,			      PCI_DEVICE_ID_INTEL_82801CA_12, 			      PCI_ANY_ID,			      PCI_ANY_ID,			      NULL);	if (speedstep_chipset_dev)		return SPEEDSTEP_CHIPSET_ICH3M;	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,			      PCI_DEVICE_ID_INTEL_82801BA_10,			      PCI_ANY_ID,			      PCI_ANY_ID,			      NULL);	if (speedstep_chipset_dev) {		/* speedstep.c causes lockups on Dell Inspirons 8000 and		 * 8100 which use a pretty old revision of the 82815 		 * host brige. Abort on these systems.		 */		static struct pci_dev   *hostbridge;		u8			rev = 0;		hostbridge  = pci_find_subsys(PCI_VENDOR_ID_INTEL,			      PCI_DEVICE_ID_INTEL_82815_MC,			      PCI_ANY_ID,			      PCI_ANY_ID,			      NULL);		if (!hostbridge)			return SPEEDSTEP_CHIPSET_ICH2M;					pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);		if (rev < 5) {			dprintk(KERN_INFO "cpufreq: hostbrige does not support speedstep\n");			speedstep_chipset_dev = NULL;			return 0;		}		return SPEEDSTEP_CHIPSET_ICH2M;	}	return 0;}/********************************************************************* *                   LOW LEVEL PROCESSOR INTERFACE                   * *********************************************************************//** * pentium3_get_frequency - get the core frequencies for PIIIs * *   Returns the core frequency of a Pentium III processor (in kHz) */static unsigned int pentium3_get_frequency (void){        /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */	struct {		unsigned int ratio;	/* Frequency Multiplier (x10) */		u8 bitmap;	        /* power on configuration bits					   [27, 25:22] (in MSR 0x2a) */	} msr_decode_mult [] = {		{ 30, 0x01 },		{ 35, 0x05 },		{ 40, 0x02 },		{ 45, 0x06 },		{ 50, 0x00 },		{ 55, 0x04 },		{ 60, 0x0b },		{ 65, 0x0f },		{ 70, 0x09 },		{ 75, 0x0d },		{ 80, 0x0a },		{ 85, 0x26 },		{ 90, 0x20 },		{ 100, 0x2b },		{ 0, 0xff }     /* error or unknown value */	};	/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */	struct {		unsigned int value;     /* Front Side Bus speed in MHz */		u8 bitmap;              /* power on configuration bits [18: 19]					   (in MSR 0x2a) */	} msr_decode_fsb [] = {

⌨️ 快捷键说明

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