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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM