Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15530752
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: 嵌入式

2009-08-11 12:41:27

如下为kernel打印的log信息:
physmap platform flash device: 02000000 at 60000000
physmap-flash.0: Found 2 x16 devices at 0x0 in 32-bit bank
 Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
cfi_cmdset_0001: Erase suspend on write enabled
Searching for RedBoot partition table in physmap-flash.0 at offset 0x1fc0000
5 RedBoot partitions found on MTD device physmap-flash.0
Creating 5 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000040000 : "RedBoot"
0x000000040000-0x000000600000 : "ramdisk"
0x000000600000-0x000000700000 : "zImage"
0x000001f80000-0x000001f81000 : "RedBoot config"

文件:drivers/mtd/redboot.c
module_init(redboot_parser_init);
static struct mtd_part_parser redboot_parser = {
    .owner = THIS_MODULE,
    .parse_fn = parse_redboot_partitions,   // 该函数将打印上面的log信息
    .name = "RedBoot",
};

static int __init redboot_parser_init(void)
{
    return register_mtd_parser(&redboot_parser);
}

调用register_mtd_parser注册本parser解释器

文件:drivers/mtd/mtdpart.c
static LIST_HEAD(part_parsers);
int register_mtd_parser(struct mtd_part_parser *p)
{
    spin_lock(&part_parser_lock);
    list_add(&p->list, &part_parsers);  // 将redboot_parser解释器追加到part_parsers解释器链表上[luther.gliethttp]
    spin_unlock(&part_parser_lock);

    return 0;
}
那part_parsers解释器链表上注册的众多mtd分区解释器什么时候被引用呢,以及通过什么接口被引用呢,
答案是:parse_mtd_partitions
来看看,首先是接口get_partition_parser(parser_name),它会根据传进的parser_name参数,
返回part_parsers解释器链表上名为parser_name的解释器,我们这里当然查询的是名为"RedBoot"的redboot_parser解释器了[luther.gliethttp]
static struct mtd_part_parser *get_partition_parser(const char *name)
{
    struct mtd_part_parser *p, *ret = NULL;

    spin_lock(&part_parser_lock);

    list_for_each_entry(p, &part_parsers, list)
        if (!strcmp(p->name, name) && try_module_get(p->owner)) {
            ret = p;
            break;
        }

    spin_unlock(&part_parser_lock);

    return ret;
}

int parse_mtd_partitions(struct mtd_info *master, const char **types,
             struct mtd_partition **pparts, unsigned long origin)
{
    struct mtd_part_parser *parser;
    int ret = 0;

    for ( ; ret <= 0 && *types; types++) {
        parser = get_partition_parser(*types);      // *types等于"RedBoot",返回redboot_parser
        if (!parser && !request_module("%s", *types))
                parser = get_partition_parser(*types);
        if (!parser) {
            printk(KERN_NOTICE "%s partition parsing not available\n",
                   *types);
            continue;
        }
        ret = (*parser->parse_fn)(master, pparts, origin); // 执行parse_redboot_partitions
        if (ret > 0) {
            printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
                   ret, parser->name, master->name);
        }
        put_partition_parser(parser);
    }
    return ret;
}
EXPORT_SYMBOL_GPL(parse_mtd_partitions);            // 导出,以供其他驱动调用该函数

对于2.6.30.4内核支持的ep9312开发板设备注册[luther.gliethttp].
可以先参考浅析开发板相关函数init_machine即edb9312_init_machine什么时候执行
文件:arch/arm/mach-ep93xx/edb9312.c
static struct physmap_flash_data edb9312_flash_data = {
    .width        = 4,
};
#define EP93XX_CS6_PHYS_BASE        0x60000000
#define SZ_32M                      0x02000000
static struct resource edb9312_flash_resource = {
    .start        = EP93XX_CS6_PHYS_BASE,                 // 物理起始地址0x60000000
    .end        = EP93XX_CS6_PHYS_BASE + SZ_32M - 1,    // nor flash大小32M
    .flags        = IORESOURCE_MEM,
};

static struct platform_device edb9312_flash = {
    .name        = "physmap-flash",              // 将由同名的"physmap-flash"驱动程序physmap_flash_driver管理[luther.gliethttp].
    .id        = 0,
    .dev        = {
        .platform_data    = &edb9312_flash_data,
    },
    .num_resources    = 1,
    .resource    = &edb9312_flash_resource,
};

static void __init edb9312_init_machine(void)
{
    ep93xx_init_devices();
    platform_device_register(&edb9312_flash);

    ep93xx_register_eth(&edb9312_eth_data, 1);
}

MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
    /* Maintainer: Toufeeq Hussain */
    .phys_io    = EP93XX_APB_PHYS_BASE,
    .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
    .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
    .map_io        = ep93xx_map_io,
    .init_irq    = ep93xx_init_irq,
    .timer        = &ep93xx_timer,
    .init_machine    = edb9312_init_machine,
MACHINE_END


对于2.6.30.4内核支持的ep9312开发板驱动接管设备[luther.gliethttp].
文件:drivers/mtd/maps/physmap.c
static struct platform_driver physmap_flash_driver = {
    .probe        = physmap_flash_probe,
    .remove        = physmap_flash_remove,
    .suspend    = physmap_flash_suspend,
    .resume        = physmap_flash_resume,
    .shutdown    = physmap_flash_shutdown,
    .driver        = {
        .name    = "physmap-flash",
        .owner    = THIS_MODULE,
    },
};

static int __init physmap_init(void)
{
    int err;

    err = platform_driver_register(&physmap_flash_driver);  // 名为"physmap-flash"的flash设备将使用该驱动[luther.gliethttp].
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
    if (err == 0)
        platform_device_register(&physmap_flash);
#endif

    return err;
}

module_init(physmap_init);


#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };// 使用RedBoot解释器redboot_parser
#endif

static int physmap_flash_probe(struct platform_device *dev)
{
    for (i = 0; i < dev->num_resources; i++) {
        printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
               (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
               (unsigned long long)dev->resource[i].start);
        ......
    }
    #ifdef CONFIG_MTD_PARTITIONS
    err = parse_mtd_partitions(info->cmtd, part_probe_types,// 寻找名为"RedBoot"的mtd分区parser解释器,然后执行它解释分区[luther.gliethttp].
                &info->parts, 0);
    if (err > 0) {
        add_mtd_partitions(info->cmtd, info->parts, err);   // 这样/proc/mtd下面就可以读到redboot烧写的分区了.
        info->nr_parts = err;
        return 0;
    }

    if (physmap_data->nr_parts) {
        printk(KERN_NOTICE "Using physmap partition information\n");
        add_mtd_partitions(info->cmtd, physmap_data->parts,
                   physmap_data->nr_parts);
        return 0;
    }
#endif

    add_mtd_device(info->cmtd);
    return 0;
}
阅读(3939) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~