zoukankan      html  css  js  c++  java
  • [转]hisi mmz模块驱动讲解

    一、概述

             如图所示,在海思平台上将内存分为两个部分:os内存和mmz内存。os内存指:由linux操作系统管理的内存;mmz内存:由mmz驱动模块进行管理供媒体业务单独使用的内存,在驱动加载时可以指定该模块管理内存的大小:

    insmod mmz.ko mmz=anonymous,0,0x4fa00000,6Manony=1 || report_error

             该驱动主要由两个文件组成:media-mem.c和mmz-userdev.c,加载驱动后相应的设备文件:/dev/mmz_userdev,应用层通过打开该设备文件进行ioctl(申请mmz内存、释放mmz内存、重映射mmz内存到内核等)和直接mmap操作,而媒体底层驱动模块则直接调用mmz驱动的导出接口进行相应操作。

    二、数据结构

    1、mmz区域描述符

             hil_media_memory_zone描述了一个mmz区域的所有信息,可以有多个mmz区域,通过链表连接在一起。

    struct hil_media_memory_zone {

       char name[HIL_MMZ_NAME_LEN+1]; //mmz区域名字:anonymous

           

       unsigned long gfp;   //区域标识:0

       unsigned long phys_start; //mmz区域起始物理地址:0x4fa00000

       unsigned long nbytes; //mmz区域大小:6M

           

       struct list_head list; //mmz链表

       unsigned char *bitmap; //位图

       struct list_head mmb_list; //mmz区域的mmb链表,存放所有申请到的物理内存

       

       unsigned int alloc_type;

       unsigned long block_align;

       

       void (*destructor)(const void *);

    };

    2、mmb内存描述符

             hil_media_memory_block描述了从mmz区域申请一块内存,同一个mmz区域内的所有mmb通过链表连接。

    struct hil_media_memory_block {

       #ifndef MMZ_V2_SUPPORT

       unsigned int id;

       #endif

       char name[HIL_MMB_NAME_LEN+1]; //该mmb模块使用者名字

       struct hil_media_memory_zone *zone; //指向mmb所属的mmz区域

       struct list_head list; //mmb链表

            

       unsigned long phys_addr; //申请到的mmb起始物理地址

       void *kvirt;  //对应内核虚拟地址,从代码看未用

       unsigned long length; //申请的mmb大小

       

       unsigned long flags; //标识

       

       unsigned int order;

       int phy_ref; //引用计数

       int map_ref; //引用计数

    };

    3、mmz_userdev_info

             该结构体保存打开该设备文件的进程信息,存放在file结构体的private_data成员里。

    struct mmz_userdev_info {

       pid_t pid;         //打开设备文件的进程pid

       pid_t mmap_pid;

       struct semaphore sem; //信号量

       struct list_head list; //指向mmb_info链表

    };

    4、mmb_info

             该结构体描述应用申请到mmb后的相关信息,同进程的mmb_info通过链表形式管理。

    struct mmb_info {

       unsigned long phys_addr;    //申请到的物理内存,同mmb.phys.addr

       unsigned long align;        /* ifyou need your phys-memory have special align size */

       unsigned long size;     //申请的物理内存大小

       unsigned int order;

       

        void *mapped;       //指向mmap后的虚拟地址空间

           

       union {

           struct {

               unsigned long prot  :8; /*PROT_READ or PROT_WRITE */

               unsigned long flags :12;/* MAP_SHARED or MAP_PRIVATE */

       

    #ifdef __KERNEL__

               unsigned long reserved :8; /* reserved, do not use */

               unsigned long delayed_free :1;

               unsigned long map_cached :1;

    #endif

           };

           unsigned long w32_stuf;

       };

       

       char mmb_name[HIL_MMB_NAME_LEN+1];

       char mmz_name[HIL_MMZ_NAME_LEN+1];

       unsigned long gfp;      /*reserved, do set to 0 */

       

    #ifdef __KERNEL__

       int map_ref;

       int mmb_ref;

           

       struct list_head list;    //mmb_info链表

       hil_mmb_t *mmb;     //指向申请到的mmb

    #endif

    };

    三、关系图

    1、mmz和mmb关系

             下图展示了mmz驱动管理mmz和mmb的关系。mmz驱动模块支持多个mmz区域,只要在加载mmz.ko时通过参数传递即可,一般情况下只有一个mmz区域。多个mmz区域之间通过链表的形式组织在一起,链表头为mmz_list;而每个mmz区域通过mmb_list维护mmb链表,管理该区域内所有已经申请了的物理内存区域;每个mmb通过zone成员知道自己属于哪个mmz区域。

             通过/proc/media-mem可以查看mmz和mmb使用情况:

    +---ZONE: PHYS(0x4FA00000, 0x4FFFFFFF),GFP=0, nBYTES=6144KB,  NAME="anonymous"

      |-MMB: phys(0x4FA00000, 0x4FA81FFF), kvirt=0x  (null), flags=0x00000000, length=520KB,       name="DCCM_MSG_BUF"

      |-MMB: phys(0x4FA82000, 0x4FA84FFF), kvirt=0x  (null), flags=0x00000000, length=12KB,        name="SYS_scale_coef"

      |-MMB: phys(0x4FA85000, 0x4FA87FFF), kvirt=0x  (null), flags=0x00000000, length=12KB,        name="SYS_scale_coef"

      |-MMB: phys(0x4FA88000, 0x4FB07FFF), kvirt=0x  (null), flags=0x00000000, length=512KB,       name="TDE_MemPool"

       |-MMB: phys(0x4FB08000, 0x4FB3CFFF),kvirt=0x  (null), flags=0x00000000,length=212KB,      name="IVE_QUEUE"

      |-MMB: phys(0x4FB3D000, 0x4FB3DFFF), kvirt=0x  (null), flags=0x00000000, length=4KB,name="IVE_TEMP_NODE"

    ---MMZ_USE_INFO:

     total size=6144KB(6MB),used=1272KB(1MB +248KB),remain=4872KB(4MB + 776KB),zone_number=1,block_number=6

     

     

    2、mmb、mmb_info和mmb_userdev_info关系

             下图展示了mmz驱动和应用申请数据结构之间的关系:

             当应用打开设备文件/dev/mmz_userdev时会申请一个属于该进程的mmb_userdev_info结构体,mmb_userdev_info成员list指向属于该进程的所有mmb_info,mmb_info的mmb成员指向为其分配的mmb,而*mmaped存放mmb物理内存(phy_addr)进行映射后的虚拟地址供用户空间使用。

    由于mmz大部分为媒体业务独立使用,内存在媒体硬件模块流转,应用无需访问,这时不用映射,只有当应用需要访问时才需要进行映射。可以把mmz管理的整个内存看做存储盘上的一个大文件,应用层要访问mmz的物理内存通过mmap方式进行映射(类似文件),映射的文件偏移就是mmb.phy_addr,映射大小就是申请的mmb.length,通过mmap方式映射到内核后根据返回的虚拟地址就可以访问该mmb内存。

  • 相关阅读:
    多想一点和多做一步
    js 判断字符是否以汉字开头
    代码片断编辑测试窗
    部署WAR文件到tomcat
    ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse
    ROS机器人程序设计(原书第2版)补充资料 (陆) 第六章 点云 PCL
    ROS机器人程序设计(原书第2版)补充资料 (伍) 第五章 计算机视觉
    ROS机器人程序设计(原书第2版)补充资料 (肆) 第四章 在ROS下使用传感器和执行器
    ROS机器人程序设计(原书第2版)补充资料 (叁) 第三章 可视化和调试工具
    ROS机器人程序设计(原书第2版)补充资料 (贰) 第二章 ROS系统架构及概念
  • 原文地址:https://www.cnblogs.com/wlzy/p/9733110.html
Copyright © 2011-2022 走看看