jffs2文件系统——MTD驱动挂载 .

总所周知,jffs2是主要用到的是mtd驱动,用mtd驱动作为jffs2文件系统的工具。所以在mount jffs2之前,必须要挂载MTD驱动。MTD驱动最关键的其实是往mtd_table[]这张表里添加东西。

  1. platform_driver_register(&a)  
  2.     a.probe  
  3.         add_mtd_partitions  
  4.             add_mtd_device  
  5.                  mtd_table[i]= mtd  
platform_driver_register(&a)
    a.probe
        add_mtd_partitions
            add_mtd_device
                 mtd_table[i]= mtd
mtd挂载其实就是一个platform_driver_register,但是这个注册的元素,在platform初始化的时候就添加了,所以probe有作用。

  1. probe是被这样调用的  
  2. bus_add_driver  
  3.     driver_attach  
  4.         bus_for_each_drv  
  5.             __driver_attach  
  6.                 driver_probe_device  
  7.                     really_probe  
probe是被这样调用的
bus_add_driver
	driver_attach
		bus_for_each_drv
			__driver_attach
				driver_probe_device
					really_probe

  1. static int really_probe(void *void_data)  
  2. {  
  3.     struct stupid_thread_structure *data = void_data;  
  4.     struct device_driver *drv = data->drv;//本次platform的driver   
  5.     struct device *dev = data->dev;//原先就已经注册的platform   
  6.     dev->driver = drv;  
  7.   
  8.     if (dev->bus->probe) {  
  9.         ret = dev->bus->probe(dev);  
  10.     } else if (drv->probe) {  
  11.         ret = drv->probe(dev);   //这里   
  12.     }  
  13.   
  14.     driver_bound(dev);  
  15.   
  16. }  
static int really_probe(void *void_data)
{
	struct stupid_thread_structure *data = void_data;
	struct device_driver *drv = data->drv;//本次platform的driver
	struct device *dev = data->dev;//原先就已经注册的platform
	dev->driver = drv;

	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
	} else if (drv->probe) {
		ret = drv->probe(dev);	//这里
	}

	driver_bound(dev);

}
从上面这个代码可以得出,probe探测到了元素,参数将是原来的dev,也就是platform初始化的时候添加的元素。

  1. static int __init probe(struct platform_device *plat_dev)     
  2. //这里的入口参数不是opconn_spi_drive而是plat_dev   flash_device(在platform.c中)   
  3. {  
  4.   
  5.     /* Platform data helps sort out which chip type we have, as 
  6.      * well as how this board partitions it.  If we don't have 
  7.      * a chip ID, try the JEDEC id commands; they'll work for most 
  8.      * newer chips, even if we don't recognize the particular chip. 
  9.      */  
  10.     //下面的方法是,各种方法去获得flash信息,flash一般是放在一个大表里,通过读jedec去查找   
  11.     //info的扇区数,扇区大小,型号   
  12.     ……  
  13.     //接下来是给mtd赋值操作   
  14.     flash->mtd.type = MTD_NORFLASH;  //nor flash   
  15.     flash->mtd.writesize = 1;  
  16.     /* writeable */  
  17.     flash->mtd.flags = MTD_CAP_NORFLASH | MTD_WRITEABLE; //电容 nor flash ,可写   
  18.     flash->mtd.size = info->sector_size * info->n_sectors; //flash大小,整片flash的大小   
  19.   
  20.     flash->mtd.erase = spi_erase;    //擦函数   
  21.     flash->mtd.read = spi_read;  //读函数   
  22.     flash->mtd.write = spi_write;    //写函数   
  23.   
  24.     /* partitions should match sector boundaries; and it may be good to 
  25.      * use readonly partitions for writeprotected sectors (BP2..BP0). 
  26.      */  
  27.      //mtd是分区的   
  28.     if (mtd_has_partitions()) { //      亲,分区的不?   
  29.         struct mtd_partition    *parts = NULL;  
  30.         int         nr_parts = 0;  
  31.   
  32.         if (nr_parts <= 0 && data && data->parts) {  
  33.             parts = data->parts; //指向分区数组地址   
  34.             nr_parts = data->nr_parts;   //分区数量   
  35.         }  
  36.   
  37.         if (nr_parts > 0) {  //开始分区   
  38.             flash->partitioned = 1;  
  39.             return add_mtd_partitions(&flash->mtd, parts, nr_parts);//在mtdtable那种表中加入,这个分区   
  40.             //入口参数:mtd主要信息,分区信息,分区数量   
  41.         }  
  42.     }   
  43. }  
static int __init probe(struct platform_device *plat_dev) 	
//这里的入口参数不是opconn_spi_drive而是plat_dev   flash_device(在platform.c中)
{

	/* Platform data helps sort out which chip type we have, as
	 * well as how this board partitions it.  If we don't have
	 * a chip ID, try the JEDEC id commands; they'll work for most
	 * newer chips, even if we don't recognize the particular chip.
	 */
	//下面的方法是,各种方法去获得flash信息,flash一般是放在一个大表里,通过读jedec去查找
	//info的扇区数,扇区大小,型号
	……
	//接下来是给mtd赋值操作
	flash->mtd.type = MTD_NORFLASH;	//nor flash
	flash->mtd.writesize = 1;
	/* writeable */
	flash->mtd.flags = MTD_CAP_NORFLASH | MTD_WRITEABLE;	//电容 nor flash ,可写
	flash->mtd.size = info->sector_size * info->n_sectors;	//flash大小,整片flash的大小

	flash->mtd.erase = spi_erase;	//擦函数
	flash->mtd.read = spi_read;	//读函数
	flash->mtd.write = spi_write;	//写函数

	/* partitions should match sector boundaries; and it may be good to
	 * use readonly partitions for writeprotected sectors (BP2..BP0).
	 */
	 //mtd是分区的
	if (mtd_has_partitions()) {	//		亲,分区的不?
		struct mtd_partition    *parts = NULL;
		int         nr_parts = 0;

		if (nr_parts <= 0 && data && data->parts) {
			parts = data->parts;	//指向分区数组地址
			nr_parts = data->nr_parts;	//分区数量
		}

		if (nr_parts > 0) {	//开始分区
			flash->partitioned = 1;
			return add_mtd_partitions(&flash->mtd, parts, nr_parts);//在mtdtable那种表中加入,这个分区
			//入口参数:mtd主要信息,分区信息,分区数量
		}
	} 
}
上面的代码里,分两部分,第一部分是给flash->mtd各种赋值,这个flash->mtd可以理解成master,后面的分区很多信息都得向它继承;第二部分是add_mtd_partitions,这个是将分区一片片放入mtd_table中。

  1. /* 
  2.  * This function, given a master MTD object and a partition table, creates 
  3.  * and registers slave MTD objects which are bound to the master according to 
  4.  * the partition definitions. 
  5.  * (Q: should we register the master MTD object as well?) 
  6.  */  
  7.   
  8. int add_mtd_partitions(struct mtd_info *master,  
  9.                const struct mtd_partition *parts,  
  10.                int nbparts)  
  11. {  
  12.     for (i = 0; i < nbparts; i++) {  
  13.   
  14.         list_add(&slave->list, &mtd_partitions); //将这个分区添加到mtd_parttiions的链表中   
  15.   
  16.         /* set up the MTD object for this partition */  
  17.         //在各个分区的信息设置,slave->master很重要,有些part操作都是定位到master的   
  18.         slave->mtd.type = master->type;  
  19.         slave->mtd.flags = master->flags & ~parts[i].mask_flags;  
  20.         slave->mtd.size = parts[i].size;  
  21.         slave->mtd.writesize = master->writesize;  
  22.         slave->mtd.oobsize = master->oobsize;  
  23.         slave->mtd.oobavail = master->oobavail;  
  24.         slave->mtd.subpage_sft = master->subpage_sft;  
  25.   
  26.         slave->mtd.name = parts[i].name;  
  27.         slave->mtd.bank_size = master->bank_size;  
  28.         slave->mtd.erase = part_erase;  
  29.         slave->master = master;  //这个很重要,那些part操作,很多都是要定位到这位大爷里来的   
  30.         slave->offset = parts[i].offset;  
  31.         slave->index = i;  
  32.   
  33.         /* let's do some sanity checks */  
  34.   
  35.         //下面两个if判断,擦除是否能正常进行,必须是一个擦写块一个擦写块   
  36.         if ((slave->mtd.flags & MTD_WRITEABLE) &&  
  37.             (slave->offset % slave->mtd.erasesize)) { //如果不在擦出块的边界,只可读   
  38.             /* Doesn't start on a boundary of major erase size */  
  39.             /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */  
  40.             slave->mtd.flags &= ~MTD_WRITEABLE;  
  41.             printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",  
  42.                 parts[i].name);  
  43.         }  
  44.         if ((slave->mtd.flags & MTD_WRITEABLE) &&  
  45.             (slave->mtd.size % slave->mtd.erasesize)) {   //如果大小不能整除擦出块,只可读   
  46.             slave->mtd.flags &= ~MTD_WRITEABLE;  
  47.             printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",  
  48.                 parts[i].name);  
  49.         }  
  50.   
  51.         if(parts[i].mtdp)   //如果它有私有的mtd表,就私有   
  52.         {   /* store the object pointer (caller may or may not register it */  
  53.             *parts[i].mtdp = &slave->mtd;  
  54.             slave->registered = 0;  
  55.         }  
  56.         else        //一般都是放入共有的mtdtable   
  57.         {  
  58.             /* register our partition */  
  59.             add_mtd_device(&slave->mtd); //将这个分区的mtd注册到mtd_table中   
  60.             slave->registered = 1;  
  61.         }  
  62.     }  
  63.   
  64. }  
/*
 * This function, given a master MTD object and a partition table, creates
 * and registers slave MTD objects which are bound to the master according to
 * the partition definitions.
 * (Q: should we register the master MTD object as well?)
 */

int add_mtd_partitions(struct mtd_info *master,
		       const struct mtd_partition *parts,
		       int nbparts)
{
	for (i = 0; i < nbparts; i++) {

		list_add(&slave->list, &mtd_partitions);	//将这个分区添加到mtd_parttiions的链表中

		/* set up the MTD object for this partition */
		//在各个分区的信息设置,slave->master很重要,有些part操作都是定位到master的
		slave->mtd.type = master->type;
		slave->mtd.flags = master->flags & ~parts[i].mask_flags;
		slave->mtd.size = parts[i].size;
		slave->mtd.writesize = master->writesize;
		slave->mtd.oobsize = master->oobsize;
		slave->mtd.oobavail = master->oobavail;
		slave->mtd.subpage_sft = master->subpage_sft;

		slave->mtd.name = parts[i].name;
		slave->mtd.bank_size = master->bank_size;
		slave->mtd.erase = part_erase;
		slave->master = master;	//这个很重要,那些part操作,很多都是要定位到这位大爷里来的
		slave->offset = parts[i].offset;
		slave->index = i;

		/* let's do some sanity checks */

		//下面两个if判断,擦除是否能正常进行,必须是一个擦写块一个擦写块
		if ((slave->mtd.flags & MTD_WRITEABLE) &&
		    (slave->offset % slave->mtd.erasesize)) {	//如果不在擦出块的边界,只可读
			/* Doesn't start on a boundary of major erase size */
			/* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
			slave->mtd.flags &= ~MTD_WRITEABLE;
			printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
				parts[i].name);
		}
		if ((slave->mtd.flags & MTD_WRITEABLE) &&
		    (slave->mtd.size % slave->mtd.erasesize)) {	//如果大小不能整除擦出块,只可读
			slave->mtd.flags &= ~MTD_WRITEABLE;
			printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
				parts[i].name);
		}

		if(parts[i].mtdp)	//如果它有私有的mtd表,就私有
		{	/* store the object pointer (caller may or may not register it */
			*parts[i].mtdp = &slave->mtd;
			slave->registered = 0;
		}
		else		//一般都是放入共有的mtdtable
		{
			/* register our partition */
			add_mtd_device(&slave->mtd);	//将这个分区的mtd注册到mtd_table中
			slave->registered = 1;
		}
	}

}
上面的代码,干的事情很简单,slave可以理解成分区,分区有自己的操作,自己的信息,他可以从master继承过来很多东西,but大小尺寸偏移,这些是私有的,最后将分区信息放进mtd_table中,供系统调用,比如jffs2之类的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值