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 Smile.

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.

2 Comments

Alexander BreckelMay 26th, 2009 at 12:38 pm

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 Angel ) can find this article more easily.

Regards

ras0irMay 26th, 2009 at 12:57 pm

Hey Alexander,

I’ve fixed it, BTW, the article is in Turkish.

Leave a comment

Your comment

Click to Insert Smiley

SmileBig SmileGrinLaughFrownBig FrownCryNeutralWinkKissRazzChicCoolAngryReally AngryConfusedQuestionThinkingPainShockYesNoLOLSillyBeautyLashesCuteShyBlushKissedIn LoveDroolGiggleSnickerHeh!SmirkWiltWeepIDKStruggleSide FrownDazedHypnotizedSweatEek!Roll EyesSarcasmDisdainSmugMoney MouthFoot in MouthShut MouthQuietShameBeat UpMeanEvil GrinGrit TeethShoutPissed OffReally PissedMad RazzDrunken RazzSickYawnSleepyDanceClapJumpHandshakeHigh FiveHug LeftHug RightKiss BlowKissingByeGo AwayCall MeOn the PhoneSecretMeetingWavingStopTime OutTalk to the HandLoserLyingDOH!Fingers CrossedWaitingSuspenseTremblePrayWorshipStarvingEatVictoryCurseAlienAngelClownCowboyCyclopsDevilDoctorFemale FighterMale FighterMohawkMusicNerdPartyPirateSkywalkerSnowmanSoldierVampireZombie KillerGhostSkeletonBunnyCatCat 2ChickChickenChicken 2CowCow 2DogDog 2DuckGoatHippoKoalaLionMonkeyMonkey 2MousePandaPigPig 2SheepSheep 2ReindeerSnailTigerTurtleBeerDrinkLiquorCoffeeCakePizzaWatermelonBowlPlateCanFemaleMaleHeartBroken HeartRoseDead RosePeaceYin YangUS FlagMoonStarSunCloudyRainThunderUmbrellaRainbowMusic NoteAirplaneCarIslandAnnouncebrbMailCellPhoneCameraFilmTVClockLampSearchCoinsComputerConsolePresentSoccerCloverPumpkinBombHammerKnifeHandcuffsPillPoopCigarette