/drivers/mtd/chips下文件的主要功能是探测MTD,该目录下文件是chipreg.c、gen_probe.c、cfi_probe.c、jedec_probe.c、cfi_cmdset_0001.c、cfi_cmdset_0002.c、map_rom.c、map_ram.c、map_absent.c、amd_flash.c、jedec.c和sharp.c,下面介绍每个文件的功能
为了确定一个Flash是否是一个CFI使能的flash memory器件,首先要往Flash的地址0x55H写入数据0x98H,然后从Flash的地址0x10H处开始连续读取3个存储单元中的内容,如果数据总线返回的3个存储单元的字符分别为'Q','R'和'Y',那么该器件是一个CFI使能的Flash。在识别Flash为CFI使能器件后,通过查询命令来读取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文件。
不同的制造商使用不同的命令集,目前Linux的MTD实现的命令集有AMD/Fujitsu的标准命令集和Intel/Sharp的扩展命令集(兼容Intel/Sharp标准命令集)两个,这两个命令集分别在cfi_cmdset_0002.c和cfi_cmdset_0001.c中实现。
此外还有一些非CFI标准的Flash,其中“jedec”类型的Flash的探测程序在jedec.c中,“sharp”类型的Flash的探测程序在sharp.c中“amd_flash”类型的Flash的探测程序在amd_flash.c中。
最后,还有一些非Flash的MTD,比如ROM或absent(无)设备。这些设备的探测程序在map_rom.c、map_ram.c和map_absent.c中。
所有类型的芯片都通过chipreg.c中的do_map_probe()程序驱动
关于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()获得符合指定name的MTD芯片驱动器,再调用获得的芯片驱动器的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的芯片驱动器
说明:
根据name从chip_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)
注释:
无
功能:
根据name和map的信息探测MTD并返回mtd_info结构
说明:
1. 根据name获得mtd_chip_driver
2. 调用mtd_chip_driver中的probe函数
参数:
name:MTD芯片类型
map:MTD芯片信息
返回:
成功:返回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”型芯片的探测程序,主要由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_driver从MTD芯片驱动器列表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:基地址
cfi:CFI私有信息
返回:
成功:返回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的成员cfiq(cfi_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”型芯片的探测程序,主要由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_driver从MTD芯片驱动器列表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)
注释:
无
功能:
根据index从jedec_table中选择对应的信息赋给p_cfi
说明:
无
参数:
p_cfi:cfi_private结构的CFI私有信息
index:芯片在jedec_table中的索引
返回:
成功:返回1
失败:返回0
调用:
无
被调用:
jedec_probe_chip()
源代码:
无
通用芯片探测程序,由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结构
参数:
map:MTD芯片信息
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:芯片信息
cp:chip_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:芯片信息
cp:chip_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
参数:
map:MTD芯片信息
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
参数:
map:MTD芯片信息
primary:FIXME
返回:
存在命令集:返回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;
}