微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm驱动linux设备地址映射到用户空间

arm驱动linux设备地址映射到用户空间

时间:11-19 来源:互联网 点击:

switch (origin)
{
case SEEK_SET: /*相对文件开始位置偏移*/
if (offset < 0)/*offset不合法*/
{
ret = - EINVAL; /*无效的指针*/
break;
}
if ((unsigned int)offset > VIRTUALDISK_SIZE)/*偏移大于设备内存*/
{
ret = - EINVAL; /*无效的指针*/
break;
}
file->f_pos = (unsigned int)offset; /*更新文件指针位置*/
ret = file->f_pos;/*返回的位置偏移*/
break;
case SEEK_CUR: /*相对文件当前位置偏移*/
if ((file->f_pos + offset) > VIRTUALDISK_SIZE)/*偏移大于设备内存*/
{
ret = - EINVAL;/*无效的指针*/
break;
}
if ((file->f_pos + offset) < 0)/*指针不合法*/
{
ret = - EINVAL;/*无效的指针*/
break;
}
file->f_pos += offset;/*更新文件指针位置*/
ret = file->f_pos;/*返回的位置偏移*/
break;
default:
ret = - EINVAL;/*无效的指针*/
break;
}
return ret;
}
/*设备控制函数:ioctl()函数接受的MEM_CLEAR命令,这个命令将全局内存的有效数据长度清零,对于设备不支持的命令,ioctl()函数应该返回-EINVAL*/
static int module_drv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
struct VirtualDisk *devp = file->private_data;/*获得设备结构体指针*/

switch (cmd)
{
case MEM_CLEAR:/*设备内存清零*/
memset(devp->mem, 0, VIRTUALDISK_SIZE);
printk(KERN_INFO "VirtualDisk is set to zero\n");
break;
default:
return - EINVAL;
}
return 0;
}
/*读函数:读写函数主要是让设备结构体的mem[]数组与用户空间交互数据,并随着访问字节数变更返回用户的文件读写偏移位置*/
static ssize_t module_drv_read(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{

unsigned long p = *ppos; /*记录文件指针偏移位置*/
unsigned int countt = count;/*记录需要读取的字节数*/
int ret = 0; /*返回值*/
struct VirtualDisk *devp = file->private_data; /*获得设备结构体指针*/
printk("module_dev read\n");
/*分析和获取有效的读长度*/
if (p >= VIRTUALDISK_SIZE ) /*要读取的偏移大于设备的内存空间*/
return countt ? - ENXIO: 0;/*读取地址错误*/
if (countt > VIRTUALDISK_SIZE - p)/*要读取的字节大于设备的内存空间*/
countt = VIRTUALDISK_SIZE - p;/*将要读取的字节数设为剩余的字节数*/
/*内核空间->用户空间交换数据*/
if (copy_to_user(buf, (void*)(devp->mem + p), countt))
{
ret = - EFAULT;
}
else
{
*ppos += countt;
ret = countt;
printk("read %d bytes(s) is %ld\n", countt, p);
}
printk("bytes(s) is %s\n", buf);
return ret;
}
/*
file 是文件指针,count 是请求的传输数据长度,buff 参数是指向用户空间的缓冲区,这个缓冲区或者保存要写入的数据,或者是一个存放新读入数据的空缓冲区,该地址在内核空间不能直接读写,ppos 是一个指针指向一个"long offset type"对象, 它指出用户正在存取的文件位置. 返回值是一个"signed size type。写的位置相对于文件开头的偏移。
*/
static ssize_t module_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{

unsigned long p = *ppos; /*记录文件指针偏移位置*/
int ret = 0; /*返回值*/
unsigned int countt = count;/*记录需要写入的字节数*/
struct VirtualDisk *devp = file->private_data; /*获得设备结构体指针*/
printk("module_dev write\n");
/*分析和获取有效的写长度*/
if (p >= VIRTUALDISK_SIZE )/*要写入的偏移大于设备的内存空间*/
return countt ? - ENXIO: 0;/*写入地址错误*/
if (countt > VIRTUALDISK_SIZE - p)/*要写入的字节大于设备的内存空间*/
countt = VIRTUALDISK_SIZE - p;/*将要写入的字节数设为剩余的字节数*/
/*用户空间->内核空间*/
if (copy_from_user(devp->mem + p, buf, countt))
ret = - EFAULT;
else
{
*ppos += countt;/*增加偏移位置*/
ret = countt;/*返回实际的写入字节数*/
printk("written %d bytes(s) from%ld\n", countt, p);
}
return ret;
return 0;
}
static int memdev_mmap(struct file*file, struct vm_area_struct *vma){
struct VirtualDisk *devp = file->private_data; /*获得设备结构体指针*/
vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED;
if (remap_pfn_range(vma,vma->vm_start,virt_to_phys(devp->mem)>>PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;

return 0;
}
static struct file_operations module_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = module_drv_open,
.read = module_drv_read,
.write = module_drv_write,
.release = module_drv_release,
.llseek = module_drv_llseek,
.ioctl = module_drv_ioctl,
.mmap = memdev_mmap,
};
/*将 cdev 结构嵌入一个你自己的设备特定的结构,你应当初始化你已经分配的结构使用以上函数,有一个其他的 struct cdev 成员你需要初始化. 象 file_operations 结构,struct cdev 有一个拥有者成员,应当设置为 THIS_MODULE,一旦 cdev 结构建立, 最后的步骤是把它告诉内核, 调用:
cdev_add(&dev->cdev, devno, 1);*/
static void VirtualDisk_setup_cdev(struct VirtualDisk *dev, int minorIndex){
int err;
int devno = MKDEV(VirtualDisk_major, minorIndex);
cdev_init(&dev->cdev, &module_drv_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if(err){
printk("error %d cdev file added\n", err);
}
}
static int module_drv_init(void)
{
int result;
dev_t devno = MKDEV(VirtualDisk_major, 0);
if(VirtualDisk_major){
result =

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top