自己写的linux字符设备驱动读写IO端口

来源:互联网 发布:mac硬件检测工具 编辑:程序博客网 时间:2024/05/16 10:40




#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <asm/io.h>//#include <asm/system.h>#include <asm/uaccess.h>#include <linux/slab.h>#define homework_MAJOR 248  //设备号#define HOMEWORK_SIZE 128 //cmos最大内存static int homework_major=homework_MAJOR;                                                                                                                                                                                                                                                                                 struct homework_dev {                                                            struct cdev cdev; /*一个cdev结构体代表一个字符设备,与字符设备一一对应*/   struct semaphore sem;    //信号量                                                                };                                                                                                                                                        struct homework_dev *homework_devp;                                                                                                                                                                                                                                                                                                                          int homework_open(struct inode *inode, struct file *filp)                      {                                                                                                                                       printk("open success\n");  filp->private_data = homework_devp;                                                                                                  return 0;                                                                  }                                                                                                                                         int homework_release(struct inode *inode, struct file *filp)                   {                                                                                                                       printk("release success\n");                                                                             return 0;                                                                  }                                                                                                                                                                                                                         static ssize_t homework_read(struct file *filp, char __user *buf, size_t count,loff_t *ppos)                                                              {                                                                                                                                              char data;    int i=0;                                                                                                                                                         printk("read ppos=%d\n",(unsigned int)*ppos);   if(down_interruptible(&homework_devp->sem))    //获得信号量   {      return -ERESTARTSYS;   }   for(i=0;i<count;i++){       outb(*(ppos+i),0x70);   //将地址写入70H       data=inb(0x71);         //将数据从71H拿出到data       printk("read data=%c\n",data);       if(copy_to_user(buf+i,&data,sizeof(data)))  //将data写到用户空间buf       {          return -EFAULT;       }    }    *ppos+=count;    printk("read buf=%c\n",*buf);    up(&homework_devp->sem);  //释放信号量    return 0;                                          } static ssize_t homework_write(struct file *filp, const char __user *buf, size_t count,loff_t *ppos)                                                              {    char data;   int i;  if(down_interruptible(&homework_devp->sem))   {      return -ERESTARTSYS;   }   printk("in the write..\n");    printk("write ppos=%d\n",(unsigned int)*ppos);   for(i=0;i<count;i++){       // put *ppos to 70H       outb(*(ppos+i),0x70);  //将地址写入70H       //read 71H to buf        printk("buf=%c\n",*buf);          if(copy_from_user(&data,buf+i,sizeof(data)))   //将buf中数据拿到data       {          return -EFAULT;       }       printk("data=%c\n",data);       outb(data,0x71);  //将data写入71H    }    *ppos+=count;   up(&homework_devp->sem); //释放信号量   return 0;             }                                                                           static loff_t homework_llseek(struct file *filp, loff_t offset, int orig){   loff_t ret = 0;   //printk("orig=%d\n",orig);    switch (orig)   {     case 0:   //相对文件开始位置偏移         //printk("case0\n");           if (offset < 0)           {             ret =  -EINVAL;             break;           }          if ((unsigned int)offset > HOMEWORK_SIZE)          {             ret =  -EINVAL;             break;           }          //printk("offset=%d\n",(unsigned int)offset);          filp->f_pos = (unsigned int)offset;  //修改filp->f_pos值偏移当前指针位置          ret = filp->f_pos;           break;     case 1:   //相对文件当前位置偏移           if ((filp->f_pos + offset) > HOMEWORK_SIZE)           {             ret =  -EINVAL;             break;           }           if ((filp->f_pos + offset) < 0)           {             ret =  -EINVAL;             break;           }           filp->f_pos += offset;           ret = filp->f_pos;           break;     default:           ret =  -EINVAL;           break;   }   return ret;}                                                                        //文件操作结构体                                                        static const struct file_operations homework_fops = {                            .owner = THIS_MODULE,   .llseek = homework_llseek,                                                        .open = homework_open,                                                         .release = homework_release,                                                   .read = homework_read,   .write = homework_write,                                                     };                                                                                                                                                        //初始化设备cdev结构体                                                       static void homework_setup_cdev(struct homework_dev *dev, int index)             {                                                                              int err, devno = MKDEV(homework_major, index);                                                                                                              cdev_init(&dev->cdev, &homework_fops);                                         dev->cdev.owner = THIS_MODULE;                                               err = cdev_add(&dev->cdev, devno, 1);//向操作系统注册cdev结构体                                   if (err)                                                                       printk(KERN_NOTICE "Error %d adding LED%d", err, index);                 }                                                                                                                                                         //模块加载函数                                                    int homework_init(void)                                                        {                                                                              int ret=0;                                                                     dev_t devno = MKDEV(homework_major, 0); //将主设备号和次设备号转换成dev_t类型                                                                                                                                                                               if (homework_major)                                                              ret = register_chrdev_region(devno, 1, "homework");//手工分配主设备号                      else {                                                     ret = alloc_chrdev_region(&devno, 0, 1, "homework");//动态分配主设备号                        homework_major = MAJOR(devno);                                               }                                                                            if (ret < 0)                                                                   return ret;                                                                                                              homework_devp = kmalloc(sizeof(struct homework_dev), GFP_KERNEL);                if (!homework_devp) {                                            ret =  - ENOMEM;                                                             goto fail_malloc;                                                          }                                                                            memset(homework_devp, 0, sizeof(struct homework_dev));                           homework_setup_cdev(homework_devp, 0);      //init_MUTEX(&homework_devp->sem);      sema_init(&homework_devp->sem,1);   //初始化信号量结构体                            return 0;                                                                  fail_malloc:  unregister_chrdev_region(devno, 1);//释放设备号  return ret;                           }                                                                            //模块卸载函数                                                           void homework_exit(void)                                                       {                                                                              cdev_del(&homework_devp->cdev);    //注销字符设备                               kfree(homework_devp);               //释放设备结构体占用内存                   unregister_chrdev_region(MKDEV(homework_major, 0), 1);    //释放设备号  //printk("exit success\n");      }                                                                            MODULE_AUTHOR("liushan");MODULE_LICENSE("Dual BSD/GPL");                                                                                                                                                                                                        module_param(homework_major, int, S_IRUGO);                                                                                                                 module_init(homework_init);                                                    module_exit(homework_exit);                                                    







0 0