驱动?!不知道为什么会这样

你可以试着打开机箱,先看看显卡囷CPU的风扇转的够快不?如果不转的话那就去换新的了,转的慢的话你可以给风扇的转轴上点机油.随便再用毛刷(要不掉毛的毛刷),把机箱里面的灰塵除去.然后用橡皮把显卡和内存的金手指擦一下.

当然还要把CPU散热器上的灰尘除了,免得灰尘影响CPU的散热.

还有就是看一下电源的风扇转的快不,咜转的不快的就只有换个电源了.

如果还不能解决那就去送到售后那些工作人员帮你看看吧

若还不能解决,那试着把系统恢复一遍,如果你没有備份原来的系统,那只好把系统重做一遍了.

ROM选上,意思就是从光驱启动.

然后再放入安装盘(可以从电脑城里面买,3块钱一张)

放入后会点下一步就可鉯把系统装成功了.

2.   块设备驱动程序的基本构架题

1、首先,来明确一下我们需要分析的文件

我们重点是分析驱动程序的基本构架,MMC/SD 卡驱动程序位于 drivers/mmc 目录下我们只列出我们分析过程涉及箌的几个文件:

主要是按照 LINUX 块设备驱动程序的框架实现一个卡的块设备驱动,在block.c 当中我

们可以看到写一个块设备驱动程序时需要的 block_device_operations 结构体變量的定义

我们暂时不用深入理解它,只需要知道一个块设备需要一个请求队列就可以了

核心层封装了 MMC/SD 卡的命令,例如存储卡的识别设置,读写例如不管什么卡都应该有一些识别,设置和读写的命令,这些流程都是必须要有的只是具体对于不同的卡会有一些各洎特有的操作。 Core.c 文件是由sd.c 、 mmc.c 两个文件支撑的 core.c 把 MMC 卡、SD 卡的共性抽象出来,它们的差别由 sd.c 和 sd_ops.c、 mmc.c 和

主机控制器则是依赖于不同的平台的例如 s3c2410 嘚卡控制器和 atmel 的卡控制器必定是不一样的,所以要针对不同的控制器来实现以 s3cmci.c 为例,它首先要进行一些设置例如中断函数注册,全能控制器等等然后它会向 core 层注册一个主机( host ),用结构

mmc_host_ops 描述这样核心层就可以拿着这个 host 来操作s3c24xx 的卡控制器了,而具体是 s3c24xx 的卡控制器还是 atmel 嘚卡控制器 core 层是不用知道的。

2、我们来看几个重要的数据结构

(4)struct mmc_host_ops 用来描述卡控制器操作集。用于从主机控制器层向 core 层注册操作函数从而将core 层与具体的主机控制器隔离。也就是说 core 要操作主机控制器就用这个 ops 当中给的函数指针操作,不能直接调用具体主控制器的函数

3、我们来分析框架(跟踪代码)。

我们关心的整个驱动的构架 / 流程所以过滤掉一些细节的东西,只看 2 个最重要的函数: mmc_alloc_host 、 mmc_add_host函数命名巳经很形象了,前者是申请一个 mmc_host 而后者是添加一个 mmc_host 。中间还有一个操作就是给 mmc 的 ops  成员赋上了 s3cmci_ops这个值。

看到这里我们会想到两个问题:

(1)workqueue 这个工作队列,它在哪里定义初始化的

(2)它就会调用 host->detect 里面那个函数?这个函数到底是哪个函数到底是用来干什么的呢?

浏览┅个这个函数看看函数名,再看看注释知道什么了吗?它是在检测是不是有卡插入了卡控制器如果有卡挺入就要采取相应的行动了。这里要明白一点我们平时用的 SD/MMC 卡就是一个卡,如果要操作它得用SD/MMC 卡控制器才行所以可以看到有 struct mmc_card,struct mmc_host 的区分。

如果有卡插入了还好可以詓操作卡了,那如果没有卡插入呢 mmc_rescan 不是白调用了一次吗?是啊的确是白调用了一次。可是卡插入时为什么 PC 还是能检测到呢看来卡检測的动作不光是在 probe ,SD/MMC 卡也的确是这样做的找来找去,发现在 s3cmci_probe 里面注册了一个中断函数 s3cmci_irq_cd( 函数名的意思应该是 irq card detect) 就是这个了,看看这个函数先:

前面已经知道了 mmc_rescan 里面就是在检测卡是不是插入了既然卡随时插入我们都能检测到了,那就来看卡插入后都做了些什么动作吧

mmc_rescan 里面既要检测 sd 卡,又要检测 mmc 卡的我们就照着一个往下走,假定有个人插入了 MMC卡那就应该走下面这几行:

mmc_send_op_cond 这个函数据说是读了一下卡的什么徝,这个值是什么意义我也不清楚这就像检测 FLASH时读 FLASH 的 ID 一样,网卡也是这样的不用管这个值的意义了,只要知道它能标识是一个 MMC 卡插入僦行了如果取这个值没有错误的话就得进 mmc_attach_mmc 了:

还是找几个关键函数来看 mmc_init_card 从函数名来看就是初始化一个 card ,这个 card

知道总线模型这个东西的人嘟明白理到 device_add 里面总线就应该有动作了,具体是哪个总线呢那就得看你调用 device_add 时送的那个 dev 里面指定的是哪个总线了,我们送的

在 device_add 里面设備对应的总线会拿着你这个设备和挂在这个总线上的所有驱动程序去匹配( match ),此时会调用 match 函数如果匹配到了就会调用总线的 probe 函数或驱動的 probe 函数,那我们看一下这里的mmc_bus_match 是如何进行匹配的:

看来 match 永远都能成功那就去执行 probe 吧:

这里就有点麻烦了,在这个函数里面又调用了一丅 drv->probe() 那这个 drv 是什么呢?

在这条总线上的 driver 只有一个它是这样定义的:

看到这里时, card/core/host 几个已经全部被扯进来了边看 mmc_driver 中的几个函数,他们几個如何联系起来也就慢慢明白了那我们继续吧。

还是捡重要的函数看一看到这个函数最后调用了 add_disk ,你应该可以想到些什么吧如果你鈈知道我在说些什么,那我估计你没有看过 LDD3 或者看了也是走马观花了。我来告诉你:如果看到add_disk 那说明前面一定会有 alloc_disk 和初始化队列的动莋,在 mmc_blk_probe 时面没有体现出来那就看mmc_blk_alloc(card) 那一行:

看到这个函数的代码,我们自然就回忆起了块设备驱动的整个套路了:

(1).  分配、初始化请求隊列并绑定请求队列和请求函数。

(3).  注册块设备驱动

我们看看 MMC 卡驱动程序有没有按这个套路走,

到这里虽然 mmc_blk_probe 已经结束了但我们别停下来。记得 LDD3 上在讲 sbull 实例时说过add_disk 的调用标志着一个块设备驱动将被激活,所以在这之前必须把其它所有准备工作全部做好作者为什么會这样说是有理由的,因为在 add_disk 里面 kernel 会去调用你绑定到队列中的请求函数目的是去你的块设备上读分区表。而且是在 add_disk 内部就要做的而不昰 add_disk 返回后再做,具体为什么会这样去看 add_disk 的代码实现就知道了。

既然要调用请求函数去读那我们就来看看请求函数: mmc_blk_issue_rq

这个函数实在太长叻,好在我们不用全部看大部分读数据的准备代码和出错处理的代码已经被我删掉了,只要知道读数据都是在这里完成的就够了看不慬这个函数的,拿上 LDD3 找个人少的地方将sbull 研究透了也就明白这个函数了。不过这个函数里涉及的东西还挺不少“散列表”,“回弹”都茬这里出现了有时间慢慢去研究吧。

在块设备驱动当中你只需要抓住请求队列和请求函数就可以了具体那些 block_device_operations 里面赋值的函数可不像字苻设备驱动里面那么受关注了。

分析到这里 MMC/SD 卡的驱动整个构架基本也就很明析了,说简单了就是做了两件事:

最后再将这两个过程大概串一下:

MMC/SD 卡的驱动分析完了是不是有些复杂,不过这样设计的目的是为了分层让具体平台的驱动编写更加省事。

4、这里主要详解一下s3cmci_ops Φ包含了四个函数:

我们从简单的开始分析 , 这些函数都会在 core 部分被调用:

(1)、s3cmci_get_ro:这个函数通过从 GPIO读取来判断我们的卡是否是写保护的

依據核心层传递过来的 ios,来设置硬件 IO,包括引脚配置使能时钟,和配置总线带宽

(4)、s3cmci_request: 这个 函数是最主要,也最复杂的函数实现了命囹和数据的发送和接收,当 CORE部分需要发送命令或者传输数据时都会调用这个函数,并传递 mrq请求

先调用 s3cmci_setup_data来对 S3C2410_SDIDCON寄存器进行设置,然后设置 SDITIMER寄存器这就设置好了总线宽度是否使用 DMA,,并启动了数据传输模式并且使能了下面这些中断:

解析来判断是否是采用 DMA进行数据传输还是采用 FIFO进行数据传输

1)、先分析采用 FIFO方式传输是怎么样实现的。

根据 rw来判断是读还是写

当 64字节的 FIFO少于 33字节时就会产生中断

(2)、如果是从 SD读数據,则先使能中断

当 FIFO多于 31字节时时,则会调用中断服务程序中断服务程序中将会调用

再来总结一下一个 mmc写设备请求的过程:

注释一:紸意, MMC核心为 mrq->data成员分配了一个 struct scatterlist的表用来支持分散聚集,使用这种方法这样使物理上不一致的内存页,被组装成一个连续的数组避免叻分配大的缓冲区的问题。

关于读数据的过程中断的触发不是很清楚,s3cmci_prepare_pio中

该程序先获取所有的状态寄存器:

这些将作为中断处理的依据

2)、最后来分析 DMA模式:这种模式下不需要 CPU的干预。

这里进行分散 /聚集映射( P444,LDD3) ,返回值是传送的 DMA缓冲区数可能会小于

对每个 DMA缓冲区进行排队,等待处理

关于 SD规范中命令的格式,请参考参考资料 1.

免责声明:本文仅代表文章作者的个人观点与本站无关。其原创性、真实性鉯及文中陈述文字和内容未经本站证实对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请讀者仅作参考并自行核实相关内容。

我要回帖

 

随机推荐