DirectFB显卡驱动的加载和初始化

        前面我们提到,dfb_core_part_initialize会完成各个核心部件的初始化。

   具体是怎么完成这些初始化工作呢?答案是遍历调用各个部件提供的初始化函数。这个调用规则是通过宏 DFB_CORE_PART来制定的。这个宏的定义如下:

DirectFB显卡驱动的加载和初始化_第1张图片

       由上图的定义可见,DFB_CORE_PART宏指定的规则就是:每一个核心部件都应该在相应的.c文件中填充此宏,也就是为需要实现的各自的initialize、join、shutdown、leave、suspend、resume等函数做一个声明,然后再对这些函数进行定义。读者可参阅gfxcard.c,input.c,screens.c,surface_core.c,system.c,wm.c等文件验证我这个说法。

   OK,到此为止我们知道了针对每个部件的初始化调用规则。那么是如何做到遍历调用呢?它由dfb_core_initialize函数实现。请看下图:DirectFB显卡驱动的加载和初始化_第2张图片

    随后,dfb_core_part_initialize会逐个调用DFB_CORE_PART指定的初始化函数。至此,我们对核心部件的初始化阐述完毕。接下来我们选择graphics core进一步作阐述。

    前面有提到,由DFB_CORE_PART宏暴露其接口函数和调用规则实现:

     DFB_CORE_PART( graphics_core, GraphicsCore );

 

    graphics driver可分为两部分:(1)用户态,是DFB的一部分,以动态链接库的形式存在;(2)内核态,传统意义上得驱动程序,也就是跟具体硬件相关的部分。

     一般,为了区分用户态和内核态,我们将用户态称为gfx driver,把内核态称为gfx module.但是你自己需要知道,内核态的module才是我们真正的驱动程序。

      graphic core的初始化函数为dfb_graphics_core_initialize.它的工作主要包括以下几个部分:

    (1)查找并建立可用的driver链表。

       这一步通过调用 direct_modules_explore_directory( &dfb_graphics_drivers )来实现。dfb_graphics_drivers是一个指定的目录,它是按如下以宏定义的方式指定的:

       DEFINE_MODULE_DIRECTORY( dfb_graphics_drivers, "gfxdrivers", DFB_GRAPHICS_DRIVER_ABI_VERSION );

     可见,该函数通过搜索并打开dfb_graphics_drivers指定的目录的目录中的所有动态链接库,自动调用一个统一的注册函数(由dlopen的性质 和DFB_GRAPHICS_DRIVER宏实现),建立了一个当前系统可用的gfx driver 链表。

      上述建立链表的过程解释如下:

      direct_modules_explore_directory( &dfb_graphics_drivers )函数最后会调用dlopen( buf, RTLD_NOW )函数。理解dlopen函数至关重要:

对于每一个以动态链接库(或称为 插件)形式实现的用户态gfx driver,都应该实现前面提到的DFB_GRAPHICS_DRIVER宏。该宏的定义如下所示:

#define DFB_GRAPHICS_DRIVER(shortname)                           \
__attribute__((constructor)) void directfb_##shortname( void );  \
                                                                 \
void                                                             \
directfb_##shortname( void )                                     \
{                                                                \
     direct_modules_register( &dfb_graphics_drivers,             \
                              DFB_GRAPHICS_DRIVER_ABI_VERSION,   \
                              #shortname, &driver_funcs);       \
}

#endif

同时,对上面的红色字体,有下述定义:

static GraphicsDriverFuncs driver_funcs = {
     .Probe              = driver_probe,
     .GetDriverInfo      = driver_get_info,
     .InitDriver         = driver_init_driver,
     .InitDevice         = driver_init_device,
     .CloseDevice        = driver_close_device,
     .CloseDriver        = driver_close_driver
};

    可见。如果某个gfx driver使用了该宏,就会在调用dlopen打开指定目录之后,通过调用  direct_modules_register函数,把gfx driver的信息注册到dfb_graphics_drivers对应的链表中去。

   (2)根据系统是否支持加速,在前面的链表中选择和加载一个合适的gfx driver;

      这一步是通过调用dfb_gfxcard_find_driver函数来实现的。该函数首先会在前面的链表中调用 direct_list_foreach (link, dfb_graphics_drivers.entries)遍历,如果查到某个gfx driver元素的的驱动函数不为空,则调用driver_probe函数去检测驱动设备;如果该函数返回为true,则填充显卡card这个变量,以便后续使用这些信息。

    (3)前面找到了driver,并设置了card这个变量。首先,这一步会依次调用InitDriver和InitDevice函数,完成gfx driver的初始化。根据第一步我们知道,实际上是调用driver_init_driver函数和driver_init_device.这些接口函数,每个gfx driver都有一个同样函数名字的函数实现。

     driver_init_driver函数,主要是用于安装一些函数指针。这些函数,最终将调用我们实际的驱动的图形函数。ati的该函数示例如下:

            DirectFB显卡驱动的加载和初始化_第3张图片

     自此,dfb侧的 gfx driver的初始化基本完成。剩下的工作,即真正的画图函数,留给具体的module即硬件驱动去实现了。

   

 

你可能感兴趣的:(工作,Module,化工,Constructor,硬件驱动)