linux2.6.20 sd/mmc卡驱动学习日记1(基于s3c2440)
2011-05-18 09:30
253 查看
首先,我们来看Makefile文件吧,Makefile中文件的目标文件的顺序是很重要的,因为这个会涉及到模块的依赖关系,比如说,如果这些源文件中
有module_init(),则这些module_init就按在Makefile中的顺序链接进内核,之后也按照链接的顺序进行调用。根据我们的内核
配置选项,将要编译进内核的文件就只有mmc.c,mmc_sysfs.c,mmc_block.c,mmc_queue.c,s3cmci.c这几个文
件。其中mmc.c与mmc_queue.c主要是定义了一些其他文件中将要使用的函数,我们暂时不管它。接下来,我们来分析mmc_sysfs.c
我们先来看mmc_init(),这是系统启动后将要调用的,在mmc_init函数中,主要完成3项工作 :
workqueue = create_singlethread_workqueue("kmmcd");//创见一个单线程的工作队列
bus_register(&mmc_bus_type);//注册总线
class_register(&mmc_host_class);//注册mmc_host_class
mmc_bus_type的定义为:
这里,我们主要关注mmc_bus_match与mmc_bus_probe,此两函数将要在device_register和driver_register向总线注册设备的时候被调用。
可见,对于mmc总线,mmc_bus_match是通过返回struct mmc_card中的状态标示state位来实现的。
在使用bus_register之后,我们可以在sysfs的/sys/bus目录里看到它
---------------------------------------------------------------------------------
接下来,我们看mmc_block.c,还是从初始化函数mmc_blk_init开始分析
在mmc_blk_init中, register_blkdev(major, "mmc")的作用是注册一个块设备。如果传递的major为0,这内核将分派一个新的主设备号给设备。
register_blkdev的功能比较少,一是动态分配设备号,二是在/proc/devices中创建一个入口项 。故通过它之后,系统还是不能使用块设备的。
接着我们看
return mmc_register_driver(&mmc_driver);
mmc_register_driver在mmc_sysfs.c中定义:
这两句代码比较好理解吧。在注册一个struct driver之前,都要先设置它的bus,类似的,在platform_driver_register中我们也可所以看到:
drv->driver.bus=&platform_bus_type
driver_register将到相应总线mmc_bus_type上去搜索相应设备。找到设备后就设置dev->driver=drv,并调用mmc_bus_type总线的probe函数被调用,即mmmc_bus_probe函数.
我们跟踪driver_register(&drv->drv),它会调应bus_add_driver。
在调用kobject_register之后,我们可以在/sys/bus/mmc/driver目录下看到mmcblk文件driver_attach
函数会遍历相应总线(mmc_bus_type)上的dev,对这些dev执行总线的match函数(mmc_bus_match)。如果match成
功,它会调用mmc_bus_type总线的probe函数mmc_bus_probe(如果总线的probe存在的话).我们在以上走过的流程中可以看
到,我们并没有向总线添加任何设备,故mmc_bus_probe是不会调用的。但相应的driver已经注册到系统了。
那么,现在mmc_block.c中的分析就先暂时到此为止。。。不过,等会儿我们还会继续回到这个文件的。。
----------------------------------未完待续-----------------------------------
http://blog.chinaunix.net/space.php?uid=14782631&do=blog&id=111888
有module_init(),则这些module_init就按在Makefile中的顺序链接进内核,之后也按照链接的顺序进行调用。根据我们的内核
配置选项,将要编译进内核的文件就只有mmc.c,mmc_sysfs.c,mmc_block.c,mmc_queue.c,s3cmci.c这几个文
件。其中mmc.c与mmc_queue.c主要是定义了一些其他文件中将要使用的函数,我们暂时不管它。接下来,我们来分析mmc_sysfs.c
我们先来看mmc_init(),这是系统启动后将要调用的,在mmc_init函数中,主要完成3项工作 :
workqueue = create_singlethread_workqueue("kmmcd");//创见一个单线程的工作队列
bus_register(&mmc_bus_type);//注册总线
class_register(&mmc_host_class);//注册mmc_host_class
mmc_bus_type的定义为:
static struct bus_type mmc_bus_type = { . name = "mmc" , . dev_attrs = mmc_dev_attrs, . match = mmc_bus_match, . uevent = mmc_bus_uevent, . probe = mmc_bus_probe, . remove = mmc_bus_remove, . suspend = mmc_bus_suspend, . resume = mmc_bus_resume, } ; |
static int mmc_bus_match( struct device * dev, struct device_driver * drv) { struct mmc_card * card = dev_to_mmc_card( dev) ; return ! mmc_card_bad( card) ; } # define mmc_card_bad( c) ( ( c) - > state& ( MMC_STATE_BAD) |
static int mmc_bus_probe( struct device * dev) { struct mmc_driver * drv = to_mmc_driver( dev- > driver) ; struct mmc_card * card = dev_to_mmc_card( dev) ; return drv- > probe( card) ; } |
static struct class mmc_host_class = { . name = "mmc_host" , . dev_release = mmc_host_classdev_release, } ; class_register之后,在/ sys/ class目录下将出现mmc_host目录 |
接下来,我们看mmc_block.c,还是从初始化函数mmc_blk_init开始分析
static int __init mmc_blk_init( void ) { int res = - ENOMEM; res = register_blkdev( major, "mmc" ) ; if ( res < 0) { printk( KERN_WARNING "Unable to get major %d for MMC media: %d/n" , major, res) ; goto out; } if ( major = = 0) major = res; return mmc_register_driver( & mmc_driver) ; out: return res; } |
register_blkdev的功能比较少,一是动态分配设备号,二是在/proc/devices中创建一个入口项 。故通过它之后,系统还是不能使用块设备的。
接着我们看
return mmc_register_driver(&mmc_driver);
mmc_register_driver在mmc_sysfs.c中定义:
static struct mmc_driver mmc_driver = { . drv = { . name = "mmcblk" , } , . probe = mmc_blk_probe, . remove = mmc_blk_remove, . suspend = mmc_blk_suspend, . resume = mmc_blk_resume, } ; int mmc_register_driver( struct mmc_driver * drv) { drv- > drv. bus = & mmc_bus_type; return driver_register( & drv- > drv) ; } |
drv->driver.bus=&platform_bus_type
driver_register将到相应总线mmc_bus_type上去搜索相应设备。找到设备后就设置dev->driver=drv,并调用mmc_bus_type总线的probe函数被调用,即mmmc_bus_probe函数.
我们跟踪driver_register(&drv->drv),它会调应bus_add_driver。
int bus_add_driver( struct device_driver * drv) { . . . . . . error = kobject_set_name( & drv- > kobj, "%s" , drv- > name) ; if ( error ) goto out_put_bus; drv- > kobj. kset = & bus- > drivers; if ( ( error = kobject_register( & drv- > kobj) ) ) goto out_put_bus; error = driver_attach( drv) ; . . . . . . } |
函数会遍历相应总线(mmc_bus_type)上的dev,对这些dev执行总线的match函数(mmc_bus_match)。如果match成
功,它会调用mmc_bus_type总线的probe函数mmc_bus_probe(如果总线的probe存在的话).我们在以上走过的流程中可以看
到,我们并没有向总线添加任何设备,故mmc_bus_probe是不会调用的。但相应的driver已经注册到系统了。
那么,现在mmc_block.c中的分析就先暂时到此为止。。。不过,等会儿我们还会继续回到这个文件的。。
----------------------------------未完待续-----------------------------------
http://blog.chinaunix.net/space.php?uid=14782631&do=blog&id=111888
相关文章推荐
- linux2.6.20 sd/mmc卡驱动学习日记1(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记2(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记4(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记2(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记3(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记4(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记4(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记4(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记3(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记4(基于s3c2440)
- linux2.6.20 sd/mmc卡驱动学习日记
- linux2.6.20 sd/mmc卡驱动学习日记
- 基于S3C2440的嵌入式Linux驱动——Framebuffer子系统解读
- 基于S3C2440的Linux-3.6.6移植——SD卡的应用(一),SD卡的插拔检测
- 基于S3C2440的Linux内核移植和yaffs2文件系统制作-- Linux内核入口
- 基于S3C2440的linux-3.6.6移植——内核移植,建立自己的平台系统
- 基于S3C2440的Linux SPI驱动移植笔记
- 基于S3C2440的嵌入式Linux驱动——看门狗(watchdog)驱动解读
- 基于Linux2.6.22和s3c2440的串口驱动简析
- 基于S3C2440的Linux-3.6.6移植——sysfs文件系统的IIC应用