自己写的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
- 自己写的linux字符设备驱动读写IO端口
- 字符设备驱动第十四课----IO读写
- 《Linux总线、设备与驱动》自己写的demo
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux设备驱动第三篇:如何写一个简单的字符设备驱动?
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux 驱动-----字符设备驱动的组成
- Linux 字符设备驱动开发--内存读写操作
- linux设备驱动的安全端口分配
- Linux字符设备驱动对IO操作有三种方式
- 字符设备驱动基础篇4——字符设备驱动读写接口的操作实践
- LINUX--字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- 开发笔记之20140226
- BUPT OJ89 时间间隔
- linux 驱动调试笔记二----背光
- iOS中查找内存问题
- python中类继承和新式类的写法
- 自己写的linux字符设备驱动读写IO端口
- 项目管理的十大原则
- 关键字const有什么含义?
- BroadcastReceiver子类--AppWidgetProvider(管理桌面控件)之一
- 英语小语
- 《JAVA与模式》之观察者模式
- 深入理解Java:内省(Introspector)
- WinAPI: SetWindowsHookEx - 设置钩子
- 栈、Rails(poj1363)与Catalan数