有任何一个 MMC5 的游戏的steam盗版游戏转正版卡么

SD卡和MMC卡有什么区别_百度知道
SD卡和MMC卡有什么区别
SD卡和MMC卡有什么区别
我有更好的答案
TF是尺寸很小的卡,多用于移动设备,手机、GPS等小型的数码移动设备,SD尺寸略大,一般用于相机、摄像机等家用数码产品。存储容量和速度基本是一致的。也可以把TF卡插在卡套上当做SD卡来使用。图片中最小的是TF卡,最大的是SD卡,
江南影像工作室
来自:百度知道
电脑装机/选购
SD卡和MMC卡近来得到了广泛的应用,它们的体积小,容量大(现在市场上已经有1GB的SD卡和512MB的MMC卡),速度也还不算慢,因此很多数码相机、手机、PDA、随身听等都使用SD卡和MMC卡,尽管因为近来缺货,SD卡价格有所上涨,但总的来说,现在的SD卡和MMC卡仍然很便宜(比年初已经跌了很多),值得选购。要注意的几点是: 1.SD卡和MMC卡的形状相同,结构相似,但SD卡的接口不同于MMC卡,很多数码设备既可以使用SD卡,也可以使用MMC卡,但并非所有设备都是如此,在购买之前请先确认一下。 2.外形上,SD卡比MMC卡厚,所以在一些设备,比如诺基亚3650上,只能够安装MMC卡,不能够安装SD卡。 3.MMC卡存在着不同的规格,如果对这个和自己的设备不了解,建议购买时带机现场试用。 4.有些手机和PDA对SD卡/MMC卡的兼容性较差,所以即使是要购买sandisk、松下这样较为可靠的名牌SD卡/MMC卡,建议还是带上自己的设备现场试用最好。 现在市场中SD卡/MMC卡最多的便是PQI(劲永)、Sandisk、EagleTEC(鹰泰)、Transcend(创见)、TwinMOS(勤茂)、Samsung(三星)、Kingston(金士顿)、Panasonic(松下)等品牌 SM卡是一种使用了很久的存储卡,大而且薄,过去一般用在MP3播放器、奥林巴斯和富士相机上,现在已经用得越来越少,因此也就只介绍一两种。注意SM卡及设备有3.3V和5V电压之分。 xD卡是一种比较新的小型存储卡,用在奥林巴斯和富士相机上,现在已经有了512MB的型号。xD卡体形轻巧、耗电量小,而且速度也可以和高速CF卡媲美,和CF卡不同的是,CF卡容量大的速度会慢一些,而xD卡则是容量大的速度更快。目前xD卡主要是Olympus(奥林巴斯)和Fujifilm(富士)等几种数码相机和摄像机常使用的存储卡主要有SecureDigital简称为SD卡、MemoryStick简称为记忆棒、CompactFlash简称为CF卡、SmartMediaCard简称为SM卡、MultiMemoryCard简称为MMC卡、XDPictureCard简称为XD卡。 SD卡就是SecureDigitalCard—安全数码卡,由松下公司,东芝公司和美国SANDISK公司共同开发研制的,具有大容量、高性能、安全等多种特点的多功能存储卡。它比MMC卡多了一个进行数据著作权保护的暗号认证功能(SDMI规格)。主要用于松下数码摄像机、照相机,佳能和夏普摄像机、柯达、美能达、卡西欧数码相机等厂家使用。尺寸为32mm×24mm×2.1mm,比MMC卡略厚一点容量则要大许多,已经生产出1G的容量。此卡的读写速度比MMC卡要快4倍,达2MB/秒。同时兼容MMC卡,SD卡的插口大多支持MMC卡。 MMC卡就是MultiMediaCard多媒体卡,是由美国SANDISK公司和德国西门子公司共同开发的一种多功能存储卡,它具有小型轻量的特点,外形尺寸是32mm×24mm×1.4mm,重量在2克以下,并且耐冲击,可反复进行读写记录30万次。驱动电压为2.7-3.6V。目前最大容量为128M多用于JVC数码摄像机。 记忆棒MemoryStick是索尼推出的数码存储卡。MemoryStick采用了单一平面的10针独立针槽设计,易于从插槽中插拔而不易损坏。从规格上看MemoryStick有普通棒、高速棒MemoryStickPro和短棒MemoryStickDUO三种,其中普通棒和高速棒的外型尺寸同为50mm×21mm×2.8mm,不同在于高速棒在存储卡中加入了MagicGate版权保护技术,拥有更高的读写速度,存储容量上限也有所提升。而短棒将记忆棒的体积进一步缩减,长度约为普通棒的1/2,通过一个适配器,可以像普通棒一样使用,长棒不能在短棒的机型上使用。记忆棒目前主要在索尼数码摄像机、照相机上使用,索尼今年的HC系列摄像机及T1、T3、T11等数码相机都是用短棒。 CF卡是由SanDisk公司于1994年研制成功的,有可永久保存数据、无需电源、速度快等优点,价格低于其他类型的存储卡。常见的有两种规格,其中CFTypeI型卡的尺寸为42.6mm×36.3mm×3.2mm,而CFTypeIICF卡自身带有记忆体和控制器,存储容量也可以做得更高。目前市面上CFTypeI型卡的常见容量有32MB、64MB、128MB、512MB、1GB、1.6GB等不同的规格,II型卡的最大容量目前可达到3GB。此外,磁介质的MicroDrive的最大容量目前可以达到4.2GB。CF卡主要在佳能、柯达、尼康等数码相机上使用。 XD卡是富士和奥林巴斯联合推出的一种专为数码相机使用的小型存储卡,采用单面18针设计,外型尺寸仅有20mm×25mm×1.7mm,是目前体积最小的存储卡。XD卡的理论最大容量可达8GB,目前市场上见到的XD卡有16MB、32MB、64MB、128MB、256MB等不同的容量规格。 SM卡是日本东芝推出的小型存储卡,具有22针的接口,尺寸为45mm×37mm×0.9mm,重量为1.8g左右。与大部分数码存储卡不同的是,SM卡由塑胶制成,控制器被内置到了数码相机中,由于相机的兼容性不强,所以并没有被厂商广泛推广,产品的最大容量也非常有限,SM卡的最高存储容量只有128MB。奥林巴斯的老款数码相机以及富士的老款数码相机多采用SM存储卡,新推出的数码相机中都已经没有采用SM存储卡的产品了。 数码相机中使用较为普遍的是CF卡和SD卡,记忆棒主要在索尼的数码相机中使用,XD卡主要用在富士和奥林巴斯的数码相机。从读写性能的实际比较中看,不同规格的存储卡在平均读取性能方面差异并不十分明显。 SD卡就是安全数码卡,MMC就是多媒体卡,手机建议使用MMC,速度无明显区别,但MMC的稳定性高。在手机上有格式化方式,FAT分区。
本回答被提问者采纳
通俗的说就和5号电池跟7号电池的区别一样/
内核也不一样 所以价钱也有所不同
其他2条回答
为您推荐:
其他类似问题
mmc卡的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。查看: 4792|回复: 20
chenci1988 FC 2.0制作感想
本帖最后由 n805 于
22:32 编辑
( [; N9 w! f8 C" E- N
首先要感谢chenci1988 的帮助才能让机子复活。
周五拿到配件,今天花了一下午完成,很悲剧发现无法动作,以为工夫都打水漂了。晚上在网上请教chenci1988如何检查修理,他很耐心地指导我一步一步检查电路,最后还是找到了问题所在,终于让机子复活了。
适才很兴奋地试了下游戏,画面及立体声输出都很棒。拍了些实物照,顺便做一下和原版机改AV输出的画面对比,画面均是有AV转HDMI 1080p输出到液晶显示器上。) l# r$ A3 C% |9 f+ w- G2 [
成品图,之前的问题就出在那颗电容那里...
我很喜欢这个立体声输出,带有扩展音源的游戏卡带或者BGM重低音比较强的游戏,比如霸王的大陆,烈火92,赤影战士等,立体声输出的BGM超赞。% J7 M&&U- H
' C8 J* D1 i+ O! e
不过发现一个问题,不知道是不是硬件兼容性问题。在运行带VRC7的拉格朗日点时候,如果使用机器后面的普通音频输出,声音都OK,但换到立体声输出的时候,游戏中只能听到音效,而听不到任何BGM。0 Q- v&&?' n1 O9 D" ?9 m+ n
=======6 d# o' u# B; e7 T0 o" x4 S( q
接下来是画面输出的对比。# s4 S, f, C/ ~
原版机改AV
6 ?5 u- I4 }& L# b&&_- h
FC 2.0, d7 @2 Z4 Z&&m! N' j
0 _, A&&j1 c: c" k. K
我的改造电路是之前在国外FAMICOM WORLD论坛上参照一个日本技术宅电路图的改的,实机上画面有些偏暗,白色背景下能看到jail bar,一般颜色下基本看不到,不过我转接成HDMI输出基本都看不见。4 {! w7 v+ o4 t3 _
=======, G8 T2 F; A0 f9 v+ K! U
说起来惭愧。我自己大学里专业好歹一般是跟电子挂钩的,可考完试后,模电数电的知识基本都忘光了。下午在焊接时候,我老爹看到FC的卡槽就猜到我在做FC,他说我只是依样画葫芦在焊接,而不是真正去了解这些硬件。DIY的乐趣不只是在动手做,很多时候需要自己的想法和思考,在遇到问题时自己的解决思路。我很感谢chenci1988今天很耐心指导我去检查电路。我发现自己电子的知识欠缺太多了,有时间要抽空补一补了。
' t% Q8 K8 A" p: k
本帖子中包含更多资源
才可以下载或查看,没有帐号?
“DIY的乐趣不只是在动手做,很多时候需要自己的想法和思考,在遇到问题时自己的解决思路。”这句话说得很对。8 D0 ]5 [# N' }, F+ ]7 D' S
恭喜楼主完成并稳定运行。' V' i" \; W( `+ X) k
又看到烈火92了,激动啊!
本帖最后由 n805 于
22:32 编辑
5 q! Y* l/ W9 ]' X* C' b
关于改立体声我一直有个疑问,也是关于扩展音源处理的。因为我没有看过chenci1988或孙大师的电路图,不知道立体声处理是分别取2A03的pin1和pin2的信号然后用类似Qsound的方法处理成虚拟环绕声还是直接取原始的单声道信号再处理成虚拟立体声的方法。因为对于使用了卡带辅助芯片如VRC6&7,MMC5或N163的游戏,主机的音频信号输入到卡带的pin45,经辅助芯片处理后包含扩展音频的信号再由pin46输出。不知道自制FC在电路设计中考没考虑到扩展音频输入和输出的问题。因为从楼主试机的几个游戏看,只有拉格朗日点是有扩展音频的,据我所知是中原的霸者而不是霸王的大陆用到扩展音频,简易楼主再选择几个VRC6和MMC5的游戏进行一下测试。( F9 S&&[: D& C- j& _
グ グ グ グ& &
本帖最后由 n805 于
22:32 编辑 ! C" `1 p: Y4 n1 [
3 |$ Y6 L( p, t&&v, {" r0 [; A
“DIY的乐趣不只是在动手做,很多时候需要自己的想法和思考,在遇到问题时自己的解决思路。”这句话说得很 ...[/quote]
这个烈火烧录的...原卡太贵了,买不起哈...
; w. x. f& q8 n: d
本帖最后由 n805 于
22:32 编辑 ' `9 V- W7 {9 Q7 g" w
) q- |8 n0 ]; c* |' Q% B( _# c. V
已知是这样的:
FC2.0的增强音频输出不支持带有扩展音频的卡带。因为这类卡带的音源是从Pin46引出的,以前制作FC2.0的时候我手头还没有任何有扩展音频的卡带,所以对于这个问题有所忽视。
不过解决此问题也有简单的办法,具体的我会完善后开贴说明。
感谢大家的支持!!!/ [+ p0 c( T* \& f2 J0 T" X! }
7 a- @! Z( L7 L9 Z
[url] & & 虍 虍 虍 虍& &
本帖最后由 n805 于
22:32 编辑
LZ的拉格朗日箱说全多少钱收的
[url] & & ╋ ╋ ╋ ╋& &
本帖最后由 n805 于
22:32 编辑 % E$ g! U# I! b: x5 e' t- M" G
3 v" L7 R- S% q( W( @0 c
非常赞楼主的diy,希望再接再厉!
4 e- X9 ~) N8 z$ s5 ]&&p8 J( y
本帖最后由 n805 于
22:32 编辑
LZ的拉格朗日箱说全多少钱收的[/quote]
我告诉你1400日币从日网上买的你相信么* U2 n7 [! O1 L& s* u
箱说全,带贴纸和宣传广告小纸,盒子无磨损。
8 Y6 }0 s$ O- p' {* Q5 V
本帖最后由 n805 于
22:32 编辑 - B8 ]2 m" I1 q# Q- ]
&&B# T( F* X7 q6 n. p6 v
关于立体声,多数都是用一个声道虚拟而成
网上有很多相关电路# ]+ C2 ^8 s. l0 G' ~0 u+ @
不知道动态降噪能否应用于FC音源上# o6 e$ T% E. S4 v* W! ~
&&s! c* B5 c( B5 K, P5 C. w
本帖最后由 n805 于
22:32 编辑 ' A! X! K/ U: ^) ~, F2 [9 ?) [& }
. _5 K0 G7 v& d$ {; s
原装机没改好, 颜色明显有问题。2 l4 z& R! r% @5 e6 s
Powered by200){this.value=this.value.slice(0,199)}">
服务评分:
评分明细与行业对比
商品描述:5.00
100.00%箭头
发货速度:5.00
100.00%箭头
服务质量:5.00
100.00%箭头
400-633-8839
公司名称:Sanwa 官方旗舰店
所在地:上海&&闵行区
商品编号:
SANWASD卡专用收藏盒FC-MMC5CF
国&&美&&价
好评度100%
领  劵
促  销
特  色
送  至
服  务
发货并负责售后服务。
凡是在国美购买的家安保服务,在保障期间内遇到无论是正常使用中的问题还是意外事故,即可享受家安保服务。国美家安保内容包括:延长保修、只换不修、屏碎保护、意外保护、服务保障。覆盖家电、手机数码、电脑办公等商品。
家安保服务,只能提供增值税普通电子发票,如有疑问,请与在线客服联系
人成功预约
预约抢购规则
1、欢迎预约购买,请在正式开售之后下单付款;
2、商品开售后,仅有已预约的用户可购买商品;
3、每人限购一件,先到先得。
正品保障;
支持7天无理由退货
国美易卡&分期
扫一扫,开启美好之旅
回复 summer:
回复 您还可以输入400字
SANWASD卡专用收藏盒FC-MMC5CF
商品名称:SANWASD卡专用收藏盒FC-MMC5CF
店铺名称:Sanwa 官方旗舰店
如果您发现商品信息不准确,
Sanwa Supply
签收与验货流程
【报价】查看
【评价】查看
售后内容icon
国美商城服务承诺:
国美商城向您保证所售商品均为正品行货,国美商城自营商品自带机打发票,与商品一起寄送(部分商品,需在您收到货物之后,我司为您邮寄)。凭质保证书及国美商城发票,可享受全国联保服务,与您亲临商场选购的商品享受相同的质量保证。
温馨提示:因厂家会在没有任何提前通知的情况下更改产品包装、产地或者一些附件,本司不能确保客户收到的货物与商城图片、产地、附件说明完全一致。只能确保为原厂正货!并且保证与当时市场上同样主流新品一致。若本商城没有及时更新,请大家谅解!
查看&第三方退换货政策
icon家安保 (延长保修 碎屏保修 意外保修)
icon专业维修
icon家电回收
icon家电清洗
icon上门安装
价格说明:
未划线价格:该价格是商品的销售标价,最终成交价格可能会因使用优惠券等原因而发生变化,请以订单结算页面价格为准。
划线价格:该价格是商品的参考价,可能是商品的厂商指导价、正品零售价、商品吊牌价、品牌专柜价,或者是在国美平台上曾经展示过的销售价等价格,仅供您选购商品时参考。
其他:1.商品促销信息以商品详情页促销栏目中的信息为准;2.如您发现活动商品售价或促销信息有异常,请购买前先联系销售商咨询。
只看当前商品评价
温馨提醒:因厂家同步信息存在时间误差,且每位用户购买情况、提问时间不尽相同,以下回复仅在提问时间3天内有效,仅供参考,谢谢~
我要发表咨询
咨询类型:&
咨询内容:&
如何尽快找到咨询答案:1、使用本页面左侧的搜索功能2、仔细查看相关提示信息和帮助文档
评分明细与行业对比
商品描述:5.00
100.00%箭头
发货速度:5.00
100.00%箭头
服务质量:5.00
100.00%箭头
&&&&价格:
店铺商品分类
支付与账户
扫描下载客户端
本公司游戏产品适合18岁以上成年人使用&&违法和不良信息举报电话:021-&&
国美在线电子商务有限公司&&办公地址:上海市嘉定区沪宜公路号一楼A区&&客服电话:&&
(C)&&国美在线电子商务有限公司版权所有&&京公安网备62&&沪ICP备号&&沪B2-号fc卡带的针脚开路或短路屏幕和声音为什么会奇怪?_百度知道
fc卡带的针脚开路或短路屏幕和声音为什么会奇怪?
我有更好的答案
FC 游戏机由于 6502处理器速度原始 内存极小
所以要时不时从卡带ROM 芯片中 读取数据 如果ROM 芯片针脚 开路 或者短路 会造成读取数据 地址位或者数据位 无法读取 或者 读取错误(前提是ROM芯片的电压正和负没短路 这2线短路 就是烧卡带或者烧游戏机)ROM 芯片的 地址线和数据线短路 就出现数据错误了 FC游戏机就会 死机 或者花屏幕 或者缺少部分图象层(FC 部分卡带 有图象ROM 俗称CHR ROM 或者是CHR缓存)或者卡机 音乐出错(音乐部分可能是在PRGROM芯片内 PRG ROM 出错就音乐错乱的可能
具体哪里地址 短路 会出什么问题 可以通过模拟器等软件 分析 游戏ROM 在芯片中存储地址位置 得出一些结论 这些位置到底存储是什么数据 FC 使用的多是8位一次性ROM 原理和8位闪存差不多
后期 国产卡带 也有通过高级MAPPER 硬件电路 使FC 卡带用上16位闪存的 比如酷哥的245合1 不重复巨型容量的卡带
说 MD 和SFC 普通卡带是存储器这个说的通
但是FC MAPPER0的卡带是存储器 也说的过去 最多也就74系列的信号地址转换芯片
但是FC 的MAPPER1 以上的卡带 是带有一定硬件处理能力的 起码有ROM 芯片多地址转换
甚至 KONAMI 的卡带有音乐处理芯片 MMC3 MMC5的卡带 甚至带有一定程度的图象处理能力 这些加强卡带硬件电路的使用 来弥补FC主机性能的不足 使游戏表现能力更上一层
所以FC的卡带盗版复杂程度 远远不是SFC 和MD 等普通卡带所能比拟的
起码SFC 和MD 普通卡带如果不带记忆功能 很有可能就是插槽上焊一片闪存
但是最简单FC 起码要2片闪存 或者1片闪存加 缓存
所以没法把所有的FC游戏做在一个卡里
只能是相同MAPPER 的游戏做成一个合卡
但是FC 的游戏MAPPER种类有 数百种之多 所以你要用卡带玩遍FC所有的游戏 起码要数百种卡带
甚至更有上百种 MAPPER电路是国内山寨厂家 和台湾厂家 研发的变种MAPPER硬件 让任天堂公司自己都惊厄
一定程度上你也可以这么理解 如果说FC加上卡带是一整套电脑的话
FC 主机只不过扮演的是CPU 和 极小的内存 和一些输出接口的角色 而卡带则扮演的是 更大内存 硬盘 乃至声卡 显卡的重要角色
部分FC卡带正版的造价甚至超过FC主机都很多 就是这个原理
后期FC 主机山货 可能1片黑豆电路就能解决的 但是很多FC卡带远远不是一片黑豆能解决的 实打实需要一些功能芯片 甚至电池 SRAM等等
造成卡带的复杂 根本原因就是FC主机性能低下 但是通过卡带功能的弥补 并不影响 FC上很多优秀游戏的成功
我真的不知道山内老头 看了国内FC山寨 的东西会有什么感想 但是有一点是可以理解的 FC在国内风行的时候 山内已经不再靠FC赚钱了
他已经靠SFC 甚至后来的GBA N64了
采纳率:80%
FC卡带就是存储器,针脚开路短路都会使主机对它的读写数据错误,错误数据生成的图像声音当然会不可预见、不可思议(如果这时程序还能继续运行的话)。#^_^#
本回答被网友采纳
为您推荐:
其他类似问题
短路的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。MMC卡驱动分析
MMC 卡驱动分析
最近花时间研究了一下 MMC 卡驱动程序,开始在网上找了很多关于 MMC 卡驱动的分析文章,但大都是在描述各个层,这对于初学者来讲帮助并不大,所以我就打算把自己的理解写下来,希望对大家有用。个人觉得理解LINUX 内核当中 MMC/SD 卡驱动程序构架是学习 MMC 卡驱动程序的重点,只有理解了它的基本框架或流程才能真正理解一个块设备驱动程序的写法,同时才能真正理解 LINUX 设备驱动模型是如何发挥作用的。
一.需要的基础知识:
LINUX 设备驱动的基本结构。
块设备驱动程序的基本构架(相信研究过 LDD3 当中的 sbull 的人应该都不成问题,如果只是走马观花的话,那可得好好再补补了)
LINUX 设备驱动模型。
二.驱动程序分析
首先,来明确一下我们需要分析的文件。下面的文件均来自 linux-2.6.24 源码,我们重点是分析驱动程序的基本构架,所以不同内核版本的差异并不是很大。 MMC/SD 卡驱动程序位于 drivers/mmc 目录下,我们只列出我们分析过程涉及到的几个文件:
queue.c/queue.h
bus.c/bus.h
core.c/core.h
host.c/host.h
mmc_ops.c/mmc_ops.h 拿 MMC 卡来分析, SD 卡驱动程序流程类似。
s3cmci.c/s3cmci.h 以 S3C24XX 的 MMC/SD 卡控制器为例,其它类型的控制器类似。
LINUX 当中对目录的划分是很有讲究的,这些文件被分布在 3 个目录下,正好对应 MMC/SD 驱动程序的 3 个层次(关于层的划分这里浏览一下,有个概念即可,当我们分析完了后再回头来看,你会觉得很形象):
主要是按照 LINUX 块设备驱动程序的框架实现一个卡的块设备驱动,这 block.c 当中我们可以看到写一个块设备驱动程序时需要的 block_device_operations 结构体变量的定义,其中有 open/release/request 函数的实现,而queue.c 则是对内核提供的请求队列的封装,我们暂时不用深入理解它,只需要知道一个块设备需要一个请求队列就可以了。
核心层封装了 MMC/SD 卡的命令,例如存储卡的识别,设置,读写。例如不管什么卡都应该有一些识别,设置,和读写的命令,这些流程都是必须要有的,只是具体对于不同的卡会有一些各自特有的操作。 Core.c 文件是由sd.c 、 mmc.c 两个文件支撑的, core.c 把 MMC 卡、 SD 卡的共性抽象出来,它们的差别由 sd.c 和 sd_ops.c、 mmc.c 和 mmc_ops.c 来完成。
主机控制器层
主机控制器则是依赖于不同的平台的,例如 s3c2410 的卡控制器和 atmel 的卡控制器必定是不一样的,所以要针对不同的控制器来实现。以 s3cmci.c 为例,它首先要进行一些设置,例如中断函数注册,全能控制器等等。然后它会向 core 层注册一个主机( host ),用结构 mmc_host_ops 描述,这样核心层就可以拿着这个 host 来操作s3c24xx 的卡控制器了,而具体是 s3c24xx 的卡控制器还是 atmel 的卡控制器, core 层是不用知道的。
驱动程序层次图
好了,对这几个目录有一个大概认识以后,我们来看几个重要的数据结构:
struct mmc_host 用来描述卡控制器
struct mmc_card 用来描述卡
struct mmc_driver 用来描述 mmc 卡驱动
struct mmc_host_ops 用来描述卡控制器操作集,用于从主机控制器层向 core 层注册操作函数,从而将core 层与具体的主机控制器隔离。也就是说 core 要操作主机控制器,就用这个 ops 当中给的函数指针操作,不能直接调用具体主控制器的函数。
第一阶段:
从 s3cmci_init 开始往下看
static int __init s3cmci_init(void)
platform_driver_register(&s3cmci_driver_2410);
有 platform_driver_register 函数,根据设备模型的知识,我们知道那一定会有对应的 platform_device_register函数的,可是在哪里呢?没有看到,那是不是这个 s3cmci_driver_2410 当中给的 probe 函数就不执行了???当然不是, mci 接口一般都是硬件做好的(我认为是这样),所以在系统启动时一定会有调用 platform_device-_register 对板上的资源进行注册,如果没有这个硬件资源,那我们这个驱动也就没有用了。好,我们就假定是有mci 接口的,而且也有与 s3cmci_driver_2410 对应的硬件资源注册了,那自己就会去跑 probe 函数。来看一下s3cmci_driver_2410:
static struct platform_driver s3cmci_driver_2410 = {
.driver.name
= "s3c2410-sdi",
= s3cmci_probe_2410,
= s3cmci_remove,
= s3cmci_suspend,
= s3cmci_resume,
我们到 s3cmci_probe_2410 函数中看,还是干脆直接看 s3cmci_probe 算了:
static int s3cmci_probe(struct platform_device *pdev, int is2440) // 来自 /host/s3cmci.c
struct mmc_host
struct s3cmci_host
mmc = mmc_alloc_host (sizeof(struct s3cmci_host), &pdev-&dev);
if (!mmc) {
ret = -ENOMEM;
goto probe_
= &s3cmci_
ret = mmc_add_host (mmc);
if (ret) {
dev_err(&pdev-&dev, "failed to add mmc host./n");
goto free_
platform_set_drvdata(pdev, mmc);
这个函数很长,做的事件也很多,但我们关心的整个驱动的构架 / 流程,所以过滤掉一些细节的东西,只看 2 个最重要的函数: mmc_alloc_host 、 mmc_add_host 。函数命名已经很形象了,前者是申请一个 mmc_host ,而后者是添加一个 mmc_host 。中间还有一个操作,就是给 mmc 的 ops
成员赋上了 s3cmci_ops 这个值。申请mmc_host 当然很简单,就是申请一个结构体(我们暂且这样认为,因为他里面还做的其它事情,后面会看到),而添加又是添加到哪里去呢?看 mmc_add_host 函数:
int mmc_add_host(struct mmc_host *host) // 来自 core/host.c
err = device_add(&host-&class_dev);
mmc_start_host(host);
很简单,就是增加了一个 device ,然后就调用 mmc_start_host 了,那就先跳过 device_add 这个动作,来看mmc_start_host:
void mmc_start_host(struct mmc_host *host) // 来自 /host/core.c
mmc_power_off(host);
// 掉电一下
mmc_detect_change(host, 0);
看上去只有两行代码,不过浓缩才是精华, mmc_power_off(host) 光看名子都知道是在干什么,先跳过,来看mmc_detect_change ,那么它到底干了些什么呢?看一下就知道了:
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
// core/core.c
mmc_schedule_delayed_work(&host-&detect, delay);
static int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
return queue_delayed_work(workqueue, work, delay);
mmc_detect_change 又跳了一下,最后调用了 queue_delayed_work ,不知道这个函数功能的去查一下〈〈LDD3 〉〉和〈〈深入理解 LINUX 内核〉〉,这几个代码告诉我们在 workqueue 这个工作队列当中添加一个延迟的工作任务,而这个工作任务就是由 host-&detect 来描述的,在随后的 delay 个 jiffies 后会有一个记录在 host-&detect 里面的函数被执行,那么到这里 s3cmci_probe 这个函数算是结束了,但事情还没有完, workqueue 这个工作队列还在忙,不一会儿它就会调用 host-&detect 里面那个函数,这个函数到底是哪个函数,到底是用来干什么的呢?好像没有看到, detect 包含在 host 里面,那估计是在刚才那个申请的地方设置的那个函数,回过头来看一下 mmc_alloc_host:
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
// 来自 core/host.c
struct mmc_host *
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
return NULL;
INIT_DELAYED_WORK(&host-&detect, mmc_rescan);
如果你看了 queue_delayed_work 这个函数功能介绍,相信对 INIT_DELAYED_WORK 也不会陌生了吧。不废话了,来看 mmc_rescan :
// 来自 core/host.c
void mmc_rescan(struct work_struct *work)
// // 来自 core/host.c
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
/* detect a newly inserted card */
* First we search for SDIO...
err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sdio(host, ocr))
mmc_power_off(host);
* ...then normal SD...
err = mmc_send_app_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sd(host, ocr))
mmc_power_off(host);
* ...and finally MMC.
err = mmc_send_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_mmc(host, ocr))
mmc_power_off(host);
mmc_release_host(host);
mmc_power_off(host);
if (host-&caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host-&detect, HZ);
浏览一个这个函数,看看函数名,再看看注释,知道什么了吗?它是在检测是不是有卡插入了卡控制器,如果有卡挺入就要采取相应的行动了。这里要明白一点,我们平时用的 SD/MMC 卡就是一个卡,如果要操作它得用SD/MMC 卡控制器才行,所以可以看到有 struct mmc_card,struct mmc_host 的区分。
到这里了,来回忆一下 s3cmci_probe 这个函数做的事情,大概就是准备一个 mmc_host 结构,然后添加一个主控制器设备到内核,最后又调用了一下 mmc_rescan 来检测是不是有卡插入了。
如果有卡插入了还好,可以去操作卡了,那如果没有卡插入呢? mmc_rescan 不是白调用了一次吗?是啊,的确是白调用了一次。可是卡插入时为什么 PC 还是能检测到呢?看来卡检测的动作不光是在 probe 的最后一步做了一次,其它地方也有做。卡插入一般都是人为地随时去插入的,像这种情况一般都是会用中断机制去提供系统有外来侵入,然后再去采取行动。 SD/MMC 卡也的确是这样做的,找来找去,发现在 s3cmci_probe 里面注册了一个中断函数 s3cmci_irq_cd( 函数名的意思应该是 irq
card detect) ,就是这个了,看看这个函数先:
static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
// host/s3cmci.c
struct s3cmci_host *host = (struct s3cmci_host *)dev_
mmc_detect_change(host-&mmc, msecs_to_jiffies(500));
return IRQ_HANDLED;
看到这个函数想都不用想,直接跳到 mmc_rescan 里面去看就行了。前面已经知道了 mmc_rescan 里面就是在检测卡是不是插入了,既然卡随时插入我们都能检测到了,那就来看卡插入后都做了些什么动作吧。
第二阶段:
mmc_rescan 里面既要检测 sd 卡,又要检测 mmc 卡的,我们就照着一个往下走,假定有个人插入了 MMC卡,那就应该走下面这几行:
err = mmc_send_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_mmc(host, ocr))
mmc_power_off(host);
mmc_send_op_cond 这个函数据说是读了一下卡的什么值,这个值是什么意义我也不清楚,这就像检测 FLASH时读 FLASH 的 ID 一样,网卡也是这样的,不用管这个值的意义了,只要知道它能标识是一个 MMC 卡插入就行了。如果取这个值没有错误的话就得进 mmc_attach_mmc 了:
* Starting point for MMC card init.
int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
// core/mmc.c
mmc_attach_bus_ops(host);
// 这个与总线的电源管理有关,暂时跳过
* Detect and init the card.
err = mmc_init_card(host, host-&ocr, NULL);
mmc_release_host(host);
err = mmc_add_card(host-&card);
goto remove_
remove_card:
还是找几个关键函数来看 mmc_init_card 从函数名来看就是初始化一个 card ,这个 card 就用 struct mmc_card结构来描述,然后又调用 mmc_add_card 将卡设备添加到了内核,先来看 mmc_init_card 都做了些什么事情:
static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
struct mmc_card *
u32 cid[4];
unsigned int max_
* Allocate card structure.
card = mmc_alloc_card(host, &mmc_type);
if (IS_ERR(card)) {
err = PTR_ERR(card);
card-&type = MMC_TYPE_MMC;
card-&rca = 1;
memcpy(card-&raw_cid, cid, sizeof(card-&raw_cid));
host-&card =
free_card:
将与硬件操作相关的全部删掉,最后对我们有用的也就这几行了 mmc_alloc_card 申请了一个 struct mmc_card结构,然后给 card-&type 赋上 MMC_TYPE_MMC ,最后将 card 又赋给了 host-&card ,这和具体硬件还是挺像的,因为一个主控制器一般就插一个卡,有卡时 host-&card 有值,没有卡时 host-&card 自己就是 NULL 了。
钻进 mmc_alloc_card 里面来看看:
* Allocate and initialise a new MMC card structure.
struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
struct mmc_card *
card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
if (!card)
return ERR_PTR(-ENOMEM);
card-&host =
device_initialize(&card-&dev);
card-&dev.parent = mmc_classdev(host);
card-&dev.bus = &mmc_bus_
card-&dev.release = mmc_release_
card-&dev.type =
Struct mmc_card 结构里面包含了一个 struct device 结构, mmc_alloc_card 不但申请了内存,而且还填充了struct device 中的几个成员,尤其 card-&dev.bus = &mmc_bus_ 这一句要重点对待。
申请一个 mmc_card 结构,并简单初始化后, mmc_init_card 的使命就完成了,然后再调用 mmc_add_card将这个 card 设备添加到内核。 mmc_add_card 其实很简单,就是调用 device_add 将 card-&dev 添加到内核当中去。
知道总线模型这个东西的人都明白,理到 device_add 里面总线就应该有动作了,具体是哪个总线呢?那就得看你调用 device_add 时送的那个 dev 里面指定的是哪个总线了,我们送的 card-&dev ,那么 card-&dev.bus具体指向什么呢?很明现是那个 mmc_bus_type :
static struct bus_type mmc_bus_type = {
.dev_attrs
= mmc_dev_attrs,
= mmc_bus_match,
= mmc_bus_uevent,
= mmc_bus_probe,
= mmc_bus_remove,
= mmc_bus_suspend,
= mmc_bus_resume,
在 device_add 里面,设备对应的总线会拿着你这个设备和挂在这个总线上的所有驱动程序去匹配( match ),此时会调用 match 函数,如果匹配到了就会调用总线的 probe 函数或驱动的 probe 函数,那我们看一下这里的mmc_bus_match 是如何进行匹配的:
static int mmc_bus_match(struct device *dev, struct device_driver *drv)
看来 match 永远都能成功,那就去执行 probe 吧:
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);
这里就有点麻烦了,在这个函数里面又调用了一下 drv-&probe() ,那这个 drv 是什么呢?上面有: struct mmc_driver *drv = to_mmc_driver(dev-&driver);
match 函数总是返回 1 ,那看来只要是挂在这条总线上的 driver 都有可能跑到这里来了,事实的确也是这样的,不过好在挂在这条总线上的 driver 只有一个,它是这样定义的:
static struct mmc_driver mmc_driver = {
= "mmcblk",
= mmc_blk_probe,
= mmc_blk_remove,
= mmc_blk_suspend,
= mmc_blk_resume,
看到这里时, card/core/host 几个已经全部被扯进来了,边看 mmc_driver 中的几个函数,他们几个如何联系起来也就慢慢明白了。那我们继续吧。
第三阶段:
前面已经看到了,在总线的 probe 里面调用了 drv-&probe, 而这个函数就对应的是 mmc_blk_probe ,具体这个mmc_driver 是怎么挂到 mmc_bus 上的,自己去看 mmc_blk_init() ,就几行代码,应该不难。
static int mmc_blk_probe(struct mmc_card *card) // 来自 card/block.c
struct mmc_blk_data *
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
add_disk(md-&disk);
mmc_blk_put(md);
还是捡重要的函数看,一看到这个函数最后调用了 add_disk ,你应该可以想到些什么吧?如果你不知道我在说些什么,那我估计你没有看过 LDD3 ,或者看了也是走马观花了。我来告诉你:如果看到 add_disk ,那说明前面一定会有 alloc_disk 和初始化队列的动作,在 mmc_blk_probe 时面没有体现出来,那就看mmc_blk_alloc(card) 那一行:
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
struct mmc_blk_data *
int devidx,
devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
if (devidx &= MMC_NUM_MINORS)
return ERR_PTR(-ENOSPC);
__set_bit(devidx, dev_use);
md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
if (!md) {
ret = -ENOMEM;
* Set the read-only status based on the supported commands
* and the write protect switch.
md-&read_only = mmc_blk_readonly(card);
md-&disk = alloc_disk(1 && MMC_SHIFT);
if (md-&disk == NULL) {
ret = -ENOMEM;
spin_lock_init(&md-&lock);
md-&usage = 1;
ret = mmc_init_queue(&md-&queue, card, &md-&lock);
md-&queue.issue_fn = mmc_blk_issue_
md-&queue.data =
md-&disk-&major
= MMC_BLOCK_MAJOR;
md-&disk-&first_minor = devidx && MMC_SHIFT;
md-&disk-&fops = &mmc_
md-&disk-&private_data =
md-&disk-&queue = md-&queue.
md-&disk-&driverfs_dev = &card-&
* As discussed on lkml, GENHD_FL_REMOVABLE should:
* - be set for removable media with permanent block devices
* - be unset for removable block devices with permanent media
* Since MMC block devices clearly fall under the second
* case, we do not set GENHD_FL_REMOVABLE.
* should use the block device creation/destruction hotplug
* messages to tell when the card is present.
sprintf(md-&disk-&disk_name, "mmcblk%d", devidx);
blk_queue_logical_block_size(md-&queue.queue, 512);
if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
* The EXT_CSD sector count is in number or 512 byte
* sectors.
set_capacity(md-&disk, card-&ext_csd.sectors);
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
set_capacity(md-&disk,
card-&csd.capacity && (card-&csd.read_blkbits - 9));
err_putdisk:
put_disk(md-&disk);
err_kfree:
kfree(md);
return ERR_PTR(ret);
看到这个函数的代码,我们自然就回忆起了块设备驱动的整个套路了:
分配、初始化请求队列,并绑定请求队列和请求函数。
分配,初始化 gendisk ,给 gendisk 的 major , fops , queue 等成员赋值,最后添加 gendisk 。
注册块设备驱动。
我们看看 MMC 卡驱动程序有没有按这个套路走,
1 、 mmc_init_queue 初始了队列,并将 mmc_blk_issue_ 函数绑定成请求函数;
2 、 alloc_disk 分配了 gendisk 结构,并初始化了 major , fops ,和 queue ;
3 、最后调用 add_disk 将块设备加到 KERNEL 中去。
到这里虽然 mmc_blk_probe 已经结束了,但我们别停下来。记得 LDD3 上在讲 sbull 实例时说过, add_disk 的调用标志着一个块设备驱动将被激活,所以在这之前必须把其它所有准备工作全部做好,作者为什么会这样说是有理由的,因为在 add_disk 里面 kernel 会去调用你绑定到队列中的请求函数,目的是去你的块设备上读分区表。而且是在 add_disk 内部就要做的,而不是 add_disk 返回后再做,具体为什么会这样,去看 add_disk 的代码实现就知道了。
既然要调用请求函数去读,那我们就来看看请求函数: mmc_blk_issue_rq
static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_blk_data *md = mq-&
struct mmc_card *card = md-&queue.
struct mmc_blk_
int ret = 1, disable_multi = 0;
mmc_wait_for_req(card-&host, &brq.mrq);
* A block was successfully transferred.
spin_lock_irq(&md-&lock);
ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
spin_unlock_irq(&md-&lock);
} while (ret);
这个函数实在太长了,好在我们不用全部看,大部分读数据的准备代码和出错处理的代码已经被我删掉了,只要知道读数据都是在这里完成的就够了。看不懂这个函数的,拿上 LDD3 找个人少的地方,将 sbull 研究透了也就明白这个函数了。不过这个函数里涉及的东西还挺不少,“散列表”,“回弹”都在这里出现了,有时间慢慢去研究吧。
在块设备驱动当中你只需要抓住请求队列和请求函数就可以了,具体那些 block_device_operations 里面赋值的函数可不像字符设备驱动里面那么受关注了。
分析到这里, MMC/SD 卡的驱动整个构架基本也就很明析了,说简单了就是做了两件事:
卡的检测;
卡数据的读取。
最后再将这两个过程大概串一下:
卡的检测:
S3cmci_probe(host/s3cmci.c)
Mmc_alloc_host(core/core.c)
Mmc_rescan(core/core.c)
Mmc_attach_mmc(core/mmc.c)
Mmc_init_card(core/mmc.c)
mmc_add_card(core/bus.c)
device_add
mmc_bus_match(core/bus.c)
mmc_bus_probe(core/bus.c)
mmc_blk_probe(card/block.c)
alloc_disk/add_disk
读写数据:
mmc_blk_issue_rq ( card/block.c )
mmc_wait_for_req(core/core.c)
mmc_start_request(core/core.c)
host-&ops-&request(host, mrq)
// s3cmci 中 s3cmci_request
MMC/SD 卡的驱动分析完了,是不是有些复杂,不过这样设计的目的是为了分层,让具体平台的驱动编写更加省事。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!}

我要回帖

更多关于 什么游戏没有盗版 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信