zoukankan      html  css  js  c++  java
  • linux驱动(五)内核中静态映射表的建立

    1:我们在linux内核中都是开启mmu的所以都是用的虚拟地址,需要建立VA到PA的映射表;

    我们内核中映射表在arch/arm/mach-s5pv210/mach-smdkc110.c文件中

    建立映射的函数是,smdkc110_map_io建立映射表

    smdkc110_map_io 这个函数调用s5p_init_io函数真正

        s5p_init_io 

            iotable_init

        s3c24xx_init_clocks

        s5pv210_gpiolib_init

        s3c24xx_init_uarts

    smdkc110_map_io 这个函数调用s5p_init_io函数,s5p_init_io

    void __init s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr)

    我们来看一下s5p_init_io函数的原型需要三个参数:参数1:结构体数组指针,参数2:数组的成员个数;参数三:虚拟地址基地址

    函数s5p_init_io 在调用iotable_init函数建立静态映射表,实际上我们看一下iotable_init函数中跟没有用到之前传的参数2、参数3;

    直接把s5p_iodesc数组名当做数组首地址作为iotable_init函数的第一个参数、ARRAY_SIZE这个时自动计算的这个数组有几个成员组成;

    iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));

     下面我们来分析一下这个man_desc 这个类型的结构体

    struct map_desc {
      unsigned long virtual;      //虚拟地址
      unsigned long pfn;        //物理地址 .pfn = __phys_to_pfn(S5P_PA_CHIPID), 这里把物理地址放入__phys_to_pfn函数中传给.pfn

      unsigned long length;      //长度
      unsigned int type;        //type 
    };

    static struct map_desc s5p_iodesc为一个全局变量,实际上只需要有我们初始化好的这个全局变量数组 

    static struct map_desc s5p_iodesc[] __initdata = {
        {
            .virtual    = (unsigned long)S5P_VA_CHIPID,      //0xFD70_0000
            .pfn        = __phys_to_pfn(S5P_PA_CHIPID),      //0xE000_0000 >> 12
            .length        = SZ_4K,                  //4k
            .type        = MT_DEVICE,                 //0
        }, {
            .virtual    = (unsigned long)S3C_VA_SYS,        //0xFD10_0000
            .pfn        = __phys_to_pfn(S5P_PA_SYSCON),      //0xE010_0000 >> 12
            .length        = SZ_64K,                  //64k
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S3C_VA_UART,      //0xFE00_0000
            .pfn        = __phys_to_pfn(S3C_PA_UART),      //0xE290_0000 >> 12
            .length        = SZ_4K,  
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)VA_VIC0,
            .pfn        = __phys_to_pfn(S5P_PA_VIC0),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)VA_VIC1,
            .pfn        = __phys_to_pfn(S5P_PA_VIC1),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S3C_VA_TIMER,
            .pfn        = __phys_to_pfn(S5P_PA_TIMER),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S5P_VA_GPIO,      //0xFD50_0000
            .pfn        = __phys_to_pfn(S5P_PA_GPIO),      //0xE020_0000
            .length        = SZ_4K,                //大小 4k
            .type        = MT_DEVICE,                //0
        },
    };

    我们有了这个map_desc结构体通过iotable_init函数就可以创建我们再map_desc数组中的设置好的物理地址到虚拟地址映射;

    而真正建立虚拟地址到物理地址映射的函数是:create_mapping这个函数;

    static void __init smdkc110_map_io(void)
    {
        s5p_init_io(NULL, 0, S5P_VA_CHIPID);
        s3c24xx_init_clocks(24000000);
        s5pv210_gpiolib_init();
        s3c24xx_init_uarts(smdkc110_uartcfgs, ARRAY_SIZE(smdkc110_uartcfgs));
        s5p_reserve_bootmem(smdkc110_media_devs, ARRAY_SIZE(smdkc110_media_devs));
    #ifdef CONFIG_MTD_ONENAND
        s5pc110_device_onenand.name = "s5pc110-onenand";
    #endif
    #ifdef CONFIG_MTD_NAND
        s3c_device_nand.name = "s5pv210-nand";
    #endif
        s5p_device_rtc.name = "smdkc110-rtc";
    }
    void __init s5p_init_io(struct map_desc *mach_desc,
                int size, void __iomem *cpuid_addr)
    {
        unsigned long idcode;
    
        /* initialize the io descriptors we need for initialization */
        iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
        if (mach_desc)
            iotable_init(mach_desc, size);
    
        idcode = __raw_readl(cpuid_addr);
        s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
    }

     

    void __init iotable_init(struct map_desc *io_desc, int nr)
    {
        int i;
    
        for (i = 0; i < nr; i++)
            create_mapping(io_desc + i);
    }

     关于create_maping函数如何建立映射表参考

    http://blog.csdn.net/huyugv_830913/article/details/5884628

    http://blog.csdn.net/longyue0917/article/details/7424536

    映射表建立函数被调用

    http://blog.csdn.net/tongxinv/article/details/54698188

  • 相关阅读:
    第三节:模板模式——在Spring框架应用
    第二节:模板模式——模板模式应用
    idea ---- intelij IDEA安装
    计算机基础 ---- 编码(er)
    preg_match一些问题
    php 两个值进行比较的问题
    php中in_array一些问题
    配置完php.ini中的扩展库后,重启apache出现错误1067
    基于Intel 174;E810 的OVS-DPDK VXLAN TUNNEL性能优化
    tc filter 工作模式:传统模式和 direct-action 模式
  • 原文地址:https://www.cnblogs.com/biaohc/p/6626062.html
Copyright © 2011-2022 走看看