NORFlash协议层

来源:互联网 发布:java程序员适合用mac吗 编辑:程序博客网 时间:2024/06/14 02:46

1、CFI mode:
①、注册 cfi_chipdrv :

static int __init cfi_probe_init(void){    register_mtd_chip_driver(&cfi_chipdrv);    return 0;}/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

在cfi_probe_init函数中调用register_mtd_chip_driver函数,将cfi_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv){    spin_lock(&chip_drvs_lock);    list_add(&drv->list, &chip_drvs_list);    spin_unlock(&chip_drvs_lock);}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

其中,cfi_chipdrv 结构体变量定义如下:

static struct mtd_chip_driver cfi_chipdrv = {    .probe      = cfi_probe,    .name       = "cfi_probe",    .module     = THIS_MODULE};/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

struct mtd_info *do_map_probe(const char *name, struct map_info *map){    struct mtd_chip_driver *drv;    struct mtd_info *ret;    drv = get_mtd_chip_driver(name);    ...}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &cfi_chipdrv给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name){    struct list_head *pos;    struct mtd_chip_driver *ret = NULL, *this;    spin_lock(&chip_drvs_lock);    list_for_each(pos, &chip_drvs_list) {        this = list_entry(pos, typeof(*this), list);        if (!strcmp(this->name, name)) {            ret = this;            break;        }    }    if (ret && !try_module_get(ret->module))        ret = NULL;    spin_unlock(&chip_drvs_lock);    return ret; //ret = &cfi_chipdrv}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map){    struct mtd_chip_driver *drv;    struct mtd_info *ret;    ...    ret = drv->probe(map); //drv = &cfi_chipdrv    ...    return ret;}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &cfi_chipdrv,执行执行drv->probe即相当于执行cfi_chipdrv.probe = cfi_probe:

struct mtd_info *cfi_probe(struct map_info *map){    /*     * Just use the generic probe stuff to call our CFI-specific     * chip_probe routine in all the possible permutations, etc.     */    return mtd_do_chip_probe(map, &cfi_chip_probe);}/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

其中,cfi_chip_probe如下定义:

static struct chip_probe cfi_chip_probe = {    .name       = "CFI",    .probe_chip = cfi_probe_chip};/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

cfi_probe ->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp){    struct mtd_info *mtd = NULL;    struct cfi_private *cfi;    /* First probe the map to see if we have CFI stuff there. */    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe     ...}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp){    struct cfi_private cfi;    struct cfi_private *retcfi;    unsigned long *chip_map;    int i, j, mapsize;    int max_chips;    memset(&cfi, 0, sizeof(cfi));    /* Call the probetype-specific code with all permutations of       interleave and device type, etc. */    if (!genprobe_new_chip(map, cp, &cfi)) {        /* The probe didn't like it */        pr_debug("%s: Found no %s device at location zero\n",             cp->name, map->name);        return NULL;    }    ...}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,                 struct cfi_private *cfi){    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */    int max_chips = map_bankwidth(map); /* And minimum 1 */    int nr_chips, type;    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {        ...        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {            ...            if (cp->probe_chip(map, 0, NULL, cfi))                return 1;        }    }    return 0;}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &cfi_chip_probe 所以执行执行cp->probe_chip相当于执行cfi_chip_probe.probe_chip = cfi_probe_chip。
2、JEDEC mode:
①、注册jedec_chipdrv :

static int __init jedec_probe_init(void){    register_mtd_chip_driver(&jedec_chipdrv);    return 0;}

在jedec_probe_init函数中调用register_mtd_chip_driver函数,将jedec_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv){    spin_lock(&chip_drvs_lock);    list_add(&drv->list, &chip_drvs_list);    spin_unlock(&chip_drvs_lock);}

其中,jedec_chipdrv 定义如下:

static struct mtd_chip_driver jedec_chipdrv = {    .probe  = jedec_probe,    .name   = "jedec_probe",    .module = THIS_MODULE};

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

struct mtd_info *do_map_probe(const char *name, struct map_info *map){    struct mtd_chip_driver *drv;    struct mtd_info *ret;    drv = get_mtd_chip_driver(name);    ...}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &jedec_chipdrv 给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name){    struct list_head *pos;    struct mtd_chip_driver *ret = NULL, *this;    spin_lock(&chip_drvs_lock);    list_for_each(pos, &chip_drvs_list) {        this = list_entry(pos, typeof(*this), list);        if (!strcmp(this->name, name)) {            ret = this;            break;        }    }    if (ret && !try_module_get(ret->module))        ret = NULL;    spin_unlock(&chip_drvs_lock);    return ret; //ret = &jedec_chipdrv }/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map){    struct mtd_chip_driver *drv;    struct mtd_info *ret;    ...    ret = drv->probe(map); //drv = &jedec_chipdrv     ...    return ret;}/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &jedec_chipdrv ,执行执行drv->probe即相当于执行jedec_chipdrv .probe = jedec_probe:

static struct mtd_info *jedec_probe(struct map_info *map){    /*     * Just use the generic probe stuff to call our CFI-specific     * chip_probe routine in all the possible permutations, etc.     */    return mtd_do_chip_probe(map, &jedec_chip_probe);}/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

其中,jedec_chip_probe 定义如下:

static struct chip_probe jedec_chip_probe = {    .name = "JEDEC",    .probe_chip = jedec_probe_chip};/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

jedec_probe->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp){    struct mtd_info *mtd = NULL;    struct cfi_private *cfi;    /* First probe the map to see if we have CFI stuff there. */    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe     ...}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp){    struct cfi_private cfi;    struct cfi_private *retcfi;    unsigned long *chip_map;    int i, j, mapsize;    int max_chips;    memset(&cfi, 0, sizeof(cfi));    /* Call the probetype-specific code with all permutations of       interleave and device type, etc. */    if (!genprobe_new_chip(map, cp, &cfi)) {        /* The probe didn't like it */        pr_debug("%s: Found no %s device at location zero\n",             cp->name, map->name);        return NULL;    }    ...}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,                 struct cfi_private *cfi){    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */    int max_chips = map_bankwidth(map); /* And minimum 1 */    int nr_chips, type;    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {        ...        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {            ...            if (cp->probe_chip(map, 0, NULL, cfi))                return 1;        }    }    return 0;}/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &jedec_chip_probe,所以执行执行cp->probe_chip相当于执行jedec_chip_probe.probe_chip =jedec_probe_chip 。

0 0
原创粉丝点击