wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmlongrun / src / longrun_linux.c
blob89227ebbbd06c45f61ed37a39d880a290e17d283
1 /*
2 * longrun_linux.c - module to get LongRun(TM) status, for GNU/Linux
4 * Copyright(C) 2001 Transmeta Corporation
5 * Copyright(C) 2001 Seiichi SATO <ssato@sh.rim.or.jp>
7 * licensed under the GPL
8 */
9 #undef USE_PREAD
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #ifdef USE_PREAD
23 #define __USE_UNIX98 /* for pread/pwrite */
24 #endif
25 #define __USE_FILE_OFFSET64 /* msr/cpuid needs 64bit address with newer linuxes */
26 #include <unistd.h>
27 #include "common.h"
29 #define MSR_DEVICE "/dev/cpu/0/msr"
30 #define MSR_TMx86_LONGRUN 0x80868010
31 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
33 #define LONGRUN_MASK(x) ((x) & 0x0000007f)
34 #define LONGRUN_RESERVED(x) ((x) & 0xffffff80)
35 #define LONGRUN_WRITE(x, y) (LONGRUN_RESERVED(x) | LONGRUN_MASK(y))
37 #define CPUID_DEVICE "/dev/cpu/0/cpuid"
38 #define CPUID_TMx86_VENDOR_ID 0x80860000
39 #define CPUID_TMx86_PROCESSOR_INFO 0x80860001
40 #define CPUID_TMx86_LONGRUN_STATUS 0x80860007
41 #define CPUID_TMx86_FEATURE_LONGRUN(x) ((x) & 0x02)
43 static int cpuid_fd; /* CPUID file descriptor */
44 static char *cpuid_device; /* CPUID device name */
45 static int msr_fd; /* MSR file descriptor */
46 static char *msr_device; /* MSR device name */
48 static void
49 read_cpuid(loff_t address, int *eax, int *ebx, int *ecx, int *edx)
51 uint32_t data[4];
53 #ifdef USE_PREAD
54 if (pread(cpuid_fd, &data, 16, address) != 16) {
55 perror("pread");
56 #else
57 if (lseek(cpuid_fd, address, SEEK_SET) != address) {
58 perror("lseek");
59 exit(1);
61 if (read(cpuid_fd, &data, 16) != 16) {
62 perror("read");
63 #endif
64 exit(1);
67 if (eax)
68 *eax = data[0];
69 if (ebx)
70 *ebx = data[1];
71 if (ecx)
72 *ecx = data[2];
73 if (edx)
74 *edx = data[3];
77 /* note: if an output is NULL, then don't set it */
78 static void
79 read_msr(loff_t address, int *lower, int *upper)
81 uint32_t data[2];
83 #ifdef USE_PREAD
84 if (pread(msr_fd, &data, 8, address) != 8) {
85 perror("pread");
86 #else
87 if (lseek(msr_fd, address, SEEK_SET) != address) {
88 perror("lseek");
89 exit(1);
91 if (read(msr_fd, &data, 8) != 8) {
92 perror("read");
93 #endif
94 exit(1);
97 if (lower)
98 *lower = data[0];
99 if (upper)
100 *upper = data[1];
103 void
104 longrun_init(char *cpuid_dev, char *msr_dev)
106 int eax, ebx, ecx, edx;
108 /* set CPUID device */
109 cpuid_device = CPUID_DEVICE;
110 if (cpuid_dev)
111 cpuid_device = cpuid_dev;
113 /* set MSR device */
114 msr_device = MSR_DEVICE;
115 if (msr_dev)
116 msr_device = msr_dev;
118 /* open CPUID device */
119 if ((cpuid_fd = open(cpuid_device, O_RDONLY)) < 0) {
120 fprintf(stderr, "error opening %s\n", cpuid_device);
121 if (errno == ENODEV)
122 fprintf(stderr,
123 "make sure your kernel was compiled with CONFIG_X86_CPUID=y\n");
124 exit(1);
127 /* open MSR device */
128 if ((msr_fd = open(msr_device, O_RDONLY)) < 0) {
129 fprintf(stderr, "error opening %s\n", msr_device);
130 if (errno == ENODEV)
131 fprintf(stderr,
132 "make sure your kernel was compiled with CONFIG_X86_MSR=y\n");
133 exit(1);
136 /* test for "TransmetaCPU" */
137 read_cpuid(CPUID_TMx86_VENDOR_ID, &eax, &ebx, &ecx, &edx);
138 if (ebx != 0x6e617254 || ecx != 0x55504361 || edx != 0x74656d73) {
139 fprintf(stderr, "not a Transmeta x86 CPU\n");
140 exit(1);
143 /* test for LongRun feature flag */
144 read_cpuid(CPUID_TMx86_PROCESSOR_INFO, &eax, &ebx, &ecx, &edx);
145 if (!CPUID_TMx86_FEATURE_LONGRUN(edx)) {
146 printf("LongRun: unsupported\n");
147 exit(0);
150 /* close device */
151 close(cpuid_fd);
152 close(msr_fd);
158 * percent: performance level (0 to 100)
159 * flags: performance/economy/unknown
160 * mhz: frequency
161 * volts: voltage
163 void
164 longrun_get_stat(int *percent, int *flags, int *mhz, int *voltz)
166 int eax, ebx, ecx;
168 /* open CPUID device */
169 if ((cpuid_fd = open(cpuid_device, O_RDWR)) < 0) {
170 fprintf(stderr, "error opening %s\n", cpuid_device);
171 if (errno == ENODEV)
172 fprintf(stderr,
173 "make sure your kernel was compiled with CONFIG_X86_CPUID=y\n");
174 exit(1);
177 /* open MSR device */
178 if ((msr_fd = open(msr_device, O_RDWR)) < 0) {
179 fprintf(stderr, "error opening %s\n", msr_device);
180 if (errno == ENODEV)
181 fprintf(stderr,
182 "make sure your kernel was compiled with CONFIG_X86_MSR=y\n");
183 exit(1);
186 /* frequency, voltage, performance level, */
187 read_cpuid(CPUID_TMx86_LONGRUN_STATUS, &eax, &ebx, &ecx, 0);
188 *mhz = eax;
189 *voltz = ebx;
190 *percent = ecx;
192 /* flags */
193 read_msr(MSR_TMx86_LONGRUN_FLAGS, flags, NULL);
194 *flags =
195 (*flags & 1) ? LONGRUN_FLAGS_PEFORMANCE : LONGRUN_FLAGS_ECONOMY;
197 /* close device */
198 close(cpuid_fd);
199 close(msr_fd);