QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1345|回复: 2

求助,为什么我编的驱动程序会出错?(附源码)

[复制链接]
发表于 2005-7-9 10:24:14 | 显示全部楼层 |阅读模式
我的
驱动程序:
#include <linux/module.h>

#include <linux/slab.h>

#include <asm/io.h>

#include <linux/poll.h>

#if defined(CONFIG_MODVERSIONS) &&!defined(MODVERSIONS)
#include <linux/modversions.h>
#define MODVERSIONS
#endif

#define __NO_VERSION__
#include <linux/version.h>

#include <linux/kernel.h>

#include <linux/ioport.h>

#define        GFN_MAJOR        254

#define        BASE                0x26a
#define        LDATAPORT        (BASE)
#define        MDATAPORT        (BASE+1)
#define        HDATAPORT        (BASE+2)


#define        MYIRQ                9

static DECLARE_WAIT_QUEUE_HEAD(my_wait_queue);

static volatile int        waiting_for_irq;


static void isr(int irq, void *dev_id, struct pt_regs *regs)
{
        if(irq != MYIRQ)
        {
        printk(KERN_INFO "Stray Interrupt from IRQ %d\n",irq);
        return;
        }

        /*outb(0, CONPORT);        // Disable further interrupts from Parallel port*/
        disable_irq(MYIRQ);
        if(!waiting_for_irq)
        {
        printk(KERN_INFO "unexpected Interrupt from %d\n",irq);
        return;
        }

        waiting_for_irq = 0;
        wake_up_interruptible(&my_wait_queue);

        printk(KERN_INFO "ISR: Done Interrupt from IRQ %d\n",irq);
}


static ssize_t
gfn_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
        printk(KERN_INFO "Sorry,this operation isn't supported.\n");
        return -EINVAL;
}


static ssize_t gfn_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
        u8 data;
        unsigned long flags;
        if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
        printk(KERN_INFO "READ: Process going to Sleep ...\n");
        enable_irq(MYIRQ);
        save_flags(flags);

        cli();


        waiting_for_irq = 1; /* atomic copy */
        restore_flags(flags);



        /*outb(IRQENBIT, CONPORT);        // Enable Interrupt from  port*/
        interruptible_sleep_on(&my_wait_queue);
        /*sleep_on(&my_wait_queue); */


        data = inb(LDATAPORT);
        /*data[1] = inb(MDATAPORT);
        data[2] = inb(HDATAPORT);        */                // read the printer status port
        printk(KERN_INFO "Woken up. data = %x hex\n", data);        // for debugging only
        // transfer data from kernel address space to user address space
        if(copy_to_user( buffer, &data, sizeof(u)) return -EFAULT;

        return sizeof(u;
}

static int gfn_open(struct inode * inode, struct file * file)
{
        printk(KERN_INFO "GFN open: Usage = %d\n", MOD_IN_USE);
        MOD_INC_USE_COUNT;
        return 0;
}

static int gfn_release(struct inode * inode, struct file * file)
{
        MOD_DEC_USE_COUNT;
        printk(KERN_INFO "GFN release: Usage = %d\n", MOD_IN_USE);
        return 0;
}

struct file_operations gfn_fops = {
        owner: THIS_MODULE,
        open:    gfn_open,
        release: gfn_release,
        write:  gfn_write,
        read:   gfn_read
      };


int init_module(void)
{
        int result;

        result=check_region(BASE,16);
        if(result)
        {
                printk(KERN_INFO "short: can't get I/O port address 0x%1x\n",BASE);
                return result;
        }
        if (register_chrdev(GFN_MAJOR,"gfn",&gfn_fops)) {
        printk("gfn: Failed to get major %d\n", GFN_MAJOR);
        return -EIO;
        }
        request_region(BASE, 16,"gfn");
        if(request_irq(MYIRQ, isr, SA_INTERRUPT, "gfn", NULL) ) {
        printk("mkscc: Failed to get IRQ %d\n",MYIRQ);
        return -EIO;
        }

        disable_irq(MYIRQ);// disable Interrupt from  port*/

        printk(KERN_INFO "Registered device gfn: major %d\n",GFN_MAJOR);
        return 0;
}

void cleanup_module(void)
{
        free_irq(MYIRQ, NULL);
        release_region(BASE,16);
        printk(KERN_INFO "Freed resources: MOD_IN_USE = %d\n", MOD_IN_USE);
        unregister_chrdev(GFN_MAJOR,"gfn");
        printk(KERN_INFO "Unregistered device gfn: major %d\n",GFN_MAJOR);
}
MODULE_LICENSE("GPL");


/********testdrv.c 测试程序*/
#include <stdio.h>
//#include <sys/ioctl.h>
#include <fcntl.h>

int        handle;


int main()
{
        int data;

        handle = open("/dev/testsleepdrv", O_RDWR);
        if(handle > 0)
        printf("GFN Driver opened %d\n", handle);
        else
        {
        printf("Error opening GFN\n");
        exit(1);
        }

        data=0;


        printf("Going to call GFN read. Will sleep....");
        if(read(handle, &data, 1, 0) < 0)
        printf("Error reading GFN\n");

        printf("Woken Up. Printer Status = %x hex\n",data&255);

        return 0;
}
/*********************/


编译:gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include -c mydriver.c
gcc ./testdrv.c
mknod /dev/testsleepdrv c 254 0
insmod ./mydriver.o
./testdrv.o
提示
Process going to Sleep
Unable to handle kernel NULL pointer dereference at virtual address 00000
......
segment fault .....

interrupt
我的内核是2.4.30,该如何使用interruptible_sleep_on,wait_up_interruptible
发表于 2006-3-3 12:22:12 | 显示全部楼层
你定义#define MODULE了没有
回复

使用道具 举报

发表于 2006-3-4 21:25:58 | 显示全部楼层
以后贴源码用[code:1][/code:1]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-23 15:25 , Processed in 0.056685 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表