1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
|
/* digifan.c - Fan control program for the ASUS Digimatrix.
*
* (C) Copyright 2006 Andrew Calkin <calkina@geexbox.org>
* (C) Copyright 2004 Richard Taylor <richard@artaylor.co.uk>
*
* based on code for accessing/initializing it8712/it8705 written by
*
* (C) Copyright 2004 Wojtek Kaniewski <wojtekka@toxygen.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/io.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include "it8705.h"
#include "digifan.h"
#include "digitools.h"
static double min = FAN_DEFAULT_MIN; /* minimum fan speed default (%) */
static double gradient = FAN_DEFAULT_GRADIENT; /* speed increase rate */
static double offset = FAN_DEFAULT_OFFSET; /* temp for minimum speed */
static struct option digifan_longopts[] = {
{ "min", 1, 0, 'm' },
{ "gradient", 1, 0, 'g' },
{ "offset", 1, 0, 'o' },
{ "auto", 0, 0, 'a' },
{ "intelligent", 0, 0, 'i' },
{ "set", 1, 0, 's' },
{ "read", 0, 0, 'r' },
{ "kill", 0, 0, 'k' },
{ "version", 0, 0, 'v' },
{ "help", 0, 0, 'h' },
{ NULL, 0, 0, 0 }
};
static int set_fan (unsigned char state)
{
unsigned char speed, temp1, temp2;
double percentage = 0;
it87_ec_port_open();
daemon_kill();
temp1 = it87_read_ec_byte(IT8705_TEMP_REG1);
temp2 = it87_read_ec_byte(IT8705_TEMP_REG2);
switch (state)
{
case FAN_AUTO:
#ifndef SILENT
printf("Setting Fan to AUTO\n");
#endif
it87_write_ec_byte(FAN1, AUTO);
it87_write_ec_byte(FAN2, AUTO);
it87_write_ec_byte(FAN3, AUTO);
break;
case FAN_OFF:
it87_write_ec_byte(FAN1, OFF);
it87_write_ec_byte(FAN2, OFF);
it87_write_ec_byte(FAN3, OFF);
break;
case FAN_INTELLIGENT:
#ifndef SILENT
printf("Running in intelligent mode (update = 5s)\n");
#endif
daemon_init();
while (1)
{
temp1 = it87_read_ec_byte(IT8705_TEMP_REG1);
temp2 = it87_read_ec_byte(IT8705_TEMP_REG2);
if (temp2 > temp1)
{
/* Go with the average of the two temperatures.
(we need to cool down the mainboard too)*/
temp1 = (temp1 + temp2) / 2;
}
percentage = min + ( (temp1 - offset) * gradient);
/* We can't go more than 100%! */
if (percentage > 100)
percentage = 100;
/* No slower than min */
if (percentage < min)
percentage = min;
speed = (unsigned char) ((percentage * (double)FAN_MAX_PWM) / 100);
it87_write_ec_byte(FAN1, (speed&0x7f));
it87_write_ec_byte(FAN2, (speed&0x7f));
sleep(5);
} /* end while*/
break;
default:
#ifndef SILENT
printf("Setting fan speed to: %d%%\n",
(100 *(state & 0x7f)) / 0x7f);
#endif
it87_write_ec_byte(FAN1, state);
it87_write_ec_byte(FAN2, state);
break;
} /* end switch*/
it87_ec_port_close();
return(0);
}
static void digifan_help(const char *argv0)
{
#ifndef SILENT
printf(
"Usage: %s [OPTIONS]\n"
"\n"
" Program to control the fan speeds in the Asus Digimatrix.\n"
" -v, --version Print version information\n"
" -h, --help Display this help message\n"
"\n"
" Fan control is initiated via one of the following options:\n"
" -r, --read Display the current fan speed (%%)\n"
" Note: does not alter the fan setting\n"
" -s, --set=VALUE Set the current fan speed (%%)\n"
" -a, --auto Set to H/W monitoring (as in BIOS)\n"
" -i, --intelligent Set the fan speed based on current temperature\n"
" -k, --kill Stop the daemon (if running), and exit\n"
"\n"
" The -i option may also be used with any of the following options to\n"
" override program defaults.\n"
"\n"
" -m, --min=VALUE Set the minimum Fan speed (Default: 30)\n"
" -o, --offset=VALUE The temperature (deg C) for minimum fan speed \n"
" (Default: 30)\n"
" -g, --gradient=VALUE Set the rate at which speed increases with\n"
" temperature (Default: 4)\n"
" e.g. gradient = (100 - min) \n"
" -------------------\n"
" (max_temp - offset)\n"
"\n", argv0);
#endif
}
int digifan_main(int argc, char **argv)
{
unsigned char next_state = 0;
if ( (int)getuid() != 0)
{
#ifndef SILENT
fprintf(stderr,"Must be root to run this program!\n");
#endif
return(-1);
}
int ch, longindex = 0;
if (argc == 1)
{
#ifndef SILENT
printf("\nPlease supply some parameters.\n"
"Use %s -h for list.\n\n", argv[0]);
#endif
return(1);
}
it87_open();
it87_ldn_set(IT8705_EC_LDN);
it87_close();
for (;;)
{
if ((ch = getopt_long(argc, argv, "m:g:o:ais:rkvh",
digifan_longopts, &longindex)) == -1)
{
break;
}
switch (ch)
{
case 'm':
if (atof(optarg)<5)
{
#ifndef SILENT
printf("Specified minimum too low! Using default.\n");
#endif
}
else
{
if (atof(optarg)>100)
{
#ifndef SILENT
printf("Specified minimum too high! Using default.\n");
#endif
}
else
min=atof(optarg);
}
#ifndef SILENT
printf("Setting min to: %.02f%%\n", min);
#endif
break;
case 'g':
if (atof(optarg)<2)
{
#ifndef SILENT
printf("Specified gradient too low! Using default.\n");
#endif
}
else
{
if (atof(optarg)>100)
{
#ifndef SILENT
printf("Specified gradient too high! Using default.\n");
#endif
}
else
gradient=atof(optarg);
}
#ifndef SILENT
printf("Setting gradient to: %.02f\n", gradient);
#endif
break;
case 'o':
if (atof(optarg)<18)
{
#ifndef SILENT
printf("Specified offset too low! Using default.\n");
#endif
}
else
{
if (atof(optarg)>55)
{
#ifndef SILENT
printf("Specified offset too high! Using default.\n");
#endif
}
else
offset=atof(optarg);
}
#ifndef SILENT
printf("Setting offset to: %.02fDegC\n", offset);
#endif
break;
case 'r':
it87_ec_port_open();
printf("Current Fan setting is: %d%%\n",
(100 *(it87_read_ec_byte(FAN1) & 0x7f)) / 0x7f);
it87_ec_port_close();
return(0);
break;
case 's':
if (atoi(optarg) < OFF)
{
#ifndef SILENT
printf("Warning: Value provided (%d%%) too low!\n"
"Minimum fan speed: %d%%\n", atoi(optarg),OFF);
#endif
next_state = ( OFF * 0x7f) / 100;
}
else if (atoi(optarg)>100)
{
#ifndef SILENT
printf("Warning: Value provided (%d%%) too high!\n"
"Maximum fan speed: 100%%\n", atoi(optarg));
#endif
next_state = FAN_MAX_PWM;
}
else
{
next_state = ( atoi(optarg) * 0x7f) / 100;
}
break;
case 'a':
next_state = FAN_AUTO;
break;
case 'i':
next_state = FAN_INTELLIGENT;
break;
case 'k':
#ifndef SILENT
printf("Stopping the %s daemon\n",argv[0]);
#endif
daemon_kill();
exit(0);
case 'v':
#ifndef SILENT
printf("ASUS DigiMatrix Fan Controller, from DigiTools Version "
"%s\n",DIGI_VER);
#endif
/* Exit program after giving version info */
return(0);
break;
case 'h':
digifan_help(argv[0]);
/* Exit program after giving help info */
return(0);
break;
default:
#ifndef SILENT
printf("Undefined input parameter(s) provided\n");
#endif
/* Impossible to get here (unless programming error?) */
return(1);
break;
} /* end switch */
} /* end for loop */
if (next_state != 0)
set_fan(next_state);
else
{
#ifndef SILENT
printf("No fan mode selected!\n");
#endif
}
return(0);
}
|