解析DRM代码,以从底层介绍显卡驱动的初始化过程,显卡类型是AMD的radeon r600以后的系列显卡。基本的过程就是驱动载入,硬件初始化,设置硬件独立的模块(如内存管理器),设置显示(分辨率等)。 代码如下:

drivers/gpu/drm/radeon/radeon_drv.c

module_init(radeon_init);
module_exit(radeon_exit);MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
static int __init radeon_init(void)
{if (vgacon_text_force() && radeon_modeset == -1) {DRM_INFO("VGACON disable radeon kernel modesetting.\n");radeon_modeset = 0;}/* set to modesetting by default if not nomodeset */if (radeon_modeset == -1)radeon_modeset = 1;if (radeon_modeset == 1) {DRM_INFO("radeon kernel modesetting enabled.\n");driver = &kms_driver;pdriver = &radeon_kms_pci_driver;driver->driver_features |= DRIVER_MODESET;driver->num_ioctls = radeon_max_kms_ioctl;radeon_register_atpx_handler();} else {DRM_ERROR("No UMS support in radeon module!\n");return -EINVAL;}return pci_register_driver(pdriver);
}static void __exit radeon_exit(void)
{pci_unregister_driver(pdriver);radeon_unregister_atpx_handler();
}

重点说一下这行代码:driver->driver_features |= DRIVER_MODESET;。driver指针指向了&kms_driver,这一句的意思是给kms_driver.driver_features添加上DRIVER_MODESET标志位,以告知DRM Coce当前驱动支持modesetting操作。

radeon_init函数中调用pci_register_driver(pdriver)注册pdriver,pdriver实际指向了radeon_kms_pci_driver,初始化内容如下:

static struct drm_driver *driver;
static struct pci_driver *pdriver;
static struct pci_driver radeon_kms_pci_driver = {.name = DRIVER_NAME,.id_table = pciidlist,.probe = radeon_pci_probe,.remove = radeon_pci_remove,.shutdown = radeon_pci_shutdown,.driver.pm = &radeon_pm_ops,
};

驱动和设备匹配之后调用radeon_pci_probe,源码如下:

static int radeon_pci_probe(struct pci_dev *pdev,const struct pci_device_id *ent)
{unsigned long flags = 0;int ret;if (!ent)return -ENODEV; /* Avoid NULL-ptr deref in drm_get_pci_dev */flags = ent->driver_data;if (!radeon_si_support) {switch (flags & RADEON_FAMILY_MASK) {case CHIP_TAHITI:case CHIP_PITCAIRN:case CHIP_VERDE:case CHIP_OLAND:case CHIP_HAINAN:dev_info(&pdev->dev,"SI support disabled by module param\n");return -ENODEV;}}if (!radeon_cik_support) {switch (flags & RADEON_FAMILY_MASK) {case CHIP_KAVERI:case CHIP_BONAIRE:case CHIP_HAWAII:case CHIP_KABINI:case CHIP_MULLINS:dev_info(&pdev->dev,"CIK support disabled by module param\n");return -ENODEV;}}if (vga_switcheroo_client_probe_defer(pdev))return -EPROBE_DEFER;/* Get rid of things like offb */ret = radeon_kick_out_firmware_fb(pdev);if (ret)return ret;return drm_get_pci_dev(pdev, ent, &kms_driver);
}

radeon_si_support和radeon_cik_support由启动参数得来,在/etc/default/grub文件中的GRUB_CMDLINE_LINUX_DEFAULT=一行可以添加诸如"modprobe.blacklist=radeon radeon.si_support=1 radeon.cik_support=1"的语句,其中的si_support和cik_support实际上就是设置了这里的radeon_si_support和radeon_cik_support。两个模块参数的初始化代码如下:

int radeon_si_support = 1;
MODULE_PARM_DESC(si_support, "SI support (1 = enabled (default), 0 = disabled)");
module_param_named(si_support, radeon_si_support, int, 0444);int radeon_cik_support = 1;
MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = disabled)");
module_param_named(cik_support, radeon_cik_support, int, 0444);

radeon_pci_probe函数最后调用drm_get_pci_dev(pdev, ent, &kms_driver),kms_driver的初始化内容如下:

static struct drm_driver kms_driver = {.driver_features =DRIVER_USE_AGP |DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |DRIVER_PRIME | DRIVER_RENDER,.load = radeon_driver_load_kms,.open = radeon_driver_open_kms,.postclose = radeon_driver_postclose_kms,.lastclose = radeon_driver_lastclose_kms,.unload = radeon_driver_unload_kms,.get_vblank_counter = radeon_get_vblank_counter_kms,.enable_vblank = radeon_enable_vblank_kms,.disable_vblank = radeon_disable_vblank_kms,.get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,.get_scanout_position = radeon_get_crtc_scanout_position,.irq_preinstall = radeon_driver_irq_preinstall_kms,.irq_postinstall = radeon_driver_irq_postinstall_kms,.irq_uninstall = radeon_driver_irq_uninstall_kms,.irq_handler = radeon_driver_irq_handler_kms,.ioctls = radeon_ioctls_kms,.gem_free_object_unlocked = radeon_gem_object_free,.gem_open_object = radeon_gem_object_open,.gem_close_object = radeon_gem_object_close,.dumb_create = radeon_mode_dumb_create,.dumb_map_offset = radeon_mode_dumb_mmap,.fops = &radeon_driver_kms_fops,.prime_handle_to_fd = drm_gem_prime_handle_to_fd,.prime_fd_to_handle = drm_gem_prime_fd_to_handle,.gem_prime_export = radeon_gem_prime_export,.gem_prime_import = drm_gem_prime_import,.gem_prime_pin = radeon_gem_prime_pin,.gem_prime_unpin = radeon_gem_prime_unpin,.gem_prime_res_obj = radeon_gem_prime_res_obj,.gem_prime_get_sg_table = radeon_gem_prime_get_sg_table,.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,.gem_prime_vmap = radeon_gem_prime_vmap,.gem_prime_vunmap = radeon_gem_prime_vunmap,.name = DRIVER_NAME,.desc = DRIVER_DESC,.date = DRIVER_DATE,.major = KMS_DRIVER_MAJOR,.minor = KMS_DRIVER_MINOR,.patchlevel = KMS_DRIVER_PATCHLEVEL,
};

drm_get_pci_dev函数代码如下:

drivers/gpu/drm/drm_pci.c

/*** drm_get_pci_dev - Register a PCI device with the DRM subsystem* @pdev: PCI device* @ent: entry from the PCI ID table that matches @pdev* @driver: DRM device driver** Attempt to gets inter module "drm" information. If we are first* then register the character device and inter module information.* Try and register, if we fail to register, backout previous work.** NOTE: This function is deprecated, please use drm_dev_alloc() and* drm_dev_register() instead and remove your &drm_driver.load callback.** Return: 0 on success or a negative error code on failure.*/
int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,struct drm_driver *driver)
{struct drm_device *dev;int ret;DRM_DEBUG("\n");dev = drm_dev_alloc(driver, &pdev->dev);if (IS_ERR(dev))return PTR_ERR(dev);ret = pci_enable_device(pdev);if (ret)goto err_free;dev->pdev = pdev;
#ifdef __alpha__dev->hose = pdev->sysdata;
#endifif (drm_core_check_feature(dev, DRIVER_MODESET))pci_set_drvdata(pdev, dev);drm_pci_agp_init(dev);ret = drm_dev_register(dev, ent->driver_data);if (ret)goto err_agp;/* No locking needed since shadow-attach is single-threaded since it may* only be called from the per-driver module init hook. */if (drm_core_check_feature(dev, DRIVER_LEGACY))list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list);return 0;err_agp:drm_pci_agp_destroy(dev);pci_disable_device(pdev);
err_free:drm_dev_put(dev);return ret;
}
EXPORT_SYMBOL(drm_get_pci_dev);

这是一个比较关键的函数,重点讲一下。不过这一篇的内容比较多了,留在下一篇详细说明吧。

linux内核radeon gpu源码解析3 —— Radeon初始化相关推荐

  1. linux内核radeon gpu源码解析1 —— 什么是radeon

    简介 Radeon(中文名称称为镭龙™)是一个英文产品的商标.Radeon是AMD公司出品的显示芯片的一种系列.俗称A卡. 全称一般写作:AMD Radeon HD xxxx ,例如台式机显卡型号:A ...

  2. Linux 内核中RAID5源码详解之守护进程raid5d

    Linux 内核中RAID5源码详解之守护进程raid5d 对于一个人,大脑支配着他的一举一动:对于一支部队,指挥中心控制着它的所有活动:同样,对于内核中的RAID5,也需要一个像大脑一样的东西来支配 ...

  3. Libuv源码解析 - uv_loop整个初始化模块

    Libuv源码解析 - uv_loop整个初始化模块 loop_default_loop static uv_loop_t default_loop_struct; static uv_loop_t* ...

  4. datax源码解析-JobContainer的初始化阶段解析

    datax源码解析-JobContainer的初始化阶段解析 写在前面 此次源码分析的版本是3.0.因为插件是datax重要的组成部分,源码分析过程中会涉及到插件部分的源码,为了保持一致性,插件都已大 ...

  5. Radeon Gpu源码分析

    1.什么是Radeon 简介: Radeon(中文名称称为镭龙™)是一个英文产品的商标.Radeon是AMD公司出品的显示芯片的一种系列.俗称A卡. 全称一般写作:AMD Radeon HD xxxx ...

  6. linux内核函数open源码,open()在Linux内核的实现(1)-基本实现

    原标题:open()在Linux内核的实现(1)-基本实现 1.基本说明 在用户态使用open()时,必须向该函数传入文件路径和打开权限.这两个参数传入内核后,内核首先检查这个文件路径存在的合法性,同 ...

  7. Linux内核的TCP源码入门(一)

    文章目录 前言 一.TCP报文段结构 1.报文段整体结构 2.TCP首部-固定部分 3.TCP首部-选项(options) 二.TCP接收和发送数据 1.TCP的"接口" 2.发送 ...

  8. android 全志a10(2.3.4)开发二(linux内核编译及源码编译)

    <android 全志a10(2.3.4)开发二>文档详细可下载地址:http://www.a10bbs.com/forum.php?mod=viewthread&tid=504& ...

  9. linux的top命令源码解析:RES指标

    CLion:2019.3.6 源码管理平台:Macbook Pro 10.12.6 C语言源码程序:Makefile格式的linux系统的top命令源码. top所在的系统:ubuntu 14.04 ...

最新文章

  1. 【HDU】1005 Number Sequence (有点可爱)
  2. 详细解读Spatial Transformer Networks(STN)-一篇文章让你完全理解STN了
  3. jQuery对select操作
  4. python一个try块后接一个或多个finally块_Python * with *语句是否完全等同于try-(例外)-finally块?...
  5. VsCode 配置 C/C++ 开发环境,真的很简单
  6. 导入工程后编译不过,报错: apply plugin: 'com.github.dcendents.android-maven'
  7. 电脑雕刻教程_C4D无敌渲染神器! 阿诺德全套预设+案例教程+3.0汉化插件合集!真香!【810期】...
  8. php中连接网页头尾部,网页共用头部和尾部的部分方法
  9. 史上最强大的浏览器嗅探
  10. 电脑如何让两个文件夹同步更新备份?
  11. 《JAVA并发编程实践》读书笔记(一)
  12. 学Java开发需要考什么证书?
  13. CV控制输出的图片大小
  14. Saas 多租户模式介绍
  15. 微信PC端小程序所在位置
  16. vue 中的 attribute 和 property
  17. Java生鲜电商平台-订单架构实战
  18. android 添加系统日历事件,添加系统日历事件
  19. 互联网汽车金融「退潮记」:易鑫投身腾讯,收获最佳结局
  20. 马上要参加天梯赛分享优质题目-L3-011 直捣黄龙 (30分)---三个关键字的最短路径算法

热门文章

  1. 备战S4!想上钻石必须注意的20个细节
  2. java swing暂停继续_如何在Java Swing应用程序中暂停/睡眠/等待?
  3. 台州职业技术学院计算机工程系,台州职业技术学院计算机工程系
  4. NSError错误码解读
  5. OpenStack基础环境搭建----运行“mysql_secure_installation”出现错的解决方法
  6. 前端项目 热点资讯01
  7. python3生成自定义大小的图片
  8. 程序员的自我修炼---小白成长历程
  9. linux安卓mac修改,如何伪装或改变android智能手机wifi网卡的mac地址
  10. 祖国万岁 母校千秋