linux lcd驱动分析四

来源:互联网 发布:淘宝互动平台在哪看 编辑:程序博客网 时间:2024/04/30 23:57

前面的probe函数已经分析完了,但是我们还是不明白帧缓冲设备到底是一个什么样的设备,这一节我们将得到答案。

   1657 /**
   1658  *      fbmem_init - init frame buffer subsystem
   1659  *
   1660  *      Initialize the frame buffer subsystem.
   1661  *
   1662  *      NOTE: This function is _only_ to be called by drivers/char/mem.c.
   1663  *
   1664  */
   1665
   1666 static int __init
   1667 fbmem_init(void)
   1668 {
   1669         proc_create("fb", 0, NULL, &fb_proc_fops);
   1670
   1671         if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
   1672                 printk("unable to get major %d for fb devs\n", FB_MAJOR);
   1673
   1674         fb_class = class_create(THIS_MODULE, "graphics");
   1675         if (IS_ERR(fb_class)) {
   1676                 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
   1677                 fb_class = NULL;
   1678         }
   1679         return 0;
   1680 }

fbmem_init中注册了一个字符设备,并且创建了一个class。

   1685 fbmem_exit(void)
   1686 {
   1687         remove_proc_entry("fb", NULL);
   1688         class_destroy(fb_class);
   1689         unregister_chrdev(FB_MAJOR, "fb");
   1690 }

那么在它的注销函数中当然是做了相反的工作,释放这个class和注销这个字符设备。

既然这里注册了一个字符设备,那我们就去看看这个字符设备相关定义。

1. major

FB_MAJOR定义在inclue/linux/major.h中。

     56 #define FB_MAJOR                29   /* /dev/fb* framebuffers */

说明这个字符设备的主设备号为29。

2. file_operations

   1424 static const struct file_operations fb_fops = {
   1425         .owner =        THIS_MODULE,
   1426         .read =         fb_read,
   1427         .write =        fb_write,
   1428         .unlocked_ioctl = fb_ioctl,
   1429 #ifdef CONFIG_COMPAT
   1430         .compat_ioctl = fb_compat_ioctl,
   1431 #endif
   1432         .mmap =         fb_mmap,
   1433         .open =         fb_open,
   1434         .release =      fb_release,
   1435 #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
   1436         .get_unmapped_area = get_fb_unmapped_area,
   1437 #endif
   1438 #ifdef CONFIG_FB_DEFERRED_IO
   1439         .fsync =        fb_deferred_io_fsync,
   1440 #endif
   1441 };

再看看我们调用register_framebuffer注册一个帧缓冲设备时发生了什么事情。

   1481 /**
   1482  *      register_framebuffer - registers a frame buffer device
   1483  *      @fb_info: frame buffer info structure
   1484  *
   1485  *      Registers a frame buffer device @fb_info.
   1486  *
   1487  *      Returns negative errno on error, or zero for success.
   1488  *
   1489  */
   1490
   1491 int
   1492 register_framebuffer(struct fb_info *fb_info)
   1493 {
   1494         int i;
   1495         struct fb_event event;
   1496         struct fb_videomode mode;
   1497
   1498         if (num_registered_fb == FB_MAX)
   1499                 return -ENXIO;
   1500
   1501         if (fb_check_foreignness(fb_info))
   1502                 return -ENOSYS;
   1503
   1504         /* check all firmware fbs and kick off if the base addr overlaps */
   1505         for (i = 0 ; i < FB_MAX; i++) {
   1506                 if (!registered_fb[i])

   1507                         continue;
   1508
   1509                 if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) {
   1510                         if (fb_do_apertures_overlap(registered_fb[i], fb_info)) {
   1511                                 printk(KERN_ERR "fb: conflicting fb hw usage "
   1512                                        "%s vs %s - removing generic driver\n",
   1513                                        fb_info->fix.id,
   1514                                        registered_fb[i]->fix.id);
   1515                                 unregister_framebuffer(registered_fb[i]);
   1516                                 break;
   1517                         }
   1518                 }
   1519         }
   1520
   1521         num_registered_fb++;
   1522         for (i = 0 ; i < FB_MAX; i++)
   1523                 if (!registered_fb[i])
   1524                         break;
   1525         fb_info->node = i;
   1526         mutex_init(&fb_info->lock);
   1527         mutex_init(&fb_info->mm_lock);
   1528
   1529         fb_info->dev = device_create(fb_class, fb_info->device,
   1530                                      MKDEV(FB_MAJOR, i), NULL, "fb%d", i);

   1531         if (IS_ERR(fb_info->dev)) {
   1532                 /* Not fatal */
   1533                 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR        _ERR(fb_info->dev));
   1534                 fb_info->dev = NULL;
   1535         } else
   1536                 fb_init_device(fb_info);
   1537
   1538         if (fb_info->pixmap.addr == NULL) {
   1539                 fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
   1540                 if (fb_info->pixmap.addr) {
   1541                         fb_info->pixmap.size = FBPIXMAPSIZE;
   1542                         fb_info->pixmap.buf_align = 1;
   1543                         fb_info->pixmap.scan_align = 1;
   1544                         fb_info->pixmap.access_align = 32;
   1545                         fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
   1546                 }
   1547         }
   1548         fb_info->pixmap.offset = 0;
   1549
   1550         if (!fb_info->pixmap.blit_x)
   1551                 fb_info->pixmap.blit_x = ~(u32)0;
   1552
   1553         if (!fb_info->pixmap.blit_y)
   1554                 fb_info->pixmap.blit_y = ~(u32)0;

   1555
   1556         if (!fb_info->modelist.prev || !fb_info->modelist.next)
   1557                 INIT_LIST_HEAD(&fb_info->modelist);
   1558
   1559         fb_var_to_videomode(&mode, &fb_info->var);
   1560         fb_add_videomode(&mode, &fb_info->modelist);
   1561         registered_fb[i] = fb_info;
   1562
   1563         event.info = fb_info;
   1564         if (!lock_fb_info(fb_info))
   1565                 return -ENODEV;
   1566         fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
   1567         unlock_fb_info(fb_info);
   1568         return 0;
   1569 }

直接到for循环。

   1504         /* check all firmware fbs and kick off if the base addr overlaps */
   1505         for (i = 0 ; i < FB_MAX; i++) {
   1506                 if (!registered_fb[i])
   1507                         continue;
   1508
   1509                 if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) {
   1510                         if (fb_do_apertures_overlap(registered_fb[i], fb_info)) {
   1511                                 printk(KERN_ERR "fb: conflicting fb hw usage "
   1512                                        "%s vs %s - removing generic driver\n",
   1513                                        fb_info->fix.id,
   1514                                        registered_fb[i]->fix.id);
   1515                                 unregister_framebuffer(registered_fb[i]);
   1516                                 break;
   1517                         }
   1518                 }
   1519         }

registered_fb它是一个数组,它的类型就是struct fb_info,它用于保存我们调用register_framebuffer传进来的struct fb_info。

num_registered_fb代表注册帧缓冲设备的个数。

   1522         for (i = 0 ; i < FB_MAX; i++)
   1523                 if (!registered_fb[i])
   1524                         break;
   1525         fb_info->node = i;

找到一个空的次设备号。

   1529         fb_info->dev = device_create(fb_class, fb_info->device,
   1530                                      MKDEV(FB_MAJOR, i), NULL, "fb%d", i);

在dev下创建设备节点。

然后对struct fb_info做了一些初始化。

最后将我们这个struct fb_info添加到registered_fb数组里面。

从这里我们可以理解到,其实帧缓冲设备它就是一个字符设备,它也有相关的file_operations操作。从这里我们也能大致明白帧缓冲设备的应用程序该如何编写,肯定也是先调用open打开这个字符设备,最后调用close关闭这个字符设备,至于是如何往显存里写数据将在以后介绍。像linux下GUI程序都是这样实现的,只不过它向上封装了API,供更上一级的应用程序开发者调用。