|
一个很简单的驱动程序(初学),控制8253模拟电子琴的,驱动程序在下面
本来只是播放一段声音的话,没有问题,但是考虑要模拟琴键按下才响的情况,学着加了中断,可是确实不行,直接编译模块的地方就过不去了,我的linux是 opensuse10.3,内核2.6.22.5,在request_irq地方出错,如果直接request的话,死机,不能动弹,放在if后面显示编译有warning
/home/yuan/Desktop/demo1/beep.c: In function ‘init_module’:
/home/yuan/Desktop/demo1/beep.c:123: warning: passing argument 2 of ‘request_irq’ from incompatible pointer type
如果采用request_irq(1, key_handler, SA_INTERRUPT, "beep", NULL)的话,还有一个‘deprecated_irq_flag’ is deprecated (declared at /usr/src/linux-2.6.22.5-31/include/linux/interrupt.h:66)
直接加载模块的话,提示出错insmod: error inserting 'beep.ko': -1 Input/output error
大家帮帮忙阿,头一回写中断,晕死了,看了书,看了网上的材料还是不明白
//beep.h
#ifndef __BEEP_H__
#define __BEEP_H__
#define MAJOR_NUM 145 // no dynamic Major number
#define DEVICE_NAME "beep" // The name for our device
#define BEEPSETCFG _IOR('c', 0, int)
#define BEEPSTART _IOR('c', 1, int)
#define BEEPSTOP _IOR('c', 2, int)
#endif
//beep.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#endif
#include <linux/fs.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/signal.h>
#include <asm/uaccess.h>
#include "beep.h"
#define SUCCESS 0
static int Device_Open = 0;
static spinlock_t key_lock = SPIN_LOCK_UNLOCKED;
static irqreturn_t key_handler(int irq, void *dev_id, struct pt_regs *regs);
static void key_task(unsigned long data);
DECLARE_TASKLET(key_tasklet, key_task, 0);
static int beep_open(struct inode *inode,struct file *file){
printk("beep driver opened\n");
if(Device_Open) return -EBUSY;
Device_Open ++;
return SUCCESS;
}
static int beep_release(struct inode *inode,struct file *file){
Device_Open --;
return 0;
}
int beep_read(struct file *file,char *buffer,size_t length,loff_t *offset){
return 0;
}
int beep_write(struct file *file,char *buffer,size_t length,loff_t *offset){
return 0;
}
int beep_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){
int retval,bit;
retval = 0;
bit = 0;
switch(cmd){
case BEEPSETCFG:
outb(0xb6,0x43);
outb((arg & 0xff),0x42);
outb((arg > > 8),0x42);
break;
case BEEPSTART:
bit=inb(0x61);
outb(3 ¦ bit,0x61);
break;
case BEEPSTOP:
outb(0xfc ¦ bit,0x61);
break;
default:
retval = -ENOIOCTLCMD;
break;
}
return retval;
}
struct file_operations Fops = {
.owner =THIS_MODULE,
.open =beep_open,
.release =beep_release,
.ioctl =beep_ioctl,
.read =beep_read,
.write =beep_write,
};
static irqreturn_t key_handler(int irq, void *dev_id, struct pt_regs *regs)
{
disable_irq(1);
tasklet_schedule(&key_tasklet);
return IRQ_RETVAL(1);
}
static void key_task(unsigned long data){
unsigned long flags;
int bit;
spin_lock_irqsave(&key_lock, flags);
{
bit=inb(0x61);
outb(3 ¦ bit,0x61);
}
spin_unlock_irqrestore(&key_lock, flags);
outb(0xfc ¦ bit,0x61);
return;
}
int init_module(){
int ret_val;
unsigned long flags;
ret_val = register_chrdev(MAJOR_NUM,DEVICE_NAME,&Fops);
printk(" <1> -----\n");
if (ret_val < 0) {
printk ("%s failed with %d\n","?Sorry, registering the character device ",ret_val);
return ret_val;
}
free_irq(1, NULL);
printk(" <1> free_irq(1, NULL);\n");
spin_lock_irqsave(&key_lock, flags);
if (request_irq(1,key_handler,0,"beep", NULL)){
printk(KERN_ERR"cannot register IRQ 1+++%d\n",-EIO);
return -EIO;
}
request_irq(1, key_handler, SA_INTERRUPT, "beep", NULL);
disable_irq(1);
spin_unlock_irqrestore(&key_lock, flags);
return 0;
}
void cleanup_module()
{
int ret;
ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
if (ret < 0)
printk("Error in module_unregister_chrdev: %d\n", ret);
free_irq(1,NULL);
} |
|