4.  Framebuffer internal API


Now that we understand the basic ideas behind graphics card technology and mode setting, we can now look at how the framebuffer devices abstract. Also we will see that fbdev actually handles most of the mode setting issues for you which make life much easier. In the older API, the console code was heavily linked to the framebuffer devices. The newer API has now moved all the console handling code into fbcon itself. Now, fbcon is a true wrapper around the graphics card’s abilities. This allows for massive code and easier driver development. It also allows for a framebuffer system to run independent of the VT console layer. A good example of a working framebuffer driver is the virtual framebuffer (vfb). The vfb driver is not a true framebuffer driver. All it does is map a chunk of memory to userspace. It's used for demonstration purposes and testing. For a more detailed file that explains each function look at skeletonfb.c. It is not a driver at all but it explains everything you need for a real one.

4.1 Data Structures

The framebuffer drivers depend heavily on four data structures. These structures are declared in fb.h. They are:

 
   struct fb_var_screeninfo
    struct fb_fix_screeninfo
    struct fb_monospecs
    struct fb_info

The first three can be made available to and from userland. First let me describe what each means and how they are used.

Struct fb_var_screeninfo is used to describe the features of a graphics you normally can set. With struct fb_var_screeninfo, you can define such things as depth and the resolution you want.

The next structure is struct fb_fix_screeninfo. This defines the non changeable properties of a graphics card that are set when you change the resolution. A good example is the start of the framebuffer memory. It is possible this address depends on what resolution, endians, or color depth the graphics card is running at. Now while using that mode, you don't want to have the memory position change on you. In this case, the graphics hardware tells you the memory location and you have no say about it.

The third structure is struct fb_monospecs. In the old API, the importance of struct fb_monospecs was very little. This allowed for forbidden things such as setting a mode of 800x600 on a fix frequency monitor. With the new API, struct fb_monospecs prevents such things. With DDC it can even be expanded to support Plug-n-Play of monitors. This would lead to preventing blank screens or worst fried montiors.

The final data structure is struct fb_info. This defines the current hardware independent state of the framebuffer of a graphics card. It is possible that a graphics card has mulitple framebuffers. In this case that device would have two struct fb_info.Struct fb_info is only visible from the kernel. Struct fb_info is defined as:

  struct fb_info {
     kdev_t node;
     int flags;
     int open;
     struct fb_var_screeninfo var;
     struct fb_fix_screeninfo fix;
     struct fb_monspecs monspecs;
     struct fbcursor cursor;
     struct fb_cmap cmap;
     struct fb_ops *fbops;
     struct pm_dev *pm_fb;
     char *screen_base;
     wait_queue_head_t wait;
     devfs_handle_t devfs_handle;
     devfs_handle_t devfs_lhandle;
     void *pseudo_palette;
  #ifdef CONFIG_MTRR
     int mtrr_handle;
  #endif
     void *par;
  }                        
there exist a struct fb_ops which is a collection of needed functions to make fbdev work.

4.2 Driver layout

Here I describe a clean way to code your drivers. A good example of the basic layout is vfb.c. In the example driver, we first present our data structures in the beginning of the file. Note that there is nostruct fb_monospecs since this is handled by code in fbmon.c. This can be done since monitors are independent in behavior from video cards. First, we define our three basic data structures. For all the data structures I defined them static and declare the default values. The reason I do this is because it's less memory intensive than to allocate a piece of memory and filling in the default values. Note that drivers can support multihead on the same card, then in that case we would have multiple struct fb_info . If the device is hot pluggable then we should dynamically allocated struct fb_info for each framebuffer present on the graphics card present. For struct fb_var_screeninfo and struct fb_fix_screeninfo, they still are declared static since all the cards can be set to the same mode.

4.3 Initialization and boot time parameter handling

There are two functions that handle the video card at boot time:

    int xxfb_init(void);
    int xxfb_setup(char*);

In the example driver as with most drivers, these functions are placed at the end of the driver. Both are very card specific. In order to link your driver directly into the kernel, both of these functions must add the above functions to fbmem.c similiar to what follows:

    static struct {
             const char *name;
             int (*init)(void);
             int (*setup)(char*);
} fb_drivers[] __initdata = {
     #ifdef CONFIG_FB_YOURCARD
             { "driver_name", xxxfb_init, xxxfb_setup },
     #endif

Setup is used to pass card specific options from the boot prompt of your favorite boot loader. A good example is:

boot: video=matrox: vesa: 443

The basic setup function is:

     int __init xxxfb_setup(char *options)
     {
     char *this_opt;
 
     if (!options || !*options)
          return 0;
 

     for (this_opt = strtok(options, ","); this_opt;
        this_opt = strtok(NULL,      ","))
        if (!strcmp(this_opt, "my_option")) {
        /* Do your stuff. Usually set some static flags that the driver l  
        } else if (!strncmp(this_opt, "Other_option:", 5))
            strcpy(some_flag_driver_uses, this_opt+5);
        } else ....
    }
}

The xxfb_init function sets the initial state of the video card. This function has to consider bus and pla handling since today most cards can exist on many platforms. For bus types we have to deal with, there are PCI, ISA, and zorro. Also, some platforms offer firmware that returns information about the video card. In this case, we often don't need to deal with the bus unless we need more control over the card. Let us look at Open Firmware that’s available on PowerPCs.

The next major part of the driver is declaring the functions of fb_ops that are declared in fb_info for the driver.

index back