MTD源代码分析(四)

/drivers/mtd/chips子目录

/drivers/mtd/chips下文件的主要功能是探测MTD,该目录下文件是chipreg.cgen_probe.ccfi_probe.cjedec_probe.ccfi_cmdset_0001.ccfi_cmdset_0002.cmap_rom.cmap_ram.cmap_absent.camd_flash.cjedec.csharp.c,下面介绍每个文件的功能

为了确定一个Flash是否是一个CFI使能的flash memory器件,首先要往Flash的地址0x55H写入数据0x98H,然后从Flash的地址0x10H处开始连续读取3个存储单元中的内容,如果数据总线返回的3个存储单元的字符分别为'Q','R''Y',那么该器件是一个CFI使能的Flash。在识别FlashCFI使能器件后,通过查询命令来读取CFI查询结构,这些数据的地址和含义在cfi_ident.h文件中。探测CFI接口Flash设备的程序在文件cfi_probe.c中,这些设备的类型为“cfi_probe”。

也可以用JEDEC(电子电器设备联合会)标准设备模仿CFI接口,探测JEDEC设备的程序在jedec_probe.c中,JEDEC设备的类型为“jedec_probe”。

CFI设备和JEDEC设备都要用到gen_probe.c文件。

不同的制造商使用不同的命令集,目前LinuxMTD实现的命令集有AMD/Fujitsu的标准命令集和Intel/Sharp的扩展命令集(兼容Intel/Sharp标准命令集)两个,这两个命令集分别在cfi_cmdset_0002.ccfi_cmdset_0001.c中实现。

此外还有一些非CFI标准的Flash,其中“jedec”类型的Flash的探测程序在jedec.c,sharp”类型的Flash的探测程序在sharp.c中“amd_flash”类型的Flash的探测程序在amd_flash.c中。

       最后,还有一些非FlashMTD,比如ROMabsent(无)设备。这些设备的探测程序在map_rom.cmap_ram.cmap_absent.c中。

       所有类型的芯片都通过chipreg.c中的do_map_probe()程序驱动

 

chipreg.c

关于MTD芯片注册的文件,此文件中定义的chip_drvs_list是所有芯片类型的驱动器链表,在/drivers/mtd/chips子目录下的其他文件通过调用register_mtd_chip_driver()unregister_mtd_chip_driver()向此链表中添加或去除MTD芯片驱动器。

/drivers/mtd/map/下的文件根据芯片类型调用do_map_probe()do_map_probe()通过get_mtd_chip_driver()获得符合指定nameMTD芯片驱动器,再调用获得的芯片驱动器的probe程序。

chip_drvs_list

static LIST_HEAD(chip_drvs_list);

MTD芯片驱动器列表

 

register_mtd_chip_driver

格式:

       void register_mtd_chip_driver(struct mtd_chip_driver *drv)

注释:

      

功能:

       注册MTD的芯片驱动器

说明:

       chip_drvs_list里添加mtd_chip_driver

参数:

       drv:被注册的MTD的芯片驱动器

返回:

      

调用:

       list_add()

被调用:

各种芯片驱动的初始化程序

源代码:

{

       spin_lock(&chip_drvs_lock);

       list_add(&drv->list, &chip_drvs_list);

       spin_unlock(&chip_drvs_lock);

}

 

 

unregister_mtd_chip_driver

格式:

       void unregister_mtd_chip_driver(struct mtd_chip_driver *drv)

注释:

      

功能:

       删除一个MTD芯片的驱动器

说明:

       chip_drvs_list中删除一个mtd_chip_driver

参数:

       drv:被删除的MTD芯片的驱动器

返回:

      

调用:

       list_del()

被调用:

       各种芯片驱动的清除程序

源代码:

{

       spin_lock(&chip_drvs_lock);

       list_del(&drv->list);

       spin_unlock(&chip_drvs_lock);

}

 

 

get_mtd_chip_driver

格式:

       static struct mtd_chip_driver *get_mtd_chip_driver (char *name)

注释:

      

功能:

获得指定名称的MTD的芯片驱动器

说明:

       根据namechip_drvs_list中获得一个mtd_chip_driver

参数:

       name:该芯片驱动器的名称

返回:

       找到:返回该mtd_chip_driver

       没找到:返回NULL

调用:

      

被调用:

       do_map_probe

源代码:

{

       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_inc_mod_count(ret->module)) {

              /* Eep. Failed. */

              ret = NULL;

       }

 

       spin_unlock(&chip_drvs_lock);

 

       return ret;

}

 

do_map_probe

格式:

struct mtd_info *do_map_probe(char *name, struct map_info *map)

注释:

      

功能:

       根据namemap的信息探测MTD并返回mtd_info结构

说明:

1.  根据name获得mtd_chip_driver

2.  调用mtd_chip_driver中的probe函数

参数:

       nameMTD芯片类型

       mapMTD芯片信息

返回:

       成功:返回MTD设备的结构mtd_info

       失败:返回NULL

调用:

       get_mtd_chip_driver()

       drv->probe()

被调用:

       /drivers/mtd/maps/下的板子相关文件中的init_xxxx

源代码:

{

       struct mtd_chip_driver *drv;

       struct mtd_info *ret;

 

       drv = get_mtd_chip_driver(name);

 

       if (!drv && !request_module(name))

              drv = get_mtd_chip_driver(name);

 

       if (!drv)

              return NULL;

 

       ret = drv->probe(map);

#ifdef CONFIG_MODULES

       /* We decrease the use count here. It may have been a

          probe-only module, which is no longer required from this

          point, having given us a handle on (and increased the use

          count of) the actual driver code.

       */

       if(drv->module)

              __MOD_DEC_USE_COUNT(drv->module);

#endif

 

       if (ret)

              return ret;

      

       return NULL;

}

 

cfi_probe.c

“cfi_probe”型芯片的探测程序,主要由cfi_chip_probe()cfi_probe()cfi_chip_setup()qry_present()cfi_probe_init()cfi_probe_exit()这几个函数组成。

cfi_probe()“cfi_probe”类型芯片的探测程序,它调用通用探测程序mtd_do_chip_probe(),并将cfi_chip_probe作为参数传递给mtd_do_chip_probe()mtd_do_chip_probe()将间接调用cfi_chip_probe的成员函数cfi_probe_chip()cfi_probe()注册在“cfi_probe”芯片的驱动器cfi_chipdrv中。

cfi_probe_chip()将调用qry_present()cfi_chip_setup()初始化cfi_private结构,qry_presetn()负责验证该MTD设备支持CFI接口,cfi_chip_setup()则读出CFI查询结构中的数据(见cfi.h

cfi_probe_init()cfi_probe_exit()“cfi_prbe”型芯片驱动器的注册程序和清除程序。

 

 

cfi_chipdrv

static struct mtd_chip_driver cfi_chipdrv = {

       probe: cfi_probe,           芯片的探测程序

       name: "cfi_probe",         芯片名称

       module: THIS_MODULE

};

“cfi_probe”类型MTD芯片的驱动器

 

cfi_probe_init

格式:

       int __init cfi_probe_init(void)

注释:

      

功能:

       初始化“cfi_probe”类型的MTD芯片

说明:

       调用register_mtd_chip_driver()cfi_chipdrv加入MTD驱动器列表chip_drvs_list

参数:

      

返回:

       0

调用:

       register_mtd_chip_driver()

被调用:

       __init

       module_init

源代码:

{

       register_mtd_chip_driver(&cfi_chipdrv);

       return 0;

}

 

cfi_probe_exit

格式:

static void __exit cfi_probe_exit(void)

注释:

      

功能:

       清除“cfi_probe”MTD芯片驱动

说明:

       调用unregister_mtd_chip_driverMTD芯片驱动器列表chip_drvs_list中删除cfi_chipdrv

参数:

      

返回:

      

调用:

       unregister_mtd_chip_driver()

被调用:

       __exit

       module_exit

源代码:

{

       unregister_mtd_chip_driver(&cfi_chipdrv);

}

 

cfi_probe

格式:

struct mtd_info *cfi_probe(struct map_info *map)

注释:

      

功能:

       “cfi_probe”类型MTD芯片的探测程序

说明:

       调用通用的探测程序mtd_do_chip_probe(),并将cfi_chip_probe作为参数传进去

参数:

       map:芯片的相关信息

返回:

       MTD设备信息结构mtd_info

调用:

       mtd_do_chip_probe

被调用:

       注册在cfi_chipdrv中,根据芯片类型被do_map_probe()调用

源代码:

{

       /*

        * 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);

}

 

 

cfi_chip_probe

static struct chip_probe cfi_chip_probe = {

       name: "CFI",

       probe_chip: cfi_probe_chip

};

cfi_probe传递给通用探测程序mtd_do_chip_probe的参数

 

 

cfi_probe_chip

格式:

static int cfi_probe_chip(struct map_info *map, __u32 base,

                       struct flchip *chips, struct cfi_private *cfi)

注释:

      

功能:

       “cfi_probe”类型MTD芯片驱动程序

说明:

1.  调用qry_present()检查是否CFI接口的MTD

2.  如果cfi->numchips=0,调用cfi_chip_setup()设置;(搜索新芯片)

3.  否则探测此芯片是否为原芯片的别名,如果不是,此芯片作为同类芯片加入

参数:

       FIXME

返回:

       成功:返回1

       失败:返回0-1

调用:

       qry_present()

       cfi_chip_setup()

被调用:

       注册在cfi_chip_probe

源代码:

{

       int i;

      

       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);   //reset,进入读模式

       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);       //发送查询命令

 

       if (!qry_present(map,base,cfi))            //如果不存在QRY,则不是CFI接口

              return 0;

 

       if (!cfi->numchips) {            //如果是MTD原始设备中的第一块芯片

              /* This is the first time we're called. Set up the CFI

                 stuff accordingly and return */

              return cfi_chip_setup(map, cfi);

       }

 

       /* Check each previous chip to see if it's an alias */

       for (i=0; i<cfi->numchips; i++) {

              /* This chip should be in read mode if it's one

                 we've already touched. */

              if (qry_present(map,chips[i].start,cfi)) {

                     /* Eep. This chip also had the QRY marker.

                      * Is it an alias for the new one? */

                     cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);

 

                     /* If the QRY marker goes away, it's an alias */

                     if (!qry_present(map, chips[i].start, cfi)) {

                            printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx/n",

                                   map->name, base, chips[i].start);

                            return 0;

                     }

                     /* Yes, it's actually got QRY for data. Most

                      * unfortunate. Stick the new chip in read mode

                      * too and if it's the same, assume it's an alias. */

                     /* FIXME: Use other modes to do a proper check */

                     cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);

                    

                     if (qry_present(map, base, cfi)) {

                            printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx/n",

                                   map->name, base, chips[i].start);

                            return 0;

                     }

              }

       }

      

       /* OK, if we got to here, then none of the previous chips appear to

          be aliases for the current one. */

       if (cfi->numchips == MAX_CFI_CHIPS) {

              printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d./n", map->name, MAX_CFI_CHIPS);

              /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */

              return -1;

       }

       chips[cfi->numchips].start = base;

       chips[cfi->numchips].state = FL_READY;

       cfi->numchips++;

      

       /* Put it back into Read Mode */

       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);

 

       printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode/n",

              map->name, cfi->interleave, cfi->device_type*8, base,

              map->buswidth*8);

      

       return 1;

}

 

 

qry_present

格式:

       static inline int qry_present(struct map_info *map, __u32 base,

                            struct cfi_private *cfi)

注释:

/* check for QRY, or search for jedec id.

   in: interleave,type,mode

   ret: table index, <0 for error

 */  

功能:

       检查QRY

说明:

       读出从0x10开始的三个字节,如果为”QRY”,则说明是CFI接口的MTD

参数:

       map:芯片信息

       base:基地址

       cfiCFI私有信息

返回:

       成功:返回1

       失败:返回0

调用:

      

被调用:

       cfi_probe_chip()

源代码:

{

       int osf = cfi->interleave * cfi->device_type; // scale factor

 

       if (cfi_read(map,base+osf*0x10)==cfi_build_cmd('Q',map,cfi) &&

           cfi_read(map,base+osf*0x11)==cfi_build_cmd('R',map,cfi) &&

           cfi_read(map,base+osf*0x12)==cfi_build_cmd('Y',map,cfi))

              return 1;  // ok !

 

       return 0;        // nothing found

}

 

cfi_chip_setup

格式:

       static int cfi_chip_setup(struct map_info *map,

                 struct cfi_private *cfi)

注释:

      

功能:

       设置cfi_private结构变量cfi的成员cfiqcfi_ident结构)

说明:

1.  读取器件可擦除块区域个数

2.  分配并清零内存块

3.  调用cfi_read_query()读取CFI数据结构cfi_ident

参数:

       map:芯片信息

       cfi:被设置的cfi_private结构

返回:

       成功:返回1

       失败:返回0

调用:

      

被调用:

       cfi_chip_probe()

源代码:

{

       int ofs_factor = cfi->interleave*cfi->device_type;

       __u32 base = 0;

       int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);

       int i;

 

#ifdef DEBUG_CFI

       printk("Number of erase regions: %d/n", num_erase_regions);

#endif

       if (!num_erase_regions)

              return 0;

 

       cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);

       if (!cfi->cfiq) {

              printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure/n", map->name);

              return 0;

       }

      

       memset(cfi->cfiq,0,sizeof(struct cfi_ident));      

      

       cfi->cfi_mode = 1;        //JEDEC仿真模式

       cfi->fast_prog=1;          /* CFI supports fast programming *///CFI支持Fast Program模式

      

       /* Read the CFI info structure */

       for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) {

              ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);

       }

      

       /* Do any necessary byteswapping */

       cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);

      

       cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);

       cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);

       cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);

       cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);

       cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);

 

#ifdef DEBUG_CFI

       /* Dump the information therein */

       print_cfi_ident(cfi->cfiq);

#endif

 

       for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {

              cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);

             

#ifdef DEBUG_CFI             

              printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks/n",

                     i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,

                     (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);

#endif

       }

       /* Put it back into Read Mode */

       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);

 

       return 1;

}

 

 

jedec_probe.c

“jedec_probe”型芯片的探测程序,主要由jedec_probe()jedec_probe_chip()cfi_jedec_setup()jedec_probe_init()jedec_probe_exit()这几个函数组成。

jedec_probe()“jedec_probe”类型芯片的探测程序,它调用通用探测程序mtd_do_chip_probe(),并将jedec_chip_probe作为参数传递给mtd_do_chip_probe()mtd_do_chip_probe()将间接调用jedec_chip_probe的成员函数jedec_probe_chip()jedec_probe()注册在“jedec_probe”芯片的驱动器jedec_chipdrv中。

jedec_probe_chip()调用cfi_jedec_setup()初始化cfi_private结构,cfi_jedec_setup()根据

jedec_probe_init()jedec_probe_exit()“cfi_prbe”型芯片驱动器的注册程序和清除程序

 

 

amd_flash_info

struct amd_flash_info {

       const __u16 mfr_id;

       const __u16 dev_id;

       const char *name;

       const int DevSize;

       const int InterfaceDesc;

       const int NumEraseRegions;

       const int CmdSet;

       const ulong regions[4];

};

AMD Flash芯片的信息结构

 

 

jedec_table

static const struct amd_flash_info jedec_table[] = {}

包含各种jedec_probe类型芯片信息的结构

 

 

jedec_chipdrv

static struct mtd_chip_driver jedec_chipdrv = {

       probe: jedec_probe,              芯片的探测程序

       name: "jedec_probe",     芯片名称

       module: THIS_MODULE

};

“jedec_probe”型芯片的驱动器

 

jedec_probe_init

格式:

       int __init jedec_probe_init(void)

注释:

      

功能:

       初始化“jedec_probe”类型的MTD芯片

说明:

       调用register_mtd_chip_driver()jedec_chipdrv加入MTD驱动器列表chip_drvs_list

参数:

      

返回:

       0

调用:

       register_mtd_chip_driver()

被调用:

       __init

       module_init

源代码:

{

       register_mtd_chip_driver(&jedec_chipdrv);

       return 0;

}

 

 

jedec_probe_exit

格式:

       static void __exit jedec_probe_exit(void)

注释:

      

功能:

       清除“jedec_probe”MTD芯片驱动

说明:

       调用unregister_mtd_chip_driverMTD芯片驱动器列表chip_drvs_list中删除jedec_chipdrv

参数:

      

返回:

      

调用:

       unregister_chip_driver

被调用:

       __exit

       module_exit

源代码:

{

       unregister_mtd_chip_driver(&jedec_chipdrv);

}

 

 

jedec_probe

格式:

       struct mtd_info *jedec_probe(struct map_info *map)

注释:

      

功能:

       “jedec_probe”MTD芯片的探测程序

说明:

       调用通用探测程序mtd_do_chip_probe(),并将jedec_chip_probe作为参数传递给mtd_do_chp_probe()

参数:

       map:芯片信息

返回:

       MTD设备信息结构mtd_info

调用:

       mtd_do_chip_probe()

被调用:

       注册在jedec_chipdrv中,根据芯片类型被do_map_probe()调用

源代码:

{

       /*

        * 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);

}

 

jedec_probe_chip

static struct chip_probe jedec_chip_probe = {

       name: "JEDEC",

       probe_chip: jedec_probe_chip

};

jedec_probe传递给通用探测程序mtd_do_chip_probe的参数

 

 

jedec_probe_chip

格式:

       static int jedec_probe_chip(struct map_info *map, __u32 base,

                           struct flchip *chips, struct cfi_private *cfi)

注释:

      

功能:

       “jedec_probe”类型MTD芯片驱动程序

说明:  

       主要工作是设置传进的cfi_private型参数cfi

参数:

       FIXME

返回:

       成功:返回1

       失败:返回0

调用:

       cfi_jedec_stup()

被调用:

       注册在jedec_chip_probe

源代码:

      

 

 

cfi_jedec_setup

格式:

static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)

注释:

      

功能:

       根据indexjedec_table中选择对应的信息赋给p_cfi

说明:

      

参数:

       p_cficfi_private结构的CFI私有信息

       index:芯片在jedec_table中的索引

返回:

       成功:返回1

       失败:返回0

调用:

      

被调用:

       jedec_probe_chip()

源代码:

      

 

 

 

gen_probe.c

通用芯片探测程序,由mtd_do_chip_probe()genprobe_ident_chips()genprobe_new_chip()check_cmd_set()cfi_cmdset_unknown()组成

cfi_probe()jedec_probe()调用mtd_do_chip_probe()mtd_do_chip_probe()调用genprobe_ident_chips()genprobe_ident_chips()调用genprobe_new_chip()genprobe_new_chip()则调用mtd_do_chip_probe()的参数chip_probe->probe_chip()

 

mtd_do_chip_probe

格式:

       struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)

注释:

      

功能:

       根据MTD芯片的信息map和参数cp返回MTD设备mtd_info结构

说明:

       获得cfi_private结构

       调用check_cmd_set()返回mtd_info结构

参数:

       mapMTD芯片信息

       cp:由cfi_probe()jedec_probe()传进来的信息

返回:

       MTD设备信息

调用:

       genprobe_ident_chips()

       check_cmd_set()

被调用:     

       cfi_probe()

       jedec_probe()

源代码:

{

       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);

      

       if (!cfi)

              return NULL;

 

       map->fldrv_priv = cfi;

       /* OK we liked it. Now find a driver for the command set it talks */

 

       mtd = check_cmd_set(map, 1); /* First the primary cmdset */

       if (!mtd)

              mtd = check_cmd_set(map, 0); /* Then the secondary */

      

       if (mtd)

              return mtd;

 

       printk(KERN_WARNING"cfi_probe: No supported Vendor Command Set found/n");

      

       kfree(cfi->cfiq);

       kfree(cfi);

       map->fldrv_priv = NULL;

       return NULL;

}

 

 

 

genprobe_ident_chips

格式:

       struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)

注释:

      

功能:

       生成cfi_private结构并返回

说明:

1.  调用genprobe_new_chip搜索第一块flash芯片

2.  设置cfi.chipshift,并将cfi.numchips设置为1

3.  循环调用cp->probe_chip()搜索所有的flash芯片

参数:

       map:芯片信息

       cpchip_probe结构参数

返回:

       cfi_private结构

调用:

       genprobe_new_chip()

被调用:

       mtd_do_chip_probe()

源代码:

      

 

genprobe_new_chip

格式:

       static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,

                          struct cfi_private *cfi)

注释:

      

功能:

       设置cfi

说明:

       调用cp->probe_chip()

参数:

       map:芯片信息

       cpchip_probe结构参数

       cfi:被设置的cfi_private结构

返回:

       成功:返回1

       失败:返回0

调用:

       cfi-> probe_chip()

被调用:

       genprobe_ident_chips()

源代码:

      

 

 

 

check_cmd_set

格式:

       static struct mtd_info *check_cmd_set(struct map_info *map, int primary)

注释:

      

功能:

       根据map_info中的厂商信息调用不同的命令集

说明:

       根据厂商类型调用两个不同的命令集,cfi_cmdset_0001()cfi_cmdset_0002(),如果符合的类型没有则调用cfi_cmdset_unkown

参数:

       mapMTD芯片信息

       primary:如果取1,则芯片厂商信息为map中的primary,否则为auxillary

返回:

       MTD设备信息mtd_info

调用:

       cfi_cmdset_0001()

       cfi_cmdset_0002()

       cfi_cmdset_unknown()

被调用:

       mtd_do_chip_probe()

源代码:

{

       struct cfi_private *cfi = map->fldrv_priv;

       __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;

      

       if (type == P_ID_NONE || type == P_ID_RESERVED)

              return NULL;

 

       switch(type){

              /* Urgh. Ifdefs. The version with weak symbols was

               * _much_ nicer. Shame it didn't seem to work on

               * anything but x86, really.

               * But we can't rely in inter_module_get() because

               * that'd mean we depend on link order.

               */

#ifdef CONFIG_MTD_CFI_INTELEXT

       case 0x0001:

       case 0x0003:

              return cfi_cmdset_0001(map, primary);

#endif

#ifdef CONFIG_MTD_CFI_AMDSTD

       case 0x0002:

              return cfi_cmdset_0002(map, primary);

#endif

       }

 

       return cfi_cmdset_unknown(map, primary);

}

 

cfi_cmdset_unkown

格式:

       static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, int primary)

注释:

      

功能:

       调用未知类型的命令集

说明:

       如果存在返回mtd_info,如果不存在返回NULL

参数:

       mapMTD芯片信息

       primaryFIXME

返回:

       存在命令集:返回mtd_info

       否则:返回NULL

调用:

      

被调用:

       check_cmd_set()

源代码:

{

       struct cfi_private *cfi = map->fldrv_priv;

       __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;

#if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE)

       char probename[32];

       cfi_cmdset_fn_t *probe_function;

 

       sprintf(probename, "cfi_cmdset_%4.4X", type);

             

       probe_function = inter_module_get_request(probename, probename);

 

       if (probe_function) {

              struct mtd_info *mtd;

 

              mtd = (*probe_function)(map, primary);

              /* If it was happy, it'll have increased its own use count */

              inter_module_put(probename);

              return mtd;

       }

#endif

       printk(KERN_NOTICE "Support for command set %04X not present/n",

              type);

 

       return NULL;

}

你可能感兴趣的:(MTD源代码分析(四))