*動作概要 [#m838417f]
-''電源ボタンの状態取得方法''~
LANDISKのカーネルには、元々電源ボタンの割り込み制御ルーチンが組み込まれている。~
その情報は次の2つの方法で取得可能。~
--方法1~
デバイス(99,1)を読むことで割り込みの状態を取得可能。~
電源ボタンがONの場合はEOF(End of File)が、OFFになると、'1'が出力されます。~
~
--方法2~
cat /proc/interrupts で 電源ボタンの割り込み発生回数が取得できます。~
#pre{{
 11:          &color(red){0};      Julian IRQ  SHUTDOWNSWITCH
}}
~

-''電源ボタン監視プログラム、landiskpoffの仕様''~
デーモンプロセスとして常駐し、デバイス(99,1)を5秒後毎に1byteリード。~
その結果がEOFかそうでないかで、電源ボタンの割り込み判定を行い、~
割り込みが検出されると、引数で指定されたコマンドを実行する。~
(起動時に自動的に実行されるようinit.dスクリプトも用意)~
#pre{{
landisk:~# /usr/local/sbin/landiskpoff /sbin/shutdown -h now &
}}
*landiskpoffの設定 [#i39c6267]

-''電源ボタン監視デーモン、landiskpoffの設定''~
--landiskpoff.c
#pre{{
/* 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]);
}

}}
--コンパイル&コピー
#pre{{
landisk:~# gcc -O2 landiskpoff.c -o landiskpoff
landisk:~# strip landiskpoff
landisk:~# cp landiskpoff /usr/local/sbin/
}}
--/dev/shutdownの作成~
#pre{{
landisk:~# mknod /dev/shutdown c 99 1
}}

-''initスクリプト''~
--/etc/init.d/landiskpoff~
#pre{{
#! /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
}}
を用意して、
#pre{{
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
}}
*個人メモ … カーネルのエラーログ [#ga05dda3]
-''エラーログ''~
レビジョンlandisk.0.4(以前)のカーネルでは、電源ボタンをOFFするとdmesgに次のようなエラーが表れる。~
ソースを追ってみた結果、動作に実害はないもよう。~
次回のレビジョンで修正予定。&color(red){(レビジョンlandisk.0.5で修正済み)};~
#pre{{
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)
}}
-''対策パッチ''~
#pre{{
--- 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 = {
}}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS