【Linux驱动:静态映射表建立过程】

machine_desc结构体

内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植和系统启动过程中起到相当重要的作用, 内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。

该结构体的定义和声明在arch/arm/include/asm/mach/arch.h 目录中,如下:

struct machine_desc {
	/*
	 * Note! The first four elements are used
	 * by assembler code in head.S, head-common.S
	 */
	unsigned int		nr;		/* architecture number	*/
	unsigned int		phys_io;	/* start of physical io	*/
	unsigned int		io_pg_offst;	/* byte offset for io 
						 * page tabe entry	*/

	const char		*name;		/* architecture name	*/
	unsigned long		boot_params;	/* tagged list		*/

	unsigned int		video_start;	/* start of video RAM	*/
	unsigned int		video_end;	/* end of video RAM	*/

	unsigned int		reserve_lp0 :1;	/* never has lp0	*/
	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
	unsigned int		soft_reboot :1;	/* soft reboot		*/
	void			(*fixup)(struct machine_desc *,
					 struct tag *, char **,
					 struct meminfo *);
	void			(*map_io)(void);/* IO mapping function	*/
	void			(*init_irq)(void);
	struct sys_timer	*timer;		/* system tick timer	*/
	void			(*init_machine)(void);
};
#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				\
};

而该结构体的使用在各个平台结构下的mach-xxx.c中使用,如x210的\arch\arm\mach-s5pv210\mach-x210.c 中:
在这里插入图片描述
其中,.map_io成员是静态映射的关键接口。

函数分析

函数调用关系如下:

start_kernel
    setup_arch
        mdesc = setup_machine(machine_arch_type);
        paging_init(mdesc);
            devicemaps_init
                mdesc->map_io();//最终调用smdkc110_map_io

smdkc110_map_io分析:

smdkc110_map_io();
	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
		iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
	
/*		
 * Create the architecture specific mappings
 */
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_mapping接口,使用map_desc 类型的一个结构体进行后续映射工作的材料。而该结构体的实体就是调用iotable_init时的传参 s5p_iodesc。

map_desc 结构体

map_desc 类型定义如下:

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中,定义如下:

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,
    },
};

以上这个结构体填充了所以需要被映射的地址资源。后续可按需添加相应的映射资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值