为什么这里不需要显示使用copy_to_user函数来进行用户空间地址与虚拟地址的转换?

作者: yezhiba 2014-08-25 22:52:10
这个是上飞凌公司FL2440(s3c2440)的ADC实验源代码,为什么这里不需要显示使用copy_to_user函数来进行用户空间地址与虚拟地址的转换?
代码如下:
---------------------------------------------------------
#include
#include

#include
#include
#include

#include
#include
#include


#define ADC_MAJOR 102 //定义主设备号
#define DEVICE_NAME "adc_dev" //定义设备名称
#define SUCCESS 0

#define adc_con (unsigned long)ioremap(0x58000000,4)
#define adc_dat0 (volatile unsigned long)ioremap(0x5800000c,4)

static int Device_Open = 0;

int adc_init(void);
void adc_cleanup(void);
static int device_open(struct inode *,struct file *);
static int device_release(struct inode *,struct file *);
static ssize_t device_read(struct file *,char *,size_t,loff_t *);
int init_module(void);
void cleanup_module(void);


struct file_operations adc_ops = // 该结构包含在
{ //结构中的每个字段指向驱动程序中实现特定的函数
.owner = THIS_MODULE,
.read = device_read,
.open = device_open,
.release = device_release,
};
static int Major;
int __init adc_init(void) //初始化
{

Major = register_chrdev(ADC_MAJOR,DEVICE_NAME,&adc_ops); //注册操作,返回主设备值
if(Major <0)
{
printk("ADC init_module:failed with %d\n",Major); //主设备号小于0,则注册失败
return Major;
}

devfs_mk_cdev(MKDEV(ADC_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);

printk(DEVICE_NAME " initialized\n");

return 0;
}

static int device_open(struct inode * inode,struct file *file) //与应用程序中open函数对应的驱动函数
{
if(Device_Open)
{
return -EBUSY;
}
Device_Open++;
return SUCCESS;
}

static int device_release(struct inode * inode,struct file *file)
{
Device_Open --;
return 0;
}

static ssize_t device_read(struct file *file,
char * buffer,
size_t length,
loff_t * offset)
{
unsigned long buf;
__raw_writel((1<<14)|(0x5<<6), adc_con); //设置ADCCON
__raw_writel(__raw_readl(adc_con)|0x1, adc_con); //启动AD转换;【这里的0x1是否就完成了用户地址与虚拟地址的转变?】
while(__raw_readl(adc_con) &0x1); //启动转换后,等待启动位清零
while(!(__raw_readl(adc_con) & 0x8000)); //等待转换是否完毕
buf=__raw_readl(adc_dat0) & 0x3ff; //取出转换后得到的有效数据
*buffer=(unsigned char)buf;
buffer++;
*buffer=(unsigned char)(buf>>8);
return 2;
}
void adc_cleanup() //卸载驱动时执行该函数
{
int ret;
ret = unregister_chrdev(Major,DEVICE_NAME); //注销驱动
if(ret < 0) //返回值小于0时注销失败
{
printk("unregister_chrdev:error %d\n",ret);
}
}
module_init(adc_init);
module_exit(adc_cleanup);
MODULE_LICENSE("GPL");

相关资讯