terrace
驱动牛犊
驱动牛犊
  • 注册日期2004-02-11
  • 最后登录2005-12-04
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1002回复:0

请教内核中断问题

楼主#
更多 发布于:2004-03-24 10:35
请问,在中断服务程序中对某变量(不是全局变量)赋值,普通程序可以正确访问吗?

我在写一个设备驱动时,先定义一个全局变量(其中与本问题无关的部分我都用..........省去,以减少大家阅读量,但还是显得冗余,望见谅):

DECLARE_WAIT_QUEUE_HEAD(rx_wq);
DECLARE_WAIT_QUEUE_HEAD(tx_wq);
struct device_card {
..................
unsigned short dma_error; //dma transfer err flag, 0:success, 1:tx fail 2:rx fail
int open_count;
struct semaphore sem;
} *card ;

注:大家只需注意dma_error分量就行。
在模块初始化时,给该结构体赋初值:
if((card = kmalloc(sizeof(struct device_card),GFP_KERNEL))==NULL){
printk(KERN_ERR "pci_device:out of memory!\n");
return -ENOMEM;
}
memset(card,0,sizeof(struct device_card));
...............
card->dma_error = 0; //初始值为0
card->open_count = 0;
sema_init(&card->sem,1);

然后在open函数中将该结构体指针存于文件的file->private_data中:

static int device_open(struct inode * inode,struct file *file)
{
struct device_card *dev;
dev = (struct device_card *) file->private_data; // get the file private data,namely set dev
if(!dev) {
dev = card ;
file->private_data = dev ;
}
//request to own the control right
if(down_interruptible(&dev->sem) ) {
printk("device_open lock sem error!\n");
return -ERESTARTSYS;
}
if(file->f_flags &O_NONBLOCK ) { //check open mode
up(&dev->sem);
return -EBUSY;
}
...................
dev->open_count ++;
up(&dev->sem);
MOD_INC_USE_COUNT;
return 0;
}

在实现read时,要根据dma_error的值做一些相关的处理,其中dma_error应当在中断处理程序中根据数据传输结果改变。
ssize_t device_write(struct file *filp,const void *buf,size_t count,loff_t *f_pos)
{
struct device_card *dev = filp->private_data;
if(down_interruptible(&dev->sem) ) {
printk("device_write lock sem error!\n");
return -ERESTARTSYS;
}
.......................
do {
.............// 启动中断触发事件
interruptible_sleep_on(&rx_wq); //等待中断唤醒
//dma transfer commpleted!
if( dev->dma_error ==2) //根据中断返回结果做处理
memset(dev->dma_buffer,0,MAX_LENGTH); // clear for next time to receive data

} while( (dev->dma_error == 2)&&(dma_err_cnt<3) ); //if dma rx err & rx_err_cnt < 3, restart dma
if( dev->dma_error ==2) {
printk("device_read receive error for more than 3 times! abort dma transfer!\n");
count = -5; // if return -5 ,dma transfer error!
goto out;
}
.....................//做相应的处理
out :
memset(dev->dma_buffer,0,MAX_LENGTH);
kfree(sglist);
up (&dev->sem);
return cnt;
}

中断处理程序如下:
static void device_interrupt(int irq, void *dev_id,struct pt_regs *regs)
{
struct device_card *card_int =(struct device_card *) dev_id;
u8 status;
status = inb_p(card_int->iobase +BUS_MASTER_STATUS); //读取状态字
if(!(status & INT_MASK)) {
return; //not for us
}
outw_p(status & INT_MASK,card_int->iobase +BUS_MASTER_STATUS); //clear interrupt flag
if( status & DMA_TX ) { // dma send
outb_p(0,card_int->iobase + BUS_MASTER_CMD); //stop dma transfer
if(status &DMA_ERR )
card_int-> dma_error = 1;
else
card_int-> dma_error = 0;
wake_up_interruptible(&tx_wq);
}
else { // dma receive
if(status &DMA_ERR )
card_int-> dma_error = 2;
else
card_int-> dma_error = 0;
wake_up_interruptible(&rx_wq);
}
return ;
}


(终于贴完了)
因为我的每个普通函数(如open、read)都有互斥信号量 sem,不知道在中断服务程序中能否访问改变
dma_error ,改变后也不知read函数中能否访问。

真的很不好意思,搞的那么长,浪费大家时间(但我想把问题说得清楚一点),希望大家谅解并能帮助,我想这个问题比较简单,只是我是初次写driver就问得有点对不住大家了。

游客

返回顶部