* Committed Clemens Zeidler's Intel speedstep driver. Thanks a lot, Clemens!

This is a very welcome addition.
* There are a few issues, and maybe questionable decisions (like the dependence
  on ACPI), but I see no reason why it shouldn't be added in its current form
  already.
* Unfortunately, I could not test it yet, though, as the CPU of my laptop is
  not supported; will see if I can find a supported hardware, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28903 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2009-01-14 21:08:37 +00:00
parent 7a6bda7716
commit 40890e97b3
20 changed files with 3959 additions and 0 deletions

View File

@ -0,0 +1,39 @@
#ifndef POWER_MANAGMENT_H
#define POWER_MANAGMENT_H
#include <Drivers.h>
// io controls
enum {
// ioctl response with kMagicFreqID
IDENTIFY_DEVICE = B_DEVICE_OP_CODES_END + 20001,
// CPU Frequence:
// get a list of freq_info, the list is terminated with a element with
// frequency = 0
GET_CPU_FREQ_STATES = B_DEVICE_OP_CODES_END + 20005,
// get and set a freq_info
GET_CURENT_CPU_FREQ_STATE,
SET_CPU_FREQ_STATE,
// start watching for frequency changes, ioctl blocks until the frequency
// has changed
WATCH_CPU_FREQ,
// stop all watching ioctl, ioctl return B_ERROR
STOP_WATCHING_CPU_FREQ
};
// CPU Frequence:
// magic id returned by IDENTIFY_DEVICE
const uint32 kMagicFreqID = 48921;
#define MAX_CPU_FREQUENCY_STATES 10
typedef struct {
uint16 frequency; // [Mhz]
uint16 volts;
uint16 id;
int power;
} freq_info;
#endif

View File

@ -3,3 +3,4 @@ SubDir HAIKU_TOP src add-ons kernel drivers power ;
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ;
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ;

View File

@ -0,0 +1,18 @@
SubDir HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ;
SetSubDirSupportedPlatformsBeOSCompatible ;
if $(TARGET_PLATFORM) != haiku {
# Needed for <ACPI.h>. Unfortunately we also get the other headers there,
# that we don't really want.
UsePublicHeaders drivers ;
}
UsePrivateHeaders kernel ;
KernelAddon enhanced_speedstep :
enhanced_speedstep.cpp
frequency.cpp
;
Depends acpi_enhanced_speedstep : acpi ;

View File

@ -0,0 +1,425 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include <KernelExport.h>
#include <Drivers.h>
#include <Errors.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <kernel/arch/x86/arch_cpu.h>
#include <ACPI.h>
#include "enhanced_speedstep.h"
#include <condition_variable.h>
#include "frequency.h"
#define EST_MODULE_NAME "drivers/power/enhanced_speedstep/driver_v1"
#define EST_DEVICE_MODULE_NAME "drivers/power/enhanced_speedstep/device_v1"
/* Base Namespace devices are published to */
#define EST_BASENAME "power/enhanced_speedstep/%d"
// name of pnp generator of path ids
#define EST_PATHID_GENERATOR "est/path_id"
static device_manager_info *sDeviceManager;
static ConditionVariable cv_frequency;
vint32 current_id;
status_t est_control(void* _cookie, uint32 op, void* arg, size_t len);
static status_t
est_open(void *initCookie, const char *path, int flags, void** cookie)
{
TRACE("est: open\n");
est_cookie *device = (est_cookie*)initCookie;
*cookie = device;
device->stop_watching = 0;
// enable enhanced speedstep
TRACE("est: check if enhanced speedstep is enabled\n");
uint64 msrMisc = x86_read_msr(MSR_MISC);
if ((msrMisc & MSR_EST_ENABLED) == 0) {
TRACE("est: enable enhanced speedstep\n");
x86_write_msr(MSR_MISC, msrMisc | MSR_EST_ENABLED);
uint64 msrMisc = x86_read_msr(MSR_MISC);
if ((msrMisc & MSR_EST_ENABLED) == 0) {
TRACE("est: enable enhanced speedstep failed\n");
return B_ERROR;
}
}
// get freq_info
if (est_get_info(&(device->available_states)) != B_OK)
return B_ERROR;
freq_info *freqsInfo = device->available_states;
// count number of states
TRACE("est: frequency info:\n");
freq_info *f;
device->number_states = 0;
for (f = freqsInfo; f->frequency != 0; f++) {
TRACE("est: Frequency %u, Volts %u, Power %i, Latency %u, id %u\n",
f->frequency, f->volts, f->power, f->id, EST_TRANS_LAT);
device->number_states++;
}
// print current frequency
freq_info *f2 = est_get_current(freqsInfo);
if (f2) {
TRACE("est: Current Frequency %u, Volts %u, Power %i, Latency %u\n",
f2->frequency, f2->volts, f2->power, EST_TRANS_LAT);
}
return B_OK;
}
static status_t
est_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
{
TRACE("est: est_read\n");
if (*num_bytes < 1)
return B_IO_ERROR;
est_cookie *device = (est_cookie *)_cookie;
if (position == 0) {
size_t max_len = *num_bytes;
char *str = (char *)buf;
snprintf(str, max_len, "CPU Frequency states:\n");
max_len-= strlen(str);
str += strlen(str);
freq_info *freqsInfo = device->available_states;
freq_info *f;
for (f = freqsInfo; f->frequency != 0; f++) {
snprintf(str, max_len, " Frequency %hu, Volts %hu, Power %i, Latency %i, id %hu\n",
f->frequency, f->volts, f->power, f->id,
EST_TRANS_LAT);
max_len-= strlen(str);
str += strlen(str);
}
freq_info *f2 = est_get_current(freqsInfo);
if (f2) {
snprintf(str, max_len, "\nCurrent State: Frequency %hu, Volts %hu, Power %i, Latency %i\n",
f2->frequency, f2->volts, f2->power, EST_TRANS_LAT);
}
*num_bytes = strlen((char *)buf);
} else {
*num_bytes = 0;
}
return B_OK;
}
static status_t
est_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
{
return B_ERROR;
}
status_t
est_control(void* _cookie, uint32 op, void* arg, size_t len)
{
TRACE("est: est_control op %u\n", int(op));
est_cookie* device = (est_cookie*)_cookie;
status_t err = B_ERROR;
uint32* magicId;
uint16* id;
freq_info* freqInfo = NULL;
switch (op) {
case IDENTIFY_DEVICE:
if (len < sizeof(uint32))
return B_IO_ERROR;
magicId = (uint32*)arg;
*magicId = kMagicFreqID;
err = B_OK;
break;
case GET_CPU_FREQ_STATES:
if (len < sizeof(freq_info) * (device->number_states + 1))
return B_IO_ERROR;
freqInfo = (freq_info*)arg;
user_memcpy(freqInfo, device->available_states,
sizeof(freq_info) * (device->number_states + 1));
err = B_OK;
break;
case GET_CURENT_CPU_FREQ_STATE:
if (len < sizeof(uint16))
return B_IO_ERROR;
freqInfo = est_get_current(device->available_states);
if (!freqInfo)
return B_ERROR;
atomic_set(&current_id, freqInfo->id);
*((uint16*)arg) = freqInfo->id;
err = B_OK;
break;
case SET_CPU_FREQ_STATE:
if (len < sizeof(uint16))
return B_IO_ERROR;
id = (uint16*)arg;
err = est_set_id16(*id);
if (err == B_OK) {
atomic_set(&current_id, *id);
cv_frequency.NotifyAll();
}
break;
case WATCH_CPU_FREQ:
if (len < sizeof(uint16))
return B_IO_ERROR;
cv_frequency.Wait();
if (atomic_get(&(device->stop_watching))) {
atomic_set(&(device->stop_watching), 0);
err = B_ERROR;
}
else {
*((uint16*)arg) = atomic_get(&current_id);
err = B_OK;
}
break;
case STOP_WATCHING_CPU_FREQ:
atomic_set(&(device->stop_watching), 1);
cv_frequency.NotifyAll();
err = B_OK;
break;
}
return err;
}
static status_t
est_close (void* cookie)
{
return B_OK;
}
static status_t
est_free (void* cookie)
{
return B_OK;
}
// #pragma mark - driver module API
static float
est_support(device_node *parent)
{
const char *bus;
uint32 device_type;
dprintf("EST1\n");
// make sure parent is really the ACPI bus manager
if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
return -1;
dprintf("EST2\n");
if (strcmp(bus, "acpi"))
return 0.0;
dprintf("EST3\n");
// check whether it's really a cpu Device
if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM,
&device_type, false) != B_OK
|| device_type != ACPI_TYPE_PROCESSOR) {
return 0.0;
}
dprintf("EST4\n");
TRACE("est_support: supported\n");
// check if cpu support est
uint32 cpuNum = 0;
system_info sysInfo;
if (get_system_info(&sysInfo) != B_OK)
return 0.0;
TRACE("cpu_type: %u vendor %u model %u\n", sysInfo.cpu_type,
sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK,
sysInfo.cpu_type & 0x00FF);
dprintf("EST5\n");
if ((sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK) != B_CPU_INTEL_x86)
return 0.0;
dprintf("EST6\n");
TRACE("ext\n");
cpuid_info info;
if (get_cpuid(&info, 1, cpuNum) != B_OK)
return 0.0;
dprintf("EST7\n");
TRACE("extended_features: %i\n", int(info.eax_1.extended_features));
dprintf("EST8\n");
// check for enhanced speedstep
if (info.eax_1.extended_features & IA32_FEATURE_EXT_EST)
TRACE("supprot est\n");
else
return 0.0;
dprintf("EST9\n");
TRACE("success\n");
return 0.6;
}
static status_t
est_register_device(device_node *node)
{
device_attr attrs[] = {
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
{ string: "ACPI Enhanced Speedstep" }},
{ NULL }
};
return sDeviceManager->register_node(node, EST_MODULE_NAME, attrs,
NULL, NULL);
}
static status_t
est_init_driver(device_node *node, void **_driverCookie)
{
*_driverCookie = node;
cv_frequency.Init(NULL, "frequency cv");
current_id = -1;
return B_OK;
}
static void
est_uninit_driver(void *driverCookie)
{
}
static status_t
est_register_child_devices(void *_cookie)
{
device_node *node = (device_node*)_cookie;
int path_id;
char name[128];
path_id = sDeviceManager->create_id(EST_PATHID_GENERATOR);
if (path_id < 0) {
TRACE("est_register_child_devices: couldn't create a path_id\n");
return B_ERROR;
}
snprintf(name, sizeof(name), EST_BASENAME, path_id);
return sDeviceManager->publish_device(node, name, EST_DEVICE_MODULE_NAME);
}
static status_t
est_init_device(void *driverCookie, void **cookie)
{
est_cookie *device;
device = (est_cookie *)calloc(1, sizeof(est_cookie));
if (device == NULL)
return B_NO_MEMORY;
*cookie = device;
device_node *node = (device_node *)driverCookie;
device->node = node;
device_node *parent;
parent = sDeviceManager->get_parent_node(node);
sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
(void **)&device->acpi_cookie);
sDeviceManager->put_node(parent);
return B_OK;
}
static void
est_uninit_device(void *_cookie)
{
TRACE("est: est_uninit_device\n");
est_cookie *device = (est_cookie*)_cookie;
free(device);
}
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
{}
};
driver_module_info est_driver_module = {
{
EST_MODULE_NAME,
0,
NULL
},
est_support,
est_register_device,
est_init_driver,
est_uninit_driver,
est_register_child_devices,
NULL, // rescan
NULL, // removed
};
struct device_module_info est_device_module = {
{
EST_DEVICE_MODULE_NAME,
0,
NULL
},
est_init_device,
est_uninit_device,
NULL,
est_open,
est_close,
est_free,
est_read,
est_write,
NULL,
est_control,
NULL,
NULL
};
module_info *modules[] = {
(module_info *)&est_driver_module,
(module_info *)&est_device_module,
NULL
};

View File

@ -0,0 +1,29 @@
#ifndef _EST_H
#define _EST_H
#include <KernelExport.h>
#include <ACPI.h>
#include "frequency.h"
// Model Specific Register
#define MSR_MISC 0x1a0
#define MSR_EST_ENABLED (1<<16)
struct est_cookie {
// this three variables are not needed yet but helpfull when extend this
// driver to use acpi
device_node *node;
acpi_device_module_info *acpi;
acpi_device acpi_cookie;
// array of states don't delete it
freq_info* available_states;
uint8 number_states;
vint32 stop_watching;
};
#endif /* _EST_H */

View File

@ -0,0 +1,197 @@
#include "frequency.h"
#include <kernel/arch/x86/arch_cpu.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
est_get_id16(uint16 *id16_p)
{
*id16_p = x86_read_msr(MSR_GET_FREQ_STATE) & 0xffff;
}
status_t
est_set_id16(uint16 id16, bool need_check)
{
uint64 msr;
// Read the current register, mask out the old, set the new id.
msr = x86_read_msr(MSR_GET_FREQ_STATE);
msr = (msr & ~0xffff) | id16;
x86_write_msr(MSR_SET_FREQ_STATE, msr);
if (need_check) {
// Wait a short while for the new setting. XXX Is this necessary?
snooze(EST_TRANS_LAT);
uint16 new_id16;
est_get_id16(&new_id16);
if (new_id16 != id16)
return B_ERROR;
TRACE("EST: set frequency ok, id %i\n", id16);
}
return B_OK;
}
freq_info *
est_get_current(freq_info *freq_list)
{
freq_info *f;
int i;
uint16 id16;
/*
* Try a few times to get a valid value. Sometimes, if the CPU
* is in the middle of an asynchronous transition (i.e., P4TCC),
* we get a temporary invalid result.
*/
for (i = 0; i < 5; i++) {
est_get_id16(&id16);
for (f = freq_list; f->id != 0; f++) {
if (f->id == id16)
return (f);
}
snooze(100);
}
return NULL;
}
status_t
est_get_info(freq_info **freqsInfo)
{
uint64 msr;
status_t error = B_ERROR;
msr = x86_read_msr(MSR_GET_FREQ_STATE);
error = est_table_info(msr, freqsInfo);
if (error != B_OK) {
TRACE("EST: Get frequency table from model specific register\n");
error = est_msr_info(msr, freqsInfo);
}
if (error) {
TRACE("est: CPU supports Enhanced Speedstep, but is not recognized.\n");
return error;
}
return B_OK;
}
status_t
est_table_info(uint64 msr, freq_info **freqs)
{
ss_cpu_info *p;
uint32 id;
/* Find a table which matches (vendor, id32). */
system_info sysInfo;
if (get_system_info(&sysInfo) != B_OK)
return B_ERROR;
id = msr >> 32;
for (p = ESTprocs; p->id32 != 0; p++) {
if (p->vendor_id == uint32(sysInfo.cpu_type & B_CPU_x86_VENDOR_MASK)
&& p->id32 == id)
break;
}
if (p->id32 == 0)
return B_ERROR;
/* Make sure the current setpoint is valid. */
if (est_get_current(p->freqtab) == NULL) {
TRACE("current setting not found in table\n");
return B_ERROR;
}
*freqs = p->freqtab;
return B_OK;
}
bool
bus_speed_ok(int bus)
{
switch (bus) {
case 100:
case 133:
case 333:
return true;
default:
return false;
}
}
/*
* Flesh out a simple rate table containing the high and low frequencies
* based on the current clock speed and the upper 32 bits of the MSR.
*/
status_t
est_msr_info(uint64 msr, freq_info **freqs)
{
freq_info *fp;
int32 bus, freq, volts;
uint16 id;
// Figure out the bus clock.
system_info sysInfo;
if (get_system_info(&sysInfo) != B_OK)
return B_ERROR;
freq = sysInfo.cpu_clock_speed / 1000000;
id = msr >> 32;
bus = freq / (id >> 8);
TRACE("est: Guessed bus clock (high) of %d MHz\n", int(bus));
if (!bus_speed_ok(bus)) {
// We may be running on the low frequency.
id = msr >> 48;
bus = freq / (id >> 8);
TRACE("est: Guessed bus clock (low) of %d MHz\n", int(bus));
if (!bus_speed_ok(bus))
return B_ERROR;
// Calculate high frequency.
id = msr >> 32;
freq = ((id >> 8) & 0xff) * bus;
}
// Fill out a new freq table containing just the high and low freqs.
fp = (freq_info*)malloc(sizeof(freq_info) * 3);
memset(fp, 0, sizeof(freq_info) * 3);
// First, the high frequency.
volts = id & 0xff;
if (volts != 0) {
volts <<= 4;
volts += 700;
}
fp[0].frequency = freq;
fp[0].volts = volts;
fp[0].id = id;
fp[0].power = CPUFREQ_VAL_UNKNOWN;
TRACE("Guessed high setting of %d MHz @ %d Mv\n", int(freq), int(volts));
// Second, the low frequency.
id = msr >> 48;
freq = ((id >> 8) & 0xff) * bus;
volts = id & 0xff;
if (volts != 0) {
volts <<= 4;
volts += 700;
}
fp[1].frequency = freq;
fp[1].volts = volts;
fp[1].id = id;
fp[1].power = CPUFREQ_VAL_UNKNOWN;
TRACE("Guessed low setting of %d MHz @ %d Mv\n", int(freq), int(volts));
// Table is already terminated due to M_ZERO.
*freqs = fp;
return B_OK;
}

View File

@ -0,0 +1,852 @@
#ifndef FREQ_TABLE_H
#define FREQ_TABLE_H
#include <OS.h>
#include <KernelExport.h>
#include <Errors.h>
#include "device/power_managment.h"
#define TRACE_EST
#ifdef TRACE_EST
# define TRACE(x...) dprintf(x)
#else
# define TRACE(x...)
#endif
// this code is taken from freeBSD
#define MSR_GET_FREQ_STATE 0x198
#define MSR_SET_FREQ_STATE 0x199
/* Estimate in microseconds of latency for performing a transition. */
#define EST_TRANS_LAT 1000
/* Identifying characteristics of a processor and supported frequencies. */
typedef struct {
const uint32 vendor_id;
uint32 id32;
freq_info *freqtab;
} ss_cpu_info;
status_t est_get_info(freq_info **freqsInfo);
status_t est_table_info(uint64 msr, freq_info **freqs);
status_t est_msr_info(uint64 msr, freq_info **freqs);
freq_info* est_get_current(freq_info *freq_list);
void est_get_id16(uint16 *id16_p);
status_t est_set_id16(uint16 id16, bool need_check = false);
/* Convert MHz and mV into IDs for passing to the MSR. */
#define ID16(MHz, mV, bus_clk) \
(((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
#define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk) \
((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
/* Format for storing IDs in our table. */
#define CPUFREQ_VAL_UNKNOWN (-1)
#define CPU_VENDOR_INTEL B_CPU_INTEL_x86
#define CPU_VENDOR_CENTAUR B_CPU_VIA_IDT_x86
#define FREQ_INFO_PWR(MHz, mV, bus_clk, mW) \
{ MHz, mV, ID16(MHz, mV, bus_clk), mW }
#define FREQ_INFO(MHz, mV, bus_clk) \
FREQ_INFO_PWR(MHz, mV, bus_clk, CPUFREQ_VAL_UNKNOWN)
#define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \
{ CPU_VENDOR_INTEL, ID32(zhi, vhi, zlo, vlo, bus_clk), tab }
#define CENTAUR(tab, zhi, vhi, zlo, vlo, bus_clk) \
{ CPU_VENDOR_CENTAUR, ID32(zhi, vhi, zlo, vlo, bus_clk), tab }
/* Default bus clock value for Centrino processors. */
#define INTEL_BUS_CLK 100
/*
* Frequency (MHz) and voltage (mV) settings. Data from the
* Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
*
* Dothan processors have multiple VID#s with different settings for
* each VID#. Since we can't uniquely identify this info
* without undisclosed methods from Intel, we can't support newer
* processors with this table method. If ACPI Px states are supported,
* we get info from them.
*/
static freq_info PM17_130[] = {
/* 130nm 1.70GHz Pentium M */
FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM16_130[] = {
/* 130nm 1.60GHz Pentium M */
FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM15_130[] = {
/* 130nm 1.50GHz Pentium M */
FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM14_130[] = {
/* 130nm 1.40GHz Pentium M */
FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM13_130[] = {
/* 130nm 1.30GHz Pentium M */
FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM13_LV_130[] = {
/* 130nm 1.30GHz Low Voltage Pentium M */
FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
FREQ_INFO( 800, 988, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM12_LV_130[] = {
/* 130 nm 1.20GHz Low Voltage Pentium M */
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM11_LV_130[] = {
/* 130 nm 1.10GHz Low Voltage Pentium M */
FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM11_ULV_130[] = {
/* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
FREQ_INFO(1000, 988, INTEL_BUS_CLK),
FREQ_INFO( 900, 972, INTEL_BUS_CLK),
FREQ_INFO( 800, 956, INTEL_BUS_CLK),
FREQ_INFO( 600, 844, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM10_ULV_130[] = {
/* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
FREQ_INFO( 900, 988, INTEL_BUS_CLK),
FREQ_INFO( 800, 972, INTEL_BUS_CLK),
FREQ_INFO( 600, 844, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
/*
* Data from "Intel Pentium M Processor on 90nm Process with
* 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
*/
static freq_info PM_765A_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #A */
FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_765B_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #B */
FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_765C_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #C */
FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_765E_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #E */
FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_755A_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #A */
FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_755B_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #B */
FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_755C_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #C */
FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_755D_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #D */
FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_745A_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #A */
FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_745B_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #B */
FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_745C_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #C */
FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_745D_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #D */
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_735A_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #A */
FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_735B_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #B */
FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_735C_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #C */
FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_735D_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #D */
FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_725A_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #A */
FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_725B_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #B */
FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_725C_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #C */
FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_725D_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #D */
FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_715A_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #A */
FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_715B_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #B */
FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_715C_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #C */
FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_715D_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #D */
FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_778_90[] = {
/* 90 nm 1.60GHz Low Voltage Pentium M */
FREQ_INFO(1600, 1116, INTEL_BUS_CLK),
FREQ_INFO(1500, 1116, INTEL_BUS_CLK),
FREQ_INFO(1400, 1100, INTEL_BUS_CLK),
FREQ_INFO(1300, 1084, INTEL_BUS_CLK),
FREQ_INFO(1200, 1068, INTEL_BUS_CLK),
FREQ_INFO(1100, 1052, INTEL_BUS_CLK),
FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_758_90[] = {
/* 90 nm 1.50GHz Low Voltage Pentium M */
FREQ_INFO(1500, 1116, INTEL_BUS_CLK),
FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
FREQ_INFO(1300, 1100, INTEL_BUS_CLK),
FREQ_INFO(1200, 1084, INTEL_BUS_CLK),
FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_738_90[] = {
/* 90 nm 1.40GHz Low Voltage Pentium M */
FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_773G_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #G */
FREQ_INFO(1300, 956, INTEL_BUS_CLK),
FREQ_INFO(1200, 940, INTEL_BUS_CLK),
FREQ_INFO(1100, 924, INTEL_BUS_CLK),
FREQ_INFO(1000, 908, INTEL_BUS_CLK),
FREQ_INFO( 900, 876, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_773H_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #H */
FREQ_INFO(1300, 940, INTEL_BUS_CLK),
FREQ_INFO(1200, 924, INTEL_BUS_CLK),
FREQ_INFO(1100, 908, INTEL_BUS_CLK),
FREQ_INFO(1000, 892, INTEL_BUS_CLK),
FREQ_INFO( 900, 876, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_773I_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #I */
FREQ_INFO(1300, 924, INTEL_BUS_CLK),
FREQ_INFO(1200, 908, INTEL_BUS_CLK),
FREQ_INFO(1100, 892, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_773J_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #J */
FREQ_INFO(1300, 908, INTEL_BUS_CLK),
FREQ_INFO(1200, 908, INTEL_BUS_CLK),
FREQ_INFO(1100, 892, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_773K_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #K */
FREQ_INFO(1300, 892, INTEL_BUS_CLK),
FREQ_INFO(1200, 892, INTEL_BUS_CLK),
FREQ_INFO(1100, 876, INTEL_BUS_CLK),
FREQ_INFO(1000, 860, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_773L_90[] = {
/* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #L */
FREQ_INFO(1300, 876, INTEL_BUS_CLK),
FREQ_INFO(1200, 876, INTEL_BUS_CLK),
FREQ_INFO(1100, 860, INTEL_BUS_CLK),
FREQ_INFO(1000, 860, INTEL_BUS_CLK),
FREQ_INFO( 900, 844, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753G_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #G */
FREQ_INFO(1200, 956, INTEL_BUS_CLK),
FREQ_INFO(1100, 940, INTEL_BUS_CLK),
FREQ_INFO(1000, 908, INTEL_BUS_CLK),
FREQ_INFO( 900, 892, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753H_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #H */
FREQ_INFO(1200, 940, INTEL_BUS_CLK),
FREQ_INFO(1100, 924, INTEL_BUS_CLK),
FREQ_INFO(1000, 908, INTEL_BUS_CLK),
FREQ_INFO( 900, 876, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753I_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #I */
FREQ_INFO(1200, 924, INTEL_BUS_CLK),
FREQ_INFO(1100, 908, INTEL_BUS_CLK),
FREQ_INFO(1000, 892, INTEL_BUS_CLK),
FREQ_INFO( 900, 876, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753J_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #J */
FREQ_INFO(1200, 908, INTEL_BUS_CLK),
FREQ_INFO(1100, 892, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753K_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #K */
FREQ_INFO(1200, 892, INTEL_BUS_CLK),
FREQ_INFO(1100, 892, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_753L_90[] = {
/* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #L */
FREQ_INFO(1200, 876, INTEL_BUS_CLK),
FREQ_INFO(1100, 876, INTEL_BUS_CLK),
FREQ_INFO(1000, 860, INTEL_BUS_CLK),
FREQ_INFO( 900, 844, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JG_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #G */
FREQ_INFO(1100, 956, INTEL_BUS_CLK),
FREQ_INFO(1000, 940, INTEL_BUS_CLK),
FREQ_INFO( 900, 908, INTEL_BUS_CLK),
FREQ_INFO( 800, 876, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JH_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #H */
FREQ_INFO(1100, 940, INTEL_BUS_CLK),
FREQ_INFO(1000, 924, INTEL_BUS_CLK),
FREQ_INFO( 900, 892, INTEL_BUS_CLK),
FREQ_INFO( 800, 876, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JI_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #I */
FREQ_INFO(1100, 924, INTEL_BUS_CLK),
FREQ_INFO(1000, 908, INTEL_BUS_CLK),
FREQ_INFO( 900, 892, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JJ_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #J */
FREQ_INFO(1100, 908, INTEL_BUS_CLK),
FREQ_INFO(1000, 892, INTEL_BUS_CLK),
FREQ_INFO( 900, 876, INTEL_BUS_CLK),
FREQ_INFO( 800, 860, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JK_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #K */
FREQ_INFO(1100, 892, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733JL_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #L */
FREQ_INFO(1100, 876, INTEL_BUS_CLK),
FREQ_INFO(1000, 876, INTEL_BUS_CLK),
FREQ_INFO( 900, 860, INTEL_BUS_CLK),
FREQ_INFO( 800, 844, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
};
static freq_info PM_733_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1100, 940, INTEL_BUS_CLK),
FREQ_INFO(1000, 924, INTEL_BUS_CLK),
FREQ_INFO( 900, 892, INTEL_BUS_CLK),
FREQ_INFO( 800, 876, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
static freq_info PM_723_90[] = {
/* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1000, 940, INTEL_BUS_CLK),
FREQ_INFO( 900, 908, INTEL_BUS_CLK),
FREQ_INFO( 800, 876, INTEL_BUS_CLK),
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
/*
* VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants.
* Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet.
*/
static freq_info C7M_795[] = {
/* 2.00GHz Centaur C7-M 533 Mhz FSB */
FREQ_INFO_PWR(2000, 1148, 133, 20000),
FREQ_INFO_PWR(1867, 1132, 133, 18000),
FREQ_INFO_PWR(1600, 1100, 133, 15000),
FREQ_INFO_PWR(1467, 1052, 133, 13000),
FREQ_INFO_PWR(1200, 1004, 133, 10000),
FREQ_INFO_PWR( 800, 844, 133, 7000),
FREQ_INFO_PWR( 667, 844, 133, 6000),
FREQ_INFO_PWR( 533, 844, 133, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_785[] = {
/* 1.80GHz Centaur C7-M 533 Mhz FSB */
FREQ_INFO_PWR(1867, 1148, 133, 18000),
FREQ_INFO_PWR(1600, 1100, 133, 15000),
FREQ_INFO_PWR(1467, 1052, 133, 13000),
FREQ_INFO_PWR(1200, 1004, 133, 10000),
FREQ_INFO_PWR( 800, 844, 133, 7000),
FREQ_INFO_PWR( 667, 844, 133, 6000),
FREQ_INFO_PWR( 533, 844, 133, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_765[] = {
/* 1.60GHz Centaur C7-M 533 Mhz FSB */
FREQ_INFO_PWR(1600, 1084, 133, 15000),
FREQ_INFO_PWR(1467, 1052, 133, 13000),
FREQ_INFO_PWR(1200, 1004, 133, 10000),
FREQ_INFO_PWR( 800, 844, 133, 7000),
FREQ_INFO_PWR( 667, 844, 133, 6000),
FREQ_INFO_PWR( 533, 844, 133, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_794[] = {
/* 2.00GHz Centaur C7-M 400 Mhz FSB */
FREQ_INFO_PWR(2000, 1148, 100, 20000),
FREQ_INFO_PWR(1800, 1132, 100, 18000),
FREQ_INFO_PWR(1600, 1100, 100, 15000),
FREQ_INFO_PWR(1400, 1052, 100, 13000),
FREQ_INFO_PWR(1000, 1004, 100, 10000),
FREQ_INFO_PWR( 800, 844, 100, 7000),
FREQ_INFO_PWR( 600, 844, 100, 6000),
FREQ_INFO_PWR( 400, 844, 100, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_784[] = {
/* 1.80GHz Centaur C7-M 400 Mhz FSB */
FREQ_INFO_PWR(1800, 1148, 100, 18000),
FREQ_INFO_PWR(1600, 1100, 100, 15000),
FREQ_INFO_PWR(1400, 1052, 100, 13000),
FREQ_INFO_PWR(1000, 1004, 100, 10000),
FREQ_INFO_PWR( 800, 844, 100, 7000),
FREQ_INFO_PWR( 600, 844, 100, 6000),
FREQ_INFO_PWR( 400, 844, 100, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_764[] = {
/* 1.60GHz Centaur C7-M 400 Mhz FSB */
FREQ_INFO_PWR(1600, 1084, 100, 15000),
FREQ_INFO_PWR(1400, 1052, 100, 13000),
FREQ_INFO_PWR(1000, 1004, 100, 10000),
FREQ_INFO_PWR( 800, 844, 100, 7000),
FREQ_INFO_PWR( 600, 844, 100, 6000),
FREQ_INFO_PWR( 400, 844, 100, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_754[] = {
/* 1.50GHz Centaur C7-M 400 Mhz FSB */
FREQ_INFO_PWR(1500, 1004, 100, 12000),
FREQ_INFO_PWR(1400, 988, 100, 11000),
FREQ_INFO_PWR(1000, 940, 100, 9000),
FREQ_INFO_PWR( 800, 844, 100, 7000),
FREQ_INFO_PWR( 600, 844, 100, 6000),
FREQ_INFO_PWR( 400, 844, 100, 5000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_771[] = {
/* 1.20GHz Centaur C7-M 400 Mhz FSB */
FREQ_INFO_PWR(1200, 860, 100, 7000),
FREQ_INFO_PWR(1000, 860, 100, 6000),
FREQ_INFO_PWR( 800, 844, 100, 5500),
FREQ_INFO_PWR( 600, 844, 100, 5000),
FREQ_INFO_PWR( 400, 844, 100, 4000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_775_ULV[] = {
/* 1.50GHz Centaur C7-M ULV */
FREQ_INFO_PWR(1500, 956, 100, 7500),
FREQ_INFO_PWR(1400, 940, 100, 6000),
FREQ_INFO_PWR(1000, 860, 100, 5000),
FREQ_INFO_PWR( 800, 828, 100, 2800),
FREQ_INFO_PWR( 600, 796, 100, 2500),
FREQ_INFO_PWR( 400, 796, 100, 2000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_772_ULV[] = {
/* 1.20GHz Centaur C7-M ULV */
FREQ_INFO_PWR(1200, 844, 100, 5000),
FREQ_INFO_PWR(1000, 844, 100, 4000),
FREQ_INFO_PWR( 800, 828, 100, 2800),
FREQ_INFO_PWR( 600, 796, 100, 2500),
FREQ_INFO_PWR( 400, 796, 100, 2000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_779_ULV[] = {
/* 1.00GHz Centaur C7-M ULV */
FREQ_INFO_PWR(1000, 796, 100, 3500),
FREQ_INFO_PWR( 800, 796, 100, 2800),
FREQ_INFO_PWR( 600, 796, 100, 2500),
FREQ_INFO_PWR( 400, 796, 100, 2000),
FREQ_INFO(0, 0, 1),
};
static freq_info C7M_770_ULV[] = {
/* 1.00GHz Centaur C7-M ULV */
FREQ_INFO_PWR(1000, 844, 100, 5000),
FREQ_INFO_PWR( 800, 796, 100, 2800),
FREQ_INFO_PWR( 600, 796, 100, 2500),
FREQ_INFO_PWR( 400, 796, 100, 2000),
FREQ_INFO(0, 0, 1),
};
static ss_cpu_info ESTprocs[] = {
INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM14_130, 1400, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM13_130, 1300, 1388, 600, 956, INTEL_BUS_CLK),
INTEL(PM13_LV_130, 1300, 1180, 600, 956, INTEL_BUS_CLK),
INTEL(PM12_LV_130, 1200, 1180, 600, 956, INTEL_BUS_CLK),
INTEL(PM11_LV_130, 1100, 1180, 600, 956, INTEL_BUS_CLK),
INTEL(PM11_ULV_130, 1100, 1004, 600, 844, INTEL_BUS_CLK),
INTEL(PM10_ULV_130, 1000, 1004, 600, 844, INTEL_BUS_CLK),
INTEL(PM_765A_90, 2100, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_765B_90, 2100, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_765C_90, 2100, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_765E_90, 2100, 1356, 600, 988, INTEL_BUS_CLK),
INTEL(PM_755A_90, 2000, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_755B_90, 2000, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_755C_90, 2000, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_755D_90, 2000, 1276, 600, 988, INTEL_BUS_CLK),
INTEL(PM_745A_90, 1800, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_745B_90, 1800, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_745C_90, 1800, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_745D_90, 1800, 1276, 600, 988, INTEL_BUS_CLK),
INTEL(PM_735A_90, 1700, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_735B_90, 1700, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_735C_90, 1700, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_735D_90, 1700, 1276, 600, 988, INTEL_BUS_CLK),
INTEL(PM_725A_90, 1600, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_725B_90, 1600, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_725C_90, 1600, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_725D_90, 1600, 1276, 600, 988, INTEL_BUS_CLK),
INTEL(PM_715A_90, 1500, 1340, 600, 988, INTEL_BUS_CLK),
INTEL(PM_715B_90, 1500, 1324, 600, 988, INTEL_BUS_CLK),
INTEL(PM_715C_90, 1500, 1308, 600, 988, INTEL_BUS_CLK),
INTEL(PM_715D_90, 1500, 1276, 600, 988, INTEL_BUS_CLK),
INTEL(PM_778_90, 1600, 1116, 600, 988, INTEL_BUS_CLK),
INTEL(PM_758_90, 1500, 1116, 600, 988, INTEL_BUS_CLK),
INTEL(PM_738_90, 1400, 1116, 600, 988, INTEL_BUS_CLK),
INTEL(PM_773G_90, 1300, 956, 600, 812, INTEL_BUS_CLK),
INTEL(PM_773H_90, 1300, 940, 600, 812, INTEL_BUS_CLK),
INTEL(PM_773I_90, 1300, 924, 600, 812, INTEL_BUS_CLK),
INTEL(PM_773J_90, 1300, 908, 600, 812, INTEL_BUS_CLK),
INTEL(PM_773K_90, 1300, 892, 600, 812, INTEL_BUS_CLK),
INTEL(PM_773L_90, 1300, 876, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753G_90, 1200, 956, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753H_90, 1200, 940, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753I_90, 1200, 924, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753J_90, 1200, 908, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753K_90, 1200, 892, 600, 812, INTEL_BUS_CLK),
INTEL(PM_753L_90, 1200, 876, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JG_90, 1100, 956, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JH_90, 1100, 940, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JI_90, 1100, 924, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JJ_90, 1100, 908, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JK_90, 1100, 892, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733JL_90, 1100, 876, 600, 812, INTEL_BUS_CLK),
INTEL(PM_733_90, 1100, 940, 600, 812, INTEL_BUS_CLK),
INTEL(PM_723_90, 1000, 940, 600, 812, INTEL_BUS_CLK),
CENTAUR(C7M_795, 2000, 1148, 533, 844, 133),
CENTAUR(C7M_794, 2000, 1148, 400, 844, 100),
CENTAUR(C7M_785, 1867, 1148, 533, 844, 133),
CENTAUR(C7M_784, 1800, 1148, 400, 844, 100),
CENTAUR(C7M_765, 1600, 1084, 533, 844, 133),
CENTAUR(C7M_764, 1600, 1084, 400, 844, 100),
CENTAUR(C7M_754, 1500, 1004, 400, 844, 100),
CENTAUR(C7M_775_ULV, 1500, 956, 400, 796, 100),
CENTAUR(C7M_771, 1200, 860, 400, 844, 100),
CENTAUR(C7M_772_ULV, 1200, 844, 400, 796, 100),
CENTAUR(C7M_779_ULV, 1000, 796, 400, 796, 100),
CENTAUR(C7M_770_ULV, 1000, 844, 400, 796, 100),
{ 0, 0, NULL },
};
#endif

View File

@ -2,6 +2,7 @@ SubDir HAIKU_TOP src preferences ;
SubInclude HAIKU_TOP src preferences appearance ;
SubInclude HAIKU_TOP src preferences backgrounds ;
SubInclude HAIKU_TOP src preferences cpufrequency ;
SubInclude HAIKU_TOP src preferences datatranslations ;
SubInclude HAIKU_TOP src preferences devices ;
#SubInclude HAIKU_TOP src preferences dun ;

View File

@ -0,0 +1,243 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include "CPUFrequencyView.h"
#include "StatusView.h"
#include <Box.h>
#include <Deskbar.h>
#include <GroupView.h>
#include <MenuField.h>
#include <SpaceLayoutItem.h>
const char* kCPUFreqPreferencesFile = "CPUFrequency";
const char* kPrefSignature = "application/x-vnd.Haiku-CPUFrequencyPref";
const char* kPreferencesFileName = "CPUFrequency";
const uint32 kInstallIntoDeskbar = '&iid';
const uint32 kIntegrationTimeChanged = '&itc';
const bigtime_t kMilliSecond = 1000;
CPUFrequencyView::CPUFrequencyView(BRect frame,
PreferencesStorage<freq_preferences>* storage)
: BView(frame, "CPUFrequencyView", B_FOLLOW_NONE, B_WILL_DRAW),
fStorage(storage)
{
BGroupLayout* mainLayout = new BGroupLayout(B_VERTICAL);
SetLayout(mainLayout);
mainLayout->SetSpacing(10);
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// stepping policy
BRect rect = Bounds();
rect.InsetBy(5, 5);
BBox *policyBox = new BBox(rect, "policyBox");
policyBox->SetLabel("Stepping Policy");
BGroupLayout* policyLayout = new BGroupLayout(B_VERTICAL);
policyLayout->SetInsets(10, policyBox->TopBorderOffset() * 2 + 10, 10, 10);
policyLayout->SetSpacing(10);
policyBox->SetLayout(policyLayout);
mainLayout->AddView(policyBox);
fPolicyMenu = new BMenu("Stepping Policy");
BMenuField *menuField = new BMenuField("Stepping Policy", fPolicyMenu);
policyLayout->AddView(menuField);
// dynamic stepping
BBox *dynamicBox = new BBox(rect, "dynamicBox");
dynamicBox->SetLabel("Dynamic Stepping");
BGroupLayout* dynamicLayout = new BGroupLayout(B_VERTICAL);
dynamicLayout->SetInsets(10, dynamicBox->TopBorderOffset() * 2 + 10,
10, 10);
dynamicLayout->SetSpacing(10);
dynamicBox->SetLayout(dynamicLayout);
mainLayout->AddView(dynamicBox);
fColorStepView = new ColorStepView(frame);
fColorStepView->SetFrequencys(fDriverInterface.GetCpuFrequencyStates());
fIntegrationTime = new BTextControl(BRect(0,0,Bounds().Width(),10),
"intergal",
"Integration Time [ms]", "",
new BMessage(kIntegrationTimeChanged));
dynamicLayout->AddView(fColorStepView);
dynamicLayout->AddView(fIntegrationTime);
// status view
BBox *statusBox = new BBox(rect, "statusBox");
statusBox->SetLabel("CPU Frequency Status View");
BGroupLayout* statusLayout = new BGroupLayout(B_HORIZONTAL);
statusLayout->SetInsets(10, statusBox->TopBorderOffset() * 2 + 10, 10, 10);
statusLayout->SetSpacing(10);
statusBox->SetLayout(statusLayout);
mainLayout->AddView(statusBox);
fStatusView = new StatusView(BRect(0, 0, 5, 5), false,
fStorage);
fStatusView->ShowPopUpMenu(false);
fInstallButton = new BButton("installButton",
"Install Replicant into Deskbar",
new BMessage(kInstallIntoDeskbar));
statusLayout->AddView(fStatusView);
statusLayout->AddView(fInstallButton);
statusLayout->AddItem(BSpaceLayoutItem::CreateGlue());
}
void
CPUFrequencyView::MessageReceived(BMessage* message)
{
freq_preferences* pref = fStorage->GetPreferences();
bool configChanged = false;
switch (message->what) {
case kUpdatedPreferences:
fStatusView->MessageReceived(message);
if (pref->mode == DYNAMIC) {
fColorStepView->SetEnabled(true);
fIntegrationTime->SetEnabled(true);
}
else {
fColorStepView->SetEnabled(false);
fIntegrationTime->SetEnabled(false);
}
configChanged = true;
break;
case kSteppingChanged:
// from ColorStepView
pref->stepping_threshold = fColorStepView->GetSliderPosition();
fStorage->SavePreferences();
configChanged = true;
break;
case kIntegrationTimeChanged:
_ReadIntegrationTime();
fStorage->SavePreferences();
configChanged = true;
break;
case kInstallIntoDeskbar:
_InstallReplicantInDeskbar();
break;
case kRevertMsg:
case kDefaultMsg:
fStatusView->UpdateCPUFreqState();
_UpdateViews();
break;
default:
BView::MessageReceived(message);
}
if (configChanged)
Window()->PostMessage(kConfigChangedMsg);
}
void
CPUFrequencyView::AttachedToWindow()
{
fFrequencyMenu = new FrequencyMenu(fPolicyMenu, this,
fStorage, &fDriverInterface);
AddFilter(fFrequencyMenu);
fColorStepView->SetTarget(this);
fIntegrationTime->SetTarget(this);
fInstallButton->SetTarget(this);
_UpdateViews();
}
void
CPUFrequencyView::DetachedFromWindow()
{
// emty menu for the case the view is attached again
while (true) {
BMenuItem* item = fPolicyMenu->RemoveItem(int32(0));
if (!item)
break;
delete item;
}
if (RemoveFilter(fFrequencyMenu))
delete fFrequencyMenu;
_ReadIntegrationTime();
}
status_t
our_image(image_info& image)
{
int32 cookie = 0;
while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) {
if ((char *)our_image >= (char *)image.text
&& (char *)our_image <= (char *)image.text + image.text_size)
return B_OK;
}
return B_ERROR;
};
void
CPUFrequencyView::_InstallReplicantInDeskbar()
{
image_info info;
entry_ref ref;
if (our_image(info) == B_OK
&& get_ref_for_path(info.name, &ref) == B_OK) {
BDeskbar deskbar;
deskbar.AddItem(&ref);
}
}
void
CPUFrequencyView::_UpdateViews()
{
fFrequencyMenu->UpdateMenu();
freq_preferences* pref = fStorage->GetPreferences();
fColorStepView->SetSliderPosition(pref->stepping_threshold);
if (pref->mode == DYNAMIC) {
fColorStepView->SetEnabled(true);
fIntegrationTime->SetEnabled(true);
}
else {
fColorStepView->SetEnabled(false);
fIntegrationTime->SetEnabled(false);
}
BString out;
out << pref->integration_time / kMilliSecond;
fIntegrationTime->SetText(out.String());
}
void
CPUFrequencyView::_ReadIntegrationTime()
{
freq_preferences* pref = fStorage->GetPreferences();
bigtime_t integration_time = atoi(fIntegrationTime->Text()) * kMilliSecond;
if (integration_time == 0) {
BString out;
out << pref->integration_time / kMilliSecond;
fIntegrationTime->SetText(out.String());
}
else {
pref->integration_time = integration_time;
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#ifndef CPUFREQUENCYVIEW_h
#define CPUFREQUENCYVIEW_h
#include "DriverInterface.h"
#include "ColorStepView.h"
#include "PreferencesWindow.h"
#include <Handler.h>
#include <Menu.h>
#include <MenuItem.h>
#include <TextControl.h>
extern const char* kPrefSignature;
extern const char* kPreferencesFileName;
enum stepping_mode {
DYNAMIC,
PERFORMANCE,
LOW_ENERGIE,
CUSTOM
};
struct freq_preferences
{
// stepping mode
stepping_mode mode;
int16 custom_stepping;
// dynamic stepping
float stepping_threshold;
bigtime_t integration_time;
};
const freq_preferences kDefaultPreferences =
{
DYNAMIC,
-1,
0.25,
500000 //half second
};
class FrequencyMenu;
class StatusView;
class CPUFrequencyView : public BView
{
public:
CPUFrequencyView(BRect frame,
PreferencesStorage<freq_preferences>* storage);
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
private:
void _InstallReplicantInDeskbar();
void _UpdateViews();
void _ReadIntegrationTime();
BMenu* fPolicyMenu;
FrequencyMenu* fFrequencyMenu;
ColorStepView* fColorStepView;
BTextControl* fIntegrationTime;
StatusView* fStatusView;
BButton* fInstallButton;
PreferencesStorage<freq_preferences>* fStorage;
CPUFreqDriverInterface fDriverInterface;
};
#endif

View File

@ -0,0 +1,329 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include "ColorStepView.h"
#include <Window.h>
const int32 kColorBarHeight = 15;
const uint32 kMSGSliderChanged = '&slc';
ColorStepView::ColorStepView(BRect frame)
: BControl(frame, "ColorStepView", "", new BMessage(kSteppingChanged),
B_FOLLOW_ALL, B_WILL_DRAW),
fOffScreenView(NULL),
fOffScreenBitmap(NULL)
{
fPerformanceList = new PerformanceList(20, true);
fSliderPosition = 0;
fNSteps = 0;
fLowFreqColor.red = 0;
fLowFreqColor.blue = 255;
fLowFreqColor.green = 0;
fHighFreqColor.red = 255;
fHighFreqColor.blue = 0;
fHighFreqColor.green = 0;
fMinFrequencyLabel = "? MHz";
fMaxFrequencyLabel = "? MHz";
_InitView();
}
ColorStepView::~ColorStepView()
{
delete fPerformanceList;
}
void
ColorStepView::AttachedToWindow()
{
fSlider->SetTarget(this);
if (!fOffScreenView) {
fOffScreenView = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW);
}
if (!fOffScreenBitmap) {
fOffScreenBitmap = new BBitmap(Bounds(), B_CMAP8, true, false);
Window()->Lock();
if (fOffScreenBitmap && fOffScreenView)
fOffScreenBitmap->AddChild(fOffScreenView);
Window()->Unlock();
}
}
void
ColorStepView::DetachedFromWindow()
{
BView::DetachedFromWindow();
if (fOffScreenBitmap) {
delete fOffScreenBitmap;
fOffScreenBitmap = NULL;
fOffScreenView = NULL;
}
}
void
ColorStepView::FrameResized(float w,float h)
{
BView::FrameResized(w, h);
BRect bounds(Bounds());
if (bounds.right <= 0.0f || bounds.bottom <= 0.0f)
return;
if (fOffScreenBitmap) {
fOffScreenBitmap->RemoveChild(fOffScreenView);
delete fOffScreenBitmap;
fOffScreenView->ResizeTo(bounds.Width(), bounds.Height());
fOffScreenBitmap = new BBitmap(Bounds(), B_RGBA32, true, false);
fOffScreenBitmap->AddChild(fOffScreenView);
}
Invalidate();
}
void
ColorStepView::GetPreferredSize(float *width, float *height)
{
*width = Frame().Width();
font_height fontHeight;
GetFontHeight(&fontHeight);
*height = fSlider->Frame().Height();
*height += kColorBarHeight;
*height += fontHeight.descent + fontHeight.ascent + 5;
}
void
ColorStepView::Draw(BRect updateRect)
{
BView *view = NULL;
if(fOffScreenView){
view = fOffScreenView;
}
else{
view = this;
}
if (!fOffScreenBitmap || !fOffScreenBitmap->Lock())
return;
view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
view->FillRect(updateRect);
BRect colorBarRect = fSlider->BarFrame();
colorBarRect.top = 0;
colorBarRect.bottom = kColorBarHeight;
colorBarRect.OffsetTo(colorBarRect.left, fSlider->Frame().bottom);
float pos = 0.0;
for (int i = fPerformanceList->CountItems() - 1; i >= 0 ; i--) {
performance_step* perfState = fPerformanceList->ItemAt(i);
float nextPos = perfState->cpu_usage;
float width = colorBarRect.Width();
BRect subRect(colorBarRect);
subRect.left += pos * width;
subRect.right = colorBarRect.left + nextPos * width;
view->SetHighColor(perfState->color);
view->FillRect(subRect);
pos = nextPos;
}
// draw label
if (IsEnabled()) {
view->SetHighColor(0, 0, 0);
} else {
view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT));
}
font_height fontHeight;
GetFontHeight(&fontHeight);
float totalFontHeight = fontHeight.descent + fontHeight.ascent;
view->DrawString(fMinFrequencyLabel.String(),
BPoint(0.0,
colorBarRect.bottom + totalFontHeight + 5));
view->DrawString(fMaxFrequencyLabel.String(),
BPoint(Bounds().right
- StringWidth(fMaxFrequencyLabel.String()),
colorBarRect.bottom + totalFontHeight + 5));
// blit bitmap
fOffScreenView->Sync();
fOffScreenBitmap->Unlock();
DrawBitmap(fOffScreenBitmap, B_ORIGIN);
BView::Draw(updateRect);
}
void
ColorStepView::MessageReceived(BMessage *message)
{
switch (message->what) {
case kMSGSliderChanged:
fSliderPosition = fSlider->Position();
_CalculatePerformanceSteps();
Invalidate();
break;
case kSteppingChanged:
Invoke();
break;
default:
BView::MessageReceived(message);
break;
}
}
void
ColorStepView::SetEnabled(bool enabled)
{
fSlider->SetEnabled(enabled);
BControl::SetEnabled(enabled);
}
void
ColorStepView::SetFrequencys(StateList *list)
{
fStateList = list;
fNSteps = fStateList->CountItems();
if (fNSteps >= 2) {
float minFreq = fStateList->ItemAt(fNSteps - 1)->frequency;
float maxFreq = fStateList->ItemAt(0)->frequency;
fMinFrequencyLabel = CreateFrequencyString(minFreq);
fMaxFrequencyLabel = CreateFrequencyString(maxFreq);
}
// fit size of fPerformanceList
int32 perfNumber = fPerformanceList->CountItems();
if (perfNumber < fNSteps) {
for (int i = 0; i < fNSteps - perfNumber; i++)
fPerformanceList->AddItem(new performance_step);
}
else {
for (int i = 0; i < perfNumber - fNSteps; i++)
fPerformanceList->RemoveItemAt(0);
}
// and fill the list
_CalculatePerformanceSteps();
}
PerformanceList*
ColorStepView::GetPerformanceSteps()
{
return fPerformanceList;
}
BString
ColorStepView::CreateFrequencyString(uint16 frequency)
{
BString string = "";
if (frequency >= 1000) {
char buffer [10];
sprintf (buffer, "%.1f", float(frequency) / 1000);
string << buffer;
string += " GHz";
}
else {
string << frequency;
string += " MHz";
}
return string;
}
float
ColorStepView::UsageOfStep(int32 step, int32 nSteps, float base)
{
float singleWidth = (1 - base) / (nSteps - 1);
return base + singleWidth * step;
}
void
ColorStepView::_InitView()
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BRect sliderFrame(Bounds());
fSlider = new BSlider(sliderFrame, "StepSlider", "Step up by CPU usage:",
new BMessage(kSteppingChanged), 0, 100);
fSlider->SetModificationMessage(new BMessage(kMSGSliderChanged));
fSliderPosition = 0.25 - fNSteps * 0.05;
fSlider->SetPosition(fSliderPosition);
fSlider->SetLimitLabels("0%", "100%");
fSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
fSlider->SetHashMarkCount(5);
AddChild(fSlider);
}
void
ColorStepView::_CalculatePerformanceSteps()
{
for (int i = 0; i < fNSteps; i++) {
// begin with the lowest frequency
performance_step* perfState = fPerformanceList->ItemAt(fNSteps -1 - i);
perfState->cpu_usage = _PositonStep(i);
_ColorStep(i, perfState->color);
}
}
float
ColorStepView::_PositonStep(int32 step)
{
if (step >= fNSteps)
return 1.0;
return UsageOfStep(step, fNSteps, fSliderPosition);
}
void
ColorStepView::_ColorStep(int32 step, rgb_color &color)
{
color.red = fLowFreqColor.red
+ (fHighFreqColor.red - fLowFreqColor.red)
/ (fNSteps - 1) * step;
color.green = fLowFreqColor.green
+ (fHighFreqColor.green - fLowFreqColor.green)
/ (fNSteps - 1) * step;
color.blue = fLowFreqColor.blue
+ (fHighFreqColor.blue - fLowFreqColor.blue)
/ (fNSteps - 1) * step;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#ifndef COLORSTEPVIEW_H
#define COLORSTEPVIEW_H
#include <Bitmap.h>
#include <Control.h>
#include <ObjectList.h>
#include <Slider.h>
#include <String.h>
#include "DriverInterface.h"
const uint32 kSteppingChanged = '&spc';
struct performance_step {
float cpu_usage; // upper limit
rgb_color color;
};
typedef BObjectList<performance_step> PerformanceList;
class ColorStepView : public BControl
{
public:
ColorStepView(BRect frame);
~ColorStepView();
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void FrameResized(float w,float h);
virtual void GetPreferredSize(float *width, float *height);
virtual void Draw(BRect updateRect);
virtual void MessageReceived(BMessage *message);
virtual void SetEnabled(bool enabled);
void SetFrequencys(StateList *list);
PerformanceList* GetPerformanceSteps();
static BString CreateFrequencyString(uint16 frequency);
void SetSliderPosition(float pos) {
fSlider->SetPosition(pos);
fSliderPosition = pos;
_CalculatePerformanceSteps();
}
float GetSliderPosition() { return fSliderPosition; }
static float UsageOfStep(int32 step, int32 nSteps, float base);
private:
void _InitView();
void _CalculatePerformanceSteps();
float _PositonStep(int32 step);
void _ColorStep(int32 step, rgb_color &color);
BSlider* fSlider;
float fSliderPosition;
int32 fNSteps;
rgb_color fLowFreqColor;
rgb_color fHighFreqColor;
BView* fOffScreenView;
BBitmap* fOffScreenBitmap;
BString fMinFrequencyLabel;
BString fMaxFrequencyLabel;
PerformanceList* fPerformanceList;
StateList* fStateList;
};
#endif

View File

@ -0,0 +1,217 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include "DriverInterface.h"
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#define DRIVER_DIR "/dev/power"
CPUFreqDriverInterface::CPUFreqDriverInterface()
: fInitOK(false),
fDriverHandler(-1),
fIsWatching(false),
fWatchingMessenger(NULL)
{
fFrequencyStates = new StateList(20, true);
if (_FindSpeedStepDriver(DRIVER_DIR) == B_OK)
fInitOK = true;
status_t ret;
freq_info states[MAX_CPU_FREQUENCY_STATES];
ret = ioctl(fDriverHandler, GET_CPU_FREQ_STATES, &states,
sizeof(freq_info) * MAX_CPU_FREQUENCY_STATES);
if (ret != B_OK)
return;
for (int i = 0; i < MAX_CPU_FREQUENCY_STATES && states[i].frequency != 0;
i++) {
fFrequencyStates->AddItem(new freq_info(states[i]));
}
}
CPUFreqDriverInterface::~CPUFreqDriverInterface()
{
delete fFrequencyStates;
if (InitCheck() == B_OK)
close(fDriverHandler);
}
status_t
CPUFreqDriverInterface::InitCheck()
{
if (fInitOK)
return B_OK;
return B_ERROR;
}
StateList*
CPUFreqDriverInterface::GetCpuFrequencyStates()
{
return fFrequencyStates;
}
freq_info*
CPUFreqDriverInterface::GetCurrentFrequencyState()
{
uint16 stateId = 0;
status_t ret;
ret = ioctl(fDriverHandler, GET_CURENT_CPU_FREQ_STATE, &stateId,
sizeof(uint16));
if (ret != B_OK)
return NULL;
int32 i = 0;
while (true) {
freq_info* state = fFrequencyStates->ItemAt(i);
if (!state)
break;
i++;
if (state->id == stateId)
return state;
}
return NULL;
}
int32
CPUFreqDriverInterface::GetNumberOfFrequencyStates()
{
return fFrequencyStates->CountItems();
}
status_t
CPUFreqDriverInterface::SetFrequencyState(const freq_info* state)
{
status_t ret;
ret = ioctl(fDriverHandler, SET_CPU_FREQ_STATE, &(state->id),
sizeof(uint16));
return ret;
}
status_t
CPUFreqDriverInterface::StartWatching(BHandler* target)
{
if (fIsWatching)
return B_ERROR;
if (fWatchingMessenger)
delete fWatchingMessenger;
fWatchingMessenger = new BMessenger(target);
status_t status = B_ERROR;
fThreadId = spawn_thread(&_ThreadWatchFreqFunction, "FreqThread",
B_LOW_PRIORITY, this);
if (fThreadId >= 0)
status = resume_thread(fThreadId);
else
return fThreadId;
if (status == B_OK) {
fIsWatching = true;
return B_OK;
}
return status;
}
status_t
CPUFreqDriverInterface::StopWatching()
{
if (fIsWatching &&
ioctl(fDriverHandler, STOP_WATCHING_CPU_FREQ) == B_OK)
{
delete fWatchingMessenger;
fWatchingMessenger = NULL;
fIsWatching = false;
status_t status;
return wait_for_thread(fThreadId, &status);
}
return B_ERROR;
}
int32
CPUFreqDriverInterface::_ThreadWatchFreqFunction(void* data)
{
CPUFreqDriverInterface* that = (CPUFreqDriverInterface*)data;
that->_WatchFrequency();
return 0;
}
void
CPUFreqDriverInterface::_WatchFrequency()
{
uint16 newId = 0;
while (ioctl(fDriverHandler, WATCH_CPU_FREQ, &newId,
sizeof(uint16)) == B_OK)
{
int i = 0;
while (true) {
freq_info* state = fFrequencyStates->ItemAt(i);
if (!state)
break;
i++;
if (state->id == newId) {
BMessage msg(kMSGFrequencyChanged);
msg.AddPointer("freq_info", state);
fWatchingMessenger->SendMessage(&msg);
break;
}
}
}
}
status_t
CPUFreqDriverInterface::_FindSpeedStepDriver(const char* path)
{
BDirectory dir(path);
BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK) {
BPath path;
entry.GetPath(&path);
if (entry.IsDirectory()) {
if (_FindSpeedStepDriver(path.Path()) == B_OK)
return B_OK;
}
else {
printf("path %s\n", path.Path());
fDriverHandler = open(path.Path(), O_RDWR);
if (fDriverHandler >= 0) {
uint32 magicId = 0;
status_t ret;
ret = ioctl(fDriverHandler, IDENTIFY_DEVICE, &magicId,
sizeof(uint32));
if (ret == B_OK && magicId == kMagicFreqID)
return B_OK;
}
}
}
return B_ERROR;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#ifndef DRIVERINTERFACE_H
#define DRIVERINTERFACE_H
#include <Messenger.h>
#include <ObjectList.h>
#include "device/power_managment.h"
const uint32 kMSGFrequencyChanged = '&frc';
typedef BObjectList<freq_info> StateList;
class CPUFreqDriverInterface
{
public:
CPUFreqDriverInterface();
~CPUFreqDriverInterface();
status_t InitCheck();
StateList* GetCpuFrequencyStates();
freq_info* GetCurrentFrequencyState();
int32 GetNumberOfFrequencyStates();
status_t SetFrequencyState(const freq_info* state);
status_t StartWatching(BHandler* target);
status_t StopWatching();
private:
static int32 _ThreadWatchFreqFunction(void* data);
void _WatchFrequency();
thread_id fThreadId;
status_t _FindSpeedStepDriver(const char* path);
bool fInitOK;
int32 fDriverHandler;
StateList* fFrequencyStates;
bool fIsWatching;
BMessenger* fWatchingMessenger;
};
#endif

View File

@ -0,0 +1,13 @@
SubDir HAIKU_TOP src preferences cpufrequency ;
UsePrivateHeaders shared ;
Preference CPUFrequency :
ColorStepView.cpp
CPUFrequencyView.cpp
DriverInterface.cpp
main.cpp
StatusView.cpp
: be
: cpufrequency.rdef
;

View File

@ -0,0 +1,439 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#ifndef PREFERENCESWINDOW_h
#define PREFERENCESWINDOW_h
#define DEBUG 1
#include <Debug.h>
#if DEBUG
# define LOG(text...) PRINT((text))
#else
# define LOG(text...)
#endif
#include <Button.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <Window.h>
// headers PreferencesStorage
#include <Entry.h>
#include <FindDirectory.h>
#include <File.h>
#include <String.h>
// headers PrefFileWatcher
#include <MessageFilter.h>
// headers PreferencesWindow
#include <GroupView.h>
#include <Screen.h>
#include <SpaceLayoutItem.h>
// messages PrefFileWatcher
const uint32 kUpdatedPreferences = '&UdP';
template<typename Preferences>
class PreferencesStorage
{
public:
PreferencesStorage(const char* file,
const Preferences& defaultPreferences);
~PreferencesStorage();
void Revert();
void Defaults();
BPoint WindowPosition(){return fWindowPosition;}
void SetWindowPosition(BPoint position){
fWindowPosition = position;}
Preferences* GetPreferences(){return &fPreferences;}
status_t LoadPreferences();
status_t SavePreferences();
BString& PreferencesFile() { return fPreferencesFile; }
status_t GetPreferencesPath(BPath &path);
private:
BString fPreferencesFile;
Preferences fPreferences;
Preferences fStartPreferences;
const Preferences& fDefaultPreferences;
BPoint fWindowPosition;
};
template<typename Preferences>
class PrefFileWatcher : public BMessageFilter
{
public:
PrefFileWatcher(PreferencesStorage<Preferences>* storage,
BHandler* target);
~PrefFileWatcher();
virtual filter_result Filter(BMessage *message, BHandler **target);
private:
PreferencesStorage<Preferences>* fPreferencesStorage;
node_ref fPreferencesNode;
node_ref fPreferencesDirectoryNode;
BHandler* fTarget;
};
template<typename Preferences>
class PreferencesWindow : public BWindow, public PreferencesStorage<Preferences>
{
public:
PreferencesWindow(const char* title,
const char* file,
const Preferences& defaultPreferences);
~PreferencesWindow();
virtual void MessageReceived(BMessage *msg);
virtual bool QuitRequested();
virtual bool SetPreferencesView(BView* prefView);
private:
void _MoveToPosition();
BView* fPreferencesView;
BButton* fRevertButton;
BButton* fDefaultButton;
BGroupLayout* fRootLayout;
};
const uint32 kDefaultMsg = 'dems';
const uint32 kRevertMsg = 'rems';
const uint32 kConfigChangedMsg = '&cgh';
template<typename Preferences>
PreferencesStorage<Preferences>::PreferencesStorage(const char* file,
const Preferences& defaultPreferences)
: fDefaultPreferences(defaultPreferences)
{
// default center position
fWindowPosition.x = -1;
fWindowPosition.y = -1;
fPreferencesFile = file;
if (LoadPreferences() != B_OK)
Defaults();
fStartPreferences = fPreferences;
}
template<typename Preferences>
PreferencesStorage<Preferences>::~PreferencesStorage()
{
SavePreferences();
}
template<typename Preferences>
void
PreferencesStorage<Preferences>::Revert()
{
fPreferences = fStartPreferences;
}
template<typename Preferences>
void
PreferencesStorage<Preferences>::Defaults()
{
fPreferences = fDefaultPreferences;
}
template<typename Preferences>
status_t
PreferencesStorage<Preferences>::GetPreferencesPath(BPath &path)
{
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (status < B_OK)
return status;
return path.Append(fPreferencesFile.String());
}
template<typename Preferences>
status_t
PreferencesStorage<Preferences>::LoadPreferences()
{
BPath path;
status_t status = GetPreferencesPath(path);
if (status != B_OK)
return status;
BFile settingsFile(path.Path(), B_READ_ONLY);
status = settingsFile.InitCheck();
if (status != B_OK)
return status;
if (settingsFile.Read(&fWindowPosition, sizeof(BPoint))
!= sizeof(BPoint)) {
LOG("failed to load settings\n");
return B_ERROR;
}
if (settingsFile.Read(&fPreferences, sizeof(Preferences))
!= sizeof(Preferences)) {
LOG("failed to load settings\n");
return B_ERROR;
}
return B_OK;
}
template<typename Preferences>
status_t
PreferencesStorage<Preferences>::SavePreferences()
{
BPath path;
status_t status = GetPreferencesPath(path);
if (status != B_OK)
return status;
BFile settingsFile(path.Path(), B_READ_WRITE | B_CREATE_FILE);
status = settingsFile.InitCheck();
if (status != B_OK) {
LOG("InitCheck() settings file failed \n");
return status;
}
if (settingsFile.Write(&fWindowPosition, sizeof(BPoint))
!= sizeof(BPoint)) {
LOG("can't save window position\n");
return B_ERROR;
}
if (settingsFile.Write(&fPreferences, sizeof(Preferences))
!= sizeof(Preferences)) {
LOG("can't save settings\n");
return B_ERROR;
}
return B_OK;
}
template<typename Preferences>
PrefFileWatcher<Preferences>::PrefFileWatcher(PreferencesStorage<Preferences>* storage,
BHandler* target)
: BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE),
fPreferencesStorage(storage),
fTarget(target)
{
BPath path;
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
BEntry entry(path.Path());
entry.GetNodeRef(&fPreferencesDirectoryNode);
watch_node(&fPreferencesDirectoryNode, B_WATCH_DIRECTORY,
fTarget);
path.Append(fPreferencesStorage->PreferencesFile().String());
entry.SetTo(path.Path());
entry.GetNodeRef(&fPreferencesNode);
watch_node(&fPreferencesNode, B_WATCH_STAT,
fTarget);
}
template<typename Preferences>
PrefFileWatcher<Preferences>::~PrefFileWatcher()
{
stop_watching(fTarget);
}
template<typename Preferences>
filter_result
PrefFileWatcher<Preferences>::Filter(BMessage *msg, BHandler **target)
{
const char *name;
ino_t dir = -1;
filter_result result = B_DISPATCH_MESSAGE;
int32 opcode;
BPath path;
node_ref nref;
if (msg->what != B_NODE_MONITOR
|| msg->FindInt32("opcode", &opcode) != B_OK)
return result;
switch(opcode)
{
case B_ENTRY_MOVED:
msg->FindInt64("to directory", dir);
if (dir != fPreferencesDirectoryNode.node)
break;
case B_ENTRY_CREATED:
msg->FindString("name", &name);
fPreferencesStorage->GetPreferencesPath(path);
if (path.Path() == name) {
msg->FindInt32("device", &fPreferencesNode.device);
msg->FindInt64("node", &fPreferencesNode.node);
watch_node(&fPreferencesNode, B_WATCH_STAT, fTarget);
}
fPreferencesStorage->LoadPreferences();
msg->what = kUpdatedPreferences;
break;
case B_ENTRY_REMOVED:
msg->FindInt32("device", &nref.device);
msg->FindInt64("node", &nref.node);
if (fPreferencesNode == nref) {
// stop all watching
stop_watching(fTarget);
// and start watching the directory again
watch_node(&fPreferencesDirectoryNode, B_WATCH_DIRECTORY,
fTarget);
msg->what = kUpdatedPreferences;
}
break;
case B_STAT_CHANGED:
msg->FindInt32("device", &nref.device);
msg->FindInt64("node", &nref.node);
if (fPreferencesNode == nref) {
fPreferencesStorage->LoadPreferences();
msg->what = kUpdatedPreferences;
}
break;
}
return result;
}
template<typename Preferences>
PreferencesWindow<Preferences>::PreferencesWindow(const char* title,
const char* file,
const Preferences& defaultPreferences)
: BWindow(BRect(50, 50, 400, 350), title, B_TITLED_WINDOW,
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AVOID_FRONT
| B_ASYNCHRONOUS_CONTROLS),
PreferencesStorage<Preferences>(file, defaultPreferences),
fPreferencesView(NULL)
{
BGroupView* buttonView = new BGroupView(B_HORIZONTAL);
fDefaultButton = new BButton("Defaults",
new BMessage(kDefaultMsg));
buttonView->AddChild(fDefaultButton);
buttonView->GetLayout()->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(7));
fRevertButton = new BButton("Revert", new BMessage(kRevertMsg));
fRevertButton->SetEnabled(false);
buttonView->AddChild(fRevertButton);
buttonView->GetLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
SetLayout(new BGroupLayout(B_VERTICAL));
fRootLayout = new BGroupLayout(B_VERTICAL);
fRootLayout->SetInsets(10, 10, 10, 10);
fRootLayout->SetSpacing(10);
BView* rootView = new BView("root view", 0, fRootLayout);
AddChild(rootView);
rootView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fRootLayout->AddView(buttonView);
BSize size = fRootLayout->PreferredSize();
ResizeTo(size.width, size.height);
_MoveToPosition();
}
template<typename Preferences>
PreferencesWindow<Preferences>::~PreferencesWindow()
{
SetWindowPosition(Frame().LeftTop());
}
template<typename Preferences>
void
PreferencesWindow<Preferences>::MessageReceived(BMessage *msg)
{
switch(msg->what)
{
case kConfigChangedMsg:
fRevertButton->SetEnabled(true);
break;
case kDefaultMsg:
Defaults();
fRevertButton->SetEnabled(true);
if (fPreferencesView)
PostMessage(kDefaultMsg, fPreferencesView);
break;
case kRevertMsg:
Revert();
fRevertButton->SetEnabled(false);
if (fPreferencesView)
PostMessage(kRevertMsg, fPreferencesView);
break;
default:
BWindow::MessageReceived(msg);
}
}
template<typename Preferences>
bool
PreferencesWindow<Preferences>::QuitRequested()
{
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
template<typename Preferences>
bool
PreferencesWindow<Preferences>::SetPreferencesView(BView* prefView)
{
if (fPreferencesView)
return false;
fPreferencesView = prefView;
fRootLayout->AddView(0, fPreferencesView);
BSize size = fRootLayout->PreferredSize();
ResizeTo(size.width, size.height);
_MoveToPosition();
return true;
}
template<typename Preferences>
void
PreferencesWindow<Preferences>::_MoveToPosition()
{
BPoint position = WindowPosition();
// center window on screen if it had a bad position
if(position.x < 0 && position.y < 0){
BRect rect = BScreen().Frame();
BRect windowFrame = Frame();
position.x = (rect.Width() - windowFrame.Width()) / 2;
position.y = (rect.Height() - windowFrame.Height()) / 2;
}
MoveTo(position);
}
#endif

View File

@ -0,0 +1,666 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include "StatusView.h"
#include "CPUFrequencyView.h"
#include <Alert.h>
#include <Application.h>
#include <Deskbar.h>
#include <GroupLayout.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <Roster.h>
#include <TextView.h>
#include <string.h>
extern "C" _EXPORT BView *instantiate_deskbar_item(void);
// messages FrequencySwitcher
const uint32 kMsgDynamicPolicyPuls = '&dpp';
// messages menu
const uint32 kMsgPolicyDynamic = 'pody';
const uint32 kMsgPolicyPerformance = 'popr';
const uint32 kMsgPolicyLowEnergy = 'pole';
const uint32 kMsgPolicySetState = 'poss';
// messages StatusView
const uint32 kMsgOpenSSPreferences = 'ossp';
const char* kDeskbarItemName = "CPUFreqStatusView";
FrequencySwitcher::FrequencySwitcher(CPUFreqDriverInterface* interface,
BHandler* target)
: BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE),
fDriverInterface(interface),
fTarget(target),
fMessageRunner(NULL),
fCurrentFrequency(NULL),
fDynamicPolicyStarted(false)
{
}
FrequencySwitcher::~FrequencySwitcher()
{
freq_preferences dummyPref;
_StartDynamicPolicy(false, dummyPref);
}
filter_result
FrequencySwitcher::Filter(BMessage *message, BHandler **target)
{
filter_result result = B_DISPATCH_MESSAGE;
if (message->what == kMsgDynamicPolicyPuls) {
_CalculateDynamicState();
result = B_SKIP_MESSAGE;
}
return result;
}
void
FrequencySwitcher::SetMode(const freq_preferences& pref)
{
int16 stateCount = fDriverInterface->GetNumberOfFrequencyStates();
StateList* list = fDriverInterface->GetCpuFrequencyStates();
freq_info* currentState = fDriverInterface->GetCurrentFrequencyState();
freq_info* state = NULL;
bool isDynamic = false;
switch (pref.mode) {
case DYNAMIC:
isDynamic = true;
fSteppingThreshold = pref.stepping_threshold;
if (fMessageRunner && fIntegrationTime != pref.integration_time)
{
fIntegrationTime = pref.integration_time;
fMessageRunner->SetInterval(fIntegrationTime);
}
if (!fDynamicPolicyStarted)
_StartDynamicPolicy(true, pref);
break;
case PERFORMANCE:
state = list->ItemAt(int32(0));
if (state != currentState)
fDriverInterface->SetFrequencyState(state);
break;
case LOW_ENERGIE:
state = list->ItemAt(stateCount - 1);
if (state != currentState)
fDriverInterface->SetFrequencyState(state);
break;
case CUSTOM:
if (pref.custom_stepping < stateCount) {
state = list->ItemAt(pref.custom_stepping);
fDriverInterface->SetFrequencyState(state);
}
break;
}
if (!isDynamic && fDynamicPolicyStarted) {
fDynamicPolicyStarted = false;
_StartDynamicPolicy(false, pref);
}
}
void
FrequencySwitcher::_CalculateDynamicState()
{
system_info sysInfo;
get_system_info(&sysInfo);
bigtime_t now = system_time();
bigtime_t activeTime = sysInfo.cpu_infos[0].active_time;
// if the dynamic mode is not started firt init the prev values
if (!fDynamicPolicyStarted) {
fPrevActiveTime = activeTime;
fPrevTime = now;
fDynamicPolicyStarted = true;
}
else {
float usage = (float)(activeTime - fPrevActiveTime )
/ (now - fPrevTime);
if (usage >= 1.0)
usage = 0.9999999;
int32 numberOfStates = fDriverInterface->GetNumberOfFrequencyStates();
for (int i = 0; i < numberOfStates; i++) {
float usageOfStep = ColorStepView::UsageOfStep(i, numberOfStates,
fSteppingThreshold);
LOG("usage %f, step %f\n", usage, usageOfStep);
if (usage < usageOfStep)
{
StateList* list = fDriverInterface->GetCpuFrequencyStates();
freq_info* newState = list->ItemAt(numberOfStates - 1 - i);
if (newState != fCurrentFrequency) {
LOG("change freq\n");
fDriverInterface->SetFrequencyState(newState);
fCurrentFrequency = newState;
}
break;
}
}
fPrevActiveTime = activeTime;
fPrevTime = now;
}
}
void
FrequencySwitcher::_StartDynamicPolicy(bool start,
const freq_preferences& pref)
{
if (start) {
if (!fMessageRunner) {
fIntegrationTime = pref.integration_time;
fMessageRunner = new BMessageRunner(fTarget,
new BMessage(kMsgDynamicPolicyPuls)
, pref.integration_time, -1);
fCurrentFrequency = fDriverInterface->GetCurrentFrequencyState();
}
}
else {
if (fMessageRunner) {
delete fMessageRunner;
fMessageRunner = NULL;
}
}
}
FrequencyMenu::FrequencyMenu(BMenu* menu, BHandler* target,
PreferencesStorage<freq_preferences> * storage,
CPUFreqDriverInterface* interface)
: BMessageFilter(B_PROGRAMMED_DELIVERY, B_LOCAL_SOURCE),
fTarget(target),
fStorage(storage),
fInterface(interface)
{
fDynamicPerformance = new BMenuItem("Dynamic Performance",
new BMessage(kMsgPolicyDynamic));
fHighPerformance = new BMenuItem("High Performance",
new BMessage(kMsgPolicyPerformance));
fLowEnergie = new BMenuItem("Low Energie",
new BMessage(kMsgPolicyLowEnergy));
menu->AddItem(fDynamicPerformance);
menu->AddItem(fHighPerformance);
menu->AddItem(fLowEnergie);
fCustomStateMenu = new BMenu("Set State");
StateList* stateList = fInterface->GetCpuFrequencyStates();
for (int i = 0; i < stateList->CountItems(); i++) {
freq_info* info = stateList->ItemAt(i);
BString label;
label << info->frequency;
label += " MHz";
fCustomStateMenu->AddItem(new BMenuItem(label.String(),
new BMessage(kMsgPolicySetState)));
}
menu->AddItem(fCustomStateMenu);
// set the target of the items
fDynamicPerformance->SetTarget(fTarget);
fHighPerformance->SetTarget(fTarget);
fLowEnergie->SetTarget(fTarget);
fCustomStateMenu->SetTargetForItems(fTarget);
}
inline void
FrequencyMenu::_SetL1MenuLabelFrom(BMenuItem* item)
{
BMenuItem* superItem, *markedItem;
superItem = item->Menu()->Superitem();
if (superItem)
superItem->SetLabel(item->Label());
markedItem = item->Menu()->FindMarked();
if (markedItem)
markedItem->SetMarked(false);
item->SetMarked(true);
}
filter_result
FrequencyMenu::Filter(BMessage *msg, BHandler **target)
{
filter_result result = B_DISPATCH_MESSAGE;
BMenuItem* item, *superItem, *markedItem;
msg->FindPointer("source", (void**)&item);
if (!item) {
return result;
}
bool safeChanges = false;
freq_preferences* pref = fStorage->GetPreferences();
switch (msg->what) {
case kMsgPolicyDynamic:
pref->mode = DYNAMIC;
_SetL1MenuLabelFrom(item);
safeChanges = true;
msg->what = kUpdatedPreferences;
break;
case kMsgPolicyPerformance:
pref->mode = PERFORMANCE;
_SetL1MenuLabelFrom(item);
safeChanges = true;
msg->what = kUpdatedPreferences;
break;
case kMsgPolicyLowEnergy:
pref->mode = LOW_ENERGIE;
_SetL1MenuLabelFrom(item);
safeChanges = true;
msg->what = kUpdatedPreferences;
break;
case kMsgPolicySetState:
pref->mode = CUSTOM;
pref->custom_stepping = item->Menu()->IndexOf(item);
superItem = item->Menu()->Supermenu()->Superitem();
if (superItem)
superItem->SetLabel(item->Label());
markedItem = item->Menu()->Supermenu()->FindMarked();
if (markedItem)
markedItem->SetMarked(false);
markedItem = item->Menu()->FindMarked();
if (markedItem)
markedItem->SetMarked(false);
item->SetMarked(true);
safeChanges = true;
msg->what = kUpdatedPreferences;
break;
}
if (safeChanges)
fStorage->SavePreferences();
return result;
}
void
FrequencyMenu::UpdateMenu()
{
BMenuItem* customItem, *markedItem, *superItem;
freq_preferences* pref = fStorage->GetPreferences();
switch (pref->mode) {
case DYNAMIC:
_SetL1MenuLabelFrom(fDynamicPerformance);
break;
case PERFORMANCE:
_SetL1MenuLabelFrom(fHighPerformance);
break;
case LOW_ENERGIE:
_SetL1MenuLabelFrom(fLowEnergie);
break;
case CUSTOM:
markedItem = fCustomStateMenu->FindMarked();
if (markedItem)
markedItem->SetMarked(false);
customItem = fCustomStateMenu->ItemAt(pref->custom_stepping);
if (customItem)
customItem->SetMarked(true);
superItem = fCustomStateMenu->Supermenu()->Superitem();
if (superItem && customItem)
superItem->SetLabel(customItem->Label());
break;
}
}
StatusView::StatusView(BRect frame, bool inDeskbar,
PreferencesStorage<freq_preferences>* storage = NULL)
: BView(frame, kDeskbarItemName, B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW | B_FRAME_EVENTS),
fInDeskbar(inDeskbar),
fCurrentFrequency(NULL),
fDragger(NULL)
{
if (!inDeskbar) {
// we were obviously added to a standard window - let's add a dragger
BRect bounds = Bounds();
bounds.top = bounds.bottom - 7;
bounds.left = bounds.right - 7;
fDragger = new BDragger(bounds, this,
B_FOLLOW_NONE);
AddChild(fDragger);
}
if (storage) {
fOwningStorage = false;
fStorage = storage;
}
else {
fOwningStorage = true;
fStorage = new PreferencesStorage<freq_preferences>("CPUFrequency",
kDefaultPreferences);
}
_Init();
}
StatusView::StatusView(BMessage* archive)
: BView(archive),
fInDeskbar(false),
fCurrentFrequency(NULL),
fDragger(NULL)
{
app_info info;
if (be_app->GetAppInfo(&info) == B_OK
&& !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
fInDeskbar = true;
fOwningStorage = true;
fStorage = new PreferencesStorage<freq_preferences>(kPreferencesFileName,
kDefaultPreferences);
_Init();
}
StatusView::~StatusView()
{
if (fOwningStorage)
delete fStorage;
}
void
StatusView::_AboutRequested()
{
BAlert *alert = new BAlert("about", "CPU Frequency\n"
"\twritten by Clemens Zeidler\n"
"\tCopyright 2009, Haiku, Inc.\n", "Ok");
BTextView *view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, 13, &font);
alert->Go();
}
void
StatusView::_Quit()
{
if (fInDeskbar) {
BDeskbar deskbar;
deskbar.RemoveItem(kDeskbarItemName);
} else
be_app->PostMessage(B_QUIT_REQUESTED);
}
StatusView *
StatusView::Instantiate(BMessage* archive)
{
if (!validate_instantiation(archive, "StatusView"))
return NULL;
return new StatusView(archive);
}
status_t
StatusView::Archive(BMessage* archive, bool deep) const
{
status_t status = BView::Archive(archive, deep);
if (status == B_OK)
status = archive->AddString("add_on", kPrefSignature);
if (status == B_OK)
status = archive->AddString("class", "StatusView");
return status;
}
void
StatusView::AttachedToWindow()
{
BView::AttachedToWindow();
if (Parent())
SetViewColor(Parent()->ViewColor());
else
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetLowColor(ViewColor());
// watching if the driver change the frequency
fDriverInterface.StartWatching(this);
// monitor preferences file
fPrefFileWatcher = new PrefFileWatcher<freq_preferences>(fStorage, this);
AddFilter(fPrefFileWatcher);
// FrequencySwitcher
fFrequencySwitcher = new FrequencySwitcher(&fDriverInterface, this);
fFrequencySwitcher->SetMode(*(fStorage->GetPreferences()));
AddFilter(fFrequencySwitcher);
// perferences menu
fPreferencesMenu = new BPopUpMenu(B_EMPTY_STRING, false, false);
fPreferencesMenuFilter = new FrequencyMenu(fPreferencesMenu, this,
fStorage,
&fDriverInterface);
fPreferencesMenu->SetFont(be_plain_font);
fPreferencesMenu->AddSeparatorItem();
fOpenPrefItem = new BMenuItem("Open Speedstep Preferences" B_UTF8_ELLIPSIS,
new BMessage(kMsgOpenSSPreferences));
fPreferencesMenu->AddItem(fOpenPrefItem);
fOpenPrefItem->SetTarget(this);
if (fInDeskbar) {
fQuitItem= new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED));
fPreferencesMenu->AddItem(fQuitItem);
fQuitItem->SetTarget(this);
}
AddFilter(fPreferencesMenuFilter);
fPreferencesMenuFilter->UpdateMenu();
}
void
StatusView::DetachedFromWindow()
{
fDriverInterface.StopWatching();
if (RemoveFilter(fPrefFileWatcher))
delete fPrefFileWatcher;
if (RemoveFilter(fFrequencySwitcher))
delete fFrequencySwitcher;
if (RemoveFilter(fPreferencesMenuFilter))
delete fPreferencesMenuFilter;
delete fPreferencesMenu;
}
void
StatusView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgOpenSSPreferences:
_OpenPreferences();
break;
case kMSGFrequencyChanged:
message->FindPointer("freq_info", (void**)&fCurrentFrequency);
_SetupNewFreqString();
Invalidate();
break;
case kUpdatedPreferences:
fFrequencySwitcher->SetMode(*(fStorage->GetPreferences()));
fPreferencesMenuFilter->UpdateMenu();
break;
case B_ABOUT_REQUESTED:
_AboutRequested();
break;
case B_QUIT_REQUESTED:
_Quit();
break;
default:
BView::MessageReceived(message);
}
}
void
StatusView::FrameResized(float width, float height)
{
Invalidate();
}
void
StatusView::Draw(BRect updateRect)
{
font_height fontHeight;
GetFontHeight(&fontHeight);
float height = fontHeight.ascent + fontHeight.descent;
MovePenTo(0, height);
DrawString(fFreqString.String());
}
void
StatusView::MouseDown(BPoint point)
{
if (fShowPopUpMenu) {
ConvertToScreen(&point);
fPreferencesMenu->Go(point, true, false, true);
}
}
void
StatusView::GetPreferredSize(float *width, float *height)
{
font_height fontHeight;
GetFontHeight(&fontHeight);
*height = fontHeight.ascent + fontHeight.descent;
if (!fInDeskbar)
*height += 7;
*width = StringWidth(fFreqString.String());
}
void
StatusView::ResizeToPreferred(void)
{
float width, height;
GetPreferredSize(&width, &height);
ResizeTo(width, height);
}
void
StatusView::ShowPopUpMenu(bool show = true)
{
fShowPopUpMenu = show;
}
void
StatusView::UpdateCPUFreqState()
{
fFrequencySwitcher->SetMode(*(fStorage->GetPreferences()));
}
void
StatusView::_Init()
{
fShowPopUpMenu = true;
fCurrentFrequency = fDriverInterface.GetCurrentFrequencyState();
_SetupNewFreqString();
}
void
StatusView::_SetupNewFreqString()
{
if (fCurrentFrequency)
fFreqString = ColorStepView::CreateFrequencyString(
fCurrentFrequency->frequency);
else
fFreqString = "? MHz";
ResizeToPreferred();
if (fDragger) {
BRect frame = Frame();
fDragger->MoveTo(frame.right - 7, frame.bottom - 7);
}
}
void
StatusView::_OpenPreferences()
{
status_t ret = be_roster->Launch(kPrefSignature);
if (ret < B_OK) {
BString errorMessage("Launching the CPU Frequency preflet failed.\n\n"
"Error: ");
errorMessage << strerror(ret);
BAlert* alert = new BAlert("launch error", errorMessage.String(),
"Ok");
// asynchronous alert in order to not block replicant host
// application
alert->Go(NULL);
}
}
extern "C" _EXPORT BView *
instantiate_deskbar_item(void)
{
return new StatusView(BRect(0, 0, 15, 15), true, NULL);
}

View File

@ -0,0 +1,140 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#ifndef STATUS_VIEW_H
#define STATUS_VIEW_H
#include <Dragger.h>
#include <MessageFilter.h>
#include <MessageRunner.h>
#include <String.h>
#include <View.h>
#include "CPUFrequencyView.h"
#include "DriverInterface.h"
#include "PreferencesWindow.h"
#define DEBUG 1
#include <Debug.h>
#if DEBUG
# define LOG(text...) PRINT((text))
#else
# define LOG(text...)
#endif
extern const char* kDeskbarItemName;
extern const char* kAddonSignature;
class FrequencySwitcher : public BMessageFilter
{
public:
FrequencySwitcher(CPUFreqDriverInterface* interface,
BHandler* target);
virtual ~FrequencySwitcher();
virtual filter_result Filter(BMessage *message, BHandler **target);
void SetMode(const freq_preferences& pref);
private:
void _CalculateDynamicState();
void _StartDynamicPolicy(bool start,
const freq_preferences& pref);
CPUFreqDriverInterface* fDriverInterface;
BHandler* fTarget;
BMessageRunner* fMessageRunner;
freq_info* fCurrentFrequency;
bool fDynamicPolicyStarted;
bigtime_t fPrevActiveTime;
bigtime_t fPrevTime;
float fSteppingThreshold;
bigtime_t fIntegrationTime;
};
class FrequencyMenu : public BMessageFilter
{
public:
FrequencyMenu(BMenu* menu, BHandler* target,
PreferencesStorage<freq_preferences>* storage,
CPUFreqDriverInterface* interface);
virtual filter_result Filter(BMessage *message, BHandler **target);
void UpdateMenu();
private:
inline void _SetL1MenuLabelFrom(BMenuItem* item);
BHandler* fTarget;
BMenuItem* fDynamicPerformance;
BMenuItem* fHighPerformance;
BMenuItem* fLowEnergie;
BMenu* fCustomStateMenu;
PreferencesStorage<freq_preferences>* fStorage;
CPUFreqDriverInterface* fInterface;
};
class StatusView : public BView {
public:
StatusView(BRect frame, bool inDeskbar = false,
PreferencesStorage<freq_preferences>* storage = NULL);
StatusView(BMessage* archive);
virtual ~StatusView();
static StatusView* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* archive, bool deep = true) const;
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void MessageReceived(BMessage* message);
virtual void FrameResized(float width, float height);
virtual void MouseDown(BPoint where);
virtual void Draw(BRect updateRect);
virtual void GetPreferredSize(float *width, float *height);
virtual void ResizeToPreferred(void);
virtual void ShowPopUpMenu(bool show = true);
virtual void UpdateCPUFreqState();
private:
void _Init();
void _SetupNewFreqString();
void _OpenPreferences();
void _AboutRequested();
void _Quit();
bool fInDeskbar;
CPUFreqDriverInterface fDriverInterface;
freq_info* fCurrentFrequency;
FrequencySwitcher* fFrequencySwitcher;
bool fShowPopUpMenu;
BPopUpMenu* fPreferencesMenu;
BMenuItem* fOpenPrefItem;
BMenuItem* fQuitItem;
FrequencyMenu* fPreferencesMenuFilter;
bool fOwningStorage;
PreferencesStorage<freq_preferences>* fStorage;
PrefFileWatcher<freq_preferences>* fPrefFileWatcher;
BString fFreqString;
BDragger* fDragger;
};
#endif // STATUS_VIEW_H

View File

@ -0,0 +1,102 @@
resource app_signature "application/x-vnd.Haiku-CPUFrequencyPref";
resource app_version {
major = 1,
middle = 0,
minor = 0,
variety = B_APPV_FINAL,
internal = 0,
short_info = "CPUFrequency",
long_info = "CPUFrequency ©2008 Haiku, Inc."
};
resource app_flags B_SINGLE_LAUNCH;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
resource vector_icon {
$"6E6369660E03010000020002023980000000000000004000004BE00008908100"
$"010000FFFF01000000020016023CC7EE389BC0BA16573E39B04977C842ADC700"
$"FFFFD3020006023C529D3753A2B8966F3D9D084B6044496AAF00474747FFA5A0"
$"A002001602BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238"
$"313C3B5CF0BFCD963C7AAC4C13943FCAF901ECFFC3054B04017E020006033E2F"
$"99387F17BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF01010102000602"
$"3879063B8224BE2CC83B10DB4A1F6F49B894FF9A9A9A00242222020006033C69"
$"A60000000000003E186148800049800058F3F3F300D4CECEFFD9D9D902000603"
$"3C1F1A33E78CB7ACC03FFE4F48BB3EBD7B6C0078D905818CFF05FF7ADD050200"
$"1602349C2E37B5FABA1F6036FC624A3E004B320001D3FF910200160235777837"
$"0A67B7E8CE363A844A1D684B45D800F3FF2E0D0A04486050605C51544E04033E"
$"5349594856475C49604B5C4E604B0A06262A264C485E5252523030240A04262A"
$"4838523030240A044838485E525252300A04262A264C485E48380A04453A4553"
$"2844282E0A04B6F9C0F42845282EB701B8EC0A044550455328452AC0F30A0445"
$"3A45502A43B701B8EC0408AEBAB6BCBCC32FBD4F2E3930BDA8B9ACC0A5BA9EBC"
$"03BB1EBFD937BF0DBD4FC072BCC3C019BDDBC0CB46460204BF23C726BF91C70D"
$"BEB5C73FBE9FC87EBE7AC7D9BEC5C922BFAAC97BBF3CC994C018C962C02DC823"
$"C053C8C8C008C77F0204BFCEC6FBC042C6E0BF5BC715BF48C85ABF1FC7B3BF71"
$"C902C063C95ABFF0C974C0D7C93FC0EAC7FAC113C8A2C0C1C7530E0A07010000"
$"0A0101011001178300040A0001021001178400040A020103000A080109000A0B"
$"010A1001178120040A030104000A04020506000A090107000A0A0108000A0D01"
$"0C0815FF0A0C010B0815FF0A0D010C0A3FEAF70000000000003FEAF7C573B4C2"
$"770615FF0A0C010B0A3FEAF70000000000003FEAF7C573B4C2770615FF"
};
#else // HAIKU_TARGET_PLATFORM_HAIKU
resource large_icon array {
$"FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFF001B1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFF001B1C1B1C1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFF001B1C1B1C1C1B1C1C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFF001B1C1B1C1C1B1C1C1B1C1B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFF001B1C1B1C1C1B1C1C1B1C1B1C1C1B0000FFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FF001B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B0000FFFFFFFFFFFFFFFFFFFFFF"
$"003F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B1C1B0000FFFFFFFFFFFFFFFFFF"
$"00173F3F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C1C1B1C3F00FFFFFFFFFFFFFFFF"
$"001717183F3F1B1C1B1C1C1B1C1C1B1C1B1C1C1B1C3F0E00FFFFFFFFFFFFFFFF"
$"00170F1718173F3F1B1C1B1C1C1B1C1C1B1C1B1C3F0E0F00FFFFFFFFFFFFFFFF"
$"00170F0F0F1717183F3F1B1C1B1C1C1B1C1C1B3F0E0F0F00FFFFFFFFFFFFFFFF"
$"00170F00000F0F1717183F3F1B1C1B1C1C1B3F0E0F0F0F00FFFFFFFFFFFFFFFF"
$"00170F000000000F0F1717183F3F1B1C1B3F0E0F0F0F0F00FFFFFFFFFFFFFFFF"
$"00170F0000000000000F0F1717183F1B3F0E0F0F0F0F0F00FFFFFFFFFFFFFFFF"
$"00170F00003700000000000F0F17173F0E0F0F0F0F0F0F00FFFFFFFF000000FF"
$"00170F000037000000000000003F173F0E0F0F0F0F0F0F00FFFF00000F0F0FFF"
$"00170F373600370000000000003F173F0E0F0F0F0F0F0F00FF000F0FFFFFFFFF"
$"00170F000000370036003700003F173F0E0F0F0F0F0F0F00FF000FFFFFFFFFFF"
$"00170F000000373637003700003F173F0E0F0F0F0F0F0F00FF000FFFFFFFFFFF"
$"00170F000000370036373700003F173F0E0F0F0F0F0F0F00FFFF000EFFFFFFFF"
$"00170F000000000037000036003F173F0E0F0F0F0F0F0F00FFFFFF000EFFFFFF"
$"00173F3F0000000037000000003F173F0E0F0F0F0F0F0F00FFFFFF000FFFFFFF"
$"001717183F3F000000000000003F173F0E0F0F0F0F0F0F000F0EFF000FFFFFFF"
$"FF00001717183F3F00000000003F173F0E0F0F0F0F0F0F000F0E000FFFFFFFFF"
$"FFFFFF00001717183F3F0000003F173F0E0F0F0F0F0F000F0F000FFFFFFFFFFF"
$"FFFFFFFFFF00001717183F3F003F173F0E0F0F0F0F000000000FFFFFFFFFFFFF"
$"FFFFFFFFFFFFFF00001717183F3F173F0E0F0F0F000F0F0F0FFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0000171718173F0E0F0F000F0F0FFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFF000017173F0E0F000F0F0FFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF00003F0E000F0F0FFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000E0F0FFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource mini_icon array {
$"FFFFFF0000FFFFFFFFFFFFFFFFFFFFFF"
$"FFFF001B1C0000FFFFFFFFFFFFFFFFFF"
$"FF001B1C1B1C1C0000FFFFFFFFFFFFFF"
$"003F1B1C1B1C1C1B1C0000FFFFFFFFFF"
$"00173F3F1B1C1B1C1C1B1C00FFFFFFFF"
$"000E18173F3F1B1C1B1C0F00FFFFFFFF"
$"000E000018173F3F1B0F0F00FFFFFFFF"
$"000E0000000018170F0F0F00FFFF0000"
$"000E3600370000180F0F0E00FF000E0E"
$"000E0036370000180F0F0E00FF000EFF"
$"000F0000363737180E0F0F00FF000EFF"
$"00170000370000170F0F0F00FF000FFF"
$"00001717000000180F0E0F0000000FFF"
$"FFFF0000171700180F0E0000000EFFFF"
$"FFFFFFFF000017170F000F0F0EFFFFFF"
$"FFFFFFFFFFFF0000000E0FFFFFFFFFFF"
};
#endif // HAIKU_TARGET_PLATFORM_HAIKU

View File

@ -0,0 +1,30 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@clemens-zeidler.de
*/
#include "PreferencesWindow.h"
#include "CPUFrequencyView.h"
#include <Application.h>
int
main(int argc, char* argv[])
{
BApplication *app = new BApplication(kPrefSignature);
PreferencesWindow<freq_preferences> *window;
window = new PreferencesWindow<freq_preferences>("CPU Frequency",
kPreferencesFileName,
kDefaultPreferences);
CPUFrequencyView* prefView = new CPUFrequencyView(BRect(0, 0, 400, 350),
window);
window->SetPreferencesView(prefView);
window->Show();
app->Run();
delete app;
return 0;
}