linux mtd - mtdpart.c

2019-07-12 14:32发布

转载请注明来自:http://blog.csdn.net/xgbing (1)add_mtd_partitions [cpp] view plain copy
  1. int add_mtd_partitions(struct mtd_info *master,  在flash驱动中已经初始化  
  2.                      const struct mtd_partition *parts,  
  3.                      int nbparts)  
  4. {  
  5.        struct mtd_part *slave;  
  6.        uint64_t cur_offset = 0;  
  7.        int i;  
  8.    
  9.        printk(KERN_NOTICE "Creating %d MTD partitions on "%s": ", nbparts, master->name);  
  10.    
  11. //调用add_one_partition添加每个分区  
  12.        for (i = 0; i < nbparts; i++) {  
  13.               slave = add_one_partition(master, parts + i, i, cur_offset);  
  14.               if (!slave)  
  15.                      return -ENOMEM;  
  16.               cur_offset = slave->offset + slave->mtd.size;  
  17.        }  
  18.    
  19.        return 0;  
  20. }  


(2)add_one_partition   [cpp] view plain copy
  1. static struct mtd_part *add_one_partition(struct mtd_info *master, 从mtd外部FLASH驱动已经初始化,是一个输入参数。  
  2.               const struct mtd_partition *part, int partno,  
  3.               uint64_t cur_offset)  
  4. {  
  5.        struct mtd_part *slave;  
  6.    
  7.        /* allocate the partition structure */  
  8.        slave = kzalloc(sizeof(*slave), GFP_KERNEL);  
  9.        if (!slave) {  
  10.               printk(KERN_ERR"memory allocation error while creating partitions for "%s" ",  
  11.                      master->name);  
  12.               del_mtd_partitions(master);  
  13.               return NULL;  
  14.        }  
  15.    
  16.    
  17.     //将新建的slave加入到mtd_partitions之后  
  18.        list_add(&slave->list, &mtd_partitions);                               #<1>  
  19.    
  20.        /* set up the MTD object for this partition */将master的一大部分属性赋给slave  
  21.        slave->mtd.type = master->type;  
  22.        slave->mtd.flags = master->flags & ~part->mask_flags;  
  23.        slave->mtd.size = part->size;  
  24.        slave->mtd.writesize = master->writesize;  
  25.        slave->mtd.oobsize = master->oobsize;  
  26.        slave->mtd.oobavail = master->oobavail;  
  27.        slave->mtd.subpage_sft = master->subpage_sft;  
  28.    
  29.        slave->mtd.name = part->name;  
  30.        slave->mtd.owner = master->owner;  
  31.        slave->mtd.backing_dev_info = master->backing_dev_info;  
  32.    
  33.        /* NOTE:  we don't arrange MTDs as a tree; it'd be error-prone 
  34.         * to have the same data be in two different partitions. 
  35.         */  
  36.        slave->mtd.dev.parent = master->dev.parent;  
  37.    
  38.        slave->mtd.read = part_read;  
  39.        slave->mtd.write = part_write;  
  40.    
  41.        if (master->panic_write)  
  42.               slave->mtd.panic_write = part_panic_write;  
  43.    
  44.        if (master->point && master->unpoint) {  
  45.               slave->mtd.point = part_point;  
  46.               slave->mtd.unpoint = part_unpoint;  
  47.        }  
  48.    
  49.        if (master->get_unmapped_area)  
  50.               slave->mtd.get_unmapped_area = part_get_unmapped_area;  
  51.        if (master->read_oob)  
  52.               slave->mtd.read_oob = part_read_oob;  
  53.        if (master->write_oob)  
  54.               slave->mtd.write_oob = part_write_oob;  
  55.        if (master->read_user_prot_reg)  
  56.               slave->mtd.read_user_prot_reg = part_read_user_prot_reg;  
  57.        if (master->read_fact_prot_reg)  
  58.               slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;  
  59.        if (master->write_user_prot_reg)  
  60.               slave->mtd.write_user_prot_reg = part_write_user_prot_reg;  
  61.        if (master->lock_user_prot_reg)  
  62.               slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;  
  63.        if (master->get_user_prot_info)  
  64.               slave->mtd.get_user_prot_info = part_get_user_prot_info;  
  65.        if (master->get_fact_prot_info)  
  66.               slave->mtd.get_fact_prot_info = part_get_fact_prot_info;  
  67.        if (master->sync)  
  68.               slave->mtd.sync = part_sync;  
  69.        if (!partno && master->suspend && master->resume) {  
  70.                      slave->mtd.suspend = part_suspend;  
  71.                      slave->mtd.resume = part_resume;  
  72.        }  
  73.        if (master->writev)  
  74.               slave->mtd.writev = part_writev;  
  75.        if (master->lock)  
  76.               slave->mtd.lock = part_lock;  
  77.        if (master->unlock)  
  78.               slave->mtd.unlock = part_unlock;  
  79.        if (master->block_isbad)  
  80.               slave->mtd.block_isbad = part_block_isbad;  
  81.        if (master->block_markbad)  
  82.               slave->mtd.block_markbad = part_block_markbad;  
  83.        slave->mtd.erase = part_erase;  
  84.        slave->master = master;  
  85.        slave->offset = part->offset;  
  86.        slave->index = partno;  
  87.    
  88.        if (slave->offset == MTDPART_OFS_APPEND)  
  89.               slave->offset = cur_offset;  
  90.        if (slave->offset == MTDPART_OFS_NXTBLK) {  
  91.               slave->offset = cur_offset;  
  92.               if (mtd_mod_by_eb(cur_offset, master) != 0) {  
  93.                      /* Round up to next erasesize */  
  94.                      slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;  
  95.                      printk(KERN_NOTICE "Moving partition %d: "  
  96.                             "0x%012llx -> 0x%012llx ", partno,  
  97.                             (unsigned long long)cur_offset, (unsigned long long)slave->offset);  
  98.               }  
  99.        }  
  100.        if (slave->mtd.size == MTDPART_SIZ_FULL)  
  101.               slave->mtd.size = master->size - slave->offset;  
  102.    
  103.        printk(KERN_NOTICE "0x%012llx-0x%012llx : "%s" ", (unsigned long long)slave->offset,  
  104.               (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);  
  105.    
  106.        /* let's do some sanity checks */  
  107.        if (slave->offset >= master->size) {  
  108.               /* let's register it anyway to preserve ordering */  
  109.               slave->offset = 0;  
  110.               slave->mtd.size = 0;  
  111.               printk(KERN_ERR"mtd: partition "%s" is out of reach -- disabled ",  
  112.                      part->name);  
  113.               goto out_register;  
  114.        }  
  115.        if (slave->offset + slave->mtd.size > master->size) {  
  116.               slave->mtd.size = master->size - slave->offset;  
  117.               printk(KERN_WARNING"mtd: partition "%s" extends beyond the end of device "%s" -- size truncated to %#llx ",  
  118.                      part->name, master->name, (unsigned long long)slave->mtd.size);  
  119.        }  
  120.        if (master->numeraseregions > 1) {  
  121.               /* Deal with variable erase size stuff */  
  122.               int i, max = master->numeraseregions;  
  123.               u64 end = slave->offset + slave->mtd.size;  
  124.               struct mtd_erase_region_info *regions = master->eraseregions;  
  125.    
  126.               /* Find the first erase regions which is part of this 
  127.                * partition. */  
  128.               for (i = 0; i < max && regions[i].offset <= slave->offset; i++)  
  129.                      ;  
  130.               /* The loop searched for the region _behind_ the first one */  
  131.               i--;  
  132.    
  133.               /* Pick biggest erasesize */  
  134.               for (; i < max && regions[i].offset < end; i++) {  
  135.                      if (slave->mtd.erasesize < regions[i].erasesize) {  
  136.                             slave->mtd.erasesize = regions[i].erasesize;  
  137.                      }  
  138.               }  
  139.               BUG_ON(slave->mtd.erasesize == 0);  
  140.        } else {  
  141.               /* Single erase size */  
  142.               slave->mtd.erasesize = master->erasesize;  
  143.        }  
  144.    
  145.        if ((slave->mtd.flags & MTD_WRITEABLE) &&  
  146.            mtd_mod_by_eb(slave->offset, &slave->mtd)) {  
  147.               /* Doesn't start on a boundary of major erase size */  
  148.               /* FIXME: Let it be writable if it is on a boundary of 
  149.                * _minor_ erase size though */  
  150.               slave->mtd.flags &= ~MTD_WRITEABLE;  
  151.               printk(KERN_WARNING"mtd: partition "%s" doesn't start on an erase block boundary -- force read-only ",  
  152.                      part->name);  
  153.        }  
  154.        if ((slave->mtd.flags & MTD_WRITEABLE) &&  
  155.            mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {  
  156.               slave->mtd.flags &= ~MTD_WRITEABLE;  
  157.               printk(KERN_WARNING"mtd: partition "%s" doesn't end on an erase block -- force read-only ",  
  158.                      part->name);  
  159.        }  
  160.    
  161.        slave->mtd.ecclayout = master->ecclayout;  
  162.        if (master->block_isbad) {  
  163.               uint64_t offs = 0;  
  164.    
  165.               while (offs < slave->mtd.size) {  
  166.                      if (master->block_isbad(master,  
  167.                                           offs + slave->offset))  
  168.                             slave->mtd.ecc_stats.badblocks++;  
  169.                      offs += slave->mtd.erasesize;  
  170.               }  
  171.        }  
  172.    
  173. out_register:  
  174.        if (part->mtdp) {  
  175.               /* store the object pointer (caller may or may not register it*/  
  176.               *part->mtdp = &slave->mtd;    
  177.               slave->registered = 0;  
  178.        } else {  
  179.               /* register our partition */  
  180.               add_mtd_device(&slave->mtd);  
  181.               slave->registered = 1;  
  182.        }  
  183.        return slave;  
  184. }  

#<1> Struct list_head list是一个双向链表,注意它没有数据区域 [cpp] view plain copy
  1. struct list_head {  
  2.        struct list_head *next, *prev;  
  3. };  

[cpp] view plain copy
  1. struct mtd_part {  
  2.        struct mtd_info mtd;  
  3.        struct mtd_info *master;  
  4.        uint64_t offset;  
  5.        int index;  
  6.        struct list_head list;  包含了一个双向链表  
  7.        int registered;  
  8. };  



在mtdpar.c的头部定义了: [cpp] view plain copy
  1. static LIST_HEAD(mtd_partitions);     //有关list的代码在include/linux/list.h中  

parse_mtd_partitions是解析FLASH中的分区信息