FrameBuffer之register_framebuffer

来源:互联网 发布:淘宝卖店铺 编辑:程序博客网 时间:2024/06/06 07:02

我们知道在各个平台上注册自己的fb驱动到kernel中都是通过register_framebuffer来实现的,下面来分析register_framebuffer的实现:

/** *  register_framebuffer - registers a frame buffer device *  @fb_info: frame buffer info structure * *  Registers a frame buffer device @fb_info. * *  Returns negative errno on error, or zero for success. * */intregister_framebuffer(struct fb_info *fb_info){    int ret;    mutex_lock(&registration_lock);    ret = do_register_framebuffer(fb_info);    mutex_unlock(&registration_lock);    return ret;}EXPORT_SYMBOL(register_framebuffer);

这里就是kernl提供给驱动注册的接口,这里的实现还是通过do_register_framebuffer来继续实现的:

static int do_register_framebuffer(struct fb_info *fb_info){    int i, ret;    struct fb_event event;    struct fb_videomode mode;    if (fb_check_foreignness(fb_info))        return -ENOSYS;    ret = do_remove_conflicting_framebuffers(fb_info->apertures,                         fb_info->fix.id,                         fb_is_primary_device(fb_info));    if (ret)        return ret;    if (num_registered_fb == FB_MAX)        return -ENXIO;    num_registered_fb++;    for (i = 0 ; i < FB_MAX; i++)        if (!registered_fb[i])            break;    fb_info->node = i;    atomic_set(&fb_info->count, 1);    mutex_init(&fb_info->lock);    mutex_init(&fb_info->mm_lock);    fb_info->dev = device_create(fb_class, fb_info->device,                 MKDEV(FB_MAJOR, i), NULL, "fb%d", i);    if (IS_ERR(fb_info->dev)) {        /* Not fatal */        printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));        fb_info->dev = NULL;    } else        fb_init_device(fb_info);    if (fb_info->pixmap.addr == NULL) {        fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);        if (fb_info->pixmap.addr) {            fb_info->pixmap.size = FBPIXMAPSIZE;            fb_info->pixmap.buf_align = 1;            fb_info->pixmap.scan_align = 1;            fb_info->pixmap.access_align = 32;            fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;        }    }       fb_info->pixmap.offset = 0;    if (!fb_info->pixmap.blit_x)        fb_info->pixmap.blit_x = ~(u32)0;    if (!fb_info->pixmap.blit_y)        fb_info->pixmap.blit_y = ~(u32)0;    if (!fb_info->modelist.prev || !fb_info->modelist.next)        INIT_LIST_HEAD(&fb_info->modelist);    if (fb_info->skip_vt_switch)        pm_vt_switch_required(fb_info->dev, false);    else        pm_vt_switch_required(fb_info->dev, true);    fb_var_to_videomode(&mode, &fb_info->var);    fb_add_videomode(&mode, &fb_info->modelist);    registered_fb[i] = fb_info;    event.info = fb_info;    if (!lockless_register_fb)        console_lock();    if (!lock_fb_info(fb_info)) {        if (!lockless_register_fb)            console_unlock();        return -ENODEV;    }    fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);    unlock_fb_info(fb_info);    if (!lockless_register_fb)        console_unlock();    return 0;}

接下来需要好好分析一下这段代码的含义:
1> 根据当前注册的fb_info的apertures属性从FrameBuffer驱动数组registered_fb中查询是否存在冲突
2> 判断已注册的驱动是否超过32个FrameBuffer驱动,如果不超过的话,则增加注册驱动的个数方便后面检查
3> 从数组registered_fb中查找空闲元素,用于存储当前注册的fb_info,然后将找到的位置赋值给fb_info->node
4> 初始化当前注册的fb_info的成员信息
5> 通过device_create接口在/dev目录下创建一个fbx的设备文件,次设备号就是该fb_info在数组registered_fb中的索引
6> 初始化fb_info结构体
7> 将初始化好的fb_info注册到registered_fb数组中
8> 使用Linux事件通知机制发送一个FrameBuffer注册事件FB_EVENT_FB_REGISTERED

总结一下这个过程就是将设备输出化的fb_info保存到registered_fb数组中,所以在注册fb_info的时候,其实就是先要构造一个fb_info然后初始化这个结构体,其实这个结构体就是描述的一个Framebuffer驱动。