割り込みデバイスドライバ
このデバイスドライバは仲吉さんによって作成されました。
#include <linux/version.h>
#include <linux/modversions.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
#include <linux/tqueue.h>
#include <asm/uaccess.h>
#include <asm/keyboard.h>
#define MOUSEINT_IRQ 12
static int bh = 0;
static int soft = 0;
static int which_tq = 0;
static int soft_level = 0;
以下のMODULE_PARMはドライバのインストール時にドライバ内の
変数の値を変更するための仕掛けです。
変数はこの場合、bh, soft, which_tq, soft_levelです。
MODULE_PARM(bh, "i");
MODULE_PARM(soft, "i");
MODULE_PARM(which_tq, "i");
MODULE_PARM(soft_level, "i");
static struct tq_struct mouseint_task;
DECLARE_WAIT_QUEUE_HEAD(mouseint_wq);
void mouseint_softirq(unsigned long);
DECLARE_TASKLET(mouseint_tasklet, mouseint_softirq, (unsigned long)0);
static int mouse_counter;
static int irqid;
static void mouseint_bottom_half(void)
{
printk("(mouseint_bottom_half)BH\n");
printk("(mouseint_bottom_half)jif:%ld\n", jiffies);
wake_up_interruptible(&mouseint_wq);
}
static void mouseint_bh_handler(void)
{
if( mouse_counter )
return;
mouse_counter++;
printk("(mouseint_bh_handler)BH handler\n");
printk("(mouseint_bh_handler)jif:%ld\n", jiffies);
switch(which_tq){
case 0:
queue_task(&mouseint_task, &tq_immediate);
break;
case 1:
queue_task(&mouseint_task, &tq_timer);
break;
default:
queue_task(&mouseint_task, &tq_immediate);
break;
}
mark_bh(IMMEDIATE_BH);
}
static void mouseint_handler(void)
{
if( mouse_counter )
return;
mouse_counter++;
printk("(mouseint_handler)Non software interrupt\n");
printk("(mouseint_handler)jif:%ld\n", jiffies);
wake_up_interruptible(&mouseint_wq);
}
void mouseint_softirq(unsigned long data)
{
printk("(mouseint_softirq)software irq\n");
printk("(mouseint_softirq)jif:%ld\n", jiffies);
wake_up_interruptible(&mouseint_wq);
}
static void mouseint_soft_handler(void)
{
if( mouse_counter )
return;
mouse_counter++;
printk("(mouseint_soft_handler)Software handler\n");
printk("(mouseint_soft_handler)jif:%ld\n", jiffies);
switch(soft_level){
case 0:
tasklet_hi_schedule (&mouseint_tasklet);
break;
case 1:
tasklet_schedule (&mouseint_tasklet);
break;
default:
tasklet_schedule (&mouseint_tasklet);
break;
}
}
static
int mouseint_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
return 0;
}
static
void mouseint_close(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
return;
}
int mouseint_read(struct inode *inode, struct file filp,
char *buf, int count)
{
printk("(mouseint_read)Waiting for mouse IRQ\n");
printk("(mouseint_read)jif:%ld\n", jiffies);
mouse_counter = 0;
//if(soft == 1)
//tasklet_schedule(&mouseint_tasklet);
interruptible_sleep_on(&mouseint_wq);
printk("(mouseint_read)wake up\n");
printk("(mouseint_read)jif:%ld\n", jiffies);
return 0;
}
static struct file_operations mouseint_fops =
{
owner:THIS_MODULE,
read: mouseint_read,
open: mouseint_open,
release: mouseint_close,
};
extern int mouseint_init(void);
module_init(mouseint_init);
static int mouseint_init(void)
{
int err;
if(register_chrdev (60, "mouseint", &mouseint_fops) != 0)
return - EIO;
printk("*** mouseint module init!\n");
if(bh == 0 && soft == 0) {
err = request_irq(MOUSEINT_IRQ, mouseint_handler, SA_SHIRQ, "mouseint", &irq
id);
if (err) printk("Request_irq failed(%d)\n", err);
printk("(mouseint_init)Non software interrupt handler was selected\n");
}
if(bh == 1 && soft == 0) {
err = request_irq(MOUSEINT_IRQ, mouseint_bh_handler, SA_SHIRQ, "mouseint", &
irqid);
if (err) printk("Request_irq failed(%d)\n", err);
mouseint_task.routine = mouseint_bottom_half;
mouseint_task.data = NULL;
printk("(mouseint_init)BH handler was selected\n");
printk("(mouseint_init)Task Queue type: %d\n", which_tq);
}
if(bh == 0 && soft == 1) {
err = request_irq(MOUSEINT_IRQ, mouseint_soft_handler, SA_SHIRQ, "mouseint",
&irqid);
if (err) printk("Request_irq failed(%d)\n", err);
printk("(mouseint_init)Software Int. handler was selected\n");
printk("(mouseint_init)Software Int. Level: %d\n", soft_level);
}
return 0;
}
extern void mouseint_cleanup(void);
module_exit(mouseint_cleanup);
void mouseint_cleanup(void)
{
free_irq(MOUSEINT_IRQ, &irqid);
unregister_chrdev (60, "mouseint");
printk("*** mouseint module removed\n");
}
DEV = mouseint
CC = gcc
KERNEL_DIR = /usr/local/src/linux
DEFS = -DMODULE -D__KERNEL__
CFLAGS = -I $(KERNEL_DIR)/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -march=i686
DEVS = mouseint
TEST = read_mouseint
all : $(DEVS).o $(TEST)
$(DEVS).o:$(DEVS).c
$(CC) $(CFLAGS) $(DEFS) -c $(DEVS).c
device:
mknod -m 666 /dev/$(DEVS) c 60 0
$(TEST): $(TEST).c
$(CC) -o $(TEST) $(TEST).c
clean:
rm -f *.o *~
ドライバのインストールの方法ですが、
bhとsoftというドライバパラメータがあります。
# insmod mouseint.o
とした場合はbh = soft = 0を選択することとなり、
no software interruptハンドラが選ばれます。
#insmod mouseint.o bh=1
とした場合はbh = 1, soft = 0を選択することとなり、
bottom halfハンドラが選ばれます。
#insmod mouseint.o soft=1
としたした場合は、bh = 0, soft = 1を選択することとなり、
software interruptハンドラが選ばれます。
また、
bottom halfハンドラが選ばれたら、
#insmod mouseint.o bh=1 which_tq=0
#insmod mouseint.o bh=1 which_tq=1
どちらかを選べます。前者はすぐにハンドラを起動するように
セットアップしますが、後者の場合はタイマにまかせます。
さらに、
software interruptハンドラが選ばれたら、
#insmod mouseint.o soft=1 soft_level=0
#insmod mouseint.o soft=1 soft_level=1
どちらかを選べます。
前者はxxx、後者はxxx。
下記のプログラムはドライバがインストールされた後、実行可能な
プログラムです。実行した後、マウスを動かしてください。プログラムは
終了します。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
main()
{
int fd;
char *buf;
size_t count;
fd = open("/dev/mouseint", O_RDWR);
printf("fd = %d\n",fd);
if(fd == -1)
exit(-1);
read(fd, buf, count);
close(fd);
}
そこで、dmesgコマンドを使ってシステムメッセージを見ると、
ドライバから出されたメッセージが書かれていて、動作を確認できます。
これはNon software interruptハンドラが選ばれた場合のメッセージです。
*** mouseint module init!
(mouseint_init)Non software interrupt handler was selected
(mouseint_handler)Non software interrupt
(mouseint_handler)jif:9767332
(mouseint_read)Waiting for mouse IRQ
(mouseint_read)jif:9767708
(mouseint_handler)Non software interrupt
(mouseint_handler)jif:9767819
(mouseint_read)wake up
(mouseint_read)jif:9767819
これはBottom half interruptハンドラが選ばれた場合のメッセージです。
*** mouseint module init!
(mouseint_init)BH handler was selected
(mouseint_init)Task Queue type: 0
(mouseint_bh_handler)BH handler
(mouseint_bh_handler)jif:9823351
(mouseint_read)Waiting for mouse IRQ
(mouseint_read)jif:9823629
(mouseint_bh_handler)BH handler
(mouseint_bh_handler)jif:9823788
(mouseint_read)wake up
(mouseint_read)jif:9825508
これはSoftware interruptハンドラが選ばれた場合のメッセージです。
*** mouseint module init!
(mouseint_init)Software Int. handler was selected
(mouseint_init)Software Int. Level: 0
(mouseint_soft_handler)Software handler
(mouseint_soft_handler)jif:9843775
(mouseint_softirq)software irq
(mouseint_softirq)jif:9843775
(mouseint_read)Waiting for mouse IRQ
(mouseint_read)jif:9844877
(mouseint_soft_handler)Software handler
(mouseint_soft_handler)jif:9844950
(mouseint_softirq)software irq
(mouseint_softirq)jif:9844950
(mouseint_read)wake up
(mouseint_read)jif:9844950