linux驱动开发扩展--静态映射表建立过程

it2024-09-29  39

start_kernel     setup_arch         mdesc = setup_machine(machine_arch_type);         paging_init(mdesc);             devicemaps_init                 mdesc->map_io();

#ifdef CONFIG_MACH_SMDKC110 MACHINE_START(SMDKC110, "SMDKC110") #elif CONFIG_MACH_SMDKV210 MACHINE_START(SMDKV210, "SMDKV210") #endif /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .phys_io = S3C_PA_UART & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, .boot_params = S5P_PA_SDRAM + 0x100, //.fixup = smdkv210_fixup, .init_irq = s5pv210_init_irq, .map_io = smdkc110_map_io, .init_machine = smdkc110_machine_init, .timer = &s5p_systimer, MACHINE_END #define MACHINE_START(_type,_name) \ static const struct machine_desc __mach_desc_##_type \ __used \ __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_##_type, \ .name = _name, #define MACHINE_END \ };

 machine_desc结构体来控制系统体系架构相关部分的初始化。map_io成员即内核提供给用户的创建外设I/O资源到内核虚拟地址静态映射表的接口函数,这个函数需要我们自己实现。通常情况下可以实现得很简单,只要直接调用iotable_init创建映射表就行了。

smdkc110_map_io     s5p_init_io         iotable_init(s5p_iodesc,...)

static struct map_desc s5p_iodesc[] __initdata = { { .virtual = (unsigned long)S5P_VA_CHIPID, .pfn = __phys_to_pfn(S5P_PA_CHIPID), .length = SZ_4K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S3C_VA_SYS, .pfn = __phys_to_pfn(S5P_PA_SYSCON), .length = SZ_64K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S3C_VA_UART, .pfn = __phys_to_pfn(S3C_PA_UART), .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, .pfn = __phys_to_pfn(S5P_PA_GPIO), .length = SZ_4K, .type = MT_DEVICE, }, }; struct map_desc { unsigned long virtual;//映射后的虚拟地址 unsigned long pfn;//I/O资源物理地址所在的页帧号 unsigned long length;//I/O资源长度(一个页的大小可能是4K,所以最少是4K) unsigned int type;//I/O资源类型 };

 经过分析,真正的内核移植时给定的静态映射表在arch/arm/plat-s5p/cpu.c中的s5p_iodesc,本质是一个结构体数组,数组中每一个元素就是一个映射,这个映射描述了一段物理地址到虚拟地址之间的映射。这个结构体数组所记录的几个映射关系被iotable_init所使用,该函数负责将这个结构体数组格式的表建立成MMU所能识别的页表映射关系,这样在开机后可以直接使用相对应的虚拟地址来访问对应的物理地址。

最新回复(0)