总所周知,jffs2是主要用到的是mtd驱动,用mtd驱动作为jffs2文件系统的工具。所以在mount jffs2之前,必须要挂载MTD驱动。MTD驱动最关键的其实是往mtd_table[]这张表里添加东西。
platform_driver_register(&a)
a.probe
add_mtd_partitions
add_mtd_device
mtd_table[i]= mtd
mtd挂载其实就是一个platform_driver_register,但是这个注册的元素,在platform初始化的时候就添加了,所以probe有作用。
probe是被这样调用的
bus_add_driver
driver_attach
bus_for_each_drv
__driver_attach
driver_probe_device
really_probe
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初始化的时候添加的元素。
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中。
/*
* 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之类的。