CFI查询(五)

2024-04-06 05:08
文章标签 查询 cfi

本文主要是介绍CFI查询(五),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接着上一篇

1、我们以前说过,CFI闪存芯片还可能提供“主算法扩充查询表”和“次算法扩充查询表”,我们对此尚未进行查询。

回到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);
这一部分是前几篇的主题。

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;

通过两次check_cmd_set函数,读入上述的主、次两个表,也就是对芯片所支持操作规程的附加参数。源码如下:

static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
{
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      intel的
case 0x0001:
case 0x0003:
return cfi_cmdset_0001(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_AMDSTD      AMD的
case 0x0002:
return cfi_cmdset_0002(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_STAA
        case 0x0020:
return cfi_cmdset_0020(map, primary);
#endif
}


return cfi_cmdset_unknown(map, primary);
}





printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");

kfree(cfi->cfiq);
kfree(cfi);
map->fldrv_priv = NULL;
return NULL;
}

2、这里是根据上面的函数和假设调用如下函数:

/* This routine is made available to other mtd code via
 * inter_module_register.  It must only be accessed through
 * inter_module_get which will bump the use count of this module.  The
 * addresses passed back in cfi are valid as long as the use count of
 * this module is non-zero, i.e. between inter_module_get and
 * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
 */
struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
{
struct cfi_private *cfi = map->fldrv_priv;
int i;
__u32 base = cfi->chips[0].start;


if (cfi->cfi_mode == CFI_MODE_CFI) {
/* 
* It's a real CFI chip, not one for which the probe
* routine faked a CFI structure. So we read the feature
* table from it.
*/
__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
struct cfi_pri_intelext *extp;对应下面的数据结构源码。
int ofs_factor = cfi->interleave * cfi->device_type;


//printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr);
if (!adr)
return NULL;


/* Switch it into Query Mode */
cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);


extp = kmalloc(sizeof(*extp), GFP_KERNEL);
if (!extp) {
printk(KERN_ERR "Failed to allocate memory\n");
return NULL;
}

/* Read in the Extended Query Table */
for (i=0; i<sizeof(*extp); i++) {
((unsigned char *)extp)[i] = 
cfi_read_query(map, (base+((adr+i)*ofs_factor)));
}

if (extp->MajorVersion != '1' || 
   (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
printk(KERN_WARNING "  Unknown IntelExt Extended Query "
      "version %c.%c.\n",  extp->MajorVersion,
      extp->MinorVersion);
kfree(extp);
return NULL;
}

/* Do some byteswapping if necessary */
extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);

#ifdef DEBUG_CFI_FEATURES
/* Tell the user about it in lots of lovely detail */
cfi_tell_features(extp);
#endif


if(extp->SuspendCmdSupport & 1) {
//#define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ 
printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
      "erase on write disabled.\n");
extp->SuspendCmdSupport &= ~1;
#else
printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
#endif
}
/* Install our own private info structure */
cfi->cmdset_priv = extp;
}


for (i=0; i< cfi->numchips; i++) {
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
cfi->chips[i].ref_point_counter = 0;
}


map->fldrv = &cfi_intelext_chipdrv;

/* Make sure it's in read mode */
cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL);
return cfi_intelext_setup(map);这个函数为Intel闪存板块创建一个mtd_info数据结构。源码在下面:
}

从扩充信息块中读入的信息保存在一个cfi_pri_intelext数据结构中,而cfi_private数据结构中的指针cmdset_priv则指向这个数据结构。


/* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */

struct cfi_pri_intelext {
  __u8  pri[3];
  __u8  MajorVersion;
  __u8  MinorVersion;
  __u32 FeatureSupport;
  __u8  SuspendCmdSupport;
  __u16 BlkStatusRegMask;
  __u8  VccOptimal;
  __u8  VppOptimal;
  __u8  NumProtectionFields;
  __u16 ProtRegAddr;
  __u8  FactProtRegSize;
  __u8  UserProtRegSize;
} __attribute__((packed));

3、紧接着上面的函数调用,此为函数源码。

此函数为Intel闪存板块创建一个mtd_info数据结构。结构中的信息来自两个方面。第一,我们已经知道用的是Intel芯片,所以芯片类型为MTD_NORFLASH。此外,结构中的诸多函数指针也都指向针对Intel芯片的操作函数。


static struct mtd_info *cfi_intelext_setup(struct map_info *map)
{
struct cfi_private *cfi = map->fldrv_priv;
struct mtd_info *mtd;
unsigned long offset = 0;
int i,j;
unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;


mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);


if (!mtd) {
printk(KERN_ERR "Failed to allocate memory for MTD device\n");
goto setup_err;
}


memset(mtd, 0, sizeof(*mtd));
mtd->priv = map;
mtd->type = MTD_NORFLASH;芯片类型
mtd->size = devsize * cfi->numchips;


mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) 
* mtd->numeraseregions, GFP_KERNEL);
if (!mtd->eraseregions) { 
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
goto setup_err;
}

for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
unsigned long ernum, ersize;
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;


if (mtd->erasesize < ersize) {
mtd->erasesize = ersize;
}
for (j=0; j<cfi->numchips; j++) {
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
}
offset += (ersize * ernum);
}


if (offset != devsize) {
/* Argh */
printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
goto setup_err;
}


for (i=0; i<mtd->numeraseregions;i++){
printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
      i,mtd->eraseregions[i].offset,
      mtd->eraseregions[i].erasesize,
      mtd->eraseregions[i].numblocks);
}


/* Also select the correct geometry setup too */ 指向Intel的芯片函数
mtd->erase = cfi_intelext_erase_varsize;
mtd->read = cfi_intelext_read;



if(map->point && map->unpoint){
mtd->point = do_point;
mtd->unpoint = do_unpoint;
}


#ifndef FORCE_WORD_WRITE
if ( cfi->cfiq->BufWriteTimeoutTyp ) {
printk("Using buffer write method\n" );
mtd->write = cfi_intelext_write_buffers;
} else {
#else
{
#endif
printk("Using word write method\n" );
mtd->write = cfi_intelext_write_words;
}
mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;
mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
mtd->sync = cfi_intelext_sync;
mtd->lock = cfi_intelext_lock;
mtd->unlock = cfi_intelext_unlock;
mtd->suspend = cfi_intelext_suspend;
mtd->resume = cfi_intelext_resume;

mtd->flags = MTD_CAP_NORFLASH;
map->fldrv = &cfi_intelext_chipdrv;
MOD_INC_USE_COUNT;
mtd->name = map->name;
return mtd;


 setup_err:
if(mtd) {
if(mtd->eraseregions)
kfree(mtd->eraseregions);
kfree(mtd);
}
kfree(cfi->cmdset_priv);
kfree(cfi->cfiq);
return NULL;
}



这篇关于CFI查询(五)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/879071

相关文章

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

ural 1026. Questions and Answers 查询

1026. Questions and Answers Time limit: 2.0 second Memory limit: 64 MB Background The database of the Pentagon contains a top-secret information. We don’t know what the information is — you

Mybatis中的like查询

<if test="templateName != null and templateName != ''">AND template_name LIKE CONCAT('%',#{templateName,jdbcType=VARCHAR},'%')</if>

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

DAY16:什么是慢查询,导致的原因,优化方法 | undo log、redo log、binlog的用处 | MySQL有哪些锁

目录 什么是慢查询,导致的原因,优化方法 undo log、redo log、binlog的用处  MySQL有哪些锁   什么是慢查询,导致的原因,优化方法 数据库查询的执行时间超过指定的超时时间时,就被称为慢查询。 导致的原因: 查询语句比较复杂:查询涉及多个表,包含复杂的连接和子查询,可能导致执行时间较长。查询数据量大:当查询的数据量庞大时,即使查询本身并不复杂,也可能导致

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

ElasticSearch的DSL查询⑤(ES数据聚合、DSL语法数据聚合、RestClient数据聚合)

目录 一、数据聚合 1.1 DSL实现聚合 1.1.1 Bucket聚合  1.1.2 带条件聚合 1.1.3 Metric聚合 1.1.4 总结 2.1 RestClient实现聚合 2.1.1 Bucket聚合 2.1.2 带条件聚合 2.2.3 Metric聚合 一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

MySQL基础(7)- 多表查询

目录 一、笛卡尔积的错误与正确的多表查询 1.出现笛卡尔积错误 2.正确的多表查询:需要有连接条件 3.查询多个表中都存在的字段 4.SELECT和WHERE中使用表的别名 二、等值连接vs非等值连接、自连接vs非自连接 1.等值连接  vs  非等值连接 2.自连接  vs  非自连接 3.内连接  vs  外连接 4.UNION  和 UNION ALL的使用 5.7种J

Hbase Filter+Scan 查询效率优化

Hbase Filter+Scan 查询效率问题 众所周知,Hbase利用filter过滤器查询时候会进行全表扫描,查询效率低下,如果没有二级索引,在项目中很多情况需要利用filter,下面针对这种情况尝试了几种优化的方案,仅供参考,欢迎交流。 根据业务要求,作者需要根据时间范围搜索所需要的数据,所以作者设计的rowKey是以时间戳为起始字符串的。 正确尝试: 1.scan 设置 开始行和结

Hbase 查询相关用法

Hbase 查询相关用法 public static void main(String[] args) throws IOException {//Scan类常用方法说明//指定需要的family或column ,如果没有调用任何addFamily或Column,会返回所有的columns; // scan.addFamily(); // scan.addColumn();// scan.se