驱动程序之_2_块设备_4_Nand Flash_2_驱动框架分析
启动内核时,有如下打印信息:
从信息可以找到内核的Nand Flash驱动,位于/drivers/mtd/nand/s3c2410.c中
初始化的调度关系如下,完成
1、控制器初始化
2、芯片初始化
3、读取芯片信息,分配mtd_info结构体,提供读写等函数接口
4、添加分区
s3c24xx_nand_probe
err = s3c2410_nand_inithw(info, pdev);
s3c2410_nand_init_chip(info, nmtd, sets);
nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
s3c2410_nand_add_partition(info, nmtd, sets);
add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
add_mtd_device(&mtd->mtd);
list_for_each(this, &mtd_notifiers) {
struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
not->add(mtd);
}
/******************************/
//字符设备
not->add(mtd); //=>mtd_notify_add
//回到以前字符设备分配操作
//块设备
not->add(mtd); //=》blktrans_notify_add
list_for_each(this, &blktrans_majors) {
struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
tr->add_mtd(tr, mtd); //=》mtdblock_add_mtd
add_mtd_blktrans_dev(dev);
//回到以前块设备简单实例的gendisk操作
}
mtd_notifiers在register_mtd_user中设置,register_mtd_user在两个地方被调用,分别属于字符设备和块设备
字符设备下:
init_mtdchar调用register_mtd_user
返回上层函数后,又调用了mtd_notifiers的add函数,在这是mtd_notify_add,创建设备
static int __init init_mtdchar(void)
{
if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_CHAR_MAJOR);
return -EAGAIN;
}
mtd_class = class_create(THIS_MODULE, "mtd");
if (IS_ERR(mtd_class)) {
printk(KERN_ERR "Error creating mtd class.\n");
unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
return PTR_ERR(mtd_class);
}
register_mtd_user(¬ifier); //!!!!!!!!
return 0;
}
static void mtd_notify_add(struct mtd_info* mtd)
{
if (!mtd)
return;
class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
NULL, "mtd%d", mtd->index);
class_device_create(mtd_class, NULL,
MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
NULL, "mtd%dro", mtd->index);
}
块设备下:
register_mtd_blktrans调用register_mtd_user
返回上层函数后,又调用了mtd_notifiers的add函数,在这是blktrans_notify_add,创建设备
blktrans_majors也在register_mtd_blktrans中设置
register_mtd_blktrans在init_mtdblock被调用
返回上层,调用tr的add_mtd函数,就是调用mtdblock_add_mtd
在mtdblock_add_mtd中分配、添加了块设备
int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
{
/****************************/
register_mtd_user(&blktrans_notifier);
/****************************/
}
static void blktrans_notify_add(struct mtd_info *mtd)
{
struct list_head *this;
if (mtd->type == MTD_ABSENT)
return;
list_for_each(this, &blktrans_majors) {
struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
tr->add_mtd(tr, mtd);
}
}
static int __init init_mtdblock(void)
{
return register_mtd_blktrans(&mtdblock_tr);
}
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return;
dev->mtd = mtd;
dev->devnum = mtd->index;
dev->size = mtd->size >> 9;
dev->tr = tr;
dev->readonly = 1;
add_mtd_blktrans_dev(dev);
}
分析代码可以知道,Nand Flash驱动层次结构如下,其中
1、硬件层负责控制传送
2、协议层负责管理操作命令
3、块设备负责优化
4、应用层负责给出传送内容