GPU初始化和启动流程(r600)

来源:互联网 发布:不好意思网络中断日语 编辑:程序博客网 时间:2024/06/06 01:05

本文是分析了显卡初始化和启动的函数调用以及每个函数的功能。

初始化显卡

int r600_init(struct radeon_device *rdev)        //debuffs        r600_debugfs_mc_info_init(rdev)        **************************BIOS********************************        //读取GPU硬件启动的bios        radeon_get_bios(struct radeon_device *rdev)            loongson3_read_bios(rdev)        //由于一个GPU系列中部分硬件架构的修改,而由硬件厂商提供的一组硬件访问方法,被翻译成了字节码        //有一个翻译表,提供给注册的驱动来调用,从而对硬件进行操作        radeon_atombios_init(struct radeon_device *rdev)        ***************************************************************        //判断显卡是否已经被初始化过了,检查所有的电路是否已将被初始化,通过读取相应寄存器的值判断        radeon_card_posted(rdev)        //初始化划痕寄存器,设置设备划痕寄存器的基地址,这一组寄存器的地址是连续的,由一个数组来维护记录        r600_scratch_init(struct radeon_device *rdev)        //surface寄存器,r600之后都没有了        radeon_surface_init(struct radeon_device *rdev)        //初始化时钟,并设置        radeon_get_clock_info(struct drm_device *dev)        //初始化所有的ring中的fence驱动,准备一些所需要的基础设施        radeon_fence_driver_init(struct radeon_device *rdev)             radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring)        //如果有AGP,那么就需要进行初始化,图形加速卡         radeon_agp_init(struct radeon_device *rdev)        //初始化显卡的内存控制器结构,获取所支持的带宽,映射在PCIE中的基地址,gtt的位置,支持的通道数量        r600_mc_init(struct radeon_device *rdev)            //确定显存和GTT的位置            r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)                radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)                radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)        ****************************************************************************************************************        //初始化memory manager,后期所有内存的申请和管理都是通过这里创建的数据结构        radeon_bo_init(struct radeon_device *rdev)            radeon_ttm_init(struct radeon_device *rdev)                radeon_ttm_global_init(rdev);                ttm_bo_device_init(struct ttm_bo_device *bdev,struct ttm_bo_global *glob,                                struct ttm_bo_driver *driver,                                    uint64_t file_page_offset,                                        bool need_dma32)                ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,                            unsigned long p_size)        ****************************************************************************************************************        //对RADEON_RING_TYPE_GFX_INDEX,R600_RING_TYPE_DMA_INDEX两个ring进行初始化设置        r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size)        //通用视频解码单元的初始化,载入相应的固件,以及bo的申请,映射等,同样接下来需要调用r600_ring_init对R600_RING_TYPE_UVD_INDEX进行初始化设置        radeon_uvd_init(struct radeon_device *rdev)        //对中断使用的ring的初始化设置,        r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)        //对GART页表结构进行初始化,注意是通过前面的ttm机制申请对应的bo对象,填写也表现,一开始对应的都是无效页        r600_pcie_gart_init(struct radeon_device *rdev)            radeon_gart_init(struct radeon_device *rdev)            //为gart表分配显存页            radeon_gart_table_vram_alloc(struct radeon_device *rdev)        *************************************************STARTUP*********************************************************        //如果启动失败,那么说明GPU加速失败,驱动不可用        r600_startup(struct radeon_device *rdev)    

启动显卡

r600_startup(struct radeon_device *rdev)        //        r600_pcie_gen2_enable(struct radeon_device *rdev)        //对显存控制器进行设置,写相关寄存器,获得显存的基地址,大小,gtt的基地址,大小等等。完全的接管显存。        r600_mc_program(struct radeon_device *rdev)        //初始化微码,从指定的目录载入三个二进制文件到内存中,***_pfp.bin,***_me.bin,***_rlc.bin        r600_init_microcode(struct radeon_device *rdev)        //分配一个显存页,用作划痕页,创建了一个bo,用作radeon_device* 的一个属性        r600_vram_scratch_init(struct radeon_device *rdev)        //启动GART机制        r600_pcie_gart_enable(struct radeon_device *rdev)            /*                pin操作固定用作GART的存储页,作为常驻存储,在显卡的整个使用过程中都不会被显存控制器所管理,换出或者回收,只有在卸载驱动的时候会被回收。            */            radeon_gart_table_vram_pin(struct radeon_device *rdev)            //重建gart页表中的每个页的基地址,然后刷新TLB。接下来就会设置二级cache等等控制寄存器,当前这些页表中都指向一个dummy page,就是GPU访问每个页表项           //都是无效页             radeon_gart_restore(struct radeon_device *rdev)            //接着就刷新TLB            r600_pcie_gart_tlb_flush(rdev)        //设置GPU的一些功能部件:初始化rdev中GPU相关的一些参数,然后设置GPU的一些寄存器,这时GPU的的初始状态就设置的差不多了         r600_gpu_init(struct radeon_device *rdev)        //对拷屏操作的初始化,指的是一个图形从屏幕上一个位置移动到另一个位置。        //设置相关参数以及注册相关函数(顶点资源,纹理资源,shader等等的设置)        r600_blit_init(struct radeon_device *rdev)        //初始化回写驱动信息并分配内存,创建了一个bo,作为wb对象,并没有实际的硬件wb机制。官方注释为:分配回写缓冲        radeon_wb_init(struct radeon_device *rdev)        //先释放当前fence所对应的划痕寄存器,然后分配一个,设置fence序列号回写地址(GPU,CPU地址都需要设置),        //最后将fence序列号回写到划痕寄存器或者wb回写buffer中        //需要连续调用三次,分别为GFX,DMA,UVD        radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)            //释放一个划痕寄存器,一个device会有多个fence,这样也就对应多个fence driver。每个fence driver会拥有一个划痕寄存器用于回写fence序列号             radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)             radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg)            //将fence值写回到划痕寄存器,如果直接支持回写机制,那么会回写到回写buffer中             radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring)        **********************************************************************************************************************************************        //中断        radeon_irq_kms_init(struct radeon_device *rdev)            //初始化用于处理垂直同步机制的所有数据结构            //垂直同步的作用是防止画面撕裂,由于存在多个CRTC,所有每个CRTC都会有一个对应的等待队列            //对应需要处理的中断就是vblank中断,设置的数据结构包括定时器,引用计数,vblank各个阶段时间间隔            drm_vblank_init(struct drm_device *dev, int num_crtcs)            //MSI (Message Signaled Interrupts)            //判断当前GPU是否支持MSI,如果支持,调用pci_enable_msi(rdev->pdev)            radeon_msi_ok(struct radeon_device *rdev)            //安装中断处理函数,向系统中断处理机制中注册中断服务,??            drm_irq_install(struct drm_device *dev)        //中断ring的读写指针地址的设置,相关的中断控制,reset以及restore等的处理         r600_irq_init(struct radeon_device *rdev)            //创建一个bo,座位中断环形缓冲            r600_ih_ring_alloc(struct radeon_device *rdev)            //设置状态位和控制寄存器的值,使得CPU不会从irq ring中处理中断,GPU也不会产生中断写入ring            r600_disable_interrupts(struct radeon_device *rdev)            //先r600_rlc_stop(rdev);然后设置相关的一些寄存器值,再r600_rlc_start(rdev);大致就是设置GPU reset以及restore功能的硬件支持            r600_rlc_init(struct radeon_device *rdev)            //强制将所有中断的状态设置为disable            r600_disable_interrupt_state(rdev);            //没有实现,大致实现的功能应该为正确设置设备挂载到master管理链中接受管理            pci_set_master(rdev->pdev);            r600_enable_interrupts(rdev);        //设置相应的中断列表以及对应的中断处理程序,中断号《--》中断处理程序        r600_irq_set(struct radeon_device *rdev)        ********************************************************************************************************************************        //初始化GFX和DMA 环形缓冲大大小和位置,读写指针        radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,                 R600_CP_RB_RPTR, R600_CP_RB_WPTR,                 0, 0xfffff, RADEON_CP_PACKET2);        ********************************************************************************************************************************        //加载微码,使得CP能够开始动起来。这些微码已经在之前加载到了内存中        //首先将CP停止,软重置,然后从主存中载入ME和PFP的微码,仅仅是写入到对应的端口        r600_cp_load_microcode(struct radeon_device *rdev)          //将CP复位,如果在某次被停止,那么就需要调用复位函数resume,首先会对CP进行软重置,设置CP相依寄存器的值,包括ring的读写指针,延迟等等。        //最后启动r600_cp_start(rdev);并进行测试r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)        //测试过程就是首先往划痕寄存器中写入一个初始值,再让CP处理一个命令,往划痕寄存器中回写一个值,判断值是否正确被写入,需要被注意的就是        //验证的过程中设置了一定的延迟        r600_cp_resume(struct radeon_device *rdev)        //设置并驱动异步dma引擎,设置DMA环形缓冲并打开。初始化读写指针以及回写地址等等,同样也进行了ring test,更新实际可用的显存大小        //radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size)         r600_dma_resume(struct radeon_device *rdev)        //对UVC的ring进行初始化        radeon_ring_init(rdev, ring, ring->ring_size,                     R600_WB_UVD_RPTR_OFFSET,                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,                     0, 0xfffff, RADEON_CP_PACKET2);        //初始化间接缓冲池。初始化二级分配器用于管理一个内存池,用于间接缓冲        radeon_ib_pool_init(struct radeon_device *rdev)            //初始化一个二级分配器以及管理器等数据结构,指定pool的domain,size以及对齐方式等等            radeon_sa_bo_manager_init(struct radeon_device *rdev,                  struct radeon_sa_manager *sa_manager,                  unsigned size, u32 align, u32 domain)            //启动二级分配器,其实就是申请一块存储作为pool,并映射到虚拟地址空间,GPU和CPU地址            radeon_sa_bo_manager_start(struct radeon_device *rdev,                   struct radeon_sa_manager *sa_manager)        //打开音频引擎,并设置音频的相关变量        r600_audio_init(struct radeon_device *rdev)            r600_audio_engine_enable(struct radeon_device *rdev, bool enable)

显卡驱动入口

module_init(drm_core_int);

drm_core_init是在系统启动的时候进行调用,用于初始化drm驱动的相关数据结构。下面是调用流程

0 0
原创粉丝点击