博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
framebuffer驱动全篇
阅读量:4137 次
发布时间:2019-05-25

本文共 21941 字,大约阅读时间需要 73 分钟。

在后续的几篇里面会详细介绍如何编写一个显卡的驱动程序。

framebuffer device在内核里面作为显卡驱动模型,许多函数和数据结构都是特定,正是这些特定的东西为我们的编程提供了方便。

要开发frame buffer device驱动,你应该阅读Source/Source/Documentation/fb下面的说明文件,三个重要文件00- INDEX,framebuffer.txt,internals.txt,其他文件都是针对具体显卡芯片的说明了。

文件00-INDEX译文

文档/documentation/fb的索引文件。如果你对frame buffer设备有什么想法,mail:Geert Uytterhoeven < >

00-index 这个文件

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

翻译:

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/fb1 etc.)可以独立工作。

 

应用程序如 X server一般使用/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()在系统中注册。使用模块更方便!

 

3.帧缓冲分辨率设定

 

帧缓冲的分辨率可以用工具fbset设定。他可以改变视频设备的显示模式。主要就是

改变当前视频模式,如在启动过程中,在/etc/rc.* 或 /etc/init.d/* 文件中调用,

可以把视频模式从单色显示变成真彩.

 

fbset使用存储在配置文件中的视频模式数据表,你可以在文件中增加自己需要的显示模式。

 

4.X Server

 

X server (XF68_FBDev)是对帧缓冲设备的最主要应用。从XFree86  3.2后,X server就是

XFree86 的一部分了,有2个工作模式:

 

  - 在/etc/XF86Config文件中,如果`Display'段关于 `fbdev'的配置:

    Modes "default"
    X server 将使用前面讨论的,从环境变量$FRAMEBUFFER获取当前帧缓冲设备.
    你也可以设定颜色位深,使用Depth关键字,使用Virtual设定虚拟分辨率。这也是

    默认设置。

   
  - 然而你也可以通过设定/etc/XF86Config,改变分辨率。这样有很多灵活性,唯一的

    不足就是你必须设定刷新频率。可以用fbset -x

通过fbset或xvidtune切换显示模式。

 

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                   |          |       |
  |          |                ?                           |          |       |
  +----------+---------------------------------------------+----------+-------+

   

6.把XFree86时序变成frame buffer device时序

典型的显示模式:

  "800x600"     50      800  856  976 1040    600  637  643  666

  < name >     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".

 

7. 引用

获取更多关于帧缓冲设备以及应用的参考,请访问:

    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:
      o linux/drivers/video/
      o linux/include/linux/fb.h
      o linux/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 buffer device driver:)

framebuffer驱动全篇(二)
    

还是要补充点,下面是/linux/fb.h的部分注释,加粗的是常用的,红色是关键的,一般不可少。旁边没有汉字,要么很简单没必要加注,要么就用不到!

注释:

 

#ifndef _LINUX_FB_H

#define _LINUX_FB_H

 

#include

#include

 

/* Definitions of frame buffers                     */

 

#define FB_MAJOR        29  /*主设备号*/

#define FB_MAX          32  /* sufficient for now */

 

/* ioctls

   0x46 is 'F'                              */

#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

#define FBIOBLANK       0x4611      /* arg: 0 or vesa level + 1 */

#define FBIOGET_VBLANK      _IOR('F', 0x12, struct fb_vblank)

#define FBIO_ALLOC              0x4613

#define FBIO_FREE               0x4614

#define FBIOGET_GLYPH           0x4615

#define FBIOGET_HWCINFO         0x4616

#define FBIOPUT_MODEINFO        0x4617

#define FBIOGET_DISPINFO        0x4618

 

 

#define FB_TYPE_PACKED_PIXELS       0   /* Packed Pixels    */

#define FB_TYPE_PLANES          1   /* Non interleaved planes */

#define FB_TYPE_INTERLEAVED_PLANES  2   /* Interleaved planes   */

#define FB_TYPE_TEXT            3   /* Text/attributes  */

#define FB_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   /* MGA Millenium I: text, attr, 14 reserved bytes */

#define FB_AUX_TEXT_MGA_STEP8   4   /* other MGAs:      text, attr,  6 reserved bytes */

 

#define FB_AUX_VGA_PLANES_VGA4      0   /* 16 color planes (EGA/VGA) */

#define FB_AUX_VGA_PLANES_CFB4      1   /* CFB4 in planes (VGA) */

#define FB_AUX_VGA_PLANES_CFB8      2   /* CFB8 in planes (VGA) */

 

#define FB_VISUAL_MONO01        0   /* Monochr. 1=Black 0=White */

#define FB_VISUAL_MONO10        1   /* Monochr. 1=White 0=Black */

#define FB_VISUAL_TRUECOLOR     2   /* True color   */

#define FB_VISUAL_PSEUDOCOLOR       3   /* Pseudo color (like atari) */

#define FB_VISUAL_DIRECTCOLOR       4   /* Direct color */

#define FB_VISUAL_STATIC_PSEUDOCOLOR    5   /* Pseudo color readonly */

 

#define FB_ACCEL_NONE       0   /* no hardware accelerator  */

#define FB_ACCEL_ATARIBLITT 1   /* Atari Blitter        */

#define FB_ACCEL_AMIGABLITT 2   /* Amiga Blitter                 */

#define FB_ACCEL_S3_TRIO64  3   /* Cybervision64 (S3 Trio64)    */

#define FB_ACCEL_NCR_77C32BLT   4   /* RetinaZ3 (NCR 77C32BLT)      */

#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 21030 TGA        */

#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  /* ATI Mach 64CT family GT class */

#define FB_ACCEL_SUN_CREATOR    11  /* Sun Creator/Creator3D    */

#define FB_ACCEL_SUN_CGSIX  12  /* Sun cg6          */

#define FB_ACCEL_SUN_LEO    13  /* Sun leo/zx           */

#define FB_ACCEL_IMS_TWINTURBO  14  /* IMS Twin Turbo       */

#define FB_ACCEL_3DLABS_PERMEDIA2 15    /* 3Dlabs Permedia 2        */

#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 (Millenium II) */

#define FB_ACCEL_MATROX_MGAG100 20  /* Matrox G100 (Productiva G100) */

#define FB_ACCEL_MATROX_MGAG200 21  /* Matrox G200 (Myst, Mill, ...) */

#define FB_ACCEL_SUN_CG14   22  /* Sun cgfourteen       */

#define FB_ACCEL_SUN_BWTWO  23  /* Sun bwtwo            */

#define FB_ACCEL_SUN_CGTHREE    24  /* Sun cgthree          */

#define FB_ACCEL_SUN_TCX    25  /* Sun tcx          */

#define FB_ACCEL_MATROX_MGAG400 26  /* Matrox G400          */

#define FB_ACCEL_NV3        27  /* nVidia RIVA 128              */

#define FB_ACCEL_NV4        28  /* nVidia RIVA TNT      */

#define FB_ACCEL_NV5        29  /* nVidia RIVA TNT2     */

#define FB_ACCEL_CT_6555x   30  /* C&T 6555x            */

#define FB_ACCEL_3DFX_BANSHEE   31  /* 3Dfx Banshee         */

#define FB_ACCEL_ATI_RAGE128    32  /* ATI Rage128 family       */

#define FB_ACCEL_IGS_CYBER2000  33  /* CyberPro 2000        */

#define FB_ACCEL_IGS_CYBER2010  34  /* CyberPro 2010        */

#define FB_ACCEL_IGS_CYBER5000  35  /* CyberPro 5000        */

#define FB_ACCEL_SIS_GLAMOUR    36  /* SiS 300/630/540              */

#define FB_ACCEL_3DLABS_PERMEDIA3 37    /* 3Dlabs Permedia 3        */

/*上面的宏定义不用关心*/

 

/*不可修改的屏幕信息,用户空间可见*/

struct fb_fix_screeninfo {

    char id[16];         /* identification string eg "TT Builtin" */

    unsigned long smem_start;   /* Start of frame buffer mem 显存的起始地址*/

                  /* (physical address) */

    __u32 smem_len;          /* Length of frame buffer mem 显存的大小 */

    __u32 type;          /* see FB_TYPE_*     */

    __u32 type_aux;          /* Interleave for interleaved Planes */

    __u32 visual;        /* see FB_VISUAL_*       */

    __u16 xpanstep;          /* zero if no hardware panning  */

    __u16 ypanstep;          /* zero if no hardware panning  */

    __u16 ywrapstep;     /* zero if no hardware ywrap    */

    __u32 line_length;       /* length of a line in bytes  每行的字节数  */

    unsigned long mmio_start;   /* Start of Memory Mapped I/O   */

                  /* (physical address) */

    __u32 mmio_len;          /* Length of Memory Mapped I/O  */

    __u32 accel;           /* Type of acceleration available */

    __u16 reserved[3];       /* Reserved for future compatibility */

};

 

/* Interpretation of offset for color fields: All offsets are from the right,

  * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you

  * can use the offset as right argument to <<). A pixel afterwards is a bit

  * stream and is written to video memory as that unmodified. This implies

  * big-endian byte order if bits_per_pixel is greater than 8.

  */

  /*像素所占字节内,各个颜色的位分配比如RGB=888,565,555等等,*/

struct fb_bitfield {

    __u32 offset;        /* beginning of bitfield */

    __u32 length;        /* length of bitfield       */

    __u32 msb_right;     /* != 0 : Most significant bit is */

                  /* right */

};

 

/*下面的宏也不常用*/

#define FB_NONSTD_HAM       1   /* Hold-And-Modify (HAM)        */

 

#define FB_ACTIVATE_NOW     0   /* set values immediately (or vbl)*/

#define FB_ACTIVATE_NXTOPEN 1   /* activate on next open    */

#define FB_ACTIVATE_TEST    2   /* don't set, round up impossible */

#define FB_ACTIVATE_MASK       15

                    /* values           */

#define FB_ACTIVATE_VBL        16   /* activate values on next vbl  */

#define FB_CHANGE_CMAP_VBL     32   /* change colormap on vbl   */

#define FB_ACTIVATE_ALL        64   /* change all VCs on this fb    */

 

#define FB_ACCELF_TEXT      1   /* text mode acceleration */

 

#define FB_SYNC_HOR_HIGH_ACT    1   /* horizontal sync high active  */

#define FB_SYNC_VERT_HIGH_ACT   2   /* vertical sync high active    */

#define FB_SYNC_EXT     4   /* external sync        */

#define FB_SYNC_COMP_HIGH_ACT   8   /* composite sync high active   */

#define FB_SYNC_BROADCAST   16  /* broadcast video timings

 

 

framebuffer驱动全篇(三)
  

Color Map 剖析

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

1. struct fb_cmap

 

/* 颜色映射表 */

struct fb_cmap {

       __u32 start;                  /* First entry   */

       __u32 len;                    /* 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_cmap cmap;                 /* 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, int fsfromto);

extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,

int (*getcolreg)(u_int, u_int *, u_int *, u_int *,u_int *, struct fb_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 如图

 

 

stifb.c
framebuffer驱动全篇(四)
    

本文介绍的设备是位于 /video 目录下面的 anakinfb.c 驱动程序。虽然我不清楚那个设备的特性,但是从对程序的分析中我们仍然知道如何编写一个 frame buffer 设备驱动。

    本文是个标准的 fb 驱动。共 221 行,包含函数如下:

 

1.         static int  anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info) 31

2.         static int anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,u_int transp, struct fb_info *info) 45

3.         static int anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) 57

4.         static int anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 75

5.         static int anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 111

6.         static int anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,     struct fb_info *info) 117

7.         static int anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,     struct fb_info *info) 130

8.         static int anakinfb_switch_con(int con, struct fb_info *info) 147

9.         static int anakinfb_updatevar(int con, struct fb_info *info) 155

10.     static void anakinfb_blank(int blank, struct fb_info *info) 161

11.     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 中的函数可以工作的很好。这样大家应该感到非常轻松了吧,只要完成上述的几个设备相关的函数, frame buffer 设备的驱动就写完了:)

 

系统的结构如图:

 

Stifb 驱动模型

linux/drivers/video/stifb.c - Generic frame buffer driver for HP * workstations with STI (standard text interface) video firmware.

这个驱动程序和前面的 anakin 设备完全不同,因为他不是采用标准的格式,而是根据 based on skeletonfb, which wasCreated 28 Dec 1997 by Geert Uytterhoeven 也就是 skeletonfb.c 提供的框架完成的。

230 行,包含函数如下:

1.         static int sti_encode_fix(struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info) 60

2.         static int sti_decode_var(const struct fb_var_screeninfo *var,void *par, struct fb_info_gen *info) 71

3.         static int sti_encode_var(struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info) 78

4.         static void sti_get_par(void *par, struct fb_info_gen *info) 94

5.         static void sti_set_par(const void *par, struct fb_info_gen *info) 99

6.         static int sti_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info) 104

7.         static int sti_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) 111

8.         static void sti_set_disp(const void *par, struct display *disp, struct fb_info_gen *info) 118

9.         static void sti_detect(void) 127

10.     static int sti_blank(int blank_mode, const struct fb_info *info) 132

11.     int __init stifb_init(void) 161

12.     void stifb_cleanup(struct fb_info *info) 201

13.     int __init stifb_setup(char *options) 208

其中 1 10 是必须的,参考下面的图。

11 是初始化代码

12 13 没有完成具体功能

 

 

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

 

 

Frame bufferconsole

Framebuffer 作为显卡在内核中的注册设备,为了满足应用需要,通常还要为 console 操作提供专用操作函数。

Console 是系统提供的一种特殊的文本输出终端,如图所示。常用的 console 已经不再是从前的单色显示,而是 16 色或者更多颜色显示。根据文本的代表的不同属性,显示不同的颜色。

把对 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 多用户模式登陆,这里是没有 X server 支持的。所有的输入输出都是基于 console 的。 Framebuffer 就相当于你的显示器。通过 ALT+CTRL+F* ,我们可以切换到不同的 console ,而每个 console 的设置都可以很独立的完成。每隔 console 会在自己的数据区记录历史命令,在不同的 console 可以登陆不同的用户到系统。但是,因为只有一个屏幕,所以当前可视的 console 只有一个。 Frame buffer 驱动程序要能够根据 ALT+CTRL+F* 切换命令去完成 console 的切换显示。

   这样大家应该明白 frame buffer console 的关系了吧。后续我们会具体讲述 fb console 的支持。但是对 console 本身不会设计太多,具体参考 tty console 的设计。当完成了 fb console 的支持, frame buffer device driver 设计就完了:)

framebuffer驱动全篇(五)
    

Fb console中的字体

/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 {

    int idx;     / 字体的索引号

    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, int dx, 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, const unsigned 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与颜色有什么关系呢?研究中….

转载地址:http://bmlvi.baihongyu.com/

你可能感兴趣的文章
利用数组来优化if else ---谈谈数组的本质
查看>>
出差一个月, 已回大本营。
查看>>
搭建只有两台电脑的局域网
查看>>
如何在一台pc搭建自己的ftp服务器?
查看>>
概率性的bug比较恼人(软件质量不是一句废话)
查看>>
如何在一台pc搭建自己的sftp服务器?
查看>>
小程序分享:str1和str2对应的串相等, 但是a.txt和b.txt不相同。
查看>>
廖雪峰的Git教程---确实是史上最易懂的Git教程
查看>>
if(...) log("a"); else log("b"); x=6; 没有日志打印, 但后面的赋值语句x=6;居然执行了?
查看>>
printf("hello world"); x=6; 日志中没有"hello world", 但x=6居然执行了?
查看>>
《html, css, javascritp网页制作》 刘西杰
查看>>
《Wireshark数据包分析实战 》 Chris Sanders
查看>>
《曾国藩传》 董丛林 (做人要学曾国藩, 做事要学张居正)
查看>>
在Windows下如何练习Linux下的vim? (为即将步入IT行业的兄弟和妹子介绍一个工具)
查看>>
大餐分享: Windows环境下学习linux的命令行,编辑器vim, 脚本和Git的绝佳工具---msysGit(才十几M)
查看>>
如何让程序只有一个实例运行(用tftp时的感想)?
查看>>
VC++6.0环境下sqlite数据库编程入门 (是该走进数据库里面了)
查看>>
如何搭建tftp服务器?
查看>>
ftp常用简易命令实战
查看>>
要学会写小程序来完成自己想要的功能
查看>>