免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1500 | 回复: 0
打印 上一主题 下一主题

[转载]Framebuffer device驱动程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-19 14:50 |只看该作者 |倒序浏览

                来源:电子开发网
引用:http://www.dzkf.cn/html/qianrushixitong/2007/0429/2025.html
---------------------------------------------------------------------------
                                                                    
    引言
    framebufferdevice在内核里面作为显卡驱动模型,许多函数和数据结构都是特定,正是这些特定的东西为我们的编程提供了方便。要开发frame bufferdevice驱动,你应该阅读Source\Source\Documentation\fb下面的说明文件,三个重要文件00-INDEX,framebuffer.txt,internals.txt,其他文件都是针对具体显卡芯片的说明了。
    文件00-INDEX译文文档/documentation/fb的索引文件。如果你对frame buffer设备有什么想法,mail:GeertUytterhoeven
    framebuffer.txt --- frame buffer 设备介绍
    internals.txt ------ frame buffer设备内部快速浏览
    modedb.txt ------- 关于视频模式的资料
    aty128fb.txt ------ 关于ATI Rage128显卡的frame buffer设备
    clgenfb.txt ------- 关于Cirrus Logic的显卡
    matroxfb.txt ----- 关于Matrox的显卡
    pvr2fb.txt -------- 关于PowerVR 2的显卡
    tgafb.txt -------- 关于TGA(DECChip 21030)显卡
    vesafb.txt ------- 关于VESA显卡
    帧缓冲设备(framebuffer.txt译文)维护: Geert Uytterhoeven
    最后校正: May 10, 2001
    翻译:
    good02xaut@hotmail.com
    0.介绍
    帧缓冲设备提供了显卡的抽象描述。他同时代表了显卡上的显存,应用程序通过定义好的接口可以访问显卡,而不需要知道底层的任何操作。该设备使用特殊的设备节点,通常位于/dev目录,如/dev/fb*.
    1.用户角度的/dev/fb*
    从用户的角度看,帧缓冲设备和其他位于/dev下面的设备类似。他是一个字符设备,通常主设备号是29,次设备号定义帧缓冲的个数。
    通常,使用如下方式(前面的数字代码次设备号)
    0 = /dev/fb0 First frame buffer
    1 = /dev/fb1 Second frame buffer
    ...
    31 = /dev/fb31 32nd frame buffer
    考虑到向下兼容,你可以创建符号链接:
    /dev/fb0current -> fb0
    /dev/fb1current -> fb1
    and so on...
    帧缓冲设备也是一种普通的内存设备,你可以读写其内容。例如,对屏幕抓屏:
    cp /dev/fb0 myfile
    你也可以同时有多个显示设备,例如你的主板上出了内置的显卡还有另一独立的显卡。对应的帧缓冲设备(/dev/fb0 and /dev/fb1etc.)可以独立工作。
    应用程序如 Xserver一般使用/dev/fb0作为默认的显示帧缓冲区。你可以自定把某个设备作为默认的帧缓冲设备,设置$FRAMEBUFFER环境变量即可。在sh/bash:
    export FRAMEBUFFER=/dev/fb1
    在csh中:
    setenv FRAMEBUFFER /dev/fb1
    设定后,X server将使用第二个帧缓冲区设备。
    2.程序员角度看/dev/fb*
    正如你所知,一个帧缓冲设备和内存设备类似/dev/mem,并且有许多共性。你可以read,write,seek以及mmap()。不同仅仅是帧缓冲的内存不是所有的内存区,而是显卡专用的那部分内存。
    /dev/fb*也允许尽行ioctl操作,通过ioctl可以读取或设定设备参数。颜色映射表也是通过Ioctl设定。查看就知道有多少ioctl应用以及相关数据结构。
    这里给出摘要:
    - 你可以获取设备一些不变的信息,如设备名,屏幕的组织(平面,象素,...)对应内存区 的长度和起始地址。
    - 也可以获取能够发生变化的信息,例如位深,颜色格式,时序等。如果你改变这些值,驱动程序将对值进行优化,以满足设备特性(返回EINVAL,如果你的设定,设备不支持)
    - 你也可以获取或设定部分颜色表。
    所有这些特性让应用程序十分容易的使用设备。X server可以使用/dev/fb*而不需知道硬件的寄存器是如何组织的。XF68_FBDev是一个用于位映射(单色)X server,唯一要做的就是在应用程序在相应的位置设定是否显示。
    在新内核中,帧缓冲设备可以工作于模块中,允许动态加载。这类驱动必须调用register_framebuffer()在系统中注册。使用模块更方便!
    [color="#993300"]3.帧缓冲分辨率设定
    帧缓冲的分辨率可以用工具fbset设定。他可以改变视频设备的显示模式。主要就是改变当前视频模式,如在启动过程中,在/etc/rc.* 或/etc/init.d/* 文件中调用,可以把视频模式从单色显示变成真彩.
    fbset使用存储在配置文件中的视频模式数据表,你可以在文件中增加自己需要的显示模式。
    [color="#993300"]4.X Server
    X server (XF68_FBDev)是对帧缓冲设备的最主要应用。从XFree86  3.2后,Xserver就是XFree86 的一部分了,有2个工作模式:
      - 在/etc/XF86Config文件中,如果`Display'段关于 `fbdev'的配置:
        Modes "default"
        X server将使用前面讨论的,从环境变量$FRAMEBUFFER获取当前帧缓冲设备.
       你也可以设定颜色位深,使用Depth关键字,使用Virtual设定虚拟分辨率。这也是默认设置。
      -然而你也可以通过设定/etc/XF86Config,改变分辨率。这样有很多灵活性,唯一的    不足就是你必须设定刷新频率。可以用fbset -x通过fbset或xvidtune切换显示模式。
    [color="#993300"]5.视频模式频率
    CRT显示器是用3个电子枪轰击磷粉完成颜色的显示的。电子枪从左到右的水平扫描,并从上至下的垂直扫描。通过改变枪的电压,所显示的颜色可以不同。当电子枪完成一行扫描重新回到下一行的开始,被称作“水平折回”。当一屏幕全部扫描完毕,电子枪将回到最左上脚,被成为“垂直折回”。在折回的途中电子枪是关闭的。电子枪打点的移动速度取决于点时钟。如果点时钟是28.37516 MHz,打一个点需要35242 ps。
        1/(28.37516E6 Hz) = 35.242E-9 s
    如果屏幕分辨率是640x480,那么一行的时间是:
           640*35.242E-9 s = 22.555E-6 s
    然而水平折回也是需要时间的,通常272个打点时间,因此一行总共需要:
           (640+272)*35.242E-9 s = 32.141E-6 s
    我们就认为水平扫描的频率是31KHz:      
           1/(32.141E-6 s) = 31.113E3 Hz
    一屏幕含有480行,加上垂直折回时间49,一屏所需的时间:
           (480+49)*32.141E-6 s = 17.002E-3 s
    我们就认为垂直扫描的频率是59Hz:
           1/(17.002E-3 s) = 58.815 Hz
    这也意味着屏幕数据每秒钟刷新59次。为了得到稳定的图像显示效果,VESA垂直扫描频率不低于72Hz。但是也因人而异,有些人50Hz感觉不到任何问题,有些至少在80Hz以上才可以。
    由于显示器不知道什么时候新行开始扫描,显卡为每一行扫描提供水平同步信号。类似的,他也为每一帧显示提供垂直同步信号。图像在屏幕上点的位置取决于这些同步信号的发生时刻。下图给出了所有时序的概要。水平折回的时间就是左边空白+右边空白+水平同步长度。垂直折回的时间就是上空白+下空白+垂直同步长。

    +----------+---------------------------------------------+----------+-------+

    |         
    |               
    ^                           
    |         
    |       |

    |         
    |               
    |upper_margin               
    |         
    |       |

    |         
    |               
    ?                       
       
    |         
    |       |

    +----------###############################################----------+-------+

    |         
    #               
    ^                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |
      |   left  
    #               
    |                           
    #  right   | hsync |
      |  margin
    #               
    |      
    xres               
    #  margin  |  len  |

    |##||

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |yres                       
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    |                           
    #         
    |       |

    |         
    #               
    ?                     
       
    #         
    |       |

    +----------###############################################----------+-------+

    |         
    |               
    ^                           
    |         
    |       |

    |         
    |               
    |lower_margin               
    |         
    |       |

    |         
    |               
    ?                     
       
    |         
    |       |

    +----------+---------------------------------------------+----------+-------+

    |         
    |               
    ^                           
    |         
    |       |

    |         
    |               
    |vsync_len                  
    |         
    |       |

    |         
    |               
    ?                     
       
    |         
    |       |

    +----------+---------------------------------------------+----------+-------+
    [color="#993300"]6.把XFree86时序变成frame buffer device时序
    [color="#993300"]典型的显示模式:
      "800x600"    50      800 856  976 1040    600 637  643  666
        DCF      HR  SH1  SH2 HFL     VR  SV1 SV2  VFL   
    而帧缓冲设备使用下面的参数:
      - pixclock: 点时钟 in ps (pico seconds)
      - left_margin: time from sync to picture
      - right_margin: time from picture to sync
      - upper_margin: time from sync to picture
      - lower_margin: time from picture to sync
      - hsync_len: length of horizontal sync
      - vsync_len: length of vertical sync
    1) Pixelclock:
       xfree: in MHz
       fb: in picoseconds (ps)
       pixclock = 1000000 / DCF
    2) horizontal timings:
       left_margin = HFL - SH2
       right_margin = SH1 - HR
       hsync_len = SH2 - SH1
    3) vertical timings:
       upper_margin = VFL - SV2
       lower_margin = SV1 - VR
       vsync_len = SV2 - SV1
    更好的VESA的例子可以在XFree86的源码中找到,"xc/programs/Xserver/hw/xfree86/doc/modeDB.txt".
    [color="#993300"]7. 引用[color="#993300"]获取更多关于帧缓冲设备以及应用的参考,请访问:   
    http://linux-fbdev.sourceforge.net/
    或者查阅下面的文档:
      - The manual pages for fbset: fbset(8), fb.modes(5)
      - The manual pages for XFree86: XF68_FBDev(1),XF86Config(4/5)
      - The mighty kernel sources:
          olinux/drivers/video/
          olinux/include/linux/fb.h
          olinux/include/video/   
    帧缓冲设备的内部数据结构(internals.txt)
    Geert Uytterhoeven ,21 July 1998
    翻译:
    good02xaut@hotmail.com
          ××××帧缓冲设备中用到的结构体××××
    以下数据结构在帧缓冲设备使用,定义。  
    1.Outside the kernel (user space)
        
    • struct fb_fix_screeninfo
         帧缓冲设备中设备无关的常值数据信息。可以通过Ioctl的FBIOGET_FSCREENINFO获取。  
    • struct fb_var_screeninfo
         帧缓冲设备中设备无关的变量数据信息和特定的显示模式。可以通过iotcl的FBIOGET_VSCREENINFO获取,并通过ioctl的FBIOPUT_VSCREENINFO设定。还有FBIOPAN_DISPLAY可以用。  
    • struct fb_cmap
          设备无关的颜色表信息。你可以通过ioctl的FBIOGETCMAP 和FBIOPUTCMAP读取或设定。
    2. Inside the kernel
        
    • struct fb_info
          常规信息,API以及帧缓冲设备的底层信息(主板地址...).  
    • struct `par'
          唯一指定该设备的显示模式的设备相关信息。  
    • struct display
          帧缓冲设备和控制台驱动之间的接口。

    --------------------------------------------------------------------------------
           ***  常用的帧缓冲 API  ***
    Monochrome (FB_VISUAL_MONO01 and FB_VISUAL_MONO10)
    -------------------------------------------------
    每个象素是黑或白。
    Pseudo color (FB_VISUAL_PSEUDOCOLOR and FB_VISUAL_STATIC_PSEUDOCOLOR)
    ---------------------------------------------------------------------
    索引颜色显示
    True color (FB_VISUAL_TRUECOLOR)
    --------------------------------
    真彩显示,分成红绿兰三基色
    Direct color (FB_VISUAL_DIRECTCOLOR)
    ------------------------------------
    每个象素颜色也是有红绿蓝组成,不过每个颜色值是个索引,需要查表。
    Grayscale displays
    ------------------
    灰度显示,红绿蓝的值都一样
    准备开始写我们自己的驱动之前,请详细阅读如下文件:
    \Documentation\fb目录  vesafb.txt,matroxfb.txt,sa1100fb.txt
    \drivers\video目录          fbmem.c,fbgen.c,fbmon.c,fbcmap.c
                                          skeletonfb.c
                                          vesafb.c,sa1100fb.c,sa1100fb.h
    include\linux目录            fb.h
    最值得关注的是skeletonfb.c,该文件给出了一个fb device 驱动的框架。准备好了,就开始写自己的fram bufferdevice driver:)
    还是要补充点,下面是/linux/fb.h的部分注释,加粗的是常用的,红色是关键的,一般不可少。旁边没有汉字,要么很简单没必要加注,要么就用不到!注释:
    good02xaut@hotmail.com
    #ifndef _LINUX_FB_H
    #define _LINUX_FB_H
    #include
    #include
    /* Definitions of framebuffers                    */
    [color="#ff0000"]#defineFB_MAJOR       29  /*主设备号*/
    #defineFB_MAX         32  /* sufficient for now */
    /* ioctls
       0x46 is'F'                             */
    [color="#ff0000"]#define FBIOGET_VSCREENINFO 0x4600
    #define FBIOPUT_VSCREENINFO 0x4601
    #define FBIOGET_FSCREENINFO 0x4602
    #define FBIOGETCMAP     0x4604
    #define FBIOPUTCMAP     0x4605
    #define FBIOPAN_DISPLAY     0x4606
    /* 0x4607-0x460B are defined below */
    /* #define FBIOGET_MONITORSPEC  0x460C */
    /* #define FBIOPUT_MONITORSPEC  0x460D */
    /* #define FBIOSWITCH_MONIBIT   0x460E */
    #define FBIOGET_CON2FBMAP   0x460F
    #define FBIOPUT_CON2FBMAP   0x4610
    #defineFBIOBLANK      0x4611      /* arg: 0 orvesa level + 1 */
    #defineFBIOGET_VBLANK     _IOR('F', 0x12, struct fb_vblank)
    #defineFBIO_ALLOC             0x4613
    #defineFBIO_FREE              0x4614
    #defineFBIOGET_GLYPH          0x4615
    #defineFBIOGET_HWCINFO        0x4616
    #defineFBIOPUT_MODEINFO       0x4617
    #defineFBIOGET_DISPINFO       0x4618
    [color="#ff0000"]#defineFB_TYPE_PACKED_PIXELS      0   /* Packed Pixels    */
    #defineFB_TYPE_PLANES         1   /* Non interleaved planes */
    #define FB_TYPE_INTERLEAVED_PLANES  2   /*Interleaved planes   */
    #defineFB_TYPE_TEXT           3   /* Text/attributes  */
    #defineFB_TYPE_VGA_PLANES     4   /* EGA/VGA planes   */
    #define FB_AUX_TEXT_MDA    0   /* Monochrome text */
    #define FB_AUX_TEXT_CGA    1   /* CGA/EGA/VGA Color text */
    #define FB_AUX_TEXT_S3_MMIO 2   /* S3 MMIO fasttext */
    #define FB_AUX_TEXT_MGA_STEP16  3   /* MGAMillenium I: text, attr, 14 reserved bytes */
    #define FB_AUX_TEXT_MGA_STEP8   4  /* other MGAs:      text,attr,  6 reserved bytes */
    #defineFB_AUX_VGA_PLANES_VGA4     0   /* 16 color planes (EGA/VGA) */
    #defineFB_AUX_VGA_PLANES_CFB4     1   /* CFB4 in planes (VGA) */
    #defineFB_AUX_VGA_PLANES_CFB8     2   /* CFB8 in planes (VGA) */
    [color="#ff0000"]#defineFB_VISUAL_MONO01       0   /* Monochr. 1=Black 0=White */
    #defineFB_VISUAL_MONO10       1   /* Monochr. 1=White 0=Black */
    #define FB_VISUAL_TRUECOLOR    2   /* True color   */
    #defineFB_VISUAL_PSEUDOCOLOR      3   /* Pseudo color (like atari) */
    #defineFB_VISUAL_DIRECTCOLOR      4   /* Direct color */
    #define FB_VISUAL_STATIC_PSEUDOCOLOR   5   /* Pseudo color readonly */
    #defineFB_ACCEL_NONE      0   /* no hardware accelerator  */
    #define FB_ACCEL_ATARIBLITT 1   /* AtariBlitter       */
    #define FB_ACCEL_AMIGABLITT 2   /* AmigaBlitter               */
    #define FB_ACCEL_S3_TRIO64  3   /*Cybervision64 (S3 Trio64)    */
    #define FB_ACCEL_NCR_77C32BLT   4  /* RetinaZ3 (NCR77C32BLT)      */
    #define FB_ACCEL_S3_VIRGE   5   /*Cybervision64/3D (S3 ViRGE)  */
    #define FB_ACCEL_ATI_MACH64GX   6  /* ATI Mach 64GX family     */
    #define FB_ACCEL_DEC_TGA   7   /* DEC 21030TGA       */
    #define FB_ACCEL_ATI_MACH64CT   8  /* ATI Mach 64CT family     */
    #define FB_ACCEL_ATI_MACH64VT   9  /* ATI Mach 64CT family VT class */
    #define FB_ACCEL_ATI_MACH64GT   10  /* ATIMach 64CT family GT class */
    #define FB_ACCEL_SUN_CREATOR    11 /* Sun Creator/Creator3D    */
    #define FB_ACCEL_SUN_CGSIX  12  /* Suncg6         */
    #define FB_ACCEL_SUN_LEO    13  /*Sunleo/zx          */
    #define FB_ACCEL_IMS_TWINTURBO  14  /* IMS TwinTurbo       */
    #define FB_ACCEL_3DLABS_PERMEDIA2 15    /*3Dlabs Permedia2       */
    #define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W(Millenium)  */
    #define FB_ACCEL_MATROX_MGA1064SG 17    /*Matrox MGA1064SG (Mystique)  */
    #define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */
    #define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (MilleniumII) */
    #define FB_ACCEL_MATROX_MGAG100 20  /* Matrox G100 (ProductivaG100) */
    #define FB_ACCEL_MATROX_MGAG200 21  /* Matrox G200 (Myst,Mill, ...) */
    #define FB_ACCEL_SUN_CG14   22  /* Suncgfourteen      */
    #define FB_ACCEL_SUN_BWTWO  23  /* Sunbwtwo           */
    #define FB_ACCEL_SUN_CGTHREE    24 /* Suncgthree         */
    #define FB_ACCEL_SUN_TCX    25  /*Suntcx         */
    #define FB_ACCEL_MATROX_MGAG400 26  /* MatroxG400         */
    #defineFB_ACCEL_NV3       27  /* nVidia RIVA128             */
    #defineFB_ACCEL_NV4       28  /* nVidia RIVATNT      */
    #defineFB_ACCEL_NV5       29  /* nVidia RIVATNT2     */
    #define FB_ACCEL_CT_6555x   30  /*C&T6555x           */
    #define FB_ACCEL_3DFX_BANSHEE   31  /* 3DfxBanshee        */
    #define FB_ACCEL_ATI_RAGE128    32 /* ATI Rage128family       */
    #define FB_ACCEL_IGS_CYBER2000  33  /* CyberPro2000       */
    #define FB_ACCEL_IGS_CYBER2010  34  /* CyberPro2010       */
    #define FB_ACCEL_IGS_CYBER5000  35  /* CyberPro5000       */
    #define FB_ACCEL_SIS_GLAMOUR    36 /* SiS300/630/540             */
    #define FB_ACCEL_3DLABS_PERMEDIA3 37    /*3Dlabs Permedia3       */
    /*上面的宏定义不用关心*/
    /*不可修改的屏幕信息,用户空间可见*/
    struct fb_fix_screeninfo {
       [color="#ff0000"]charid[16];        /* identification string eg "TT Builtin" */
        unsigned longsmem_start;   /* Start of frame buffer mem 显存的起始地址*/
                     /* (physical address) */
    [color="#ff0000"]   __u32smem_len;         /* Length of frame buffer mem 显存的大小 */
        __u32type;         /* see FB_TYPE_*     */
        __u32type_aux;         /* Interleave for interleaved Planes */
        __u32visual;       /* seeFB_VISUAL_*      */
        __u16xpanstep;         /* zero if no hardware panning  */
        __u16ypanstep;         /* zero if no hardware panning  */
        __u16ywrapstep;     /* zero if nohardware ywrap    */
    [color="#ff0000"]   __u32line_length;      /* length of a line in bytes  每行的字节数  */
        unsigned longmmio_start;   /* Start of Memory MappedI/O   */
                     /* (physical address) */
        __u32mmio_len;         /* Length of Memory Mapped I/O  */
        __u32accel;          /* Type of acceleration available */
        __u16reserved[3];      /* Reserved for future compatibility */
    };

    /* Interpretation of offset for color fields: All offsets arefrom the right,
    * inside a "pixel" value, which is exactly 'bits_per_pixel' wide(means: you
    * can use the offset as right argument to Framebuffer 驱动程序模型
      下图会向你展示目前的framebuffer设备驱动的结构,最常用的是非标准驱动。很明显他所处的层次最高,程序编写是最容易的。理解了这个图的,你已经很轻松的去完成一个fb驱动,比如给sa1100,s2410,s2440系列的ARM的LCD控制器写驱动。

    图1
    Color Map 剖析在framebuffer驱动程序设计中,cmap这个东东太晕了。现在我要把他赤裸裸的剖析给大家:)
    1. struct fb_cmap

    图2
    /*颜色映射表*/
    struct fb_cmap {
           __u32start;                 /* First entry   */
           __u32len;                   /* Number of entries */
           __u16*red;                 /* 红色   */
           __u16*green;              /*绿色*/
           __u16*blue;                /*蓝色*/
           __u16*transp;                    /* 透明度,允许 NULL */
    };
    该结构在fb.h文件中定义,在struct fb_ops结构中有两个成员函数与其相关:
        /*获取颜色表*/
        int (*fb_get_cmap)(struct fb_cmap *cmap,int kspc, int con, struct fb_info *info);
        /*设定颜色表*/
        int (*fb_set_cmap)(struct fb_cmap *cmap,int kspc, int con, struct fb_info *info);
    在struct fb_info结构中有变量:
      struct fb_cmapcmap;                /* Current cmap */
    在fpgen基础操作下提供:
    extern int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con,struct fb_info *info);
    extern int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con,struct fb_info *info);
    在文件/* drivers/video/fbcmap.c */中提供更多的cmap应用
    extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
    extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, intfsfromto);
    extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,
    int (*getcolreg)(u_int, u_int *, u_int *, u_int *,u_int *, structfb_info *),
                                   struct fb_info *fb_info);
    extern int fb_set_cmap(struct fb_cmap *cmap, int kspc,
                                 int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,struct fb_info *),
                                 struct fb_info *fb_info);
    extern struct fb_cmap *fb_default_cmap(int len);
    extern void fb_invert_cmaps(void);
    2.通过文件解析在anakinfb.c文件中,cmap如图
    [color="#993300"]


    图3

    图4
    在stifb.c

    图5
    本文介绍的设备是位于/video目录下面的anakinfb.c驱动程序。虽然我不清楚那个设备的特性,但是从对程序的分析中我们仍然知道如何编写一个frame buffer设备驱动。
       本文是个标准的fb驱动。共221行,包含函数如下:
      
  • static int  anakinfb_getcolreg(u_int regno, u_int*red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info)31行  
  • static int anakinfb_setcolreg(u_int regno, u_int red, u_intgreen, u_int blue,u_int transp, struct fb_info *info) 45行  
  • static int anakinfb_get_fix(struct fb_fix_screeninfo *fix,int con, struct fb_info *info) 57行  
  • static int anakinfb_get_var(struct fb_var_screeninfo *var,int con, struct fb_info *info) 75行  
  • static int anakinfb_set_var(struct fb_var_screeninfo *var,int con, struct fb_info *info) 111行  
  • static int anakinfb_get_cmap(struct fb_cmap *cmap, intkspc, int con,     struct fb_info*info) 117行  
  • static int anakinfb_set_cmap(struct fb_cmap *cmap, intkspc, int con,     struct fb_info*info) 130行  
  • static int anakinfb_switch_con(int con, struct fb_info*info) 147行  
  • static int anakinfb_updatevar(int con, struct fb_info*info) 155行  
  • static void anakinfb_blank(int blank, struct fb_info *info)161行  
  • int __init anakinfb_init(void) 178行函数1,2是寄存器操作用。函数3,4,5,6,7是fb_ops函数。函数8用于切换控制台。函数9用于更新变量。函数10用于闪烁屏幕。函数11用于初始化设备。
       很奇怪,对fb设备的读写函数怎么没有!值得说明的是open,release,read,write,ioctl,mmap等函数的实现是由fbmem.c文件实现了。也就是说所有的fb设备在给定了fb_info后,所有的操作都是一样的。在明确的fb_info前提下,fbmem.c中的函数可以工作的很好。这样大家应该感到非常轻松了吧,只要完成上述的几个设备相关的函数,framebuffer设备的驱动就写完了:)
        系统的结构如图:

    图6
    Stifb驱动模型
    linux/drivers/video/stifb.c - Genericframe buffer driver for HP * workstations with STI (standard textinterface) video firmware.
    这个驱动程序和前面的anakin设备完全不同,因为他不是采用标准的格式,而是根据based on skeletonfb, which wasCreated 28 Dec 1997 by GeertUytterhoeven也就是skeletonfb.c提供的框架完成的。
    共230行,包含函数如下:
      
  • static int sti_encode_fix(struct fb_fix_screeninfo *fix,const void *par, struct fb_info_gen *info) 60行  
  • static int sti_decode_var(const struct fb_var_screeninfo*var,void *par, struct fb_info_gen *info) 71行  
  • static int sti_encode_var(struct fb_var_screeninfo *var,const void *par, struct fb_info_gen *info) 78行  
  • static void sti_get_par(void *par, struct fb_info_gen*info) 94行  
  • static void sti_set_par(const void *par, struct fb_info_gen*info) 99行  
  • staticint sti_getcolreg(unsigned regno, unsigned *red, unsigned *green,unsigned *blue, unsigned *transp, struct fb_info *info) 104行  
  • staticint sti_setcolreg(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info) 111行  
  • static void sti_set_disp(const void *par, struct display*disp, struct fb_info_gen *info) 118行  
  • static void sti_detect(void) 127行  
  • static int sti_blank(int blank_mode, const struct fb_info*info) 132行  
  • int __init stifb_init(void) 161行  
  • void stifb_cleanup(struct fb_info *info) 201行  
  • int __init stifb_setup(char *options) 208行其中1到10是必须的,参考下面的图。11是初始化代码。12.13没有完成具体功能。

    图7
    再给出fb_fix_screeninfo系统调用结构图:

    图8
    Framebuffer与console
    Framebuffer作为显卡在内核中的注册设备,为了满足应用需要,通常还要为console操作提供专用操作函数。Console是系统提供的一种特殊的文本输出终端,如图所示。常用的console已经不再是从前的单色显示,而是16色或者更多颜色显示。根据文本的代表的不同属性,显示不同的颜色。

    图9
    把对console的支持内嵌到fb的驱动中,或许有其自己的道理,我没有看出来。不过既然要提供这种支持,我们的驱动程序就要添枝加叶了。
    在准fb设备设备驱动中是没有对console支持的。只有在非标准的fb驱动,也就是基于skeletonfb.c架构的程序,需要提供这部分代码。下面从各个方面介绍framebuffer对console的支持。
    1.各个文件中的支持
    fb.h文件中
    struct fb_info结构中:
    struct display*disp;             /* initial display variable */
        struct vc_data*display_fg;          /* Console visible on this display */
    int(*changevar)(int);           /* tell console var has changed */
        int (*switch_con)(int, struct fb_info*);/* tell fb to switch consoles */
    fbgen.c文件中:
    void fbgen_set_disp(int con, struct fb_info_gen *info)
    int fbgen_update_var(int con, struct fb_info *info)
    int fbgen_switch(int con, struct fb_info *info)
    新增加文件fbcon.c
    struct display fb_display[MAX_NR_CONSOLES];
    char con2fb_map[MAX_NR_CONSOLES];
    …..
    新增加文件fbcon.h:
    struct display_switch
    struct display
    新增文件console_struct.h:
    struct vc_data
    ……
    2.console中的颜色设定
    该部分内容准备略掉,可以自行参考fbcon-cfb*.c文件。
    3.console和fb的高层理解
    当我们在fb中引入console后,就相当于把一张白纸变成了一个日记本。本来对于fb来说只有颜色和位置的关系,引入console后,首先就是console的描述。
      每个console相当于日记本的一页,不同的console可以切换。Console因为是要显示文本,又和字体联系到一起。Console的管理是十分复杂的,远远超过了framebuffer本身。在RH9中,我们可以自己体验一下console和fb的协调问题。
       使用Init3多用户模式登陆,这里是没有Xserver支持的。所有的输入输出都是基于console的。Framebuffer就相当于你的显示器。通过ALT+CTRL+F*,我们可以切换到不同的console,而每个console的设置都可以很独立的完成。每隔console会在自己的数据区记录历史命令,在不同的console可以登陆不同的用户到系统。但是,因为只有一个屏幕,所以当前可视的console只有一个。Framebuffer驱动程序要能够根据ALT+CTRL+F*切换命令去完成console的切换显示。
       这样大家应该明白framebuffer和console的关系了吧。后续我们会具体讲述fb对console的支持。但是对console本身不会设计太多,具体参考tty或console的设计。当完成了fb对console的支持,frame buffer device driver设计就完了:)
    Fbconsole中的字体
    /driver/video目录下:
    font_6x11.c,font_8x8.c,font_8x16.c
    font_acorn_8x8.c,font_pearl_8x8.c,
    font_sun8x16.c,font_sun12x22.c
    fonts.c
    这些文件都是用来处理在fbcon中的字体显示问题。其中除最后一个文件fonts.c外,其他都是字模文件由cpi2fnt产生。
    /include/video/目录下:
    font.h
    1.          首先介绍font.h文件
    font.h文件中,定义了字体的描述结构
    struct fbcon_font_desc {
        intidx;     //字体的索引号
        char *name;//字体的描述
        int width, height;//字模的宽和高
        void *data;//字模的起始指针
        int pref;   //额外信息,平台用
    };
    width的值不一定是8的整数倍,考虑到计算机存储的问题,即使width小于8的整数倍,存储时仍以字节为单位,不足的右补齐0。
    Linux内核自带了7种字体,name依次为:
    font_vga_8x8,
                               font_vga_8x16,
                               font_pearl_8x8,
                               font_vga_6x11,
                               font_sun_8x16,
                               font_sun_12x22,
                               font_acorn_8x8;
    根据定义name长度不大于32字节。
    2.          Font.c文件
    /* 根据字体名返回该字体的描述结构 */
    struct fbcon_font_desc *fbcon_find_font(char *name);
    /*根据屏幕大小,获取默认字体描述 */
    struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres);
    由此看来,linux中基于fbcon的字体比较单一,描述和使用也相对简单。主要是由于采用字模描述,只描述256个ascii字符,故存储空间不大,从2048到11264不等。
    Fbcon中的颜色查找表
    Fbcon-cfbx表示该console使用的是xbpp颜色描述。颜色数为2^x。
    在此,我们仅以x=8,x=24举例,使用颜色分别是256色和真彩16M。
    /driver/video/fbcon-cfb8.c
    /driver/video/fbcon-cfb24.c
    /include/video/fbcon-cfb8.h
    /include/video/fbcon-cfb24.h
    这4个文件实现的具体的操作,而fbcon的底层操作,参考前面的fbcon的介绍,不重复了:)
    实现fbcon的颜色映射只需完成下面的功能,以fb8为例:
    struct display_switch fbcon_cfb8;   
    void fbcon_cfb8_setup(struct display *p);
    void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, intdx, int height, int width);
    void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy,int sx, int height, int width);
    void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c,int yy, int xx);
    void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, constunsigned short *s, int count, int yy, int xx);
    void fbcon_cfb8_revc(struct display *p, int xx, int yy);
    void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display*p,int bottom_only);
    fbcon_cfb8是系统的实现关键,具体解释参考fbcon介绍。
    fbcon_cfb8_setup函数完成设定display结构中next_line和next_palne的值。
    fbcon_cfb8_bmove函数完成当前坐标的移动。
    fbcon_cfb8_clear函数通过调用rectfill函数清屏幕缓冲区。
    fbcon_cfb8_putc函数向屏幕输出单字符,字体宽度必须小于等于16。
    fbcon_cfb8_putcs函数向屏幕输出字符串。
    fbcon_cfb8_revc函数从屏幕输入单个字符,并回显到fb上。
    fbcon_cfb8_clear_margins函数和fbcon_cfb8_clear类似,调用rectfill清除区域。
    其中,fb_writel函数和fb_readl函数实现输入输出的底层操作。这两个函数实际上实在fbcon_h中定义的宏操作,IOMEM操作而已。
    关注一下“(nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx,”
    这是所谓8bpp的具体实现,不同的位深就在写fb缓冲时体现了。让我们从后向前分析,
    1.()^bgx,颜色和背景色异或,只有这样才能保证背景色改变时,文字一直显示。
    2.~&eorx,eorx是前景色和背景色异或后的值,只有在前景色和背景色一致的时候,eorx才是0。
    3. nibbletab_cfb8[~],根据字体的~值,调用查找表,取颜色值
    4.~从字体文件中去读字模的值。
    还有点疑问,就是这两句的作用,attr_fgcol在fbcon_h中定义:
    fgx=attr_fgcol(p,c);
        bgx=attr_bgcol(p,c);
    从前面的看,c应该是个字符的ascii码,ascii与颜色有什么关系呢?研究中….

                   
                   

    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/77230/showart_1208619.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP