Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519289
  • 博文数量: 398
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-21 16:02
个人简介

嵌入式屌丝

文章分类

全部博文(398)

文章存档

2013年(398)

我的朋友

分类: LINUX

2013-08-21 16:24:22

Arm-linux东东nand8: nand_scan_tail

应该叹一口气了. 不得不佩服nand_scan_tail.因为下面要说坏块扫描了.

…………….

       if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&

           !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {

              switch(chip->ecc.steps) {

              case 2:

                     mtd->subpage_sft = 1;

                     break;

              case 4:

              case 8:

                     mtd->subpage_sft = 2;

                     break;

              }

       }

       chip->subpagesize = mtd->writesize >> mtd->subpage_sft;

 

       /* Initialize state */

       chip->state = FL_READY;

 

       /* De-select the device */

       chip->select_chip(mtd, -1);

 

       /* Invalidate the pagebuffer reference */

       chip->pagebuf = -1;

 

       /* Fill in remaining MTD driver data */

       mtd->type = MTD_NANDFLASH;

       mtd->flags = MTD_CAP_NANDFLASH;

       mtd->erase = nand_erase;

       mtd->point = NULL;

       mtd->unpoint = NULL;

       mtd->read = nand_read;

       mtd->write = nand_write;

       mtd->read_oob = nand_read_oob;

       mtd->write_oob = nand_write_oob;

       mtd->sync = nand_sync;

       mtd->lock = NULL;

       mtd->unlock = NULL;

       mtd->suspend = nand_suspend;

       mtd->resume = nand_resume;

       mtd->block_isbad = nand_block_isbad;

       mtd->block_markbad = nand_block_markbad;

 

       /* propagate ecc.layout to mtd_info */

       mtd->ecclayout = chip->ecc.layout;

 

       /* Check, if we should skip the bad block table scan */

       if (chip->options & NAND_SKIP_BBTSCAN)

              return 0;

 

       /* Build bad block table */

       return chip->scan_bbt(mtd);

………………..

都是一些赋值没什么.看最后一句.当时我还以后它应该不会很长.可惜错了

nand_set_defaults中应该有下面这个吧

       if (!chip->scan_bbt)

              chip->scan_bbt = nand_default_bbt;

………………

于是:

int nand_default_bbt(struct mtd_info *mtd)

{

       struct nand_chip *this = mtd->priv;

 

       /* Default for AG-AND. We must use a flash based

        * bad block table as the devices have factory marked

        * _good_ blocks. Erasing those blocks leads to loss

        * of the good / bad information, so we _must_ store

        * this information in a good / bad table during

        * startup

        */

       if (this->options & NAND_IS_AND) {

              /* Use the default pattern descriptors */

              if (!this->bbt_td) {

                     this->bbt_td = &bbt_main_descr;

                     this->bbt_md = &bbt_mirror_descr;

              }

              this->options |= NAND_USE_FLASH_BBT;

              return nand_scan_bbt(mtd, &agand_flashbased);

       }

 

       /* Is a flash based bad block table requested ? */

       if (this->options & NAND_USE_FLASH_BBT) {

              /* Use the default pattern descriptors */

              if (!this->bbt_td) {

                     this->bbt_td = &bbt_main_descr;

                     this->bbt_md = &bbt_mirror_descr;

              }

              if (!this->badblock_pattern) {

this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;

              }

       } else {

              this->bbt_td = NULL;

              this->bbt_md = NULL;

              if (!this->badblock_pattern) {

                     this->badblock_pattern = (mtd->writesize > 512) ?

                         &largepage_memorybased : &smallpage_memorybased;

              }

       }

       return nand_scan_bbt(mtd, this->badblock_pattern);

}

static struct nand_bbt_descr smallpage_memorybased = {

       .options = NAND_BBT_SCAN2NDPAGE,

       .offs = 5,

       .len = 1,

       .pattern = scan_ff_pattern

};

红色的那几个标志我们没有吧.因为它们是上面说的变态”NAND的专利.

OK 最后else会执行.

badblock_pattern是指向smallpage_memorybased;

go go

 

Go go

int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)

{

       struct nand_chip *this = mtd->priv;

       int len, res = 0;

       uint8_t *buf;

       struct nand_bbt_descr *td = this->bbt_td;

       struct nand_bbt_descr *md = this->bbt_md;

 

       len = mtd->size >> (this->bbt_erase_shift + 2);

       /* Allocate memory (2bit per block) and clear the memory bad block table */

       this->bbt = kzalloc(len, GFP_KERNEL);

       if (!this->bbt) {

              printk(KERN_ERR "nand_scan_bbt: Out of memory\n");

              return -ENOMEM;

       }

 

       /* If no primary table decriptor is given, scan the device

        * to build a memory based bad block table

        */

       if (!td) {

              if ((res = nand_memory_bbt(mtd, bd))) {

                     printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");

                     kfree(this->bbt);

                     this->bbt = NULL;

              }

              return res;

       }

 

       /* Allocate a temporary buffer for one eraseblock incl. oob */

       len = (1 << this->bbt_erase_shift);

       len += (len >> this->page_shift) * mtd->oobsize;

       buf = vmalloc(len);

       if (!buf) {

              printk(KERN_ERR "nand_bbt: Out of memory\n");

              kfree(this->bbt);

              this->bbt = NULL;

              return -ENOMEM;

       }

 

       /* Is the bbt at a given page ? */

       if (td->options & NAND_BBT_ABSPAGE) {

              res = read_abs_bbts(mtd, buf, td, md);

       } else {

              /* Search the bad block table using a pattern in oob */

              res = search_read_bbts(mtd, buf, td, md);

       }

 

       if (res)

              res = check_create(mtd, buf, bd);

 

       /* Prevent the bbt regions from erasing / writing */

       mark_bbt_region(mtd, td);

       if (md)

              mark_bbt_region(mtd, md);

 

       vfree(buf);

       return res;

}

…………………………..

.真长呀.在大学学了三年的C语言.书上从来没有看过这么长的函数.

看红色的那一段.

现在要扫描坏快.你总应该分出一些内存来记着那块是坏的吧.

本来一块一字节很好理解

mtd->size >> this->bbt_erase_shift就这样.

但本着节约的精神.人家说一块2bit.于是除于4. 8bit42bit组成吗!

我就不理解了,为什么再省一点一块1bit.我的64MRAM也不多呀.

于是就成了这样子: len = mtd->size >> (this->bbt_erase_shift + 2);

看褐色的那一段,能成立吧.上面刚做过这样的this->bbt_td = NULL;

看到return res;,下面的不用看了.

…………….

static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)

{

       struct nand_chip *this = mtd->priv;

 

       bd->options &= ~NAND_BBT_SCANEMPTY;

       return create_bbt(mtd, this->buffers->databuf, bd, -1);

}

……………………………………………………

请注意这里取消了NAND_BBT_SCANEMPTY.

…………………….

static int create_bbt(struct mtd_info *mtd, uint8_t *buf,

       struct nand_bbt_descr *bd, int chip)

{

       struct nand_chip *this = mtd->priv;

       int i, numblocks, len, scanlen;

       int startblock;

       loff_t from;

       size_t readlen;

 

       printk(KERN_INFO "Scanning device for bad blocks\n");

 

       if (bd->options & NAND_BBT_SCANALLPAGES)

              len = 1 << (this->bbt_erase_shift - this->page_shift);

       else {

              if (bd->options & NAND_BBT_SCAN2NDPAGE)

                     len = 2;

              else

                     len = 1;

       }

…………………….

 

一块不是由几个页组成的吧.那扫描一块是不是要全部页都要检查一下呢.还是?

NAND_BBT_SCANALLPAGES表示全部页都要检查.这里没有这个标志.

NAND_BBT_SCAN2NDPAGE表示头二页检查一下就行了.这里设了.

static struct nand_bbt_descr smallpage_memorybased = {

       .options = NAND_BBT_SCAN2NDPAGE,

记得不.

………………………

if (!(bd->options & NAND_BBT_SCANEMPTY)) {

              /* We need only read few bytes from the OOB area */

              scanlen = 0;

              readlen = bd->len;

       } else {

              /* Full page content should be read */

              scanlen = mtd->writesize + mtd->oobsize;

              readlen = len * mtd->writesize;

       }

………………………………………

以前取消掉了这个NAND_BBT_SCANEMPTY

看下这个: We need only read few bytes from the OOB area.OK

……………….

if (chip == -1) {

              /* Note that numblocks is 2 * (real numblocks) here, see i+=2

               * below as it makes shifting and masking less painful */

              numblocks = mtd->size >> (this->bbt_erase_shift - 1);

              startblock = 0;

              from = 0;

       } else {

              if (chip >= this->numchips) {

                     printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",

                            chip + 1, this->numchips);

                     return -EINVAL;

              }

              numblocks = this->chipsize >> (this->bbt_erase_shift - 1);

              startblock = chip * numblocks;

              numblocks += startblock;

              from = startblock << (this->bbt_erase_shift - 1);

       }

………………

Chip是不等于-1.numblocks = mtd->size >> (this->bbt_erase_shift - 1);这里乘以2,因为少移一位了.

startblock = 0;表示第0块开始

………………..

for (i = startblock; i < numblocks;) {

              int ret;

 

              if (bd->options & NAND_BBT_SCANALLPAGES)

                     ret = scan_block_full(mtd, bd, from, buf, readlen,

                                         scanlen, len);

              else

                     ret = scan_block_fast(mtd, bd, from, buf, len);

 

              if (ret < 0)

                     return ret;

 

              if (ret) {

                     this->bbt[i >> 3] |= 0x03 << (i & 0x6);

                     printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",

                            i >> 1, (unsigned int)from);

                     mtd->ecc_stats.badblocks++;

              }

 

              i += 2;

              from += (1 << this->bbt_erase_shift);

       }

       return 0;

…………………

进入for 循环了.注意了i+=2是吧.为什么上面乘以2这里又每次加2.

看下面这个句子:

this->bbt[i >> 3] |= 0x03 << (i & 0x6);

闭着眼睛都能知道就是找到那个块2 bit,如果还不懂.那就把数值代进去.

From每次就加一个块值了.

这里执行

       else

                     ret = scan_block_fast(mtd, bd, from, buf, len);

于是就要看scan_block_fast.

 

 

阅读(1095) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~