总所周知,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
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
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);
- }
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主要信息,分区信息,分区数量
- }
- }
- }
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;
- }
- }
- }
/*
* 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之类的。