1、看一个驱动程序-从入口函数开始
1.1 确定主设备号
1.2 构造file_operation结构体填充open read write 等成员函数
1.3 注册驱动
1.4 入口函数
1.5 出口函数
2、open过程分析
app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
.open = fb_open,
/*根据/dev/fb0得到这个设备节点的次设备号*/
int fbidx = iminor(inode);
//跟硬件相关的结构体
struct fb_info *info;
//根据这个设备节点的次设备号fbidx获得一个struct fb_info结构体
info = get_fb_info(fbidx);
//次设备号为:fbidx = 0
//取出registered_fb“以次设备号为0”的一项:registered_fb[0]
fb_info = registered_fb[idx];
//如果这个info = register_fd[0]的fbops有fb_open函数时就调用fb_open
if (info->fbops->fb_open)
res = info->fbops->fb_open(info,1);
3、read函数
app: read()
---------------------------------------------------------------
kernel:
.read = fb_read,
static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
//从这个文件当中获得硬件相关的fb_info结构体
struct fb_info *info = file_fb_info(file);
//如果提供了硬件相关的写函数就调用这个read
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, count, ppos);
//如果没有提供info选项
//分配一个缓冲区
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,GFP_KERNEL);
//screen_base:显存的基地址; 这里读源src 等于 显存的基地址+偏移量
src = (u8 __iomem *) (info->screen_base + p);
//一句话把用户空间的数据复制到buffer中,然后将buffer的数据复制到显存的基地址screen_base
while (count)
{
//如果count大于PAGE_SIZE 返回PAGE_SIZE 否则返回count
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
//上边使用kmalloc分配的buffer
dst = buffer;
fb_memcpy_fromfb(dst, src, c);
dst += c;
src += c;
//把数据拷贝到用户空间
if (copy_to_user(buf, buffer, c)) {
err = -EFAULT;
break;
}
*ppos += c;
buf += c;
cnt += c;
count -= c;
}
4、fb_info结构体
从上边的分析过程可知open和read函数都依赖一个fb_info结构体,这个结构体通过registered_fb[fbidx];得到。
5、 fbmem.c框架
Fbmem.c 提供的都是抽象出来的东西。最终都得依赖这个“registered_fb”数组里的“fb_info”结构体。
底层的s3c2410fb.c在pro函数中通过调用register_framebuffer实现注册fb_info结构体