ARM-Linux驅(qū)動(dòng)--MTD驅(qū)動(dòng)分析(一)
硬件平臺(tái):FL2440(S3C2440)with linux kernel 2.6.35
本文引用地址:http://m.butianyuan.cn/article/201611/319012.htmMTD(memory technology device內(nèi)存技術(shù)設(shè)備) 在硬件和文件系統(tǒng)層之間的提供了一個(gè)抽象的接口,MTD是用來(lái)訪問(wèn)內(nèi)存設(shè)備(如:ROM、flash)的中間層,它將內(nèi)存設(shè)備的共有特性抽取出來(lái),從而使增加新的內(nèi)存設(shè)備驅(qū)動(dòng)程序變得更簡(jiǎn)單。MTD的源代碼都在/drivers/mtd目錄中。
MTD中間層細(xì)分為四層,按從上到下依次為:設(shè)備節(jié)點(diǎn)、MTD設(shè)備層、MTD原始設(shè)備層和硬件驅(qū)動(dòng)層。MTD中間層層次結(jié)構(gòu)圖如下:
從上圖可以看出,原始設(shè)備是MTD字符設(shè)備和MTD塊設(shè)備的抽象。
MTD設(shè)備層、MTD原始設(shè)備層和Flash硬件驅(qū)動(dòng)層之間的接口關(guān)系如下圖:
下面首先分析下MTD原始層設(shè)備
1、mtd_info數(shù)據(jù)結(jié)構(gòu)
- structmtd_info{
- u_chartype;//內(nèi)存技術(shù)類型,例如MTD_RAM,MTD_ROM,MTD_NORFLASH,MTD_NAND_FLASH,MTD_PEROM等
- uint32_tflags;//標(biāo)志位
- uint64_tsize;//TotalsizeoftheMTD//MTD設(shè)備的大小
- /*"Major"erasesizeforthedevice.Naïveusersmaytakethis
- *tobetheonlyerasesizeavailable,ormayusethemoredetailed
- *informationbelowiftheydesire
- */
- uint32_terasesize;//最小的擦除塊大小
- /*Minimalwritableflashunitsize.IncaseofNORflashitis1(even
- *thoughindividualbitscanbecleared),incaseofNANDflashitis
- *oneNANDpage(orhalf,orone-fourthsofit),incaseofECC-edNOR
- *itisofECCblocksize,etc.Itisillegaltohavewritesize=0.
- *Anydriverregisteringastructmtd_infomustensureawritesizeof
- *1orlarger.
- */
- uint32_twritesize;//編程塊大小
- uint32_toobsize;//AmountofOOBdataperblock(e.g.16)//oob(Outofband)塊大小
- uint32_toobavail;//AvailableOOBbytesperblock//每塊的可用的oob字節(jié)
- /*
- *Iferasesizeisapowerof2thentheshiftisstoredin
- *erasesize_shiftotherwiseerasesize_shiftiszero.Dittowritesize.
- */
- unsignedinterasesize_shift;
- unsignedintwritesize_shift;
- /*Masksbasedonerasesize_shiftandwritesize_shift*/
- unsignedinterasesize_mask;
- unsignedintwritesize_mask;
- //Kernel-onlystuffstartshere.
- constchar*name;
- intindex;
- /*ecclayoutstructurepointer-readonly!*/
- structnand_ecclayout*ecclayout;//eec布局結(jié)構(gòu)
- /*Dataforvariableeraseregions.Ifnumeraseregionsiszero,
- *itmeansthatthewholedevicehaserasesizeasgivenabove.
- */
- intnumeraseregions;//擦除區(qū)域個(gè)數(shù),通常為1
- structmtd_erase_region_info*eraseregions;//擦除區(qū)域的區(qū)域信息地址
- /*
- *Eraseisanasynchronousoperation.Devicedriversaresupposed
- *tocallinstr->callback()whenevertheoperationcompletes,even
- *ifitcompleteswithafailure.
- *Callersaresupposedtopassacallbackfunctionandwaitforit
- *tobecalledbeforewritingtotheblock.
- */
- int(*erase)(structmtd_info*mtd,structerase_info*instr);//函數(shù)指針,erase函數(shù)的功能是將一個(gè)erase_info加入擦除隊(duì)列
- /*ThisstuffforeXecute-In-Place*/
- /*physisoptionalandmaybesettoNULL*/
- int(*point)(structmtd_info*mtd,loff_tfrom,size_tlen,
- size_t*retlen,void**virt,resource_size_t*phys);//point函數(shù)功能是允許片內(nèi)執(zhí)行(XIP)
- /*WeprobablyshouldntallowXIPiftheunpointisntaNULL*/
- void(*unpoint)(structmtd_info*mtd,loff_tfrom,size_tlen);//unpoint函數(shù)與point函數(shù)相反,是禁止片內(nèi)執(zhí)行(XIP)
- /*AllowNOMMUmmap()todirectlymapthedevice(ifnotNULL)
- *-returntheaddresstowhichtheoffsetmaps
- *-return-ENOSYStoindicaterefusaltodothemapping
- */
- //如果不是NULL,則允許無(wú)MMU單元的地址映射,返回偏移地址
- unsignedlong(*get_unmapped_area)(structmtd_info*mtd,
- unsignedlonglen,
- unsignedlongoffset,
- unsignedlongflags);
- /*Backingdevicecapabilitiesforthisdevice
- *-providesmmapcapabilities
- */
- structbacking_dev_info*backing_dev_info;
- //MTD設(shè)備的讀寫函數(shù)
- int(*read)(structmtd_info*mtd,loff_tfrom,size_tlen,size_t*retlen,u_char*buf);
- int(*write)(structmtd_info*mtd,loff_tto,size_tlen,size_t*retlen,constu_char*buf);
- /*Inblackboxflightrecorderlikescenarioswewanttomakesuccessful
- writesininterruptcontext.panic_write()isonlyintendedtobe
- calledwhenitsknownthekernelisabouttopanicandweneedthe
- writetosucceed.Sincethekernelisnotgoingtoberunningformuch
- longer,thisfunctioncanbreaklocksanddelaytoensurethewrite
- succeeds(butnotsleep).*/
- int(*panic_write)(structmtd_info*mtd,loff_tto,size_tlen,size_t*retlen,constu_char*buf);
- //用于MTD設(shè)備的OBB數(shù)據(jù)讀寫
- int(*read_oob)(structmtd_info*mtd,loff_tfrom,
- structmtd_oob_ops*ops);
- int(*write_oob)(structmtd_info*mtd,loff_tto,
- structmtd_oob_ops*ops);
- /*
- *Methodstoaccesstheprotectionregisterarea,presentinsome
- *flashdevices.Theuserdataisonetimeprogrammablebutthe
- *factorydataisreadonly.
- */
- int(*get_fact_prot_info)(structmtd_info*mtd,structotp_info*buf,size_tlen);
- int(*read_fact_prot_reg)(structmtd_info*mtd,loff_tfrom,size_tlen,size_t*retlen,u_char*buf);
- int(*get_user_prot_info)(structmtd_info*mtd,structotp_info*buf,size_tlen);
- int(*read_user_prot_reg)(structmtd_info*mtd,loff_tfrom,size_tlen,size_t*retlen,u_char*buf);
- int(*write_user_prot_reg)(structmtd_info*mtd,loff_tfrom,size_tlen,size_t*retlen,u_char*buf);
- int(*lock_user_prot_reg)(structmtd_info*mtd,loff_tfrom,size_tlen);
- /*kvec-basedread/writemethods.
- NB:Thecountparameteristhenumberof_vectors_,eachof
- whichcontainsan(ofs,len)tuple.
- */
- int(*writev)(structmtd_info*mtd,conststructkvec*vecs,unsignedlongcount,loff_tto,size_t*retlen);
- /*Sync*/
- //MTD設(shè)備的同步函數(shù)
- void(*sync)(structmtd_info*mtd);
- /*Chip-supporteddevicelocking*/
- //芯片的加鎖和解鎖
- int(*lock)(structmtd_info*mtd,loff_tofs,uint64_tlen);
- int(*unlock)(structmtd_info*mtd,loff_tofs,uint64_tlen);
- /*PowerManagementfunctions*/
- //支持電源管理函數(shù)
- int(*suspend)(structmtd_info*mtd);
- void(*resume)(structmtd_info*mtd);
- /*Badblockmanagementfunctions*/
- //壞塊管理函數(shù)
- int(*block_isbad)(structmtd_info*mtd,loff_tofs);
- int(*block_markbad)(structmtd_info*mtd,loff_tofs);
- structnotifier_blockreboot_notifier;/*defaultmodebeforereboot*/
- /*ECCstatusinformation*/
- structmtd_ecc_statsecc_stats;//ECC狀態(tài)信息
- /*Subpageshift(NAND)*/
- intsubpage_sft;
- void*priv;//私有數(shù)據(jù)指針
- structmodule*owner;
- structdevicedev;
- intusecount;//記錄用戶的個(gè)數(shù)
- /*Ifthedriverissomethingsmart,likeUBI,itmayneedtomaintain
- *itsownreferencecounting.Thebelowfunctionsareonlyfordriver.
- *Thedrivermayregisteritscallbacks.Thesecallbacksarenot
- *supposedtobecalledbyMTDusers*/
- //驅(qū)動(dòng)回調(diào)函數(shù)
- int(*get_device)(structmtd_info*mtd);
- void(*put_device)(structmtd_info*mtd);
- };
2、mtd_part結(jié)構(gòu)體信息
- /*Ourpartitionlinkedlist*/
- staticLIST_HEAD(mtd_partitions);//分區(qū)鏈表
- /*Ourpartitionnodestructure*/
- //分區(qū)結(jié)構(gòu)信息
- structmtd_part{
- structmtd_infomtd;//mtd_info數(shù)據(jù)結(jié)構(gòu),會(huì)被加入mtd_table中
- structmtd_info*master;//該分區(qū)的主分區(qū)
- uint64_toffset;//該分區(qū)的偏移地址
- structlist_headlist;//分區(qū)鏈表
- };
3、mtd_partition描述mtd具體分區(qū)結(jié)構(gòu)
- /*
- *Partitiondefinitionstructure:
- *
- *AnarrayofstructpartitionispassedalongwithaMTDobjectto
- *add_mtd_partitions()tocreatethem.
- *
- *Foreachpartition,thesefieldsareavailable:
- *name:stringthatwillbeusedtolabelthepartitionsMTDdevice.
- *size:thepartitionsize;ifdefinedasMTDPART_SIZ_FULL,thepartition
- *willextendtotheendofthemasterMTDdevice.
- *offset:absolutestartingpositionwithinthemasterMTDdevice;if
- *definedasMTDPART_OFS_APPEND,thepartitionwillstartwherethe
- *previousoneended;ifMTDPART_OFS_NXTBLK,atthenexteraseblock.
- *mask_flags:containsflagsthathavetobemasked(removed)fromthe
- *masterMTDflagsetforthecorrespondingMTDpartition.
- *Forexample,toforcearead-onlypartition,simplyadding
- *MTD_WRITEABLEtothemask_flagswilldothetrick.
- *
- *Note:writeablepartitionsrequiretheirsizeandoffsetbe
- *erasesizealigned(e.g.useMTDPART_OFS_NEXTBLK).
- */
- structmtd_partition{
- char*name;/*identifierstring分區(qū)名*/
- uint64_tsize;/*partitionsize分區(qū)大小*/
- uint64_toffset;/*offsetwithinthemasterMTDspace偏移地址*/
- uint32_tmask_flags;/*masterMTDflagstomaskoutforthispartition*/
- structnand_ecclayout*ecclayout;/*outofbandlayoutforthispartition(NANDonly)*/
- };
評(píng)論