解析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. 聊聊jesque的几个dao
  2. VBA最常用的基础代码、基础功能写法总结
  3. 多标签文本分类 [ALBERT](附代码)
  4. 【Socket网络编程】15. 发送端和接收端数据大小不一致时 的分析
  5. 手机麦克风声音太大_全民K歌必备利器,得胜PH-125手机K歌麦克风让你轻松拥有好声音...
  6. 【今日CS 视觉论文速览】Part2, 16 Jan 2019
  7. jenkins java版本_安装jenkins几个版本貌似都有问题
  8. Cilium架构:提供并透明地保护应用程序工作负载之间的网络连接和负载平衡
  9. springboot集成钉钉_Java(SpringBoot)实现钉钉机器人消息推送
  10. 打印zigzag矩阵
  11. layui修改窗口标题
  12. 关于html5之canvas的那些事
  13. 我对安卓recovery的流程大致总结
  14. 当前最热门的编程语言python_2020年度最热门的编程语言盘点
  15. java中什么是线程不安全给出一个例子
  16. 华为认证是自学还是报班合适
  17. 健身教程APP开发解决方案
  18. postgresql数据库字节流类型详解
  19. 无线路由登不上服务器怎么办,无线路由器管理界面怎么登录,无法进入管理界面怎么办...
  20. USBISP下载线驱动

热门文章

  1. CSS3实现列表无限滚动/轮播
  2. 国金证券这么看新钢钒
  3. mac、windows、centos、ubuntu 如何安装使用 docker 的?
  4. 基于maplefetion的飞信客户端v1.0
  5. matlab中的括号
  6. 几十行代码实现Java爬虫,结合jsoup爬取网名昵称
  7. dataTable 改变搜索框位置
  8. 学计算机可以用算盘吗,看图猜成语黑板学生算盘计算机答案玩法经验分享
  9. mac maven安装和配置本地仓库
  10. 到韩国我苹果7手机显示无服务器,谁来救救我啊!!!