ASUS F3J serilerinde fan kontrolü
GNU/Linux kullanıcısı iseniz, donanımınızı üreten firmanın GNU/Linux ile pek haşır neşir olmadığı ürünleri karşısında deneyimsel tecrübelere dayanarak ortaya çeşitli sürücüler ve yardımcı yazılımlar çıkarabilmeniz pek mümkün.
Velhasıl kelam, geçenlerde okuduğum fan kontrolü hakkındaki yazıda yazanları uyguladıktan sonra, GNU/Linux kullanırken gayet sessiz bir ortama sahip olduğumu farkettim.
ASUS marka F3Jr bir dizüstü bilgisayar sahibiyim ki yazıda anlatılanlar F3Jp içindi. Dolayısıyla, F3J serisinde donanım niteliği ve BIOS özellikleri arasında fark yok.
Alexander Breckel’in şu adreste yazmış olduğu NASIL belgesinden yola çıkarak fan kontrolünü sağlayabilirsiniz.
İlk olarak, DSDT’yi okumalı ve kontrolünü yapmanız gerekmekte. /proc/acpi/dsdt altında bulunabilen dsdt’yi cat ile okumanızı tavsiye etmemekle birlikte, bunu “disassemble” etmeniz gerekmekte. Bunun için iasl (Intel ACPI Source Language Compiler) aracını kullanacaksınız.
Öncelikle, “root” yetkileriyle,
cp /proc/acpi/dsdt /kopyalamak/istediğiniz/dizin/dsdt
iasl /kopyalamak/istediğiniz/dizin/dsdt
İşlemlerini gerçekleştirdikten sonra, dsdt.dsl dosyasının oluştuğunu göreceksiniz. (F3Jp ve F3Jr’de sorunsuz oluyor)
Oluşan dsdt.dsl makine dilinden, assembler diline çevrilmiş vaziyette sizi bekliyor olacak. Herhangi bir metin editörü ile açıp, şu satırların varlığını kontrol ettikten sonra aşağıda vereceğim bash betiklerini kullanmaya başlayabilirsiniz. (sol sütun satır numarası)
4521 Mutex (ASIO, 0x00) [...] 5884 OperationRegion (KAID, SystemIO, 0x025C, 0x01) 5885 Field (KAID, ByteAcc, NoLock, Preserve) 5886 { 5887 AEID, 8 5888 } 5889 5890 OperationRegion (KAIC, SystemIO, 0x025D, 0x01) 5891 Field (KAIC, ByteAcc, NoLock, Preserve) 5892 { 5893 AEIC, 8 5894 } 5895 5896 Method (WEIE, 0, Serialized) 5897 { 5898 Store (0x4000, Local0) 5899 And (AEIC, 0x02, Local1) 5900 While (LAnd (LNotEqual (Local0, Zero), LEqual (Local1, 0x02))) 5901 { 5902 And (AEIC, 0x02, Local1) 5903 Decrement (Local0) 5904 } 5905 } [...] 5982 Method (WMFN, 1, Serialized) 5983 { 5984 If (LEqual (Acquire (ASIO, 0xFFFF), 0x00)) 5985 { 5986 WEIE () 5987 Store (0x98, AEIC) 5988 WEIE () 5989 Store (Arg0, AEID) 5990 WEIE () 5991 Release (ASIO) 5992 } 5993 }
Bu satırların varlığını kontrol ettikten sonra, fan kontrol uygulamasına geçebiliriz. Öncelikle, fan’ı kontrol eden bir program oluşturmak zorundayız. Arkasından, fan’ı kontrol eden programa komut verecek betiği oluşturmalıyız.
Öncelikle fan için uygulamayı oluşturalım:
fan.c olarak isimlendirdiğinizi düşünerek, içerisine:
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 | #include <stdio.h> // printf #include <stdlib.h> // atoi #include <stdint.h> // uint8_t, uint16_t #include <string.h> // strcmp #include <sys/io.h> // inb, outb // IO ports const uint16_t AEIC = 0x025D; // command register const uint16_t AEID = 0x025C; // data register // waits for the status bit to clear, max 0x4000 tries void WEIE() { uint16_t Local0 = 0x4000; uint8_t Local1 = inb(AEIC) & 0x02; while(Local0 != 0 && Local1 == 0x02) { Local1 = inb(AEIC) & 0x02; Local0--; } } // sets the fan speed void WMFN(uint8_t Arg0) { WEIE(); outb(0x98, AEIC); WEIE(); outb(Arg0, AEID); WEIE(); } int main(int argc, char ** argv) { if(argc != 2) { printf("usage: %s speed\n", argv[0]); printf("speed: `auto' or a value between 1 and 15\n"); printf("keep in mind that `auto' will be even faster than 15!\n"); return 1; } uint8_t speed = 0xFF; if(strcmp(argv[1], "auto") == 0) printf("setting speed to 'auto'\n"); else { int arg = atoi(argv[1]); if(arg < 1 || arg > 15) { printf("Error: the speed %d is not possible\n", arg); return 1; } printf("setting speed to %d\n", arg); speed = (arg << 3) | 0x07; } if(ioperm(AEID, 1, 1)) { printf("Error: could not gain access to IO port AEID (0x025C)\n"); return 1; } if(ioperm(AEIC, 1, 1)) { printf("Error: could not gain access to IO port AEIC (0x025D)\n"); return 1; } WMFN(speed); printf("done.\n"); return 0; } |
fan.c bu haliyle tabii ki bir işe yaramayacak. Öncelikle derlememiz gerekmekte:
gcc fan.c -o fan
Bunun ardından, bu uygulamayı otomatiğe bağlayacak bash betiğimizi oluşturalım:
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 | #!/bin/sh OLD_SPEED="0" OLD_TEMP="0" setSpeed () { if [ "$1" != "$OLD_SPEED" ]; then echo "new speed $1" OLD_SPEED="$1" ./fan "$1" > /dev/null fi } while [ 1 ]; do TEMP=`cat /proc/acpi/thermal_zone/THRM/temperature | awk '{print $2}'` if [ "$TEMP" != "$OLD_TEMP" ]; then echo "temperature $TEMP C" OLD_TEMP="$TEMP" fi if [ $TEMP -gt 65 ]; then setSpeed auto elif [ $TEMP -gt 60 ]; then setSpeed 13 elif [ $TEMP -gt 55 ]; then setSpeed 11 elif [ $TEMP -gt 50 ]; then setSpeed 9 else setSpeed 1 fi sleep 2 done |
./fan “$1″ > /dev/null satırına dikkatinizi çekerim. Yukarıda derlemiş olduğumuz fan isimli aracın tam yolunu burada belirtmek gerek. fan ve fan kontrolünü sağlayan betik aynı dizinde ise sorun yok tabii ki
.
Fanların en gürültülü çalıştığı durumlarda bu betiği birden devreye sokun ve farkı görün, pişman olmayacaksınız. Ancak yine de bunun deneysel bir teknoloji olduğunu, herhangi bir zarar durumunda kesinlikle sorumlu olmayacağımı, kullanıcının buradaki işlemleri tamamen kendi rızasıyla uyguladığını kabul etmiş olduğunu varsayıyorum.
Someone noticed a bug in my C code on line 43:
if(arg 15) {
should be
if(arg 15) {
If you want, you could add a comment on http://aneas.org/knowledge/asus_f3jp_fan_control.php with your url, so users of your language (whatever that is
) can find this article more easily.
Regards
Hey Alexander,
I’ve fixed it, BTW, the article is in Turkish.