<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM-Linux驅(qū)動(dòng)--MTD驅(qū)動(dòng)分析(三)

          ARM-Linux驅(qū)動(dòng)--MTD驅(qū)動(dòng)分析(三)

          作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò) 收藏
          主機(jī):Gentoo Linux 11.2 with linux kernel 3.0.6

          硬件平臺(tái):FL2440(S3C2440)with linux kernel 2.6.35

          本文引用地址:http://www.ex-cimer.com/article/201611/319014.htm

          本文分析MTD設(shè)備的分區(qū)管理機(jī)制

          分區(qū)管理實(shí)際上是將一個(gè)MTD設(shè)備分成幾個(gè)分區(qū),將其作為單獨(dú)的MTD原始設(shè)備進(jìn)行管理。

          1、分區(qū)的結(jié)構(gòu)體描述結(jié)構(gòu)體mtd_part

          1. /*Ourpartitionnodestructure*/
          2. //分區(qū)結(jié)構(gòu)信息
          3. structmtd_part{
          4. structmtd_infomtd;//mtd_info數(shù)據(jù)結(jié)構(gòu),會(huì)被加入mtd_table中
          5. structmtd_info*master;//該分區(qū)的主分區(qū)
          6. uint64_toffset;//該分區(qū)的偏移地址
          7. structlist_headlist;
          8. };

          2、分區(qū)鏈表mtd_partitions

          1. /*Ourpartitionlinkedlist*/
          2. //聲明mtd_partitions鏈表
          3. staticLIST_HEAD(mtd_partitions);

          3、add_mtd_partitions函數(shù)
          1. /*
          2. *Thisfunction,givenamasterMTDobjectandapartitiontable,creates
          3. *andregistersslaveMTDobjectswhichareboundtothemasteraccordingto
          4. *thepartitiondefinitions.
          5. *
          6. *Wedontregisterthemaster,orexpectthecallertohavedoneso,
          7. *forreasonsofdataintegrity.
          8. */
          9. //根據(jù)一個(gè)MTD主設(shè)備和分區(qū)表,創(chuàng)建新的主設(shè)備下的副設(shè)備并記錄到分區(qū)表中
          10. //這里我們不將注射被注冊(cè)到分區(qū)表中,只注冊(cè)副設(shè)備到到分區(qū)表中
          11. intadd_mtd_partitions(structmtd_info*master,
          12. conststructmtd_partition*parts,
          13. intnbparts)
          14. {
          15. structmtd_part*slave;
          16. uint64_tcur_offset=0;
          17. inti;
          18. printk(KERN_NOTICE"Creating%dMTDpartitionson"%s":n",nbparts,master->name);
          19. for(i=0;i
          20. slave=add_one_partition(master,parts+i,i,cur_offset);
          21. if(!slave)
          22. return-ENOMEM;
          23. cur_offset=slave->offset+slave->mtd.size;
          24. }
          25. return0;
          26. }
          27. EXPORT_SYMBOL(add_mtd_partitions);

          而add_one_partition函數(shù)實(shí)現(xiàn)如下:
          1. //創(chuàng)建一個(gè)分區(qū)
          2. staticstructmtd_part*add_one_partition(structmtd_info*master,
          3. conststructmtd_partition*part,intpartno,
          4. uint64_tcur_offset)
          5. {
          6. structmtd_part*slave;
          7. /*allocatethepartitionstructure*/
          8. slave=kzalloc(sizeof(*slave),GFP_KERNEL);//分配內(nèi)存
          9. if(!slave){
          10. printk(KERN_ERR"memoryallocationerrorwhilecreatingpartitionsfor"%s"n",
          11. master->name);
          12. del_mtd_partitions(master);
          13. returnNULL;
          14. }
          15. list_add(&slave->list,&mtd_partitions);//將原始設(shè)備表添加到分區(qū)表中
          16. /*setuptheMTDobjectforthispartition*/
          17. //大部分根據(jù)master相應(yīng)的信息設(shè)置MTD分區(qū)slave的信息
          18. slave->mtd.type=master->type;
          19. slave->mtd.flags=master->flags&~part->mask_flags;
          20. slave->mtd.size=part->size;
          21. slave->mtd.writesize=master->writesize;
          22. slave->mtd.oobsize=master->oobsize;
          23. slave->mtd.oobavail=master->oobavail;
          24. slave->mtd.subpage_sft=master->subpage_sft;
          25. slave->mtd.name=part->name;
          26. slave->mtd.owner=master->owner;
          27. slave->mtd.backing_dev_info=master->backing_dev_info;
          28. /*NOTE:wedontarrangeMTDsasatree;itdbeerror-prone
          29. *tohavethesamedatabeintwodifferentpartitions.
          30. */
          31. slave->mtd.dev.parent=master->dev.parent;
          32. slave->mtd.read=part_read;
          33. slave->mtd.write=part_write;
          34. if(master->panic_write)
          35. slave->mtd.panic_write=part_panic_write;
          36. if(master->point&&master->unpoint){
          37. slave->mtd.point=part_point;
          38. slave->mtd.unpoint=part_unpoint;
          39. }
          40. if(master->get_unmapped_area)
          41. slave->mtd.get_unmapped_area=part_get_unmapped_area;
          42. if(master->read_oob)
          43. slave->mtd.read_oob=part_read_oob;
          44. if(master->write_oob)
          45. slave->mtd.write_oob=part_write_oob;
          46. if(master->read_user_prot_reg)
          47. slave->mtd.read_user_prot_reg=part_read_user_prot_reg;
          48. if(master->read_fact_prot_reg)
          49. slave->mtd.read_fact_prot_reg=part_read_fact_prot_reg;
          50. if(master->write_user_prot_reg)
          51. slave->mtd.write_user_prot_reg=part_write_user_prot_reg;
          52. if(master->lock_user_prot_reg)
          53. slave->mtd.lock_user_prot_reg=part_lock_user_prot_reg;
          54. if(master->get_user_prot_info)
          55. slave->mtd.get_user_prot_info=part_get_user_prot_info;
          56. if(master->get_fact_prot_info)
          57. slave->mtd.get_fact_prot_info=part_get_fact_prot_info;
          58. if(master->sync)
          59. slave->mtd.sync=part_sync;
          60. if(!partno&&!master->dev.class&&master->suspend&&master->resume){
          61. slave->mtd.suspend=part_suspend;
          62. slave->mtd.resume=part_resume;
          63. }
          64. if(master->writev)
          65. slave->mtd.writev=part_writev;
          66. if(master->lock)
          67. slave->mtd.lock=part_lock;
          68. if(master->unlock)
          69. slave->mtd.unlock=part_unlock;
          70. if(master->block_isbad)
          71. slave->mtd.block_isbad=part_block_isbad;
          72. if(master->block_markbad)
          73. slave->mtd.block_markbad=part_block_markbad;
          74. slave->mtd.erase=part_erase;
          75. slave->master=master;
          76. slave->offset=part->offset;
          77. if(slave->offset==MTDPART_OFS_APPEND)
          78. slave->offset=cur_offset;
          79. if(slave->offset==MTDPART_OFS_NXTBLK){
          80. slave->offset=cur_offset;
          81. if(mtd_mod_by_eb(cur_offset,master)!=0){
          82. /*Rounduptonexterasesize*/
          83. slave->offset=(mtd_div_by_eb(cur_offset,master)+1)*master->erasesize;
          84. printk(KERN_NOTICE"Movingpartition%d:"
          85. "0x%012llx->0x%012llxn",partno,
          86. (unsignedlonglong)cur_offset,(unsignedlonglong)slave->offset);
          87. }
          88. }
          89. if(slave->mtd.size==MTDPART_SIZ_FULL)
          90. slave->mtd.size=master->size-slave->offset;
          91. printk(KERN_NOTICE"0x%012llx-0x%012llx:"%s"n",(unsignedlonglong)slave->offset,
          92. (unsignedlonglong)(slave->offset+slave->mtd.size),slave->mtd.name);
          93. /*letsdosomesanitychecks*/
          94. if(slave->offset>=master->size){
          95. /*letsregisteritanywaytopreserveordering*/
          96. slave->offset=0;
          97. slave->mtd.size=0;
          98. printk(KERN_ERR"mtd:partition"%s"isoutofreach--disabledn",
          99. part->name);
          100. gotoout_register;
          101. }
          102. if(slave->offset+slave->mtd.size>master->size){
          103. slave->mtd.size=master->size-slave->offset;
          104. printk(KERN_WARNING"mtd:partition"%s"extendsbeyondtheendofdevice"%s"--sizetruncatedto%#llxn",
          105. part->name,master->name,(unsignedlonglong)slave->mtd.size);
          106. }
          107. if(master->numeraseregions>1){
          108. /*Dealwithvariableerasesizestuff*/
          109. inti,max=master->numeraseregions;
          110. u64end=slave->offset+slave->mtd.size;
          111. structmtd_erase_region_info*regions=master->eraseregions;
          112. /*Findthefirsteraseregionswhichispartofthis
          113. *partition.*/
          114. for(i=0;ioffset;i++)
          115. ;
          116. /*Theloopsearchedfortheregion_behind_thefirstone*/
          117. if(i>0)
          118. i--;
          119. /*Pickbiggesterasesize*/
          120. for(;i
          121. if(slave->mtd.erasesize
          122. slave->mtd.erasesize=regions[i].erasesize;
          123. }
          124. }
          125. BUG_ON(slave->mtd.erasesize==0);
          126. }else{
          127. /*Singleerasesize*/
          128. slave->mtd.erasesize=master->erasesize;
          129. }
          130. if((slave->mtd.flags&MTD_WRITEABLE)&&
          131. mtd_mod_by_eb(slave->offset,&slave->mtd)){
          132. /*Doesntstartonaboundaryofmajorerasesize*/
          133. /*FIXME:Letitbewritableifitisonaboundaryof
          134. *_minor_erasesizethough*/
          135. slave->mtd.flags&=~MTD_WRITEABLE;
          136. printk(KERN_WARNING"mtd:partition"%s"doesntstartonaneraseblockboundary--forceread-onlyn",
          137. part->name);
          138. }
          139. if((slave->mtd.flags&MTD_WRITEABLE)&&
          140. mtd_mod_by_eb(slave->mtd.size,&slave->mtd)){
          141. slave->mtd.flags&=~MTD_WRITEABLE;
          142. printk(KERN_WARNING"mtd:partition"%s"doesntendonaneraseblock--forceread-onlyn",
          143. part->name);
          144. }
          145. slave->mtd.ecclayout=master->ecclayout;
          146. if(master->block_isbad){
          147. uint64_toffs=0;
          148. while(offsmtd.size){
          149. if(master->block_isbad(master,
          150. offs+slave->offset))
          151. slave->mtd.ecc_stats.badblocks++;
          152. offs+=slave->mtd.erasesize;
          153. }
          154. }
          155. out_register:
          156. /*registerourpartition*/
          157. //最后調(diào)用add_mtd_device根據(jù)該設(shè)備的mtd_info信息添加設(shè)備鏈表,將其作為一個(gè)獨(dú)立的MTD原始設(shè)備
          158. add_mtd_device(&slave->mtd);
          159. returnslave;
          160. }

          4、del_mtd_partition函數(shù)
          1. /*
          2. *ThisfunctionunregistersanddestroyallslaveMTDobjectswhichare
          3. *attachedtothegivenmasterMTDobject.
          4. */
          5. //將一個(gè)主設(shè)備下的所有副設(shè)備刪除
          6. intdel_mtd_partitions(structmtd_info*master)
          7. {
          8. structmtd_part*slave,*next;
          9. list_for_each_entry_safe(slave,next,&mtd_partitions,list)//遍歷mtd_partitions鏈表,查找到指定的主設(shè)備
          10. if(slave->master==master){
          11. list_del(&slave->list);//將主設(shè)備下的附屬設(shè)備刪除
          12. del_mtd_device(&slave->mtd);//調(diào)用del_mtd_device函數(shù)將每個(gè)設(shè)備從MTD原始設(shè)備表中刪除
          13. kfree(slave);//釋放內(nèi)存
          14. }
          15. return0;
          16. }
          17. EXPORT_SYMBOL(del_mtd_partitions);

          5、其他的分區(qū)管理函數(shù)
          1. /*
          2. *MTDmethodswhichsimplytranslatetheeffectiveaddressandpassthrough
          3. *tothe_real_device.
          4. */
          5. //讀取某個(gè)分區(qū)的指定數(shù)據(jù)
          6. staticintpart_read(structmtd_info*mtd,loff_tfrom,size_tlen,
          7. size_t*retlen,u_char*buf)
          8. {
          9. structmtd_part*part=PART(mtd);
          10. structmtd_ecc_statsstats;
          11. intres;
          12. stats=part->master->ecc_stats;
          13. if(from>=mtd->size)
          14. len=0;
          15. elseif(from+len>mtd->size)
          16. len=mtd->size-from;
          17. res=part->master->read(part->master,from+part->offset,
          18. len,retlen,buf);
          19. if(unlikely(res)){
          20. if(res==-EUCLEAN)
          21. mtd->ecc_stats.corrected+=part->master->ecc_stats.corrected-stats.corrected;
          22. if(res==-EBADMSG)
          23. mtd->ecc_stats.failed+=part->master->ecc_stats.failed-stats.failed;
          24. }
          25. returnres;
          26. }
          27. staticintpart_point(structmtd_info*mtd,loff_tfrom,size_tlen,
          28. size_t*retlen,void**virt,resource_size_t*phys)
          29. {
          30. structmtd_part*part=PART(mtd);
          31. if(from>=mtd->size)
          32. len=0;
          33. elseif(from+len>mtd->size)
          34. len=mtd->size-from;
          35. returnpart->master->point(part->master,from+part->offset,
          36. len,retlen,virt,phys);
          37. }
          38. staticvoidpart_unpoint(structmtd_info*mtd,loff_tfrom,size_tlen)
          39. {
          40. structmtd_part*part=PART(mtd);
          41. part->master->unpoint(part->master,from+part->offset,len);
          42. }
          43. //獲取空閑的內(nèi)存驅(qū)動(dòng)
          44. staticunsignedlongpart_get_unmapped_area(structmtd_info*mtd,
          45. unsignedlonglen,
          46. unsignedlongoffset,
          47. unsignedlongflags)
          48. {
          49. structmtd_part*part=PART(mtd);
          50. offset+=part->offset;
          51. returnpart->master->get_unmapped_area(part->master,len,offset,
          52. flags);
          53. }
          54. staticintpart_read_oob(structmtd_info*mtd,loff_tfrom,
          55. structmtd_oob_ops*ops)
          56. {
          57. structmtd_part*part=PART(mtd);
          58. intres;
          59. if(from>=mtd->size)
          60. return-EINVAL;
          61. if(ops->datbuf&&from+ops->len>mtd->size)
          62. return-EINVAL;
          63. res=part->master->read_oob(part->master,from+part->offset,ops);
          64. if(unlikely(res)){
          65. if(res==-EUCLEAN)
          66. mtd->ecc_stats.corrected++;
          67. if(res==-EBADMSG)
          68. mtd->ecc_stats.failed++;
          69. }
          70. returnres;
          71. }
          72. staticintpart_read_user_prot_reg(structmtd_info*mtd,loff_tfrom,
          73. size_tlen,size_t*retlen,u_char*buf)
          74. {
          75. structmtd_part*part=PART(mtd);
          76. returnpart->master->read_user_prot_reg(part->master,from,
          77. len,retlen,buf);
          78. }
          79. staticintpart_get_user_prot_info(structmtd_info*mtd,
          80. structotp_info*buf,size_tlen)
          81. {
          82. structmtd_part*part=PART(mtd);
          83. returnpart->master->get_user_prot_info(part->master,buf,len);
          84. }
          85. staticintpart_read_fact_prot_reg(structmtd_info*mtd,loff_tfrom,
          86. size_tlen,size_t*retlen,u_char*buf)
          87. {
          88. structmtd_part*part=PART(mtd);
          89. returnpart->master->read_fact_prot_reg(part->master,from,
          90. len,retlen,buf);
          91. }
          92. staticintpart_get_fact_prot_info(structmtd_info*mtd,structotp_info*buf,
          93. size_tlen)
          94. {
          95. structmtd_part*part=PART(mtd);
          96. returnpart->master->get_fact_prot_info(part->master,buf,len);
          97. }
          98. //分區(qū)寫(xiě)函數(shù)
          99. staticintpart_write(structmtd_info*mtd,loff_tto,size_tlen,
          100. size_t*retlen,constu_char*buf)
          101. {
          102. structmtd_part*part=PART(mtd);
          103. if(!(mtd->flags&MTD_WRITEABLE))
          104. return-EROFS;
          105. if(to>=mtd->size)
          106. len=0;
          107. elseif(to+len>mtd->size)
          108. len=mtd->size-to;
          109. returnpart->master->write(part->master,to+part->offset,
          110. len,retlen,buf);
          111. }
          112. staticintpart_panic_write(structmtd_info*mtd,loff_tto,size_tlen,
          113. size_t*retlen,constu_char*buf)
          114. {
          115. structmtd_part*part=PART(mtd);
          116. if(!(mtd->flags&MTD_WRITEABLE))
          117. return-EROFS;
          118. if(to>=mtd->size)
          119. len=0;
          120. elseif(to+len>mtd->size)
          121. len=mtd->size-to;
          122. returnpart->master->panic_write(part->master,to+part->offset,
          123. len,retlen,buf);
          124. }
          125. staticintpart_write_oob(structmtd_info*mtd,loff_tto,
          126. structmtd_oob_ops*ops)
          127. {
          128. structmtd_part*part=PART(mtd);
          129. if(!(mtd->flags&MTD_WRITEABLE))
          130. return-EROFS;
          131. if(to>=mtd->size)
          132. return-EINVAL;
          133. if(ops->datbuf&&to+ops->len>mtd->size)
          134. return-EINVAL;
          135. returnpart->master->write_oob(part->master,to+part->offset,ops);
          136. }
          137. staticintpart_write_user_prot_reg(structmtd_info*mtd,loff_tfrom,
          138. size_tlen,size_t*retlen,u_char*buf)
          139. {
          140. structmtd_part*part=PART(mtd);
          141. returnpart->master->write_user_prot_reg(part->master,from,
          142. len,retlen,buf);
          143. }
          144. staticintpart_lock_user_prot_reg(structmtd_info*mtd,loff_tfrom,
          145. size_tlen)
          146. {
          147. structmtd_part*part=PART(mtd);
          148. returnpart->master->lock_user_prot_reg(part->master,from,len);
          149. }
          150. staticintpart_writev(structmtd_info*mtd,conststructkvec*vecs,
          151. unsignedlongcount,loff_tto,size_t*retlen)
          152. {
          153. structmtd_part*part=PART(mtd);
          154. if(!(mtd->flags&MTD_WRITEABLE))
          155. return-EROFS;
          156. returnpart->master->writev(part->master,vecs,count,
          157. to+part->offset,retlen);
          158. }
          159. staticintpart_erase(structmtd_info*mtd,structerase_info*instr)
          160. {
          161. structmtd_part*part=PART(mtd);
          162. intret;
          163. if(!(mtd->flags&MTD_WRITEABLE))
          164. return-EROFS;
          165. if(instr->addr>=mtd->size)
          166. return-EINVAL;
          167. instr->addr+=part->offset;
          168. ret=part->master->erase(part->master,instr);
          169. if(ret){
          170. if(instr->fail_addr!=MTD_FAIL_ADDR_UNKNOWN)
          171. instr->fail_addr-=part->offset;
          172. instr->addr-=part->offset;
          173. }
          174. returnret;
          175. }
          176. voidmtd_erase_callback(structerase_info*instr)
          177. {
          178. if(instr->mtd->erase==part_erase){
          179. structmtd_part*part=PART(instr->mtd);
          180. if(instr->fail_addr!=MTD_FAIL_ADDR_UNKNOWN)
          181. instr->fail_addr-=part->offset;
          182. instr->addr-=part->offset;
          183. }
          184. if(instr->callback)
          185. instr->callback(instr);
          186. }
          187. EXPORT_SYMBOL_GPL(mtd_erase_callback);
          188. staticintpart_lock(structmtd_info*mtd,loff_tofs,uint64_tlen)
          189. {
          190. structmtd_part*part=PART(mtd);
          191. if((len+ofs)>mtd->size)
          192. return-EINVAL;
          193. returnpart->master->lock(part->master,ofs+part->offset,len);
          194. }
          195. staticintpart_unlock(structmtd_info*mtd,loff_tofs,uint64_tlen)
          196. {
          197. structmtd_part*part=PART(mtd);
          198. if((len+ofs)>mtd->size)
          199. return-EINVAL;
          200. returnpart->master->unlock(part->master,ofs+part->offset,len);
          201. }
          202. //分區(qū)同步函數(shù)
          203. staticvoidpart_sync(structmtd_info*mtd)
          204. {
          205. structmtd_part*part=PART(mtd);
          206. part->master->sync(part->master);
          207. }
          208. //支持電源管理的功能函數(shù)
          209. staticintpart_suspend(structmtd_info*mtd)
          210. {
          211. structmtd_part*part=PART(mtd);
          212. returnpart->master->suspend(part->master);
          213. }
          214. staticvoidpart_resume(structmtd_info*mtd)
          215. {
          216. structmtd_part*part=PART(mtd);
          217. part->master->resume(part->master);
          218. }
          219. staticintpart_block_isbad(structmtd_info*mtd,loff_tofs)
          220. {
          221. structmtd_part*part=PART(mtd);
          222. if(ofs>=mtd->size)
          223. return-EINVAL;
          224. ofs+=part->offset;
          225. returnpart->master->block_isbad(part->master,ofs);
          226. }
          227. //標(biāo)記設(shè)備地址壞塊
          228. staticintpart_block_markbad(structmtd_info*mtd,loff_tofs)
          229. {
          230. structmtd_part*part=PART(mtd);
          231. intres;
          232. if(!(mtd->flags&MTD_WRITEABLE))
          233. return-EROFS;
          234. if(ofs>=mtd->size)
          235. return-EINVAL;
          236. ofs+=part->offset;
          237. res=part->master->block_markbad(part->master,ofs);
          238. if(!res)
          239. mtd->ecc_stats.badblocks++;
          240. returnres;
          241. }

          下篇分析具體的MTD設(shè)備,字符設(shè)備和塊設(shè)備,待續(xù)........


          評(píng)論


          相關(guān)推薦

          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();