2009年12月21日 星期一

libopenh323 and libopal conflict

前陣子為了編譯 t38modem 所以需要 libopenh323 當作 library,(header files 需要 libopenh323-dev)
後來發現 the successor of OpenH323 project --- OPAL project (Open Phone Abstraction Library)
但是在 Debian sqeeze 上,這兩組有些衝突,原因是底層的 libpt 版本需求不同造成的,目前我沒有去解決(或強制把 "依賴" libpt-1.10.10 的部份以 libpt-2.6.5 取代,沒有試過不知道!)衝突關係如下列:

compile libopal-3.6.6 source get  from [ here ], needs libpt-2.6.5

libopal-3.6.6
depends on
libpt-2.6.5

header files in :
libopal-dev-3.6.6
depends on
libpt-dev-2.6.5-1


compile t38modem
needs
libopenh323-dev: /usr/share/openh323/openh323u.mak

libopenh323-dev
depends on
libpt-1.10.10-dev  <-- conflict libpt-dev-2.6.5-1
libopenh323-1.18
   

libopenh323-1.18
depends on
libpt-1.10.10 ← conflict libpt-2.6.5

結論:
所以目前 compile 使用 OpenH323 的 source 與使用 OPAL 的 source 無法同時 compile ,必需把相關的 libpt 重裝(一個用 2.6.5, 另一個用 1.10.10) #Technorati 標籤: , , , ,

2009年12月13日 星期日

Debian 升級 testing (sqeeze) 與 ATI X1450 的 driver 問題

Asus A8J 大約是兩三年前的華碩主流筆電之一,獨立顯卡採用  ATI X1450.
Debian Lenny 下有提供 ATI propietary driver (non-free) :
kernel driver(要 3D 加速,需要 kernel driver ) : fglrx-modules-2.6.26-* 等,driver source : fglrx-kernel-src
for openGL lib : fglrx-glx
根據這篇 [ arch linux ATI ] [ref 1] 知道,X1450 的 code name 為 (RV515, 即 r5xx  系列)

Debian 系統升級到  testing 後,kernel driver 套件變成 : fglrx-source , 且改為支援 r6xx-r7xx 而已,也就是說 ATI 官方 driver 不再支援 r5xx 系列,
但是這些不被支援的系列的 spec 已經  release 給 open source 社群。所以目前升級後的  xorg 7.4 裡面的  xserver-xorg-video-ati 套件,可以支援 r5xx 系列。
xorg.conf 已經不需要了,xorg 會自動偵測掛載  radeon driver。

glxgears 的數據為
1598 frames in 5.0 seconds = 319.450 FPS 
1613 frames in 5.0 seconds = 322.503 FPS  ( 本blog時間測)

6097 frames in 5.0 seconds = 1219.223 FPS 
6014 frames in 5.0 seconds = 1202.697 FPS  ( 2010年4月20測)

跟使用 ATI propietary ~1200 FPS 比較起來,稍稍等待 open source 社群是值得的,
時間會證明 open source community 提供的 code 效能,總會超越 propietary code 的,並且更穩定。
Technorati 標籤: , , ,

2009年12月7日 星期一

製作 beagle board kernel v2.6.29-58cf2f1

約四個月前,在網路上找到了一篇 [ building a customed kernel for beagle board ] ,但是事過境遷,該篇 blog 已經不存在。有位對岸的大哥把步驟給節錄下來了[ 制作beagleboard的kernel  ] ,為了避免以後有類似情形,這裡再節錄一遍過程:

Retrieve the GIT checkout:

    git clone git://git2.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
    cd linux-omap-2.6/
    git checkout 58cf2f1 -b v2.6.29-58cf2f1
    git archive --format=tar --prefix=v2.6.29-58cf2f1/ v2.6.29-58cf2f1 | gzip > ../v2.6.29-58cf2f1.tar.gz
    git checkout master
    git branch v2.6.29-58cf2f1 -D
    cd ..

Download kernel diffs and kernel config:

    wget http://rcn-ee.homeip.net:81/dl/omap/beagle/v2.6.29-58cf2f1-oer34/v2.6.29-58cf2f1-oer34.diff
    wget http://rcn-ee.homeip.net:81/dl/omap/beagle/v2.6.29-58cf2f1-oer34/defconfig

Extract Kernel Source

    tar -xf v2.6.29-58cf2f1.tar.gz
    cd v2.6.29-58cf2f1/

Apply Patch

    patch -p1 < ../v2.6.29-58cf2f1-oer34.diff

Copy Defconfig

    cp ../defconfig .config

Configure the kernel (requires libncurses5-dev installed)

    make menuconfig

Build, Cross-Compiling:

    make CROSS_COMPILE=arm-linux-gnu- uImage

A few moments later, you can find your new kernel in the ‘arch/arm/boot/’ directory.

Make modules:

    make CROSS_COMPILE=arm-linux-gnu- modules

    make CROSS_COMPILE=arm-linux-gnu- modules_install


2009年12月3日 星期四

sparse type checking

因為 compiler 只能檢查 syntax.
Linus 為了檢查程式的 semantics ,創造出 sparse. 在 [ Linux Journal "Linus & Lunatics" ] 這篇文章提到了他當初的想法:

相關的 code 在 compiler.h 可以看得到 (kernel source 2.6.28 )

#ifdef __CHECKER__
# define __user        __attribute__((noderef, address_space(1)))
# define __kernel    /* default address space */
# define __safe        __attribute__((safe))
# define __force    __attribute__((force))
# define __nocast    __attribute__((nocast))
# define __iomem    __attribute__((noderef, address_space(2)))
# define __acquires(x)    __attribute__((context(x,0,1)))
# define __releases(x)    __attribute__((context(x,1,0)))
# define __acquire(x)    __context__(x,1)
# define __release(x)    __context__(x,-1)
# define __cond_lock(x,c)    ((c) ? ({ __acquire(x); 1; }) : 0)
extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *);
#else
# define __user
# define __kernel
# define __safe
# define __force
# define __nocast
# define __iomem
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
# define __builtin_warning(x, y...) (1)
# define __acquires(x)
# define __releases(x)
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x,c) (c)
#endif

平常 gcc compile 時,不定義 __CHECKER__,所以這裡的許多 macros 就得到空定義 (程式碼 #else 部份)
那麼使用 sparse 時,就定義 __CHECKER__ ,(程式碼 #ifdef 部份) 舉例來說 第一行:

# define __user        __attribute__((noderef, address_space(1)))

使得 sparse 檢查 __user 定義的變數,是否落在 user space,例如用在 copy_to_user() :

unsigned long
copy_to_user(void __user *to, const void *from, unsigned long n)
{...}

compiler 是不會知道 "to" 的變數是不是正確!但是 sparse 檢查時,若發現 to 所指的不是在 user space 裡,就會發出 warning
因此這些 attributes 是給 sparse 用的,在 gcc 文件裡面查不到這些 attributes (是的,不要怪 gcc 文件寫不好...)

另外這篇 [ linux 內核中 compiler.h 文件的分析 ] 還解釋了 __acquire / __release 必須成對使用,否則 sparse 會發出 warning.

Linus 真神人也,可以讓 kernel source 藉由 sparse 工具來檢查 program semantic !!Technorati 標籤: ,

2009年11月25日 星期三

意外的快樂

出社會以來,因為家中經濟需要援助,一直都沒有存下甚麼錢。一直到了結婚,也就順勢把所有的收入交給了老婆,接著添了一個弟弟。所以有些年輕時候想要完成的夢,就一直擱著。排一排順序,大概是這樣:
1 最想變成 open source 的 hacker ,為某些 project 貢獻程式碼。當然,基本功還在練習,所以還沒到那個火侯可以當 hacker ...
2  一直想帶親愛的另一半,去美國玩。常出國的人,是不會理解這種渴望的...,有小朋友的父母,更是難排出時間與金錢(費用不訾啊...)
3. 希望有朝一日,圍棋可以上段。 這個夢想本來是四十歲的生日願望,結果沒有達成。因為要扛一家之計,很多時間需要支配到別處,也就擺著了。

承蒙老婆大人的體貼,跟圍棋老師約了時間,叫我去下指導棋。天啊,一對一耶!這可是有錢人才這樣玩吧!
本來想上完一堂,應付應付就好,不要讓圍棋老師以為咱們家老婆大人沒信用。
但是奇妙的心理變化發生了.....我整晚在棋院都好興奮我竟然有機會實現,十幾年來的夢想之一,老師說我有機會上段耶!!!

這是第一次 感覺到,我把錢拿來花在 "實現自己夢想" 上,好快樂!!!
這是第一次 體會到,老婆以前學鋼琴,說她很快樂,是甚麼滋味...
這是十年來第一次,覺得自己活得很有成就感
...

快樂的感覺,一直在心中徘迴,老婆大人,謝謝您!

2009年11月18日 星期三

Emacs 捲動的設定

Emacs 內定的捲動方式為一次半頁,這樣看起來跳動很大,有些不習慣。修改 .emacs 加入下面設定,可以變成『自然捲』...
(setq scroll-margin 0 scroll-conservatively 10000 )

另外,想定義新的 macro 並且紀錄於 .emacs 以供下次使用,可以這樣作,
(以 scroll other window (up/down) one line 這個動作為例) :

C-x (      定義新的 macro
M 1 C-M-v   我們的新 command --- scroll other window down one line
C-x )     結束 macro 定義

給它取一個名字:
M-x name-last-kbd-macro [Enter]
打入自取名稱 ,例如 scroll-other-window-down-one-line [Enter]

打開 ~/.emacs 準備加入這個新定義:
M-x insert-kbd-macro
打入剛剛取的名稱  scroll-other-window-down-one-line [Enter] 就會出現
(fset 'scroll-other-window-down-one-line
   "\261\226")
然後定義一個 hotkey 例如 F11 給它:
(define-key global-map [f11] 'scroll-other-window-down-one-line)

以後按 F11 就會 scroll down other window.

為了對稱,做了一個 scroll other window up one line ,最後在 .emacs 裡長成這樣:

...
(fset 'scroll-other-window-up-one-line
   "\2551\226")
(define-key global-map [M-f11] 'scroll-other-window-up-one-line)
(fset 'scroll-other-window-down-one-line
   "\261\226")
(define-key global-map [f11] 'scroll-other-window-down-one-line)
...

Technorati 標籤:

2009年11月13日 星期五

eclipse + CDT for C++ Development

這篇說明 eclipse 的設定,為了怕設定的部份翻譯不好,乾脆用英文寫...

Since `cscope + ecb + emacs' is my favorite development tool, there is no need for "eclipse", while not all people get used to `emacs' conveniently. Here we introduce another good IDE for C/C++ developemnt --- Eclipse !!

1. From [ http://www.eclipse.org/downloads/ ] download `Eclipse IDE for Java EE...' or `Eclipse IDE for Java...' or `Eclipse IDE for C/C++...', I download the eclipse-jee-galileo-linux-gtk.tar.gz  , extract,  then add path (where you untar eclipse ) to ~/.bashrc such that when I type `eclipse' command so that it can be brought up (Yes, its green software).

2. Install the CDT plugin : (If you use `Eclipse IDE for C/C++' , please skip this step)
In eclipse menu, goto (Help | Install New Software ...) then type this html page:
http://download.eclipse.org/tools/cdt/releases/galileo
(note : CDT need > eclipse 3.5 or up )
then update. The CDT component will then be installed.

3. Create C++ project :
In eclipse menu, goto "File | New | Project...|C++":
   a. Fill "Project Name".
   b. Select Makefile Project | Empty Project.  <--- yes, choose `Empty Project' for the external Makefile case !!
   c. Select Linux GCC at the right side.
   d. Press the "Finish" button.
then you have created an empty project in eclipse.

4. Import external sources/Makefile to project:
Right click on the project name, select "import...":
choose "General | File System" , click "Next" button, then "browse" to your source path, (of,course, you can filter out unnecessary files ) then press "Finish".

5. Goto "Project | properties| C/C++ Build", in the right "Build Location" field, press the "workspace" button, and given your project path , for e.g. ${workspace_loc:/test/home/tom/external_open_source}. (I was fooling around here for 6 hours --- before I learn to press the "workspace" button)

Then press "OK", the project will be built. But in our `external_open_source' project, we need use `make opt' as the building command ---goto "Project |Proties" , in "C/C++ Build",
a. select the "Behavior" tab,
b. uncheck "Build on resource save(Auot build)",
c. modify "Build (Incremental build)" to "opt",
d. then press "OK" to finish.

Now, you should build the `external_open_source'  sucessfully, instead of the 'No rule to make target `opt' error message !

ps. In Debian Lenny, make sure to use

$update-alternatives --config java

to configure your default java to `java-6(5)-sun' instead of `java-gcj' , the Eclipse will NOT start with `java-gcj' as the default java environment:

  Selection    Alternative
-----------------------------------------------
              1    /usr/bin/gij-4.3
              2    /usr/lib/jvm/java-gcj/jre/bin/java
*+          3    /usr/lib/jvm/java-6-sun/jre/bin/java

Press enter to keep the default[*], or type selection number: 3
 
Technorati 標籤: ,

2009年10月16日 星期五

Tips for setup the android-x86 build system

Of course , you will find the [Android-x86 : Get Source] site useful..
On a newly install Debian Lenny machine, we may encounter the following situations:.

1. where is my "repo"?
Ans: the `repo' is not a Debian package, this [Android download] teach us how to download/setup the `repo' script.

2.  I want to built-in a module, how to do it ?
Ans: Take DM9601 network card as an example.
First copy my_defconfig under {android-x86}/kernel/arch/x86/configs/android-x86_defconfig, then
modify my_deconfig:
CONFIG_DM9601=y

Finally following the [customized kernel] to build android-x86:
#>make iso_img TARGET_PRODUCT=eeepc TARGET_KERNEL_CONFIG=my_defconfig

3. I want to use user account instead of root to build the source, how to do it without problem ?
Ans: During the build, there are 2 commands `e2fsck' `tune2fs' needs root privilege,
now let you user_account can also use them.
under the root:
#> link -s  /sbin/e2fsck  /usr/bin/e2fsck
#> link -s  /sbin/tune2fs  /usr/bin/tune2fs
#> visudo
let user `tom' to use these 2 commands
Cmnd_Alias FS=/sbin/tune2fs,\
       /sbin/e2fsck
tom     ALL=NOPASSWD: FS

4. During the build, compiler complain about the java , what happened?
Ans: This is probably caused by using the incorrect java compiler...
Please note that Android-1.6 can accept the java-6-sun as its compile environment, use
#>update-java-alternatives -s java-6-sun
to select the compiler environment provided by sun java.

That's all.Technorati 標籤: ,

2009年10月15日 星期四

The T.38 and open source

Abstracted from:

http://www.voxgratia.net/blog/archives/2005/08/fax_facts.html

1.T.38 should not be confused with the similar-sounding T.37 which uses a totally different approach. Whereas T.38 is intended for realtime fax transmision using an encapsulated T.30 data stream, T.37 is intended for "store and forward" applications. It requires the fax data to be converted into TIFF format and then encoded using base64 into a text message and then transmitted using SMTP.


2.T.38 solves most of the problems with sending fax over an IP network. A T.38 fax call uses 20% of the bandwidth than the modulated audio approach because it is now a stream of bits at an average speed of 14400 bps rather than a stream of audio samples at 64000 bps.


3. Asterisk supports T.38 fax pass-through, origination and termination. It does

not support gateway operation.


4.Asterisk 1.6 support G.711 and T.38 FAX origination and termination. T.38 gateway features are still in development.


5 more of T.38 open source informations:

http://www.voip-info.org/wiki/view/T.38


6.more of Asterisk T.38:

http://www.voip-info.org/tiki-index.php?page=Asterisk%20T.38


7.What is T38modem ?

  • It is not a modem.

  • From a FAX application's view point (e.g. HylaFAX) T38modem looks like a class 1 FAX modem pool.

  • From an IP network view point it's a H.323 endpoint with T.38 FAX support. Recent versions also support SIP.

  • From your view point it's a gateway between a fax application and an IP network.

8.Open source components:

  • t38modem : as the modem pool of Hylafax, t38modem serves as the T.38 gateway for the T.38 machine

  • asterisk : (Fax) machine with T.38 capability, currently, the T.38 gateway feature is under development

Technorati 標籤: ,

珍貴的 quirk check script

裝了新機器後,發現需要調校休眠的部份!
驚!平日所依賴的網站[HAL Sleep Quirks]不見了,在舊機器上找到了以前下載過的 script ,乾脆貼出來,以後可以用...

#!/bin/sh
##!/bin/sh
#
# SuspendQuirks, copyright Richard Hughes 2007
# created  : 29-07-2007
# modified : 29-07-2007

# updated: 2007-08-04 Thomas Perl <thp at perli.net>
# Added support for Debian distro, fix for xorg.conf commented-out drivers

supported_distro=""
unload_modules=""
quirks=""
arch="`uname -i`"

abort ()
{
    echo "CRITICAL ERROR: $1"
    exit 1
}

warn ()
{
    echo "WARNING: $1"
}

add_quirk ()
{
    quirks="$quirks\npm-suspend $1"
}

add_module ()
{
    if [ -z "$unload_modules" ]; then
        unload_modules="$1"
    else
        unload_modules="$1 $unload_modules"
    fi
}


echo -e "Checking your system...\n"

#find distro
if [ -e /etc/redhat-release ]; then
    supported_distro="redhat"
fi
if [ -e /etc/mandriva-release ]; then
    supported_distro="mandriva"
fi
if [ -e /etc/debian_version ]; then
        supported_distro="debian"
fi

#check distro
if [ -z "$supported_distro" ]; then
    abort "No supported distro"
fi

#check quirks are installed
if [ -z "`lshal | grep quirk`" ]; then
    warn "You have no quirks!"
    #IBM
    if [ "`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.vendor`" = "IBM" ]; then
        add_quirk "--quirk-s3-bios --quirk-s3-mode"
    fi
    #LENOVO
    if [ "`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.vendor`" = "LENOVO" ]; then
        add_quirk "--quirk-s3-bios --quirk-s3-mode"
    fi
    #Intel
    if [ -n "`cat /etc/X11/xorg.conf | grep intel`" ]; then
        add_quirk "--quirk-vbemode-restore"
        add_quirk "--quirk-vbe-post"
    fi
fi

#check kernel capabilities
if [ -n "`uname -r | grep 3194`" ]; then
    abort "Do not use the default Fedora 7 GOLD kernel. It's broken. Use a kernel from updates!"
fi
if [ -n "`uname -r | grep xen`" ]; then
    abort "Do not use a XEN kernel. It will not suspend!"
fi

#check kernel capabilities
if [ -z "`cat /sys/power/state | grep mem`" ]; then
    abort "Kernel does not support suspend!"
fi
if [ -z "`cat /sys/power/state | grep disk`" ]; then
    warn "Kernel does not support hibernate!"
fi

#check pm-utils is correct arch
if [ $arch = "i386" ]; then
    if [ -n "`rpm -q pm-utils | grep athlon`" ]; then
        abort "pm-utils is the wrong arch!"
    fi
fi

#check HAL has got the right value
if [ "hal-get-property --udi /org/freedesktop/Hal/devices/computer --key power_management.can_suspend" = "false" ]; then
    abort "HAL does not detect suspend!"
fi

#check for no consolekit in GNOME
if [ -n "`ps aux | grep gnome-session | grep -v grep`" ]; then
    if [ -z "`ps aux | grep console-kit-daemon | grep -v grep`" ];then
        abort "ConsoleKit is not running. Suggest 'chkconfig ConsoleKit on' and reboot"
    fi
fi

#check for nvidia binary graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*nvidia'`" ]; then
    abort "Using nvidia binary driver. This is not supported!"
fi

#check for ati binary graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*fglrx'`" ]; then
    abort "Using ATI binary driver. This is not supported!"
fi

#check for old intel graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*i810'`" ]; then
    abort "Using old 'i810' non-modesetting intel driver. Try using 'intel' driver!"
fi

#check for broadcom networking
if [ -n "`/sbin/lsmod | grep b44`" ]; then
    add_module "b44"
    warn "Using broadcom network driver."
fi

#check for ndiswrapper
if [ -n "`/sbin/lsmod | grep ndiswrapper`" ]; then
    add_module "ndiswrapper"
    warn "Using ndiswrapper network driver."
fi

#check for 915resolution
if [ -e /usr/bin/915resolution ]; then
    warn "Do not use 915resolution with the new intel driver!"
fi

#check for suspend
if [ -e /usr/bin/suspend ]; then
    abort "Do not use suspend2, it's unsupported!"
fi

#check for old intel networking
if [ -n "`ps aux | grep ipw3945 | grep -v grep`" ]; then
    abort "Use the mac80211 based iwl3945 driver instead. ipw3945d is closed source sometimes hangs on resume."
fi

#check for iwl3945
if [ -n "`/sbin/lsmod | grep iwl3945`" ]; then
    add_module "iwl3945"
    warn "iwl3945 is usually okay for suspend - but it might be worth trying unloading it."
fi

#check for kvm
if [ -n "`/sbin/lsmod | grep kvm`" ]; then
    add_module "kvm"
    warn "KVM will not suspend in kernels less than 2.6.23, but should work okay in later kernels."
fi
if [ -n "`/sbin/lsmod | grep kvm_intel`" ]; then
    add_module "kvm_intel"
fi
if [ -n "`/sbin/lsmod | grep kvm_athlon`" ]; then
    add_module "kvm_athlon"
fi

echo

if [ -z "$unload_modules" ] && [ -z "$quirks" ]; then
    echo "Suspend should work!"
else
    echo "Suggestions:"
    echo
    if [ -n "$unload_modules" ]; then
        echo -e "Add 'SUSPEND_MODULES=\"$unload_modules\"' to /etc/pm/config.d/unload_modules!\n"
    fi
    if [ -n "$quirks" ]; then
        echo -n "You might want to try the following pm-suspend entries:"
        echo -e $quirks
    fi
fi

echo

exit 0


# SuspendQuirks, copyright Richard Hughes 2007
# created  : 29-07-2007
# modified : 29-07-2007

# updated: 2007-08-04 Thomas Perl <thp at perli.net>
# Added support for Debian distro, fix for xorg.conf commented-out drivers

supported_distro=""
unload_modules=""
quirks=""
arch="`uname -i`"

abort ()
{
    echo "CRITICAL ERROR: $1"
    exit 1
}

warn ()
{
    echo "WARNING: $1"
}

add_quirk ()
{
    quirks="$quirks\npm-suspend $1"
}

add_module ()
{
    if [ -z "$unload_modules" ]; then
        unload_modules="$1"
    else
        unload_modules="$1 $unload_modules"
    fi
}


echo -e "Checking your system...\n"

#find distro
if [ -e /etc/redhat-release ]; then
    supported_distro="redhat"
fi
if [ -e /etc/mandriva-release ]; then
    supported_distro="mandriva"
fi
if [ -e /etc/debian_version ]; then
        supported_distro="debian"
fi

#check distro
if [ -z "$supported_distro" ]; then
    abort "No supported distro"
fi

#check quirks are installed
if [ -z "`lshal | grep quirk`" ]; then
    warn "You have no quirks!"
    #IBM
    if [ "`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.vendor`" = "IBM" ]; then
        add_quirk "--quirk-s3-bios --quirk-s3-mode"
    fi
    #LENOVO
    if [ "`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.vendor`" = "LENOVO" ]; then
        add_quirk "--quirk-s3-bios --quirk-s3-mode"
    fi
    #Intel
    if [ -n "`cat /etc/X11/xorg.conf | grep intel`" ]; then
        add_quirk "--quirk-vbemode-restore"
        add_quirk "--quirk-vbe-post"
    fi
fi

#check kernel capabilities
if [ -n "`uname -r | grep 3194`" ]; then
    abort "Do not use the default Fedora 7 GOLD kernel. It's broken. Use a kernel from updates!"
fi
if [ -n "`uname -r | grep xen`" ]; then
    abort "Do not use a XEN kernel. It will not suspend!"
fi

#check kernel capabilities
if [ -z "`cat /sys/power/state | grep mem`" ]; then
    abort "Kernel does not support suspend!"
fi
if [ -z "`cat /sys/power/state | grep disk`" ]; then
    warn "Kernel does not support hibernate!"
fi

#check pm-utils is correct arch
if [ $arch = "i386" ]; then
    if [ -n "`rpm -q pm-utils | grep athlon`" ]; then
        abort "pm-utils is the wrong arch!"
    fi
fi

#check HAL has got the right value
if [ "hal-get-property --udi /org/freedesktop/Hal/devices/computer --key power_management.can_suspend" = "false" ]; then
    abort "HAL does not detect suspend!"
fi

#check for no consolekit in GNOME
if [ -n "`ps aux | grep gnome-session | grep -v grep`" ]; then
    if [ -z "`ps aux | grep console-kit-daemon | grep -v grep`" ];then
        abort "ConsoleKit is not running. Suggest 'chkconfig ConsoleKit on' and reboot"
    fi
fi

#check for nvidia binary graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*nvidia'`" ]; then
    abort "Using nvidia binary driver. This is not supported!"
fi

#check for ati binary graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*fglrx'`" ]; then
    abort "Using ATI binary driver. This is not supported!"
fi

#check for old intel graphics
if [ -n "`cat /etc/X11/xorg.conf | grep '^\s*[^#]*i810'`" ]; then
    abort "Using old 'i810' non-modesetting intel driver. Try using 'intel' driver!"
fi

#check for broadcom networking
if [ -n "`/sbin/lsmod | grep b44`" ]; then
    add_module "b44"
    warn "Using broadcom network driver."
fi

#check for ndiswrapper
if [ -n "`/sbin/lsmod | grep ndiswrapper`" ]; then
    add_module "ndiswrapper"
    warn "Using ndiswrapper network driver."
fi

#check for 915resolution
if [ -e /usr/bin/915resolution ]; then
    warn "Do not use 915resolution with the new intel driver!"
fi

#check for suspend
if [ -e /usr/bin/suspend ]; then
    abort "Do not use suspend2, it's unsupported!"
fi

#check for old intel networking
if [ -n "`ps aux | grep ipw3945 | grep -v grep`" ]; then
    abort "Use the mac80211 based iwl3945 driver instead. ipw3945d is closed source sometimes hangs on resume."
fi

#check for iwl3945
if [ -n "`/sbin/lsmod | grep iwl3945`" ]; then
    add_module "iwl3945"
    warn "iwl3945 is usually okay for suspend - but it might be worth trying unloading it."
fi

#check for kvm
if [ -n "`/sbin/lsmod | grep kvm`" ]; then
    add_module "kvm"
    warn "KVM will not suspend in kernels less than 2.6.23, but should work okay in later kernels."
fi
if [ -n "`/sbin/lsmod | grep kvm_intel`" ]; then
    add_module "kvm_intel"
fi
if [ -n "`/sbin/lsmod | grep kvm_athlon`" ]; then
    add_module "kvm_athlon"
fi

echo

if [ -z "$unload_modules" ] && [ -z "$quirks" ]; then
    echo "Suspend should work!"
else
    echo "Suggestions:"
    echo
    if [ -n "$unload_modules" ]; then
        echo -e "Add 'SUSPEND_MODULES=\"$unload_modules\"' to /etc/pm/config.d/unload_modules!\n"
    fi
    if [ -n "$quirks" ]; then
        echo -n "You might want to try the following pm-suspend entries:"
        echo -e $quirks
    fi
fi

echo

exit 0

這是個都不確定的年代,保留著的這份 script 彌足珍貴
標籤: , , ,

2009年9月14日 星期一

Suspend, Hibernate and Resume 的問題

這類問題因為 BIOS , H/W 每台機器不一樣,可能出問題的部份不一定相同,通常這樣的問題很難有系統的方式去了解原因。
但是這個 [HAL Sleep Quirks] 網站提供了一個偵測的 script ,幫助我們有系統的釐清原因。

以下紀錄以 Asus A8J 遇到的現象和解決的步驟:

安裝 Debian Lenny 後,從 Gnome 選單 |  關機 | 暫停 後,Resume 時會失敗,但是可以從遠端 ssh 回來,所以可能跟顯卡有關...
執行網站上所下載的 quirk-checker.sh ,建議把 iwl3945 無線網路模組先unload,等到 resume 後再 reload,所以 在 /etc/pm/config.d/unload_modules 加上這行:SUSPEND_MODULES="iwl3945"
但這應該不是原因,再進行一次 suspend,還是無法 resume.

研讀 pm-suspend 的參數說明,發現 --quirk-vbe-post 表示 resume 時可以用 bios 相同方式來 reset graphic device 所以試試看:
以 pm-suspend --quirk-post-vbe 來試驗,果然可以正常恢復...

現在修改 /usr/share/hal/fdi/information/10freedesktop 下的檔案.... 最有關的應該是 20-video-quirk-pm-asus.fdi :
由 lshal 指令得到,我們的機器 system.hardware.product=A8JP
找到這一段:
      <match key="system.hardware.product" prefix_outof="A6M;Z84F">
        <merge key="power_management.quirk.vbe_post" type="bool">true</merge>
      </match>

改為:
      <match key="system.hardware.product" prefix_outof="A6M;Z84F;A8JP">
        <merge key="power_management.quirk.vbe_post" type="bool">true</merge>
      </match>
     

如同紅色粗體這樣加入我們的 product ,表示我們要使用 --quirk-vbe-post 的參數即可
改完後,重新啟動 hal :
#> /etc/init.d/hal restart
現在透過 gnome-power-management 進行 suspend, hibernate 都可以正常 resume 回來了。真高興!
Technorati 標籤:


2009年9月3日 星期四

kernel 隨手記 --- 類似 oops 的系統訊息

void __this_fixmap_does_not_exist(void)
{
    WARN_ON(1);
}

在 kernel 裡看到這樣的程式碼,用在哪裡呢?
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
{
    if (idx >= __end_of_fixed_addresses)
        __this_fixmap_does_not_exist();

    return __fix_to_virt(idx);
}
(這裡為了精簡,把註解給拿掉了。)這是不希望發生 if 為真的情形,那如果發生了,就印出像 oops 的狀態,以方便偵錯!所以關鍵在 WARN_ON(1),往下追蹤,發現呼叫到 warn_on_slowpath(__FILE__,__LINE__) 來處理,裡面用了幾個好用的技巧:
1.  __builtin_return_address(0) 請 compiler 找出現在 function 的 return address。
2  sprint_symbol() 可以幫忙找出 symbol name , dump_stack() 可以列印現在的 stack 。
3  這個 WARN_ON() 不像 panic() 會中止系統,理論上,可以用來印出發生問題時的 kernel 狀態 ! 或許在開發 driver 可以用來除錯


2009年8月28日 星期五

使用 debootstrap 安裝 Debian 於 USB 大拇哥

網路上相關文章很多,但是多半有"手工"打許多指令的步驟,不適合懶人使用。
[ Install Debian on USB ]這篇Wiki前半部直到 Configure Locales 的部份做完,寫得很簡明,接下來是該作者自己的 Casper package 安裝,就不用再繼續 follow up 了。

所以歸納一下步驟如下:
1.  準備好 partition 以安裝 debian。這視個人的大拇哥規劃而定,以下假設裝在 /dev/sdb2(sda 是本機上的硬碟)
以下用 /dev/sd{D}{N} 表示,請自行代換之。

2.  準備好檔案系統 ,並且 mount 到 /mnt
#> mkfs.ext3 /dev/sd{D}{N}
#> mount /dev/sd{D}{N} /mnt

3.   重頭戲來了,從 /etc/apt/sources.list 找一個 mirror site 這裡用 http://debian.nctu.edu.tw/debian/ (要含有斜線)
#> debootstrap lenny /mnt http://debian.nctu.edu.tw/debian/
     接下來會一直抓 package 來安裝,泡盃咖啡去...

4   準備兩個設定檔,一個在裝 kernel 時會用到,另一個是 sources.list,可以直接使用 host 的 /etc/apt/sources.list
#> mkdir -p /mnt/etc/apt
#> echo "do_initrd=yes" > /mnt/etc/kernel-img.conf
#> cp /etc/apt/sources.list  /mnt/etc/apt/

5   準備 fstab 給新系統 (/etc/inittab 則不需煩惱,debootstrap 會 setup inittab)
#> echo "/dev/sd{D}{N}  /  ext3  defaults,errors=remount-ro 0" > /mnt/etc/fstab
#> echo "proc /mnt/proc  proc  none 0 0" >> /mnt/etc/fstab
#> mount proc /mnt/proc  -t  proc

6   接下來用 chroot 切換到新的系統去,
#> chroot /mnt
請注意:經過這步驟,接下來,所有的指令都是下給新系統的了!

7   先設定好 locale 並且把從 host 繼承的 locale 先設空
#> apt-get update
#> apt-get install locales
#> dpkg-reconfigure locales
#> export LANG=
#> export LANGUAGE=
localepurge 是個可裝可不裝的套件,若要省空間,可以這時候裝起來
#> apt-get install localepurge
將來裝套件時 localepurge 可幫忙 free 一些不需要的 locales 資料

8   然後安裝 kernel image,遇到問題都選 y
#> apt-get install linux-image-2.6.26-2-686

9 裝 grub package
#> apt-get install grub

10 將 grub 裝到 MBR :
#> exit
請注意:接下來,我們又回到 host 了!
#> grub-install --root-directory=/mnt --no-floppy --recheck /dev/sd{D}
#> cat > /mnt/boot/grub/menu.lst << EOF
title        Debian GNU/Linux, kernel 2.6.26-2-686
root        (hd0,1)
kernel        /boot/vmlinuz-2.6.26-2-686 root=/dev/sd{D}{N} ro
initrd        /boot/initrd.img-2.6.26-2-686
EOF
這裡把 (hd1,1) 換成了 (hd0,1)  。因為若是用  usb 開機的話,grub 把大拇哥當第一顆硬碟 (hd0), 直到進了 kernel 才又跟 host 所認知的一樣---回到 sdb。


11 打完收工
#> umount /mnt/proc
#> umount /mnt

這樣就有一個可用的 Debian on USB 了!
後記:grub 安裝時,如果抱怨找不到 grub drive 或 stage1 的問題,[這裡]有解答
Technorati 標籤: , ,

2009年8月24日 星期一

serial port 測試 driver 讀不到 data!

這一段是在摩托的問題,後來自行解決了,貼過來

在 2.6.28 下,把 CONFIG_SERIAL_8250 = m (可以卸載) ,kernel 重編安裝後開機
開機後有看到 ttyS0 硬體存在:
00:0c: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
然後把 8250_pnp, 8250, serial_core 卸載,
看到卸載訊息:
serial 00:0c: disabled
現在載入自己的測試 driver ,起始部份長這樣:

static int __init modem_init(void)
{
int ret;

printk("modem_init()\n");
if (!request_region(MODEM_IO_BASE , 8, "serial"))
ret = -EBUSY;

printk("MSR = %x\n", inb(MSR));
printk("IER =0x%X \n", inb(IER));
...
}

載入後 request_region() 成功,但是之後讀到的 register 值都是 0xFF
找過 8250.c 很多地方,都沒頭緒,為何 kernel 的 8250 driver 可以動,自己的測試 driver 就讀不到 port data ?
================================================================
解決了,在此把原因整理一下,以後有人遇到這種問題不用卡在這裡~~ 以下是參考kernel version 2.6.28 所得的結果。
若只把 kernel 的 8250.ko 模組載入,該模組一樣無法讀到 serial port,
必須一起載入 8250_pnp.ko 才可以,所以關鍵就在 8250_pnp.c 裡面--->
從 serial8250_pnp_init() 開始追...有一天會呼叫到 pnp_start_dev(),這裡面呼叫了pnp_acpi_set_resources() 然後進入一大包的 ACPI 的動作(至此無力再繼續,希望後續動作有高手指點...),

Serial Pnp
View more documents from tomjpsun.


ok,拉回來 pnp_start_dev() 這邊,繼續會印出
"serial 00:06 activated" ,其中數字是 bus 編號,每台機器不盡相同。
經過了這步驟(pnp_acpi_set_resources()),ACPI 幫你打開 port 了,就可以用了(~~竟然跟 ACPI 有關耶,所以在 embedded 環境下,若是 ACPI 不管這裡的話,就不會有開版所提的問題產生了)

實驗:把之前的 test driver 模仿 8250_pnp.c 的作法,宣告一個 pnp_device_id table & pnp_driver :

static const struct pnp_device_id pnp_dev_table[] = {
{ "ANYDEVS", 0 },
{ "", 0 }
};


static struct pnp_driver test_pnp_driver = {
.name = "serial",
.probe = test_pnp_probe,
.remove = __devexit_p(test_pnp_remove),
.id_table = pnp_dev_table,
};

這裡用 "ANYDEVS" 是要讓 device probe 的過程中 match_device() 能夠成功,match 成功後,pnp 系統才會呼叫我們的 test_pnp_probe() ,此時的 serial port 已經被 ACPI enable 了。
所以在這裡面開始使用 serial port 就沒問題了。

到這裡可告一個段落,只是後續的疑問是:ACPI 到底用甚麼方式來 enable serial port 呢?有待各位大大的指點了...


2009年8月4日 星期二

buildroot-2009.05 config file

#
# Automatically generated make config: don't edit
# Tue Jun  9 19:35:42 2009
#
BR2_HAVE_DOT_CONFIG=y
BR2_VERSION="2009.05"
# BR2_alpha is not set
BR2_arm=y
# BR2_armeb is not set
# BR2_avr32 is not set
# BR2_cris is not set
# BR2_ia64 is not set
# BR2_i386 is not set
# BR2_m68k is not set
# BR2_mips is not set
# BR2_mipsel is not set
# BR2_nios2 is not set
# BR2_powerpc is not set
# BR2_sh is not set
# BR2_sh64 is not set
# BR2_sparc is not set
# BR2_sparc64 is not set
# BR2_x86_64 is not set
# BR2_generic_arm is not set
# BR2_arm7tdmi is not set
# BR2_arm610 is not set
# BR2_arm710 is not set
# BR2_arm720t is not set
# BR2_arm920t is not set
# BR2_arm922t is not set
# BR2_arm926t is not set
# BR2_arm10t is not set
# BR2_arm1136jf_s is not set
# BR2_arm1176jz_s is not set
BR2_arm1176jzf_s=y
# BR2_sa110 is not set
# BR2_sa1100 is not set
# BR2_xscale is not set
# BR2_iwmmxt is not set
BR2_ARM_TYPE="ARM1176JZF_S"
# BR2_ARM_OABI is not set
BR2_ARM_EABI=y
BR2_ARCH="arm"
BR2_ENDIAN="LITTLE"
BR2_GCC_TARGET_TUNE="arm1176jzf-s"
BR2_GCC_TARGET_ARCH="armv6zk"
BR2_GCC_TARGET_ABI="aapcs-linux"

#
# Target options
#

#
# Project Options
#
BR2_PROJECT="uclibc"
BR2_HOSTNAME="uclibc"
BR2_BANNER="Welcome to Buildroot"

#
# Preset Devices
#
# BR2_TARGET_AMD is not set
# BR2_TARGET_ARMLTD is not set
# BR2_TARGET_ATMEL is not set
# BR2_TARGET_KWIKBYTE is not set

#
# Generic System Support
#
# BR2_TARGET_GENERIC_ACCESS_POINT is not set
# BR2_TARGET_GENERIC_FIREWALL is not set

#
# Generic development system requires a toolchain with WCHAR and PROGRAM_INVOCATION support
#
# BR2_TARGET_GENERIC_GETTY is not set

#
# Build options
#
BR2_WGET="wget --passive-ftp -nd"
BR2_SVN_CO="svn co"
BR2_SVN_UP="svn up"
BR2_GIT="git clone"
BR2_ZCAT="gzip -d -c"
BR2_BZCAT="bzcat"
BR2_TAR_OPTIONS=""
BR2_DL_DIR="$(BASE_DIR)/dl"
BR2_COPYTO=""

#
# Mirrors and Download locations
#
BR2_PRIMARY_SITE=""
BR2_BACKUP_SITE="http://buildroot.net/downloads/sources/"
BR2_SOURCEFORGE_MIRROR="easynews"
BR2_KERNEL_MIRROR="http://www.kernel.org/pub/"
BR2_GNU_MIRROR="http://ftp.gnu.org/pub/gnu"
BR2_DEBIAN_MIRROR="http://ftp.debian.org"

#
# Atmel Mirrors
#
BR2_ATMEL_MIRROR="ftp://www.at91.com/pub/buildroot/"
BR2_AT91_PATCH_MIRROR="http://maxim.org.za/AT91RM9200/2.6/"
BR2_STAGING_DIR="/usr/local/arm/buildroot-2009.05"
# BR2_FPU_SUFFIX is not set
BR2_TOPDIR_PREFIX=""
BR2_TOPDIR_SUFFIX=""
BR2_GNU_BUILD_SUFFIX="pc-linux-gnu"
BR2_GNU_TARGET_SUFFIX="linux-uclibcgnueabi"
BR2_JLEVEL=1
# BR2_PREFER_IMA is not set
# BR2_DEPRECATED is not set
BR2_RECENT=y
# BR2_CONFIG_CACHE is not set
# BR2_ENABLE_DEBUG is not set
BR2_STRIP_strip=y
# BR2_STRIP_sstrip is not set
# BR2_STRIP_none is not set
# BR2_OPTIMIZE_0 is not set
# BR2_OPTIMIZE_1 is not set
# BR2_OPTIMIZE_2 is not set
# BR2_OPTIMIZE_3 is not set
BR2_OPTIMIZE_S=y
# BR2_PREFER_STATIC_LIB is not set
# BR2_HAVE_MANPAGES is not set
# BR2_HAVE_INFOPAGES is not set
# BR2_HAVE_DOCUMENTATION is not set
# BR2_HAVE_DEVFILES is not set
BR2_UPDATE_CONFIG=y

#
# Toolchain
#
BR2_TOOLCHAIN_BUILDROOT=y
# BR2_TOOLCHAIN_EXTERNAL is not set
# BR2_TOOLCHAIN_EXTERNAL_SOURCE is not set
BR2_TOOLCHAIN_SOURCE=y
BR2_EXT_GCC_VERSION_4_1_2=y
BR2_EXT_GCC_VERSION_4_2_1=y
BR2_EXT_GCC_VERSION_4_2_2=y
BR2_EXT_GCC_VERSION_4_2_3=y
BR2_EXT_BINUTILS_VERSION_2_17=y
BR2_EXT_BINUTILS_VERSION_2_18=y
BR2_EXT_UCLIBC_VERSION_0_9_28_3=y
BR2_EXT_UCLIBC_VERSION_0_9_29=y
BR2_EXT_UCLIBC_VERSION_0_9_30=y
BR2_EXT_UCLIBC_VERSION_0_9_30_1=y

#
# Kernel Header Options
#
# BR2_KERNEL_HEADERS_2_6_23 is not set
# BR2_KERNEL_HEADERS_2_6_24 is not set
# BR2_KERNEL_HEADERS_2_6_25 is not set
# BR2_KERNEL_HEADERS_2_6_26 is not set
# BR2_KERNEL_HEADERS_2_6_27 is not set
# BR2_KERNEL_HEADERS_2_6_28 is not set
BR2_KERNEL_HEADERS_2_6_29=y
# BR2_KERNEL_HEADERS_SNAP is not set
BR2_DEFAULT_KERNEL_HEADERS="2.6.29.4"

#
# uClibc Options
#
# BR2_UCLIBC_VERSION_0_9_28_3 is not set
# BR2_UCLIBC_VERSION_0_9_29 is not set
# BR2_UCLIBC_VERSION_0_9_30 is not set
BR2_UCLIBC_VERSION_0_9_30_1=y
# BR2_UCLIBC_VERSION_SNAPSHOT is not set
BR2_UCLIBC_VERSION_STRING="0.9.30.1"
BR2_UCLIBC_CONFIG="toolchain/uClibc/uClibc-0.9.30.config"
# BR2_PTHREAD_DEBUG is not set
# BR2_UCLIBC_PROGRAM_INVOCATION is not set
# BR2_UCLIBC_INSTALL_TEST_SUITE is not set

#
# Binutils Options
#
# BR2_BINUTILS_VERSION_2_17 is not set
# BR2_BINUTILS_VERSION_2_17_50_0_17 is not set
# BR2_BINUTILS_VERSION_2_18 is not set
# BR2_BINUTILS_VERSION_2_18_50_0_1 is not set
# BR2_BINUTILS_VERSION_2_18_50_0_3 is not set
# BR2_BINUTILS_VERSION_2_18_50_0_6 is not set
# BR2_BINUTILS_VERSION_2_18_50_0_8 is not set
# BR2_BINUTILS_VERSION_2_18_50_0_9 is not set
# BR2_BINUTILS_VERSION_2_19 is not set
BR2_BINUTILS_VERSION_2_19_1=y
BR2_BINUTILS_VERSION="2.19.1"
BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""

#
# GCC Options
#
# BR2_GCC_VERSION_3_4_6 is not set
# BR2_GCC_VERSION_4_0_4 is not set
# BR2_GCC_VERSION_4_1_2 is not set
# BR2_GCC_VERSION_4_2_1 is not set
# BR2_GCC_VERSION_4_2_2 is not set
# BR2_GCC_VERSION_4_2_3 is not set
# BR2_GCC_VERSION_4_2_4 is not set
# BR2_GCC_VERSION_4_3_1 is not set
# BR2_GCC_VERSION_4_3_2 is not set
BR2_GCC_VERSION_4_3_3=y
# BR2_GCC_VERSION_4_4_X is not set
BR2_GCC_SUPPORTS_SYSROOT=y
BR2_GCC_SUPPORTS_FINEGRAINEDMTUNE=y
BR2_GCC_VERSION="4.3.3"
BR2_TOOLCHAIN_SYSROOT=y
# BR2_GCC_USE_SJLJ_EXCEPTIONS is not set
BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_GCC_CROSS_FORTRAN is not set
# BR2_INSTALL_LIBGCJ is not set
# BR2_INSTALL_OBJC is not set
# BR2_INSTALL_FORTRAN is not set
BR2_GCC_SHARED_LIBGCC=y

#
# Ccache Options
#
# BR2_CCACHE is not set

#
# Gdb Options
#
BR2_PACKAGE_GDB=y
BR2_PACKAGE_GDB_SERVER=y
BR2_PACKAGE_GDB_HOST=y
# BR2_GDB_VERSION_6_4 is not set
# BR2_GDB_VERSION_6_5 is not set
# BR2_GDB_VERSION_6_6 is not set
# BR2_GDB_VERSION_6_7_1 is not set
BR2_GDB_VERSION_6_8=y
BR2_GDB_VERSION="6.8"

#
# Common Toolchain Options
#
# BR2_LARGEFILE is not set
# BR2_INET_IPV6 is not set
# BR2_INET_RPC is not set
# BR2_ENABLE_LOCALE is not set
# BR2_USE_WCHAR is not set
# BR2_SOFT_FLOAT is not set
# BR2_USE_SSP is not set
# BR2_PTHREADS_NONE is not set
# BR2_PTHREADS is not set
BR2_PTHREADS_OLD=y
# BR2_PTHREADS_NATIVE is not set
BR2_GCC_CROSS_CXX=y
BR2_INSTALL_LIBSTDCPP=y
BR2_TARGET_OPTIMIZATION="-Os -pipe"
# BR2_ELF2FLT is not set
# BR2_MKLIBS is not set
# BR2_PACKAGE_SSTRIP_TARGET is not set
# BR2_PACKAGE_SSTRIP_HOST is not set
# BR2_ENABLE_MULTILIB is not set
# BR2_VFP_FLOAT is not set
BR2_CROSS_TOOLCHAIN_TARGET_UTILS=y

#
# Package Selection for the target
#
BR2_PACKAGE_BUSYBOX=y
# BR2_BUSYBOX_VERSION_1_12_X is not set
# BR2_BUSYBOX_VERSION_1_13_X is not set
BR2_BUSYBOX_VERSION_1_14_X=y
# BR2_PACKAGE_BUSYBOX_SNAPSHOT is not set
BR2_BUSYBOX_VERSION="1.14.1"
BR2_PACKAGE_BUSYBOX_FULLINSTALL=y
BR2_PACKAGE_BUSYBOX_CONFIG="package/busybox/busybox-1.13.x.config"
BR2_PACKAGE_BUSYBOX_HIDE_OTHERS=y
# BR2_PACKAGE_BUSYBOX_SKELETON is not set

#
# The minimum needed to build a uClibc development system
#
# BR2_PACKAGE_FLEX is not set
# BR2_PACKAGE_GCC_TARGET is not set
# BR2_PACKAGE_MAKE is not set

#
# Other development stuff
#
# BR2_PACKAGE_AUTOCONF is not set
# BR2_PACKAGE_AUTOMAKE is not set
# BR2_PACKAGE_BISON is not set
# BR2_PACKAGE_CCACHE_TARGET is not set
# BR2_PACKAGE_DISTCC is not set
# BR2_PACKAGE_DMALLOC is not set
# BR2_PACKAGE_FAKEROOT is not set
BR2_HOST_FAKEROOT=y
# BR2_PACKAGE_GETTEXT is not set
# BR2_PACKAGE_LIBINTL is not set
# BR2_PACKAGE_LIBGMP is not set
# BR2_PACKAGE_GPERF is not set
# BR2_PACKAGE_LIBMPFR is not set
# BR2_PACKAGE_LIBTOOL is not set
# BR2_PACKAGE_M4 is not set
# BR2_PACKAGE_MPATROL is not set
# BR2_PACKAGE_OPROFILE is not set
# BR2_PACKAGE_PKG_CONFIG is not set
# BR2_PACKAGE_READLINE is not set
# BR2_PACKAGE_PCRE is not set

#
# Other stuff
#
# BR2_PACKAGE_AT is not set
# BR2_PACKAGE_BEECRYPT is not set
# BR2_PACKAGE_BERKELEYDB is not set
# BR2_PACKAGE_BSDIFF is not set
# BR2_PACKAGE_CUPS is not set
# BR2_PACKAGE_CUSTOMIZE is not set
# BR2_PACKAGE_FILE is not set
# BR2_PACKAGE_GAMIN is not set

#
# icu requires a toolchain with C++ support and WCHAR enabled
#
# BR2_PACKAGE_KEXEC is not set
# BR2_PACKAGE_LIBCONFIG is not set
# BR2_PACKAGE_LIBCONFUSE is not set
# BR2_PACKAGE_LIBDAEMON is not set
# BR2_PACKAGE_LIBELF is not set
# BR2_PACKAGE_LIBEVENT is not set
# BR2_PACKAGE_LIBGCRYPT is not set
# BR2_PACKAGE_LIBGPG_ERROR is not set
# BR2_PACKAGE_LIBICONV is not set
# BR2_PACKAGE_LIBIDN is not set
# BR2_PACKAGE_LIBLOCKFILE is not set
# BR2_PACKAGE_LIBOIL is not set
# BR2_PACKAGE_LIBSYSFS is not set
# BR2_PACKAGE_LOCKFILE_PROGS is not set

#
# logrotate     - disabled (requires wchar support)
#
# BR2_PACKAGE_LSOF is not set
# BR2_PACKAGE_LTP-TESTSUITE is not set
# BR2_PACKAGE_LTRACE is not set
# BR2_PACKAGE_MEMSTAT is not set
# BR2_PACKAGE_NG_SPICE_REWORK is not set
# BR2_PACKAGE_POPT is not set
# BR2_PACKAGE_SCREEN is not set
# BR2_PACKAGE_SHARED_MIME_INFO is not set
# BR2_PACKAGE_STARTUP_NOTIFICATION is not set
# BR2_PACKAGE_STRACE is not set
# BR2_PACKAGE_SUDO is not set

#
# Database
#
# BR2_PACKAGE_MYSQL_CLIENT is not set
# BR2_PACKAGE_SQLITE is not set

#
# Networking
#

#
# Networking applications
#
# BR2_PACKAGE_ARGUS is not set
# BR2_PACKAGE_AVAHI is not set
# BR2_PACKAGE_AXEL is not set

#
# bind requires a toolchain with LARGEFILE support
#
# BR2_PACKAGE_BRIDGE is not set
# BR2_PACKAGE_DNSMASQ is not set
# BR2_PACKAGE_DROPBEAR is not set
# BR2_PACKAGE_ETHTOOL is not set
# BR2_PACKAGE_HASERL is not set
# BR2_PACKAGE_IFPLUGD is not set
# BR2_PACKAGE_IPERF is not set

#
# iproute2 requires a toolchain with IPv6 support
#
# BR2_PACKAGE_IPSEC_TOOLS is not set

#
# iptables requires a toolchain with LARGEFILE support
#
# BR2_PACKAGE_KISMET is not set
# BR2_PACKAGE_L2TP is not set
# BR2_PACKAGE_LIBCGI is not set
# BR2_PACKAGE_LIBCGICC is not set
# BR2_PACKAGE_LIBCURL is not set
# BR2_PACKAGE_LIBDNET is not set
# BR2_PACKAGE_LIBEXOSIP2 is not set
# BR2_PACKAGE_LIBOSIP2 is not set
# BR2_PACKAGE_LIBPCAP is not set
# BR2_PACKAGE_LIBSOUP is not set
# BR2_PACKAGE_LIBUPNP is not set
# BR2_PACKAGE_LINKS is not set
# BR2_PACKAGE_LRZSZ is not set
# BR2_PACKAGE_MDNSRESPONDER is not set
# BR2_PACKAGE_MIIDIAG is not set
# BR2_PACKAGE_MROUTED is not set
# BR2_PACKAGE_MUTT is not set
# BR2_PACKAGE_NBD is not set
# BR2_PACKAGE_NCFTP is not set
# BR2_PACKAGE_NEON is not set

#
# netkitbase requires a toolchain with RPC support
#
# BR2_PACKAGE_NETKITTELNET is not set
# BR2_PACKAGE_NETPLUG is not set
# BR2_PACKAGE_NETSNMP is not set

#
# nfs-utils requires a toolchain with 'Enable RPC' selected
#
# BR2_PACKAGE_NTP is not set
# BR2_PACKAGE_OLSR is not set
# BR2_PACKAGE_OPENNTPD is not set
# BR2_PACKAGE_OPENSSH is not set
# BR2_PACKAGE_OPENSSL is not set
# BR2_PACKAGE_OPENVPN is not set

#
# portmap requires a toolchain with 'Enable RPC' selected
#
# BR2_PACKAGE_PPPD is not set
# BR2_PACKAGE_RP_PPPOE is not set
# BR2_PACKAGE_PPTP_LINUX is not set
# BR2_PACKAGE_PROFTPD is not set

#
# quagga suite
#
# BR2_PACKAGE_QUAGGA_ZEBRA is not set
# BR2_PACKAGE_QUAGGA_BGPD is not set
# BR2_PACKAGE_QUAGGA_RIPD is not set
# BR2_PACKAGE_QUAGGA_RIPNGD is not set
# BR2_PACKAGE_QUAGGA_OSPFD is not set
# BR2_PACKAGE_QUAGGA_WATCHQUAGGA is not set
# BR2_PACKAGE_QUAGGA_ISISD is not set
# BR2_PACKAGE_RSYNC is not set
# BR2_PACKAGE_SAMBA is not set
# BR2_PACKAGE_SOCAT is not set
# BR2_PACKAGE_STUNNEL is not set
# BR2_PACKAGE_TCPDUMP is not set
# BR2_PACKAGE_DHCPDUMP is not set
# BR2_PACKAGE_TFTPD is not set
# BR2_PACKAGE_TN5250 is not set
# BR2_PACKAGE_TTCP is not set
# BR2_PACKAGE_UDPCAST is not set
# BR2_PACKAGE_VPNC is not set
# BR2_PACKAGE_VSFTPD is not set
# BR2_PACKAGE_VTUN is not set
# BR2_PACKAGE_WEBIF is not set
# BR2_PACKAGE_WIRELESS_TOOLS is not set
# BR2_PACKAGE_WPA_SUPPLICANT is not set

#
# Hardware handling / blockdevices and filesystem maintenance
#

#
# dbus not available (need expat or libxml2)
#

#
# dbus-glib needs dbus to be compiled with expat support
#
# BR2_PACKAGE_DEVMEM2 is not set

#
# dm requires a toolchain with LARGEFILE support
#

#
# dmraid requires a toolchain with LARGEFILE support
#

#
# e2fsprogs requires a toolchain with LARGEFILE support
#
# BR2_PACKAGE_EEPROG is not set
# BR2_PACKAGE_FCONFIG is not set
# BR2_PACKAGE_FIS is not set

#
# libfuse requires a toolchain with LARGEFILE support
#
# BR2_PACKAGE_GADGETFS_TEST is not set
# BR2_PACKAGE_HAL is not set
# BR2_PACKAGE_HWDATA is not set
# BR2_PACKAGE_I2C_TOOLS is not set
# BR2_PACKAGE_INPUT_TOOLS is not set
# BR2_PACKAGE_IOSTAT is not set
# BR2_PACKAGE_LIBAIO is not set
# BR2_PACKAGE_LIBRAW1394 is not set
# BR2_PACKAGE_LIBUSB is not set
# BR2_PACKAGE_LM_SENSORS is not set
# BR2_PACKAGE_LVM2 is not set
# BR2_PACKAGE_MDADM is not set
# BR2_PACKAGE_MEMTESTER is not set
# BR2_PACKAGE_MKDOSFS is not set
BR2_PACKAGE_MTD=y
BR2_PACKAGE_MTD_UTILS=y
# BR2_PACKAGE_MTD_20061007 is not set
# BR2_PACKAGE_MTD_20050122 is not set
# BR2_PACKAGE_MTD_UTILS_GIT is not set

#
# MTD tools selection
#
# BR2_PACKAGE_MTD_DOCFDISK is not set
# BR2_PACKAGE_MTD_DOC_LOADBIOS is not set
BR2_PACKAGE_MTD_FLASHCP=y
BR2_PACKAGE_MTD_FLASH_ERASE=y
BR2_PACKAGE_MTD_FLASH_ERASEALL=y
BR2_PACKAGE_MTD_FLASH_INFO=y
BR2_PACKAGE_MTD_FLASH_LOCK=y
BR2_PACKAGE_MTD_FLASH_UNLOCK=y
BR2_PACKAGE_MTD_FTL_CHECK=y
BR2_PACKAGE_MTD_FTL_FORMAT=y
BR2_PACKAGE_MTD_JFFS2DUMP=y
BR2_PACKAGE_MTD_MKFSJFFS2=y
# BR2_PACKAGE_MTD_MKFSJFFS is not set
BR2_PACKAGE_MTD_MTD_DEBUG=y
BR2_PACKAGE_MTD_NANDDUMP=y
BR2_PACKAGE_MTD_NANDWRITE=y
# BR2_PACKAGE_MTD_NFTL_FORMAT is not set
# BR2_PACKAGE_MTD_NFTLDUMP is not set
BR2_PACKAGE_MTD_SUMTOOL=y

#
# ntfs-3g requires a toolchain with LARGEFILE and WCHAR support
#
# BR2_PACKAGE_PCIUTILS is not set
# BR2_PACKAGE_SETSERIAL is not set
# BR2_PACKAGE_SMARTMONTOOLS is not set
# BR2_PACKAGE_USBMOUNT is not set
# BR2_PACKAGE_USBUTILS is not set
# BR2_PACKAGE_WIPE is not set
# BR2_PACKAGE_XFSPROGS is not set

#
# Audio and video libraries and applications
#
# BR2_PACKAGE_ALSA_LIB is not set

#
# alsa-utils requires a toolchain with LARGEFILE support
#

#
# asterisk    - disabled (required openssl and mpg123)
#
# BR2_PACKAGE_AUMIX is not set
# BR2_PACKAGE_FLAC is not set
# BR2_PACKAGE_GSTREAMER is not set
# BR2_PACKAGE_LIBID3TAG is not set
# BR2_PACKAGE_LIBMAD is not set
# BR2_PACKAGE_LIBMPD is not set
# BR2_PACKAGE_LIBOGG is not set
# BR2_PACKAGE_LIBSNDFILE is not set
# BR2_PACKAGE_LIBTHEORA is not set
# BR2_PACKAGE_LIBVORBIS is not set
# BR2_PACKAGE_MADPLAY is not set
# BR2_PACKAGE_MPG123 is not set
# BR2_PACKAGE_MPLAYER is not set
# BR2_PACKAGE_SPEEX is not set
# BR2_PACKAGE_FESTIVAL is not set
# BR2_PACKAGE_TAGLIB is not set
# BR2_PACKAGE_VLC is not set

#
# Graphic libraries and applications (graphic/text)
#

#
# text rendering libraries
#
BR2_PACKAGE_NCURSES=y
# BR2_PACKAGE_NCURSES_TARGET_PANEL is not set
# BR2_PACKAGE_NCURSES_TARGET_FORM is not set
# BR2_PACKAGE_NCURSES_TARGET_MENU is not set
# BR2_PACKAGE_NCURSES_TARGET_HEADERS is not set
# BR2_PACKAGE_NEWT is not set
# BR2_PACKAGE_SLANG is not set

#
# text rendering applications
#
# BR2_PACKAGE_DIALOG is not set

#
# graphic libraries
#
# BR2_PACKAGE_DIRECTFB is not set
# BR2_PACKAGE_FBDUMP is not set
# BR2_PACKAGE_IMAGEMAGICK is not set
# BR2_PACKAGE_JPEG is not set
# BR2_PACKAGE_LIBART is not set
# BR2_PACKAGE_LIBPNG is not set
# BR2_PACKAGE_LIBUNGIF is not set
# BR2_PACKAGE_LINUX_FUSION is not set
# BR2_PACKAGE_PIXMAN is not set
# BR2_PACKAGE_SDL is not set
# BR2_PACKAGE_TIFF is not set

#
# busybox graphic applications
#

#
# --> May be broken in busybox
#
# BR2_PACKAGE_FBV is not set
# BR2_PACKAGE_FBSET is not set

#
# other GUIs
#
# BR2_PACKAGE_QTOPIA4 is not set
BR2_PACKAGE_XSERVER_none=y
# BR2_PACKAGE_XSERVER_xorg is not set
# BR2_PACKAGE_XSERVER_tinyx is not set

#
# xorg requires a toolchain with C++, LOCALE, LARGEFILE and WCHAR support
#

#
# tinyx requires a toolchain with WCHAR support
#

#
# X libraries and helper libraries
#
# BR2_PACKAGE_ATK is not set
# BR2_PACKAGE_CAIRO is not set
# BR2_PACKAGE_PANGO is not set
# BR2_PACKAGE_LIBDRM is not set
# BR2_PACKAGE_LIBERATION is not set
# BR2_PACKAGE_LIBGLIB12 is not set
# BR2_PACKAGE_LIBGLIB2 is not set
# BR2_PACKAGE_OPENMOTIF is not set
# BR2_PACKAGE_FONTCONFIG is not set
# BR2_PACKAGE_FREETYPE is not set
# BR2_PACKAGE_TSLIB is not set

#
# webkit requires a toolchain with C++ support and WCHAR enabled
#

#
# X Window managers
#
# BR2_PACKAGE_MATCHBOX is not set

#
# X applications
#
# BR2_PACKAGE_ALSAMIXERGUI is not set

#
# dillo        - disabled (requires jpeg,libglib12,libgtk12,zlib,libpng and Xorg(7))
#
# BR2_PACKAGE_GQVIEW is not set
# BR2_PACKAGE_GOB2 is not set
# BR2_PACKAGE_LEAFPAD is not set

#
# midori        - disabled (requires Xorg(7))
#
# BR2_PACKAGE_PCMANFM is not set
# BR2_PACKAGE_SYLPHEED is not set
# BR2_PACKAGE_TORSMO is not set
# BR2_PACKAGE_X11VNC is not set
# BR2_PACKAGE_XPDF is not set
# BR2_PACKAGE_XSTROKE is not set
# BR2_PACKAGE_XVKBD is not set

#
# Compressors / decompressors
#
BR2_PACKAGE_LZO=y
# BR2_PACKAGE_LZOP is not set
# BR2_PACKAGE_LZMA_TARGET is not set
# BR2_PACKAGE_LZMA_HOST is not set
BR2_PACKAGE_ZLIB=y
# BR2_PACKAGE_ZLIB_TARGET_HEADERS is not set

#
# Package managers
#
# BR2_PACKAGE_IPKG is not set
# BR2_PACKAGE_PORTAGE is not set

#
# Interpreter languages / Scripting
#
# BR2_PACKAGE_LUA is not set
# BR2_PACKAGE_MICROPERL is not set
# BR2_PACKAGE_PYTHON is not set
# BR2_PACKAGE_RUBY is not set
# BR2_PACKAGE_TCL is not set
# BR2_PACKAGE_PHP is not set

#
# XML handling
#
# BR2_PACKAGE_EXPAT is not set
# BR2_PACKAGE_EZXML is not set
# BR2_PACKAGE_LIBXML2 is not set
# BR2_PACKAGE_LIBXSLT is not set
# BR2_PACKAGE_XERCES is not set

#
# Java
#
# BR2_PACKAGE_CLASSPATH is not set

#
# Games
#
# BR2_PACKAGE_GNUCHESS is not set
# BR2_PACKAGE_MAGICCUBE4D is not set
# BR2_PACKAGE_PRBOOM is not set
# BR2_PACKAGE_RUBIX is not set
# BR2_PACKAGE_VICE is not set
# BR2_PACKAGE_XBOARD is not set

#
# Target filesystem options
#
BR2_ROOTFS_PREFIX="rootfs"
BR2_ROOTFS_SUFFIX=""

#
# filesystem for target device
#
BR2_TARGET_ROOTFS_CRAMFS=y
# BR2_TARGET_ROOTFS_CLOOP is not set
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_BLOCKS=0
BR2_TARGET_ROOTFS_EXT2_INODES=0
BR2_TARGET_ROOTFS_EXT2_RESBLKS=0
BR2_TARGET_ROOTFS_EXT2_SQUASH=y
BR2_TARGET_ROOTFS_EXT2_OUTPUT="$(IMAGE).ext2"
BR2_TARGET_ROOTFS_EXT2_NONE=y
# BR2_TARGET_ROOTFS_EXT2_GZIP is not set
# BR2_TARGET_ROOTFS_EXT2_BZIP2 is not set
# BR2_TARGET_ROOTFS_EXT2_LZMA is not set
BR2_TARGET_ROOTFS_EXT2_COPYTO=""
BR2_TARGET_ROOTFS_JFFS2=y
# BR2_TARGET_ROOTFS_JFFS2_DATAFLASH_1056 is not set
BR2_TARGET_ROOTFS_JFFS2_DATAFLASH_528=y
# BR2_TARGET_ROOTFS_JFFS2_NANDFLASH_2K_128K is not set
# BR2_TARGET_ROOTFS_JFFS2_FLASH_128 is not set
# BR2_TARGET_ROOTFS_JFFS2_FLASH_64 is not set
# BR2_TARGET_ROOTFS_JFFS2_CUSTOM is not set
BR2_TARGET_ROOTFS_JFFS2_PAGESIZE=0x210
BR2_TARGET_ROOTFS_JFFS2_EBSIZE=0x1080
BR2_TARGET_ROOTFS_JFFS2_NOCLEANMARKER=y
# BR2_JFFS2_TARGET_SREC is not set
# BR2_TARGET_ROOTFS_JFFS2_PAD is not set
BR2_TARGET_ROOTFS_JFFS2_LE=y
# BR2_TARGET_ROOTFS_JFFS2_BE is not set
# BR2_TARGET_ROOTFS_JFFS2_SUMMARY is not set
BR2_TARGET_ROOTFS_JFFS2_OUTPUT="$(IMAGE).jffs2"
BR2_TARGET_ROOTFS_JFFS2_COPYTO=""
# BR2_TARGET_ROOTFS_SQUASHFS is not set
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_NONE=y
# BR2_TARGET_ROOTFS_CPIO_GZIP is not set
# BR2_TARGET_ROOTFS_CPIO_BZIP2 is not set
# BR2_TARGET_ROOTFS_CPIO_LZMA is not set
BR2_TARGET_ROOTFS_CPIO_COPYTO=""
BR2_TARGET_ROOTFS_INITRAMFS=y
# BR2_TARGET_ROOTFS_ROMFS is not set

#
# bootloader for target device
#
# BR2_TARGET_UBOOT is not set

#
# Kernel
#
BR2_KERNEL_none=y
# BR2_KERNEL_LINUX_ADVANCED is not set
# BR2_KERNEL_LINUX is not set
# BR2_KERNEL_HURD is not set

More on QEMU

兩年前在 [QEMU 安裝與試跑] 探討了模擬 ARM Versatile 系統。 原以為這樣就會使用 QEMU 了,最近兩天為了模擬 x86 不成功,只好重新拾起 [QEMU Documentation] 仔細再 K 一下,補足原本欠缺的觀念,以下紀錄的是該準備的 sources & images :

linux-2.6.28 由 [kernel archive] 下載解壓的,
linux-0.2.img.bz2 由 QEMU Documentation | [download] | 下載得到,
bzImage-2.6.28-test 由 linux-2.6.28 編好之後所得,
initrd.img-2.6.28-test.bz2 由 linux-2.6.28 編好安裝模組 (make modules_install) 後,利用 update-initramfs -c -k 2.6.28-test 所得到的
檔案系統 (bunzip2 -c initrd.img-2.6.28-test.bz2 | cpio -idm)

以下紀錄了幾次錯誤的啟動方式:
#> qemu -kernel bzImage-2.6.28-test
==>A disk image must be given for 'hda' when booting a Linux kernel
(if you really don't want it, use /dev/zero)
#> qemu -kernel bzImage-2.6.28-test -hda /dev/zero
==> booting from Hard Disk
==>failed : not a bootable disk
==> no bootable device
沒頭緒,翻翻線上手冊好了---
在 [QEMU Documentation] 3.8 節 Direct Linux Boot 提到:
`...It is very useful for fast Linux kernel testing.
The syntax is :
qemu -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda" `

"...Use ‘-kernel’ to provide the Linux kernel image and ‘-append’ to give the kernel command line arguments. The ‘-initrd’ option can be used to provide an INITRD image.
When using the direct Linux boot, a disk image for the first hard disk ‘hda’ is required because its boot sector is used to launch the Linux kernel..."

所以我們得準備一個 disk image,也就是剛才下載的 linux-0.2.img,讓 QEMU 透過 disk image 的 boot sector 載入 kernel image,並且傳 kernel parameter "root=/dev/hda" ,告訴 kernel 說 root filesystem 在 disk image 上!

#>qemu -kernel bzImage-2.6.28-test  -hda linux-0.2.img -append "root=/dev/hda"

終於成功 ,顯示出的 kernel 為餵進去的 2.6.28-test.,注意 disk image 不能用壓縮的 bz2 or gz ,否則會發生 waiting for root filesystem...的現象...殘念!

結論:在模擬 x86 上,需要有 disk image (即使不使用 disk image 上的 kernel image 也一樣),跟模擬 ARM 有所不同。





2009年6月7日 星期日

Apt-get : NO_PUBKEY / GPG error

[原文出處]
有時改過 apt source list 後,會發生 GPG error  抱怨某個 key 找不到,把該 key 帶入下列指令就可以解決,背後原理還不知道,(待查)
gpg --keyserver pgpkeys.mit.edu --recv-key  010908312D230C5F
gpg -a --export 010908312D230C5F | sudo apt-key add -
其中,把範例中的 key 換成發生問題的 key 就可解決#Technorati 標籤: ,

2009年5月26日 星期二

RCU 初步認識

從 Paul McKenney 的[網站] 有 [RCU 的基本介紹] 一文,趁著爬文後還有印象,趕快整理一下重點與常見問題:
1. RCU 的需求
  RCU (Read Copy Update) 是一種 synchronization 機制,允許多個 reads to occur concurrently with updates,它本身不使用 lock 機制,在 kernel 內,適合用在 reader 多但 writer 少的資料保護。因為現在的系統多半都有多個 CPUs,RCU 機制允許多個 readers 的 scability 特性(無限個 readers,而且進入 reader-side critical section 是非常的 low cost),使得它在這些情形下,比用 lock 有更好的 performance。

2. RCU 的工作方式及術語:(資料來源 : [RCU Wiki] )
  RCU 把 update 分成兩個 phase: "removal" and "reclamation".
  Removal phase 移除某個 data 指標,此時允許多個 readers 繼續進行,readers 可能看到兩種版本的資料(移除該 data 前跟移除後) 因為是更改指標,所以只要確保更改指標的動作是 atomic operation ,就不會破壞到資料。
  Reclamation phase 時,只要確保沒有 reader 會再參考該 data 之後,就可以安全的移除該資料---這涉及兩個條件:一、 所有 reader 讀取資料的動作是 link list 的單一方向的拜訪,不回頭。二、 所有的 reader 執行 "reader-side critical section" 內的動作時不能 block 或 preempt這樣我們的 reclamation phase 可以簡單的設計成

void synchronize_rcu(void) {
   int cpu;
   for_each_cpu(cpu);
   run_on(cpu);
}


只要令每個 CPU 都輪流完,就可確保下列情形:所有在 synchronize_rcu() 的執行時間之前,所有參考到舊版本(未移除時)的 readers 都保證結束,在這個時間點後,所有的 readers 都將只看到新版本(已移除該 data) 的資料串列了!這段等待所有 CPU 跑完的時間稱作 "Grace Period",在歷經 grace period 後,我們就可以確定該 data 已經沒有任何的 reader 參考了,可以放心的 free 掉。(即 reclamation).

剛才所討論的是 delete 的 RCU 動作, add/replace 的 RCU 動作原理也是依此類推。
 
3 一些 RCU 的 API :

假設我們有一片段程式,updater 動作如下:
例一:
  1 struct foo {
  2   int a;
  3   int b;
  4   int c;
  5 };
  6 struct foo *gp = NULL;
  7
  8 /* . . . */
  9
 10 p = kmalloc(sizeof(*p), GFP_KERNEL);
 11 p->a = 1;
 12 p->b = 2;
 13 p->c = 3;
 14 gp = p;

 這裡不能保證 11-14 行不會被 compiler reorder,所以我們改為:

  1 p->a = 1;
  2 p->b = 2;
  3 p->c = 3;
  4 rcu_assign_pointer(gp, p); 裡面加了 memory barrier 保證 pointer assign 發生於 line 1-3 之後.

同樣的,在 reader 一方,reader 也需要 memory barrier:
例二:
  1 p = gp;
  2 if (p != NULL) {
  3   do_something_with(p->a, p->b, p->c);
  4 }
在大部分的 arch 下是正確的,但是在 DEC Alpha 還是會有可能 p->a, p->b, p->c 發生得比 fetch p 來得早,
所以應該改成:
例三:
  1 rcu_read_lock();
  2 p = rcu_dereference(gp);
  3 if (p != NULL) {
  4   do_something_with(p->a, p->b, p->c);
  5 }
  6 rcu_read_unlock();


這裡 rcu_dereference()裡面有memory barrier,保證 p->a,p->b,p->c僅發生在 p 被 fetch 之後。
另外 rcu_read_lock() rcu_read_unlock() 也是必要的,它們標明了 reader-side critical section,在 preempt kernel 中,
他們的動作就是暫時 disable preempt(前面的條件二),在 non-preempt kernel 中,就沒事做,展開成空的 macro.

先跳來看一下 rcu_dereference()
#define rcu_dereference(p)     ({ \
                typeof(p) _________p1 = ACCESS_ONCE(p); \
                smp_read_barrier_depends(); \
                (_________p1); \
                })
其中 ACCESS_ONCE 確保 p 不被最佳化動作影響,可以確實讀取,smp_read_barrier_depends() 意思為 "flush all pending reads that subsequents reads depend on"(使 barrier 之後的 reads 動作不受 barrier 之前的 reads 所影響).

ok 言歸正傳,既然 pointer 有包裝了 memory barrier。因為 rcu 常用於 list operation,所以 list 動作中,也有 rcu 版本的 API:

list_add_rcu()
list_del_rcu()
list_replace_rcu()

這些 macro 中也包裝了 memory barrier。

把各種 API 做個表格來看就清楚了:
===============================================================================================================
Category          Publish                    Retract                                Subscribe

Pointers          rcu_assign_pointer()       rcu_assign_pointer(...,NULL)            rcu_dereference()

Lists              list_add_rcu()             list_del_rcu()                         list_for_each_entry_rcu()
                   list_add_tail_rcu()
                   list_replace_rcu()
===============================================================================================================
接下來看看 list 的 example,這是 updater 的程式片段:
例四:
 1 struct foo {
  2   struct list_head list;
  3   int a;
  4   int b;
  5   int c;
  6 };
  7 LIST_HEAD(head);
  8
  9 /* . . . */
 10
 11 p = search(head, key);
 12 if (p == NULL) {
 13   /* Take appropriate action, unlock, and return. */
 14 }
 15 q = kmalloc(sizeof(*p), GFP_KERNEL);
 16 *q = *p;
 17 q->b = 2;
 18 q->c = 3;
 19 list_replace_rcu(&p->list, &q->list);
 20 synchronize_rcu();
 21 kfree(p);
其中第 16 行就是 read-copy,第 17-19 行就是 update 動作。

list_replace_rcu() 如下:

static inline void list_replace_rcu(struct list_head *old,
                struct list_head *new)
{
    new->next = old->next;
    new->prev = old->prev;
    smp_wmb();
    new->next->prev = new;
    new->prev->next = new;
    old->prev = LIST_POISON2;
}
看得出來,是 list 代換加上內嵌一個 memory barrier.


好的,來看看 reader 的動作:

例五:
list_for_each_rcu(p, list_head) {
  rcu_read_lock();
  if (need_to_reference(p)) {
    reference_without_blocking(p);
    rcu_read_unlock();
    break;
  }
  rcu_read_unlock();
}

rcu_read_lock()/rcu_read_unlock() pair 是標明 reader critical section(CS)。在 CS 裡面,如果要參考某個 link data,有個條件剛剛提過---就是 reader 不能 blocking !!

總結: RCU algorithm 的動作大抵有三個部份:
1. publish-subscribe 機制,用來給 reader 參考的,如例三與例五。
2. 於 updater 端則是:waiting for pre-existing RCU readers to finish,如例四的 synchronize_rcu(),and
3. maintain multiple versions to permit change w/o harming concurrent RCU readers 就是前面說的兩個條件!


問題 1: seqlock 也是 synchronize 機制,與 RCU 比較有何不同?
Ans: seqlock 當遇到 updater update 資料時,會強迫 readers retry reading,但是 RCU 則不會。

問題 2: 當 reader 執行 list_for_each_entry_rcu() 的同時,若是(假設另一個 CPU上) updater 也正在執行 list_add_rcu()
( 或是 list_del_rcu(), list_replace_rcu() 等) 更改資料,這樣不會有問題嗎?
Ans: 因為在 Linux 系統上,load/store pointer 是 atomic operation,所以 list_for_each_entry_rcu() 參考到的資料,
可能會是原始版本的資料,或是新版本的資料,這兩種其中之一;而不會是資料 inconsistent 的情形。並且,
list_for_each_entry_rcu() 是一路前進的參考,不會回頭,所以看到的可能是新資料 or 舊資料。
之後 updater 會讓所有參考到舊資料的 readers 保證可以結束 read critical section,然後才把該筆舊資料移除 或置換掉,其餘的 reader 都將讀到新資料,所以不會有問題。

這裡有個跟以前觀念上不同之處,我們以前的 CS 是保證唯一占用被保護的資源。
但是 RCU  Reader 進入 CS 之後,並不保證他是讀到新或舊資料。讀到新舊資料的分野,是在於 updater 執行 synchronize_rcu() 的時間點,對所有的 readers,在該時間之前,所有的讀取都讀到舊資料!在該時間之後,所有的讀取都將讀到新資料!

Technorati 標籤: , ,

2009年4月20日 星期一

慣C用法

這頁紀錄著一些 kernel 裡面看到的慣C用法:

1. 這種用法好像 C++ 喔!

static inline pte_t native_make_pte(pteval_t val)
{
      return (pte_t) { .pte = val };
}


p.s: pte_t 的定義要看 Phisical Address Extension (PAE) 有沒有打開,打開的話,就是一個 64 bit 的 structure, 沒有打開的話,就是一個 32 bit 的 structure:

#ifdef CONFIG_X86_PAE
  typedef     u64    pteval_t;
  typedef     union {
          struct {
              unsigned long pte_low, pte_high;
          };
          pteval_t pte;
 } pte_t;
...
#else /* !CONFIG_X86_PAE */
typedef unsigned long    pteval_t;
typedef union {
    pteval_t pte;
    pteval_t pte_low;
} pte_t;
#endif


2.常見的 per_cpu()

#define per_cpu(var, cpu)\
          (*SHIFT_PERCPU_PTR(&per_cpu_var(var), per_cpu_offset(cpu)))
其中
#define SHIFT_PERCPU_PTR(__p, __offset)    RELOC_HIDE((__p), (__offset))

#define RELOC_HIDE(ptr, off)                    \
  ({ unsigned long __ptr;                    \
    __asm__ ("" : "=r"(__ptr) : "0"(ptr));        \
    (typeof(ptr)) (__ptr + (off)); })

the `ptr' constraint "0" means `ptr' will use the same constraints with the 0th variable,
i.e. the `__ptr'. Which has the constraints of  `='(output) and `r'(use register for the variable).
This inline asm means : __ptr = (unsigned long) ptr; and calculate the offset
in unit of `long' instead of `typeof(ptr)', finally return the calculated offset with the type `typeof(ptr)'

now let's see the other 2 defines:
#define per_cpu_var(var) per_cpu__##var

extern unsigned long __per_cpu_offset[NR_CPUS];
#define per_cpu_offset(x) (__per_cpu_offset[x])

所以 per_cpu(var,cpu_id) 展開會得到 per_cpu__##var /*注意:雙底線*/ + __per_cpu_offset[cpu_id]

例如 sys_ioperm() 裡面有這一個 C statement:
     tss = &per_cpu(init_tss, get_cpu());
展開 macro 就會得到
     tss = per_cpu__init_tss + __per_cpu_offset[get_cpu()];

3. 超簡潔的 struct 初始化

processor.h 裡頭有這樣的用法:
#define INIT_TSS  {\
    .x86_tss = {\
        .sp0        = sizeof(init_stack) + (long)&init_stack,\
        .ss0        = __KERNEL_DS,\
        .ss1        = __KERNEL_CS,\
        .io_bitmap_base    = INVALID_IO_BITMAP_OFFSET,\
     },\
    .io_bitmap        = { [0 ... IO_BITMAP_LONGS] = ~0 },\
}

這個 INIT_TSS 將來會 assign 給變數型別是 struct tss_struct ,該型別定義如下:

struct tss_struct {
    /*
     * The hardware state:
     */

    struct x86_hw_tss    x86_tss;

    /*
     * The extra 1 is there because the CPU will access an
     * additional byte beyond the end of the IO permission
     * bitmap. The extra byte must be all 1 bits, and must
     * be within the limit.
     */

    unsigned long        io_bitmap[IO_BITMAP_LONGS + 1];
    /*
     * Cache the current maximum and the last task that used the bitmap:
     */

    unsigned long        io_bitmap_max;
    struct thread_struct    *io_bitmap_owner;

    /*
     * Pad the TSS to be cacheline-aligned (size is 0x100):
     */

    unsigned long        __cacheline_filler[35];
    /*
     * .. and then another 0x100 bytes for the emergency kernel stack:
     */

    unsigned long        stack[64];

} __attribute__((packed));

struct x86_hw_tss {
    unsigned short        back_link, __blh;
    unsigned long        sp0;
    unsigned short        ss0, __ss0h;
    unsigned long        sp1;
 ...省略
} __attribute__((packed));


這樣用法相當簡潔,連同 sub structure 的初始化都可以一口氣完成!

2009年2月15日 星期日

libusb 的底層追蹤 (libusb thread support and the relation with kernel usbfs)

因為做 project,無意間找到了Greg KH 大師級的文章-- [Snooping the USB Data Stream] 文中有一段提到 kernel 對 usbfs 的支援,讓 application 可直接透過 usbfs 對 device 發出 usb transfer,實做於devio.c, inode.c, and devices.c 等三個 kernel sources. (note: 我這裡的 kernel version 是 2.6.26)


而另一方面,在 application library 端,就是依靠 usbfs 的幫忙,發展出 [libusb project] 1.0.0  版,但在 debian testing 的套件裏,還只包到 libusb-0.1.12,若要 library header 檔,請安裝 libusb-dev 套件。

從 0.1.12 到 1.0.0 做了許多改變,除了 API 幾乎重新定之外,最明顯的是增加了 thread 的支援,但是兩者在最底層的系統呼叫,都是使用了 usbfs 提供的 I/O control。因為 1.0.0 的設計蠻複雜的,所以我還是以 0.1.12 來追蹤(其實是功力不夠啦!)以下就是一些 0.1.12 追蹤的筆記:

in libusb-0.1.12:

usb_bulk_read()         
usb_interrupt_read()
usb_bulk_write()   與    usb_interrupt_write()
       :                      :
       V                      V
   USB_URB_TYPE_BULK      USB_URB_TYPE_INTERRUPT
                 :           :
                 :           :
                 V           V
               usb_urb_transfer()

usb_urb_transfer() 大致上流程,僅僅提供了 synchronous 的傳送方式(就是呼叫之後就等待它完成)---在 0.1.12 的介面上並沒有提供 asynchronous 的方式(就是呼叫後就離開,將來 urb 收/送完成後,系統會呼叫 complete function),注意:這是 libusb-0.1.12 並沒有提供 asynchronous 的函數,但是 kernel 的 IOCTL_USB_SUBMITURB 工作方式卻都是 asynchronous 的動作,等下追蹤 kernel 的部份時就會知道了。
usb_urb_transfer() 用 IOCTL_USB_SUBMITURB 送出 urb 之後,然後一直重複使用 IOCTL_USB_REAPURBNDELAY 來收取completed urb  ,並且把使用者傳入的 timeout 切成 1ms 的單位用 select() 來等待。結果有幾種:
1. select() 等到了 I/O 動作,REAPURB 得到了某個 completed urb ,返回值是所收送的 data 長度。
2. select() 等不到 I/O 動作,重複 1ms 的 select()等待,一直到 timeout 了,返回值是 -ETIMEDOUT

usb_urb_transfer() 有一段註解,是這樣說的,直接節錄下來:

#define URB_USERCONTEXT_COOKIE        ((void *)0x1)

  /*
   * HACK: The use of urb.usercontext is a hack to get threaded applications
   * sort of working again. Threaded support is still not recommended, but
   * this should allow applications to work in the common cases. Basically,
   * if we get the completion for an URB we're not waiting for, then we update
   * the usercontext pointer to 1 for the other threads URB and it will see
   * the change after it wakes up from the the timeout. Ugly, but it works.
   */

雖然這裡說 Threaded application 可以 work ! 根據這段註解說,使用了 urb.usercontext 來"標示" reapped urb---若不是我們的 urb 就把該 urb.usercontext 設定為 URB_USERCONTEXT_COOKIE,以便讓另一個 thread 可以 reap:但是另一個 thread 可以 reap 到這個作了 cookie 記號的 urb 嗎?

追蹤到這裡,我們不得不往 kernel 的 devio.c 追蹤,要徹底了解 kernel 提供 usbfs 的動作才能解答這個問題...

首先從  IOCTL_USB_SUBMITURB 開始找線索,因為這個是 libusb 定義的 I/O control code,kernel 裏相對應的是 USBDEVFS_SUBMITURB I/O control code,負責處理這個 I/O control code  的是 proc_submiturb(ps, p); 其中 ps 與 p 分別是

   struct dev_state *ps = file->private_data;
   void __user *p = (void __user *)arg;

arg 是 user 由 ioctl system call 傳入的 argument pointer,這裡傳入 user urb。
ps 是 usbdev_open() 時 allocated 得到的,定義為 :

struct dev_state {
    struct list_head list;      /* state list */
    struct usb_device *dev;
    struct file *file;
    spinlock_t lock;            /* protects the async urb lists */
    struct list_head async_pending;
    struct list_head async_completed;
   
wait_queue_head_t wait;     /* wake up if a request completed */
    unsigned int discsignr;
    struct pid *disc_pid;
    uid_t disc_uid, disc_euid;
    void __user *disccontext;
    unsigned long ifclaimed;
    u32 secid;
};


可以把這個資料結構看成 process 對於這個 device 的傳送 urb 的狀態紀錄. 其中兩個 list 分別是 urb 送出後就把對應的 async 由 async_pending 紀錄,等 urb complete 之後就把對應的 async 由 async_completed 紀錄,async 是甚麼呢?對於每個 urb 都有一個對應的 async data structure,是在 proc_do_submiturb() 時 allocate 得到的 。async 的資料結構為:

struct async {
    struct list_head asynclist;
    struct dev_state *ps;
    struct pid *pid;
    uid_t uid, euid;
    unsigned int signr;
    unsigned int ifnum;
    void __user *userbuffer;
    void __user *userurb;
    struct urb *urb;

    int status;
    u32 secid;
};  

對每個 urb 都有一個 async 紀錄,在 proc_do_submiturb() 時 allocate 得到,同時它也會紀錄 user urb 的位置,將來可以把 urb 所得的資料 copy 回 user urb。


整個 urb 的流程為:
proc_submiturb()
: 把 user's urb(user space) 拷貝一份到我們的 uurb (kernel space)
->proc_do_submiturb(): 根據 bulk,interrupt..等 type 分別 initial 一些欄位,然後 allocate async data structure (裡面還包含 urb),然後放入 ps->async_pending queue 做紀錄,接著呼叫 usb_submit_urb() (之後就交給 usb host controller 處理了)然後不等結果就返回, 所以我們說 kernel 這裡是以 asynchronous 的方式處理 urb !

等 usb host controller 把 urb 處理完後,會呼叫 async_complete(),async_complete() 將 async 紀錄從 ps->async_pending 移到 ps->completed.

另一方面 user 要透過 IOCTL_USB_REAPURBNDELAY "收割" 已完成的 urb ,對應到 kernel 為 USBDEVFS_REAPURBNDELAY。這個 I/O control 會呼叫 proc_reapurbnonblock(),它會巡視 ps->completed 是否有 async 紀錄,若無則返回 -EAGAIN,若有則把找到的 urb (kernel space) 資料拷貝到 user space,並設定 IOCTL_URB_REAPURBNDELAY 時傳入的 arg 指向 user space urb,至此,kernel 傳送的部份已經完成。

好,kernel 的部份至此大致了解,接下來討論我們的疑問,我們分兩種情形討論:
1. 每一個 thread 都使用同一個 open handle, 也就是在 kernel 裡面同一份 ps:
  當 IOCTL_USB_REAPURBNDELAY 時,在 kernel 裡,會取出 ps->completd 上已完成 urb ,但是並不知道是哪一個 thread 的 urb ,因此 libusb 使用 cookie 作記號;
在 usb_urb_transfer() 時,每一個 thread 在自己的 thread stack 上宣告一個 user space urb,如果第一個 thread reap 到不屬於自己的 urb 就打上 cookie 並繼續從 kernel reap 其他的 urb,此時當第二個 thread reap urb 時,就從 ps->completed 再抓一個 ... of course ,這樣第二個 thread 就收不到該收的 urb 了,錯誤就產生了。

2.
每一個 thread 各自開了 open handle, 也就是在 kernel 裡面對應各自的 ps:
  這樣每個 thread 都對應了自己的 ps->completed list,所收的 urb 不會混淆,好像也不需要 cookie 了喔!但是這樣有一個缺點:bulk transfer 之前要 claim interface---就是每個 thread 要使用 usb_urb_transfer() 時必須先 claim interface...,所以原來已經 claim interface 的 thread 要 release interface,那就要把之前該 thread 的 urb 結束掉才行囉,這樣多個 thread "interleave urbs transfer" 的本意就沒了啊!

所以結論是:若想以 thread 的方式使用 usblib-0.1.12,大概自己要動手改 usb_urb_transfer() 的部份,否則就直接用 usblib-1.0.0 。



2009年2月12日 星期四

繼續 R&D 的旅行

從 [樂多] 移到這裡,是為了編輯方便!,繼續紀錄我的 R&D life....

下面來看一段影片吧!這是我家小貢丸第一次上台喔!
看他毫不怯場的揮手,希望他以後上台都可以保持這麼大方的態度呢!



2009年1月20日 星期二

使用cscope 取代 source insight 以瀏覽 kernel source





解決linux下代碼查看問題

在 Windows 下面我們有 Source Insight 可以方便的瀏覽大工程中的代碼,切換到 Linux 環境下開發時, 我們也可以搭建一個這樣的環境。下面的內容將介紹如何搭建這樣一個開發環境(這裡我們假設讀者已經熟悉 emacs 的安裝和配置)。
  步驟一安裝下列軟件
 
 1)cscope :cscope是一個代碼瀏覽工具,它可以幫你在一個大的工程中,
快速定位到一個函數/變量的聲明位置,所有引用地方等,它可以結合vim和emacs一起使用。
單獨使用cscope時不同文件間的跳轉變得很難處理,這裡我們介紹cscope在emacs環境中的使用,它需要預先建立索引檔:根據
cscope.files 的內容來建立索引:cscope.[in][out]。

  步驟二修改或創建.emacs文件
  ;;加載我們需要的plugin (使用cscope的必備動作)
(load-file "/usr/share/emacs/site-lisp/xcscope.el")
(require 'xcscope)
(setq cscope-do-not-update-database "t")
  ;; 這行後面會解釋
(setq cscope-set-initial-directory "./")  ;; 在現有目錄下找 cscope.out

      步驟三添加工程:
  假設我們要把/home/tom/src/linux-2.6.23的源代碼做出cscope索引,我們可以這樣做,

       #>make ARCH=arm cscope  這裡 ARCH 可以等於 arm, x86, mips,  ...等等你想要的 CPU arch。

       手動自己來:

  1)#>cd /home/tom/src/linux-2.6.23 進入源代碼根目錄;
  2)#>touch cscope.sh 創建一個腳本文件,內容如下

#!/bin/bash
LNX=`pwd`
ARCH=arm
cd /
find $LNX/ \
-path "$LNX/arch/*" ! -path "$LNX/arch/$ARCH*" -prune -o \
-path "$LNX/include/asm-*" ! -path "$LNX/include/asm-$ARCH*" -prune -o \
-path "$LNX/tmp*" -prune -o \
-path "$LNX/Documentation*" -prune -o \
-path "$LNX/scripts*" -prune -o \
-path "$LNX/drivers*" -prune -o \
-name "*.[chxsS]" -print >$LNX/cscope.files
find $LNX/ -path "$LNX/include/asm-generic*" -name "*.[chxsS]" -print >> $LNX/cscope.files

 然後 #>cscope -b -k -q ( -q 是建立雙向鏈結,可增加搜尋速度!),這時候要等個幾分鐘,等待索引的建立!因為針對 ARCH=arm 來做,所以建出以 arm 為主的索引檔。

    成功後執行 cscope.sh 腳本。

  步驟四:關於cscope代碼瀏覽命令
            C-c s a 設定初始化的目錄(cscope-set-initial-directory) ,一般是你代碼的根目錄,為了省事,我們可以把這一行命令在進入 emacs 就執行,像剛剛的 .emacs 範例一樣。
       鬼 C-c s I (i 大寫) 對目錄中的相關文件建立列表並進行索引。內定會自動建立索引。記得嗎?我們剛剛做過索引了,並用 -q 參數,所以這裡不但不要用這個指令,(在 emacs 外面用 -q 建索引就好),還應該要 disable 自動建索引的功能,因為在 emacs 裡面會主動呼叫 cscope 建立索引。所以剛剛我們修改了(setq cscope-do-not-update-database "t")。

若不這樣改,在自動建立索引時會抱怨 -q 與 database 不合的警告,重建的 database 也將喪失雙向搜尋的能力,用起來會變得蠻慢的喔!因為 kernel symbol 實在太多了!

            C-c s s 序找符號
            C-c s g 尋找全局的定義(即是 cscope-find-global-definition)
            C-c s c 看看指定函數被哪些函數所調用
            C-c s C 看看指定函數調用了哪些函數
            C-c s e 尋找正則表達式
            C-c s f 尋找文件
            C-c s i 看看指定的文件被哪些文件include
            C-c s u 回到上一個 symbol  (即cscope-pop-mark)

結論:Source Insight 雖然直覺好用,但是你還得找到 Windows 環境才能 run,用wine 模擬 Windows 是一個辦法啦!這裡只是提供了『純 Linux 環境』的做法,供大家參考!

補充:用 etags 配合使用,更方便:(假設已經裝好 ctags 套件)       

       1)   在進入 emacs 之前先用 etags -R 建立 TAG 檔。
在 emacs 裏面的指令:
       2)   M-x visit-tags-table 會詢問是否用 default TAG file? 按 y 即可。
       3)   M-. 找定義,以游標所在位置的變數來找。
       4)   M-* 返回。
       5)   C-u M-. 尋找標籤的下一個定義。


補充:修改 .emacs 取代常用的 cscope 命令,在 (require 'xcscope) 後加上
(define-key global-map [f5] 'cscope-find-this-file)
(define-key global-map [f6] 'cscope-find-this-symbol)
(define-key global-map [f7] 'cscope-pop-mark)
(define-key global-map [f8] 'cscope-find-global-definition)
(define-key global-map [f9] 'cscope-find-global-definition-no-prompting)
(define-key global-map [M-up] 'cscope-prev-symbol)
(define-key global-map [M-down] 'cscope-next-symbol)
(define-key global-map [f12] 'c-down-conditional-with-else)
(define-key global-map [M-f12] 'c-up-conditional-with-else)

這樣,就可以用 F5, F6, F7, F8, F9 Esc-↑ Esc-↓ 來 browse code,您可以把常用的 key 如法泡製。