MACHINE_START(SMDK6410, "SMDK6410")
/* Maintainer: Ben Dooks */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smdk6410_map_io,
.init_machine = smdk6410_machine_init,
.timer = &s3c64xx_timer,
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_START(SMDK6410, "SMDK6410")
#define MACHINE_START(_type,_name)
_type == SMDK6410
_name == “SMDK6410“
//////////////////////////////////////////////////////////////////////////////
上面变形一下,展开宏就是如下:
static const struct machine_desc __mach_desc_SMDK6410 = {
.nr = MACH_TYPE_SMDK6410,
.name = “SMDK6410“,
/* Maintainer: Ben Dooks */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smdk6410_map_io,
.init_machine = smdk6410_machine_init,
.timer = &s3c64xx_timer,
};
/////////////
由__section__(".arch.info.init"))可知static const struct machine_desc __mach_desc_SMDK6410 这个
成员是放在arch/arm/kernel/vmlinux.lds链接脚本的.arch.info.init段里的。
vmlinux.lds文本如下:
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
/////////////////////////////////////////////////////////////////////////////
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);
};
///////////////////////////////////////////////////////////////////////////////
看看 .init_machine = smdk6410_machine_init, 是如何被调用的?
/////////////
static void (*init_machine)(void) __initdata;
static int __init customize_machine(void)
{
/* customizes platform devices, or adds new ones */
if (init_machine)
//此处调用的就是 .init_machine = smdk6410_machine_init,
init_machine();
return 0;
}
///////////////////////////////////////////
//类同于module_initcall(customize_machine)
arch_initcall(customize_machine);
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
展开就是:
#define arch_initcall( customize_machine ) __define_initcall("3", customize_machine ,3)
__define_initcall(level,fn,id)
level = "3" fn = customize_machine id = 3
static initcall_t __initcall_customize_machine3 = customize_machine;
__section__(".initcall" level ".init") == __section__(".initcall""3"".init") == __section__(".initcall3.init")
__initcall_customize_machine3 是存放在 arch/arm/kernel/vmlinux.lds链接脚本的.initcall3.init段里的
///////////////////////////////////////////////////////////////////////////////
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;
setup_processor();
mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
reboot_setup("s");
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
/*
* If we have the old style parameters, convert them to
* a tag list.
*/
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
}
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
parse_cmdline(cmdline_p, from);
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
smp_init_cpus();
#endif
cpu_init();
/*
* Set up various architecture-specific pointers
*/
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
//函数指针init_machine变量在这里赋值。
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
early_trap_init();
}