動作概要 †
- 電源ボタンの状態取得方法
LANDISKのカーネルには、元々電源ボタンの割り込み制御ルーチンが組み込まれている。
その情報は次の2つの方法で取得可能。
landiskpoffの設定 †
- 電源ボタン監視デーモン、landiskpoffの設定
- landiskpoff.c
/* landiskpoff.c - http://eggplant.ddo.jp/www/
*
* Usage:
* # mknod /dev/shutdown c 99 1
* # landiskpoff /usr/local/sbin/shutdown -h now &
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd, dummy;
if(argc < 2){
printf("Usage: %s command [argument(s)]\n",argv[0]);
exit(1);
}
if( (fd = open("/dev/shutdown",O_RDONLY)) < 0){
perror("/dev/shutdown");
exit(1);
}
while(read(fd, &dummy, 1) == 0){
sleep(5);
}
close(fd);
execvp(argv[1],&argv[1]);
perror(argv[1]);
}
- コンパイル&コピー
landisk:~# gcc -O2 landiskpoff.c -o landiskpoff
landisk:~# strip landiskpoff
landisk:~# cp landiskpoff /usr/local/sbin/
- /dev/shutdownの作成
landisk:~# mknod /dev/shutdown c 99 1
- initスクリプト
- /etc/init.d/landiskpoff
#! /bin/sh
set -e
NAME=landiskpoff
DAEMON=/usr/local/sbin/$NAME
SCRIPTNAME=/etc/init.d/$NAME
test -x $DAEMON || exit 0
case "$1" in
start)
echo -n "Starting $NAME"
$DAEMON /sbin/shutdown -h now &
echo "."
;;
stop)
echo -n "Stopping $NAME"
killall $DAEMON
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop}" >&2
exit 1
;;
esac
exit 0
を用意して、
landisk:~# chmod +x /etc/init.d/landiskpoff
landisk:~# update-rc.d landiskpoff defaults 99
Adding system startup for /etc/init.d/landiskpoff ...
/etc/rc0.d/K99landiskpoff -> ../init.d/landiskpoff
/etc/rc1.d/K99landiskpoff -> ../init.d/landiskpoff
/etc/rc6.d/K99landiskpoff -> ../init.d/landiskpoff
/etc/rc2.d/S99landiskpoff -> ../init.d/landiskpoff
/etc/rc3.d/S99landiskpoff -> ../init.d/landiskpoff
/etc/rc4.d/S99landiskpoff -> ../init.d/landiskpoff
/etc/rc5.d/S99landiskpoff -> ../init.d/landiskpoff
個人メモ … カーネルのエラーログ †
- エラーログ
レビジョンlandisk.0.4(以前)のカーネルでは、電源ボタンをOFFするとdmesgに次のようなエラーが表れる。
ソースを追ってみた結果、動作に実害はないもよう。
次回のレビジョンで修正予定。(レビジョンlandisk.0.5で修正済み)
irq event 11: bogus return value 5
Call trace:
[<8c02da2e>] __report_bad_irq+0x2e/0xa0
[<8c02d400>] handle_IRQ_event+0x0/0x80
[<8c013cc0>] printk+0x0/0x20
[<8c02db06>] note_interrupt+0x26/0xa0
[<8c02d526>] __do_IRQ+0xa6/0x100
[<8c007eea>] do_IRQ+0x2a/0x60
[<8c007ec0>] do_IRQ+0x0/0x60
[<8c0050e4>] ret_from_exception+0x0/0xc
[<8c1a4500>] schedule+0x0/0x500
[<8c003102>] default_idle+0x62/0x80
[<8c003114>] default_idle+0x74/0x80
[<8c013cc0>] printk+0x0/0x20
[<8c00201a>] _stext+0x1a/0x60
handlers:
[<8c00ee20>] (sw_interrupt+0x0/0xc0)
- 対策パッチ
--- linux-2.6.11/arch/sh/boards/julian/julian_pwb.c.old 2005-06-16 20:03:03.000000000 +0900
+++ linux-2.6.11/arch/sh/boards/julian/julian_pwb.c 2005-06-16 20:30:59.000000000 +0900
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/timer.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -41,7 +42,7 @@
static int swdrv_open(struct inode *, struct file *);
static int swdrv_close(struct inode *, struct file *);
static int swdrv_read(struct file *, char *, size_t, loff_t *);
-static void sw_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t sw_interrupt(int, void *, struct pt_regs *);
static void shutdown_check(void)
{
@@ -100,7 +101,7 @@
return 0;
}
-static void sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if (!shutdown_sw_flag) {
disable_irq(irq);
@@ -112,6 +113,7 @@
if (!shutdown_complete_flag)
enable_irq(irq);
}
+ return IRQ_HANDLED;
}
static struct file_operations swdrv_fops = {
|