123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974 |
- /*++
- Copyright (c) 2015 Minoca Corp. All rights reserved.
- Module Name:
- sdrk32.c
- Abstract:
- This module implements the SD/MMC driver for Rk32xx SoCs. The Rockchip SD
- controller is based on the Synopsis DesignWare controller.
- Author:
- Chris Stevens 29-Jul-2015
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include <minoca/kernel/acpi.h>
- #include "sdrk32.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // These macros read and write SD controller registers.
- //
- #define SD_DWC_READ_REGISTER(_Device, _Register) \
- HlReadRegister32((_Device)->ControllerBase + (_Register))
- #define SD_DWC_WRITE_REGISTER(_Device, _Register, _Value) \
- HlWriteRegister32((_Device)->ControllerBase + (_Register), (_Value))
- #define SD_RK32_READ_CRU(_Device, _Register) \
- HlReadRegister32((_Device)->Cru + (_Register))
- #define SD_RK32_WRITE_CRU(_Device, _Register, _Value) \
- HlWriteRegister32((_Device)->Cru + (_Register), (_Value))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- KSTATUS
- SdRk32AddDevice (
- PVOID Driver,
- PSTR DeviceId,
- PSTR ClassId,
- PSTR CompatibleIds,
- PVOID DeviceToken
- );
- VOID
- SdRk32DispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdRk32DispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdRk32DispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdRk32DispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdRk32DispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdRk32ParentDispatchStateChange (
- PIRP Irp,
- PSD_RK32_CONTEXT Context,
- PVOID IrpContext
- );
- VOID
- SdRk32ChildDispatchStateChange (
- PIRP Irp,
- PSD_RK32_CHILD Child,
- PVOID IrpContext
- );
- KSTATUS
- SdRk32ParentProcessResourceRequirements (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- );
- KSTATUS
- SdRk32ParentStartDevice (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- );
- KSTATUS
- SdRk32ParentQueryChildren (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- );
- KSTATUS
- SdRk32HardResetController (
- PSD_RK32_CONTEXT Device
- );
- KSTATUS
- SdRk32InitializeVendorResource (
- PSD_RK32_CONTEXT Device,
- PRESOURCE_ALLOCATION Resource
- );
- INTERRUPT_STATUS
- SdRk32InterruptService (
- PVOID Context
- );
- INTERRUPT_STATUS
- SdRk32InterruptServiceDispatch (
- PVOID Context
- );
- INTERRUPT_STATUS
- SdRk32CardInterruptWorker (
- PVOID Context
- );
- VOID
- SdRk32DmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- );
- PSD_RK32_CHILD
- SdRk32pCreateChild (
- PSD_RK32_CONTEXT Device
- );
- VOID
- SdRk32pDestroyChild (
- PSD_RK32_CHILD Child
- );
- VOID
- SdRk32pChildAddReference (
- PSD_RK32_CHILD Child
- );
- VOID
- SdRk32pChildReleaseReference (
- PSD_RK32_CHILD Child
- );
- KSTATUS
- SdRk32ChildBlockIoReset (
- PVOID DiskToken
- );
- KSTATUS
- SdRk32ChildBlockIoRead (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- );
- KSTATUS
- SdRk32ChildBlockIoWrite (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- );
- KSTATUS
- SdRk32PerformIoPolled (
- PIRP_READ_WRITE IrpReadWrite,
- PSD_RK32_CHILD Child,
- BOOL Write,
- BOOL LockRequired
- );
- KSTATUS
- SdRk32InitializeDma (
- PSD_RK32_CONTEXT Device
- );
- VOID
- SdRk32BlockIoDma (
- PSD_RK32_CONTEXT Device,
- ULONGLONG BlockOffset,
- UINTN BlockCount,
- PIO_BUFFER IoBuffer,
- UINTN IoBufferOffset,
- BOOL Write,
- PSD_IO_COMPLETION_ROUTINE CompletionRoutine,
- PVOID CompletionContext
- );
- KSTATUS
- SdRk32InitializeController (
- PSD_CONTROLLER Controller,
- PVOID Context,
- ULONG Phase
- );
- KSTATUS
- SdRk32ResetController (
- PSD_CONTROLLER Controller,
- PVOID Context,
- ULONG Flags
- );
- KSTATUS
- SdRk32SendCommand (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PSD_COMMAND Command
- );
- KSTATUS
- SdRk32GetSetBusWidth (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- );
- KSTATUS
- SdRk32GetSetClockSpeed (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- );
- KSTATUS
- SdRk32GetSetVoltage (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- );
- KSTATUS
- SdRk32ReadData (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PVOID Data,
- ULONG Size
- );
- KSTATUS
- SdRk32WriteData (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PVOID Data,
- ULONG Size
- );
- KSTATUS
- SdRk32SetClockSpeed (
- PSD_RK32_CONTEXT Device,
- SD_CLOCK_SPEED ClockSpeed
- );
- VOID
- SdRk32SetDmaInterrupts (
- PSD_CONTROLLER Controller,
- PSD_RK32_CONTEXT Device,
- BOOL Enable,
- ULONG BufferSize
- );
- KSTATUS
- SdRk32UpdateClock (
- PSD_RK32_CONTEXT Device
- );
- VOID
- SdRk32Rk808InterfaceNotificationCallback (
- PVOID Context,
- PDEVICE Device,
- PVOID InterfaceBuffer,
- ULONG InterfaceBufferSize,
- BOOL Arrival
- );
- KSTATUS
- SdRk32SetRegulatorVoltage (
- PSD_RK32_CONTEXT Device,
- BOOL LowVoltage
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- PDRIVER SdRk32Driver = NULL;
- UUID SdRk32DiskInterfaceUuid = UUID_DISK_INTERFACE;
- UUID SdRk32VendorResourceUuid = SD_RK32_VENDOR_RESOURCE_UUID;
- UUID SdRk32Rk808InterfaceUuid = UUID_RK808_INTERFACE;
- DISK_INTERFACE SdRk32DiskInterfaceTemplate = {
- DISK_INTERFACE_VERSION,
- NULL,
- 0,
- 0,
- NULL,
- SdRk32ChildBlockIoReset,
- SdRk32ChildBlockIoRead,
- SdRk32ChildBlockIoWrite
- };
- SD_FUNCTION_TABLE SdRk32FunctionTable = {
- SdRk32InitializeController,
- SdRk32ResetController,
- SdRk32SendCommand,
- SdRk32GetSetBusWidth,
- SdRk32GetSetClockSpeed,
- SdRk32GetSetVoltage,
- NULL,
- NULL,
- NULL,
- NULL
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- DriverEntry (
- PDRIVER Driver
- )
- /*++
- Routine Description:
- This routine is the entry point for the SD/MMC driver. It registers its
- other dispatch functions, and performs driver-wide initialization.
- Arguments:
- Driver - Supplies a pointer to the driver object.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code on error.
- --*/
- {
- DRIVER_FUNCTION_TABLE FunctionTable;
- KSTATUS Status;
- SdRk32Driver = Driver;
- RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
- FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
- FunctionTable.AddDevice = SdRk32AddDevice;
- FunctionTable.DispatchStateChange = SdRk32DispatchStateChange;
- FunctionTable.DispatchOpen = SdRk32DispatchOpen;
- FunctionTable.DispatchClose = SdRk32DispatchClose;
- FunctionTable.DispatchIo = SdRk32DispatchIo;
- FunctionTable.DispatchSystemControl = SdRk32DispatchSystemControl;
- Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
- return Status;
- }
- KSTATUS
- SdRk32AddDevice (
- PVOID Driver,
- PSTR DeviceId,
- PSTR ClassId,
- PSTR CompatibleIds,
- PVOID DeviceToken
- )
- /*++
- Routine Description:
- This routine is called when a device is detected for which the SD/MMC driver
- acts as the function driver. The driver will attach itself to the stack.
- Arguments:
- Driver - Supplies a pointer to the driver being called.
- DeviceId - Supplies a pointer to a string with the device ID.
- ClassId - Supplies a pointer to a string containing the device's class ID.
- CompatibleIds - Supplies a pointer to a string containing device IDs
- that would be compatible with this device.
- DeviceToken - Supplies an opaque token that the driver can use to identify
- the device in the system. This token should be used when attaching to
- the stack.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code if the driver was unsuccessful in attaching itself.
- --*/
- {
- PSD_RK32_CONTEXT Context;
- KSTATUS Status;
- //
- // Allocate non-paged pool because this device could be the paging device.
- //
- Context = MmAllocateNonPagedPool(sizeof(SD_RK32_CONTEXT),
- SD_ALLOCATION_TAG);
- if (Context == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto AddDeviceEnd;
- }
- RtlZeroMemory(Context, sizeof(SD_RK32_CONTEXT));
- Context->Type = SdRk32Parent;
- Context->InterruptVector = -1ULL;
- Context->CardInterruptVector = -1ULL;
- Context->InterruptHandle = INVALID_HANDLE;
- Context->CardInterruptHandle = INVALID_HANDLE;
- Context->OsDevice = DeviceToken;
- KeInitializeSpinLock(&(Context->DpcLock));
- Context->Lock = KeCreateQueuedLock();
- if (Context->Lock == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto AddDeviceEnd;
- }
- Status = IoAttachDriverToDevice(Driver, DeviceToken, Context);
- if (!KSUCCESS(Status)) {
- goto AddDeviceEnd;
- }
- AddDeviceEnd:
- if (!KSUCCESS(Status)) {
- if (Context != NULL) {
- MmFreeNonPagedPool(Context);
- }
- }
- return Status;
- }
- VOID
- SdRk32DispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_RK32_CONTEXT Context;
- ASSERT(Irp->MajorCode == IrpMajorStateChange);
- Context = DeviceContext;
- switch (Context->Type) {
- case SdRk32Parent:
- SdRk32ParentDispatchStateChange(Irp, Context, IrpContext);
- break;
- case SdRk32Child:
- SdRk32ChildDispatchStateChange(Irp,
- (PSD_RK32_CHILD)Context,
- IrpContext);
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- SdRk32DispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Open IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_RK32_CHILD Child;
- Child = DeviceContext;
- //
- // Only the child can be opened or closed.
- //
- if (Child->Type != SdRk32Child) {
- return;
- }
- SdRk32pChildAddReference(Child);
- IoCompleteIrp(SdRk32Driver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- SdRk32DispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Close IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_RK32_CHILD Child;
- Child = DeviceContext;
- if (Child->Type != SdRk32Child) {
- return;
- }
- SdRk32pChildReleaseReference(Child);
- IoCompleteIrp(SdRk32Driver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- SdRk32DispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles I/O IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- UINTN BlockCount;
- ULONGLONG BlockOffset;
- UINTN BytesToComplete;
- PSD_RK32_CHILD Child;
- BOOL CompleteIrp;
- PSD_CONTROLLER Controller;
- IO_OFFSET IoOffset;
- ULONG IrpReadWriteFlags;
- KSTATUS IrpStatus;
- KSTATUS Status;
- ULONG Value;
- BOOL Write;
- ASSERT(KeGetRunLevel() == RunLevelLow);
- Child = DeviceContext;
- Controller = Child->Controller;
- if (Child->Type != SdRk32Child) {
- ASSERT(FALSE);
- return;
- }
- CompleteIrp = TRUE;
- Write = FALSE;
- if (Irp->MinorCode == IrpMinorIoWrite) {
- Write = TRUE;
- }
- //
- // Polled I/O is shared by a few code paths and prepares the IRP for I/O
- // further down the stack. It should also only be hit in the down direction
- // path as it always completes the IRP.
- //
- if ((Child->Flags & SD_RK32_CHILD_FLAG_DMA_SUPPORTED) == 0) {
- ASSERT(Irp->Direction == IrpDown);
- CompleteIrp = TRUE;
- Status = SdRk32PerformIoPolled(&(Irp->U.ReadWrite), Child, Write, TRUE);
- goto DispatchIoEnd;
- }
- //
- // Set the IRP read/write flags for the preparation and completion steps.
- //
- IrpReadWriteFlags = IRP_READ_WRITE_FLAG_DMA;
- if (Write != FALSE) {
- IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
- }
- if (Irp->Direction == IrpDown) {
- Controller->Try = 0;
- }
- //
- // If the IRP is on the way up, then clean up after the DMA as this IRP is
- // still sitting in the channel. An IRP going up is already complete.
- //
- if (Irp->Direction == IrpUp) {
- ASSERT(Irp == Child->Irp);
- //
- // Disable DMA mode.
- //
- Value = SD_DWC_READ_REGISTER(Child->Parent, SdDwcControl);
- Value &= ~SD_DWC_CONTROL_USE_INTERNAL_DMAC;
- SD_DWC_WRITE_REGISTER(Child->Parent, SdDwcControl, Value);
- //
- // If the IO went badly, try to recover and make another attempt.
- //
- IrpStatus = IoGetIrpStatus(Irp);
- if (!KSUCCESS(IrpStatus)) {
- Status = SdErrorRecovery(Controller);
- if (!KSUCCESS(Status)) {
- IrpStatus = Status;
- IoUpdateIrpStatus(Irp, IrpStatus);
- }
- //
- // Do not make further attempts if the media is gone or enough
- // attempts have been made.
- //
- if (((Controller->Flags &
- SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) ||
- ((Controller->Flags &
- SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
- (Controller->Try >= SD_MAX_IO_RETRIES)) {
- IrpStatus = STATUS_SUCCESS;
- } else {
- Controller->Try += 1;
- }
- }
- //
- // Release the hold on the controller and complete any buffer
- // operations related to the completed transfer.
- //
- Child->Irp = NULL;
- KeReleaseQueuedLock(Child->ControllerLock);
- Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite),
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- IoUpdateIrpStatus(Irp, Status);
- }
- //
- // Potentially return the completed IRP.
- //
- if (KSUCCESS(IrpStatus)) {
- CompleteIrp = FALSE;
- goto DispatchIoEnd;
- }
- }
- //
- // Start the DMA on the way down.
- //
- BytesToComplete = Irp->U.ReadWrite.IoSizeInBytes;
- IoOffset = Irp->U.ReadWrite.IoOffset;
- Irp->U.ReadWrite.IoBytesCompleted = 0;
- ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
- ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
- ASSERT(IS_ALIGNED(IoOffset, 1 << Child->BlockShift) != FALSE);
- ASSERT(IS_ALIGNED(BytesToComplete, 1 << Child->BlockShift) != FALSE);
- //
- // Before acquiring the controller's lock and starting the DMA, prepare
- // the I/O context for SD (i.e. it must use physical addresses that
- // are less than 4GB and be sector size aligned).
- //
- Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
- 1 << Child->BlockShift,
- 0,
- MAX_ULONG,
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- goto DispatchIoEnd;
- }
- //
- // Lock the controller to serialize access to the hardware.
- //
- KeAcquireQueuedLock(Child->ControllerLock);
- if (((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
- ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0)) {
- Status = STATUS_NO_MEDIA;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Status = STATUS_MEDIA_CHANGED;
- }
- KeReleaseQueuedLock(Child->ControllerLock);
- IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
- goto DispatchIoEnd;
- }
- //
- // If it's DMA, just send it on through.
- //
- Irp->U.ReadWrite.NewIoOffset = IoOffset;
- Child->Irp = Irp;
- BlockOffset = IoOffset >> Child->BlockShift;
- BlockCount = BytesToComplete >> Child->BlockShift;
- CompleteIrp = FALSE;
- IoPendIrp(SdRk32Driver, Irp);
- //
- // Set the controller into DMA mode.
- //
- Value = SD_DWC_READ_REGISTER(Child->Parent, SdDwcControl);
- if ((Value & SD_DWC_CONTROL_USE_INTERNAL_DMAC) == 0) {
- Value |= SD_DWC_CONTROL_USE_INTERNAL_DMAC;
- SD_DWC_WRITE_REGISTER(Child->Parent, SdDwcControl, Value);
- }
- //
- // Make sure the system isn't trying to do I/O off the end of the
- // disk.
- //
- ASSERT(BlockOffset < Child->BlockCount);
- ASSERT(BlockCount >= 1);
- //
- // If it's a multiblock command, send CMD23 first if possible.
- //
- ASSERT((Controller->IoCompletionRoutine == NULL) &&
- (Controller->IoCompletionContext == NULL) &&
- (Controller->IoRequestSize == 0));
- Controller->SendStop = FALSE;
- if (BlockCount > 1) {
- Controller->IoCompletionRoutine = SdRk32DmaCompletion;
- Controller->IoCompletionContext = Child;
- Status = SdSendBlockCount(Controller, BlockCount, Write, TRUE);
- if (KSUCCESS(Status)) {
- goto DispatchIoEnd;
- } else {
- Controller->SendStop = TRUE;
- Controller->IoCompletionRoutine = NULL;
- Controller->IoCompletionContext = NULL;
- if (Status == STATUS_NOT_SUPPORTED) {
- Status = STATUS_SUCCESS;
- } else {
- CompleteIrp = TRUE;
- KeReleaseQueuedLock(Child->ControllerLock);
- goto DispatchIoEnd;
- }
- }
- }
- SdRk32BlockIoDma(Child->Parent,
- BlockOffset,
- BlockCount,
- Irp->U.ReadWrite.IoBuffer,
- 0,
- Write,
- SdRk32DmaCompletion,
- Child);
- //
- // DMA transfers are self perpetuating, so after kicking off this
- // first transfer, return. This returns with the lock held because
- // I/O is still in progress.
- //
- ASSERT(KeIsQueuedLockHeld(Child->ControllerLock) != FALSE);
- ASSERT(CompleteIrp == FALSE);
- DispatchIoEnd:
- if (CompleteIrp != FALSE) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- return;
- }
- VOID
- SdRk32DispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles System Control IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_RK32_CHILD Child;
- PVOID Context;
- PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
- PSYSTEM_CONTROL_LOOKUP Lookup;
- PFILE_PROPERTIES Properties;
- ULONGLONG PropertiesFileSize;
- KSTATUS Status;
- Context = Irp->U.SystemControl.SystemContext;
- Child = DeviceContext;
- //
- // Only child devices are supported.
- //
- if (Child->Type != SdRk32Child) {
- ASSERT(Child->Type == SdRk32Parent);
- return;
- }
- switch (Irp->MinorCode) {
- case IrpMinorSystemControlLookup:
- Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
- Status = STATUS_PATH_NOT_FOUND;
- if (Lookup->Root != FALSE) {
- //
- // Enable opening of the root as a single file.
- //
- Properties = &(Lookup->Properties);
- Properties->FileId = 0;
- Properties->Type = IoObjectBlockDevice;
- Properties->HardLinkCount = 1;
- Properties->BlockCount = Child->BlockCount;
- Properties->BlockSize = 1 << Child->BlockShift;
- WRITE_INT64_SYNC(&(Properties->FileSize),
- Child->BlockCount << Child->BlockShift);
- Status = STATUS_SUCCESS;
- }
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- break;
- //
- // Writes to the disk's properties are not allowed. Fail if the data
- // has changed.
- //
- case IrpMinorSystemControlWriteFileProperties:
- FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
- Properties = FileOperation->FileProperties;
- READ_INT64_SYNC(&(Properties->FileSize), &PropertiesFileSize);
- if ((Properties->FileId != 0) ||
- (Properties->Type != IoObjectBlockDevice) ||
- (Properties->HardLinkCount != 1) ||
- (Properties->BlockSize != (1 << Child->BlockShift)) ||
- (Properties->BlockCount != Child->BlockCount) ||
- (PropertiesFileSize != (Child->BlockCount << Child->BlockShift))) {
- Status = STATUS_NOT_SUPPORTED;
- } else {
- Status = STATUS_SUCCESS;
- }
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- break;
- //
- // Do not support hard disk device truncation.
- //
- case IrpMinorSystemControlTruncate:
- IoCompleteIrp(SdRk32Driver, Irp, STATUS_NOT_SUPPORTED);
- break;
- //
- // Gather and return device information.
- //
- case IrpMinorSystemControlDeviceInformation:
- break;
- case IrpMinorSystemControlSynchronize:
- IoCompleteIrp(SdRk32Driver, Irp, STATUS_SUCCESS);
- break;
- //
- // Ignore everything unrecognized.
- //
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- SdRk32ParentDispatchStateChange (
- PIRP Irp,
- PSD_RK32_CONTEXT Context,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs for a parent device.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Context - Supplies a pointer to the controller information.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- KSTATUS Status;
- if (Irp->Direction == IrpUp) {
- if (!KSUCCESS(IoGetIrpStatus(Irp))) {
- return;
- }
- switch (Irp->MinorCode) {
- case IrpMinorQueryResources:
- Status = SdRk32ParentProcessResourceRequirements(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- break;
- case IrpMinorStartDevice:
- Status = SdRk32ParentStartDevice(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- break;
- case IrpMinorQueryChildren:
- Status = SdRk32ParentQueryChildren(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- break;
- default:
- break;
- }
- }
- return;
- }
- VOID
- SdRk32ChildDispatchStateChange (
- PIRP Irp,
- PSD_RK32_CHILD Child,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs for a parent device.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Child - Supplies a pointer to the child device information.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- BOOL CompleteIrp;
- KSTATUS Status;
- ASSERT(Irp->MajorCode == IrpMajorStateChange);
- //
- // The IRP is on its way down the stack. Do most processing here.
- //
- if (Irp->Direction == IrpDown) {
- Status = STATUS_NOT_SUPPORTED;
- CompleteIrp = TRUE;
- switch (Irp->MinorCode) {
- case IrpMinorQueryResources:
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorStartDevice:
- Status = STATUS_SUCCESS;
- if (Child->DiskInterface.DiskToken == NULL) {
- RtlCopyMemory(&(Child->DiskInterface),
- &SdRk32DiskInterfaceTemplate,
- sizeof(DISK_INTERFACE));
- Child->DiskInterface.BlockSize = 1 << Child->BlockShift;
- Child->DiskInterface.BlockCount = Child->BlockCount;
- Child->DiskInterface.DiskToken = Child;
- Status = IoCreateInterface(&SdRk32DiskInterfaceUuid,
- Child->Device,
- &(Child->DiskInterface),
- sizeof(DISK_INTERFACE));
- if (!KSUCCESS(Status)) {
- Child->DiskInterface.DiskToken = NULL;
- }
- }
- break;
- case IrpMinorQueryChildren:
- Irp->U.QueryChildren.Children = NULL;
- Irp->U.QueryChildren.ChildCount = 0;
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorQueryInterface:
- break;
- case IrpMinorRemoveDevice:
- if (Child->DiskInterface.DiskToken != NULL) {
- Status = IoDestroyInterface(&SdRk32DiskInterfaceUuid,
- Child->Device,
- &(Child->DiskInterface));
- ASSERT(KSUCCESS(Status));
- Child->DiskInterface.DiskToken = NULL;
- }
- SdRk32pChildReleaseReference(Child);
- Status = STATUS_SUCCESS;
- break;
- //
- // Pass all other IRPs down.
- //
- default:
- CompleteIrp = FALSE;
- break;
- }
- //
- // Complete the IRP unless there's a reason not to.
- //
- if (CompleteIrp != FALSE) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- //
- // The IRP is completed and is on its way back up.
- //
- } else {
- ASSERT(Irp->Direction == IrpUp);
- }
- return;
- }
- KSTATUS
- SdRk32ParentProcessResourceRequirements (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine filters through the resource requirements presented by the
- bus for a SD RK32xx Host controller. It adds an interrupt vector
- requirement for any interrupt line requested.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this device.
- Return Value:
- Status code.
- --*/
- {
- PRESOURCE_CONFIGURATION_LIST Requirements;
- KSTATUS Status;
- RESOURCE_REQUIREMENT VectorRequirement;
- ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
- (Irp->MinorCode == IrpMinorQueryResources));
- //
- // Initialize a nice interrupt vector requirement in preparation.
- //
- RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
- VectorRequirement.Type = ResourceTypeInterruptVector;
- VectorRequirement.Minimum = 0;
- VectorRequirement.Maximum = -1;
- VectorRequirement.Length = 1;
- //
- // Loop through all configuration lists, creating a vector for each line.
- //
- Requirements = Irp->U.QueryResources.ResourceRequirements;
- Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
- &VectorRequirement);
- if (!KSUCCESS(Status)) {
- goto ProcessResourceRequirementsEnd;
- }
- ProcessResourceRequirementsEnd:
- return Status;
- }
- KSTATUS
- SdRk32ParentStartDevice (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine starts up the RK32xx SD controller.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this SD RK32xx device.
- Return Value:
- Status code.
- --*/
- {
- PRESOURCE_ALLOCATION Allocation;
- PRESOURCE_ALLOCATION_LIST AllocationList;
- IO_CONNECT_INTERRUPT_PARAMETERS Connect;
- PRESOURCE_ALLOCATION ControllerBase;
- PRESOURCE_ALLOCATION LineAllocation;
- SD_INITIALIZATION_BLOCK Parameters;
- KSTATUS Status;
- PRESOURCE_ALLOCATION VendorResource;
- ControllerBase = NULL;
- VendorResource = NULL;
- //
- // Loop through the allocated resources to get the controller base and the
- // interrupt.
- //
- AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
- Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
- while (Allocation != NULL) {
- //
- // If the resource is an interrupt vector, then it should have an
- // owning interrupt line allocation.
- //
- if (Allocation->Type == ResourceTypeInterruptVector) {
- ASSERT(Allocation->OwningAllocation != NULL);
- //
- // Save the line and vector number. The first one is the main
- // interrupt, the second one is the card detect interrupt.
- //
- LineAllocation = Allocation->OwningAllocation;
- if (Device->InterruptVector == -1ULL) {
- Device->InterruptLine = LineAllocation->Allocation;
- Device->InterruptVector = Allocation->Allocation;
- } else {
- ASSERT(Device->CardInterruptVector == -1ULL);
- Device->CardInterruptLine = LineAllocation->Allocation;
- Device->CardInterruptVector = Allocation->Allocation;
- }
- } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
- ASSERT(ControllerBase == NULL);
- ControllerBase = Allocation;
- } else if (Allocation->Type == ResourceTypeVendorSpecific) {
- ASSERT(VendorResource == NULL);
- VendorResource = Allocation;
- }
- //
- // Get the next allocation in the list.
- //
- Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
- }
- //
- // Fail to start if the controller base was not found.
- //
- if ((ControllerBase == NULL) ||
- (ControllerBase->Length < SD_RK32_CONTROLLER_LENGTH) ||
- (VendorResource == NULL)) {
- Status = STATUS_INVALID_CONFIGURATION;
- goto StartDeviceEnd;
- }
- //
- // Initialize RK32xx specific stuff.
- //
- if (Device->ControllerBase == NULL) {
- Device->PhysicalAddress = ControllerBase->Allocation;
- Device->ControllerBase = MmMapPhysicalAddress(
- ControllerBase->Allocation,
- ControllerBase->Length,
- TRUE,
- FALSE,
- TRUE);
- if (Device->ControllerBase == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto StartDeviceEnd;
- }
- }
- Status = SdRk32InitializeVendorResource(Device, VendorResource);
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("SdRk32InitializeVendorResource Failed: %x\n", Status);
- goto StartDeviceEnd;
- }
- Status = SdRk32HardResetController(Device);
- if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- goto StartDeviceEnd;
- } else if (!KSUCCESS(Status)) {
- RtlDebugPrint("SdRk32ResetController Failed: %x\n", Status);
- goto StartDeviceEnd;
- }
- //
- // Initialize the standard SD controller.
- //
- if (Device->Controller == NULL) {
- RtlZeroMemory(&Parameters, sizeof(SD_INITIALIZATION_BLOCK));
- Parameters.Voltages = SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34;
- Parameters.HostCapabilities = SD_MODE_4BIT |
- SD_MODE_HIGH_SPEED |
- SD_MODE_AUTO_CMD12 |
- SD_MODE_CMD23;
- Parameters.FundamentalClock = Device->FundamentalClock;
- Parameters.ConsumerContext = Device;
- Parameters.OsDevice = Device->OsDevice;
- RtlCopyMemory(&(Parameters.FunctionTable),
- &SdRk32FunctionTable,
- sizeof(SD_FUNCTION_TABLE));
- Device->Controller = SdCreateController(&Parameters);
- if (Device->Controller == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto StartDeviceEnd;
- }
- }
- //
- // Attempt to connect the interrupt before initializing the controller. The
- // initialization process may trigger some interrupts.
- //
- if (Device->InterruptHandle == INVALID_HANDLE) {
- RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
- Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
- Connect.Device = Irp->Device;
- Connect.LineNumber = Device->InterruptLine;
- Connect.Vector = Device->InterruptVector;
- Connect.InterruptServiceRoutine = SdRk32InterruptService;
- Connect.DispatchServiceRoutine = SdRk32InterruptServiceDispatch;
- Connect.Context = Device;
- Connect.Interrupt = &(Device->InterruptHandle);
- Status = IoConnectInterrupt(&Connect);
- if (!KSUCCESS(Status)) {
- goto StartDeviceEnd;
- }
- Device->Controller->InterruptHandle = Device->InterruptHandle;
- }
- //
- // Also wire up the card detect interrupt if it's present.
- //
- if ((Device->CardInterruptHandle == INVALID_HANDLE) &&
- (Device->CardInterruptVector != -1ULL)) {
- RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
- Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
- Connect.Device = Irp->Device;
- Connect.LineNumber = Device->CardInterruptLine;
- Connect.Vector = Device->CardInterruptVector;
- Connect.LowLevelServiceRoutine = SdRk32CardInterruptWorker;
- Connect.Context = Device;
- Connect.Interrupt = &(Device->InterruptHandle);
- Status = IoConnectInterrupt(&Connect);
- if (!KSUCCESS(Status)) {
- goto StartDeviceEnd;
- }
- }
- Status = STATUS_SUCCESS;
- StartDeviceEnd:
- if (!KSUCCESS(Status)) {
- if (Device->InterruptHandle != INVALID_HANDLE) {
- IoDisconnectInterrupt(Device->InterruptHandle);
- Device->InterruptHandle = INVALID_HANDLE;
- Device->Controller->InterruptHandle = INVALID_HANDLE;
- }
- if (Device->CardInterruptHandle != INVALID_HANDLE) {
- IoDisconnectInterrupt(Device->CardInterruptHandle);
- }
- if (Device->Controller != NULL) {
- SdDestroyController(Device->Controller);
- Device->Controller = NULL;
- }
- }
- return Status;
- }
- KSTATUS
- SdRk32ParentQueryChildren (
- PIRP Irp,
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine potentially enumerates the disk device for the SD RK32xx
- controller.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this device.
- Return Value:
- Status code.
- --*/
- {
- ULONG BlockSize;
- PSTR DeviceId;
- ULONG FlagsMask;
- PSD_RK32_CHILD NewChild;
- ULONG OldFlags;
- KSTATUS Status;
- NewChild = NULL;
- //
- // Check to see if any changes to the children are pending.
- //
- FlagsMask = SD_CONTROLLER_FLAG_INSERTION_PENDING |
- SD_CONTROLLER_FLAG_REMOVAL_PENDING;
- OldFlags = RtlAtomicAnd32(&(Device->Controller->Flags), ~FlagsMask);
- //
- // If either a removal or insertion is pending, clean out the old child.
- // In practice, not all removals interrupt, meaning that two insertions can
- // arrive in a row.
- //
- if ((OldFlags & FlagsMask) != 0) {
- if (Device->Child != NULL) {
- KeAcquireQueuedLock(Device->Lock);
- RtlAtomicAnd32(&(Device->Child->Controller->Flags),
- ~SD_CONTROLLER_FLAG_MEDIA_PRESENT);
- KeReleaseQueuedLock(Device->Lock);
- Device->Child = NULL;
- }
- }
- //
- // If an insertion is pending, try to enumerate the child.
- //
- if ((OldFlags & SD_CONTROLLER_FLAG_INSERTION_PENDING) != 0) {
- ASSERT(Device->Child == NULL);
- RtlAtomicAnd32(&(Device->Controller->Flags),
- ~SD_CONTROLLER_FLAG_MEDIA_CHANGED);
- Status = SdInitializeController(Device->Controller, FALSE);
- if (!KSUCCESS(Status)) {
- if (Status == STATUS_TIMEOUT) {
- Status = STATUS_SUCCESS;
- } else {
- RtlDebugPrint("SdInitializeController failed: %x\n", Status);
- }
- goto ParentQueryChildrenEnd;
- }
- NewChild = SdRk32pCreateChild(Device);
- if (NewChild == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto ParentQueryChildrenEnd;
- }
- BlockSize = 0;
- Status = SdGetMediaParameters(NewChild->Controller,
- &(NewChild->BlockCount),
- &BlockSize);
- if (!KSUCCESS(Status)) {
- if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- }
- goto ParentQueryChildrenEnd;
- }
- ASSERT(POWER_OF_2(BlockSize) != FALSE);
- NewChild->BlockShift = RtlCountTrailingZeros32(BlockSize);
- //
- // Try to enable DMA, but it's okay if it doesn't succeed.
- //
- Status = SdRk32InitializeDma(Device);
- if (KSUCCESS(Status)) {
- NewChild->Flags |= SD_RK32_CHILD_FLAG_DMA_SUPPORTED;
- } else if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- goto ParentQueryChildrenEnd;
- }
- DeviceId = SD_MMC_DEVICE_ID;
- if (SD_IS_CARD_SD(Device->Controller)) {
- DeviceId = SD_CARD_DEVICE_ID;
- }
- Status = IoCreateDevice(SdRk32Driver,
- NewChild,
- Irp->Device,
- DeviceId,
- DISK_CLASS_ID,
- NULL,
- &(NewChild->Device));
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Device->Child = NewChild;
- NewChild = NULL;
- }
- //
- // If there's no child present, don't enumerate it.
- //
- if (Device->Child == NULL) {
- return STATUS_SUCCESS;
- }
- ASSERT((Device->Child != NULL) && (Device->Child->Device != NULL));
- //
- // Enumerate the one child.
- //
- Status = IoMergeChildArrays(Irp,
- &(Device->Child->Device),
- 1,
- SD_ALLOCATION_TAG);
- ParentQueryChildrenEnd:
- if (NewChild != NULL) {
- ASSERT(NewChild->Device == NULL);
- SdRk32pChildReleaseReference(NewChild);
- }
- return Status;
- }
- KSTATUS
- SdRk32HardResetController (
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine hard resets the RK32xx SD controller and card.
- Arguments:
- Device - Supplies a pointer to this SD RK32xx device.
- Return Value:
- Status code.
- --*/
- {
- ULONGLONG Frequency;
- ULONG ResetMask;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Frequency = HlQueryTimeCounterFrequency();
- //
- // First perform a hardware reset on the SD card.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcPower, SD_DWC_POWER_DISABLE);
- SD_DWC_WRITE_REGISTER(Device, SdDwcResetN, SD_DWC_RESET_ENABLE);
- HlBusySpin(5000);
- SD_DWC_WRITE_REGISTER(Device, SdDwcPower, SD_DWC_POWER_ENABLE);
- SD_DWC_WRITE_REGISTER(Device, SdDwcResetN, 0);
- HlBusySpin(1000);
- //
- // Perform a complete controller reset and wait for it to complete.
- //
- ResetMask = SD_DWC_CONTROL_FIFO_RESET |
- SD_DWC_CONTROL_DMA_RESET |
- SD_DWC_CONTROL_CONTROLLER_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, ResetMask);
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- if ((Value & ResetMask) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- goto HardResetControllerEnd;
- }
- //
- // Reset the internal DMA.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- Value |= SD_DWC_BUS_MODE_INTERNAL_DMA_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- if ((Value & SD_DWC_BUS_MODE_INTERNAL_DMA_RESET) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Status = SdRk32SetRegulatorVoltage(Device, FALSE);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Clear interrupts.
- //
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_ALL_MASK);
- //
- // Set 3v3 volts in the UHS register.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcUhs, SD_DWC_UHS_VOLTAGE_3V3);
- //
- // Set the clock to 400kHz in preparation for sending CMD0 with the
- // initialization bit set.
- //
- Status = SdRk32SetClockSpeed(Device, SdClock400kHz);
- if (!KSUCCESS(Status)) {
- goto HardResetControllerEnd;
- }
- //
- // Reset the card by sending the CMD0 reset command with the initialization
- // bit set.
- //
- Value = SD_DWC_COMMAND_START |
- SD_DWC_COMMAND_USE_HOLD_REGISTER |
- SD_DWC_COMMAND_SEND_INITIALIZATION;
- SD_DWC_WRITE_REGISTER(Device, SdDwcCommand, Value);
- //
- // Wait for the command to complete.
- //
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcCommand);
- if ((Value & SD_DWC_COMMAND_START) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- goto HardResetControllerEnd;
- }
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if (Value != 0) {
- if ((Value & SD_DWC_INTERRUPT_STATUS_COMMAND_DONE) != 0) {
- Status = STATUS_SUCCESS;
- } else if ((Value &
- SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE_TIMEOUT) != 0) {
- Status = STATUS_NO_MEDIA;
- } else {
- Status = STATUS_DEVICE_IO_ERROR;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcInterruptStatus, Value);
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- goto HardResetControllerEnd;
- }
- HardResetControllerEnd:
- return Status;
- }
- KSTATUS
- SdRk32InitializeVendorResource (
- PSD_RK32_CONTEXT Device,
- PRESOURCE_ALLOCATION Resource
- )
- /*++
- Routine Description:
- This routine gets the fundamental clock frequency to use for the SD
- controller. It initializes the device context with the value.
- Arguments:
- Device - Supplies a pointer to the SD RK32 device.
- Resource - Supplies a pointer to the vendor specific resource data.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_VENDOR_RESOURCE Data;
- KSTATUS Status;
- Data = Resource->Data;
- if (Resource->DataSize < sizeof(SD_RK32_VENDOR_RESOURCE)) {
- return STATUS_DATA_LENGTH_MISMATCH;
- }
- if (RtlAreUuidsEqual(&(Data->Uuid), &SdRk32VendorResourceUuid) == FALSE) {
- return STATUS_INVALID_CONFIGURATION;
- }
- Device->FundamentalClock = Data->FundamentalClock;
- Device->Ldo = Data->Ldo;
- if (Device->Ldo != 0) {
- Status = IoRegisterForInterfaceNotifications(
- &SdRk32Rk808InterfaceUuid,
- SdRk32Rk808InterfaceNotificationCallback,
- NULL,
- Device,
- TRUE);
- if (!KSUCCESS(Status)) {
- goto InitializeVendorResourceEnd;
- }
- }
- //
- // Eventually, this should be handled by a more official clock manager.
- //
- Device->Cru = MmMapPhysicalAddress(Data->Cru,
- MmPageSize(),
- TRUE,
- FALSE,
- TRUE);
- if (Device->Cru == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto InitializeVendorResourceEnd;
- }
- Device->VendorData = Data;
- Status = STATUS_SUCCESS;
- InitializeVendorResourceEnd:
- return Status;
- }
- INTERRUPT_STATUS
- SdRk32InterruptService (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine implements the RK32xx SD interrupt service routine.
- Arguments:
- Context - Supplies the context pointer given to the system when the
- interrupt was connected. In this case, this points to the RK32xx SD
- controller.
- Return Value:
- Interrupt status.
- --*/
- {
- PSD_CONTROLLER Controller;
- PSD_RK32_CONTEXT Device;
- ULONG MaskedStatus;
- Device = (PSD_RK32_CONTEXT)Context;
- MaskedStatus = SD_DWC_READ_REGISTER(Device, SdDwcMaskedInterruptStatus);
- if (MaskedStatus == 0) {
- return InterruptStatusNotClaimed;
- }
- Controller = Device->Controller;
- SD_DWC_WRITE_REGISTER(Device, SdDwcInterruptStatus, MaskedStatus);
- RtlAtomicOr32(&(Controller->PendingStatusBits), MaskedStatus);
- return InterruptStatusClaimed;
- }
- INTERRUPT_STATUS
- SdRk32InterruptServiceDispatch (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine implements the RK32xx SD dispatch level interrupt service
- routine.
- Arguments:
- Context - Supplies the context pointer given to the system when the
- interrupt was connected. In this case, this points to the RK32xx SD
- controller.
- Return Value:
- Interrupt status.
- --*/
- {
- UINTN BytesCompleted;
- PVOID CompletionContext;
- PSD_IO_COMPLETION_ROUTINE CompletionRoutine;
- PSD_CONTROLLER Controller;
- PSD_RK32_CONTEXT Device;
- BOOL Inserted;
- ULONG PendingBits;
- BOOL Removed;
- KSTATUS Status;
- Device = (PSD_RK32_CONTEXT)Context;
- Controller = Device->Controller;
- PendingBits = RtlAtomicExchange32(&(Controller->PendingStatusBits), 0);
- if (PendingBits == 0) {
- return InterruptStatusNotClaimed;
- }
- //
- // Process a media change.
- //
- Status = STATUS_DEVICE_IO_ERROR;
- Inserted = FALSE;
- Removed = FALSE;
- if ((PendingBits & SD_DWC_INTERRUPT_STATUS_CARD_DETECT) != 0) {
- //
- // TODO: Hanndle RK32xx SD/MMC insertion and removal.
- //
- ASSERT(FALSE);
- }
- KeAcquireSpinLock(&(Device->DpcLock));
- //
- // Process the I/O completion. The only other interrupt bits that are sent
- // to the DPC are the error bits and the transfer complete bit.
- //
- if ((PendingBits & SD_DWC_INTERRUPT_ERROR_MASK) != 0) {
- Status = STATUS_DEVICE_IO_ERROR;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Inserted = TRUE;
- Removed = TRUE;
- } else if ((Controller->Flags &
- SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
- Removed = TRUE;
- }
- } else if ((PendingBits &
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER) != 0) {
- Status = STATUS_SUCCESS;
- } else if ((PendingBits & SD_DWC_INTERRUPT_STATUS_COMMAND_DONE) != 0) {
- Status = STATUS_SUCCESS;
- }
- if (Controller->IoCompletionRoutine != NULL) {
- CompletionRoutine = Controller->IoCompletionRoutine;
- CompletionContext = Controller->IoCompletionContext;
- BytesCompleted = Controller->IoRequestSize;
- Controller->IoCompletionRoutine = NULL;
- Controller->IoCompletionContext = NULL;
- Controller->IoRequestSize = 0;
- CompletionRoutine(Controller,
- CompletionContext,
- BytesCompleted,
- Status);
- }
- if (((Inserted != FALSE) || (Removed != FALSE)) &&
- (Controller->FunctionTable.MediaChangeCallback != NULL)) {
- Controller->FunctionTable.MediaChangeCallback(
- Controller,
- Controller->ConsumerContext,
- Removed,
- Inserted);
- }
- KeReleaseSpinLock(&(Device->DpcLock));
- return InterruptStatusClaimed;
- }
- INTERRUPT_STATUS
- SdRk32CardInterruptWorker (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine implements the RK32xx SD low level card detect interrupt
- service work routine.
- Arguments:
- Context - Supplies the context pointer given to the system when the
- interrupt was connected. In this case, this points to the RK32xx SD
- controller.
- Return Value:
- Interrupt status.
- --*/
- {
- PSD_RK32_CONTEXT Device;
- Device = (PSD_RK32_CONTEXT)Context;
- if (Device->Controller->FunctionTable.MediaChangeCallback != NULL) {
- Device->Controller->FunctionTable.MediaChangeCallback(
- Device->Controller,
- NULL,
- TRUE,
- TRUE);
- }
- return InterruptStatusClaimed;
- }
- VOID
- SdRk32DmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- )
- /*++
- Routine Description:
- This routine is called by the SD library when a DMA transfer completes.
- This routine is called from a DPC and, as a result, can get called back
- at dispatch level.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the library when the DMA
- request was issued.
- BytesTransferred - Supplies the number of bytes transferred in the request.
- Status - Supplies the status code representing the completion of the I/O.
- Return Value:
- None.
- --*/
- {
- UINTN BlockCount;
- ULONGLONG BlockOffset;
- PSD_RK32_CHILD Child;
- IO_OFFSET IoOffset;
- UINTN IoSize;
- PIRP Irp;
- BOOL Write;
- Child = Context;
- Irp = Child->Irp;
- ASSERT(Irp != NULL);
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("SD RK32xx Failed %x %I64x %x: %x\n",
- Irp->MinorCode,
- Irp->U.ReadWrite.IoOffset,
- Irp->U.ReadWrite.IoSizeInBytes,
- Status);
- BytesTransferred = 0;
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- return;
- }
- Irp->U.ReadWrite.IoBytesCompleted += BytesTransferred;
- Irp->U.ReadWrite.NewIoOffset += BytesTransferred;
- //
- // If this transfer's over, potentially send a stop. If that's done or
- // not needed, complete the IRP.
- //
- if (Irp->U.ReadWrite.IoBytesCompleted ==
- Irp->U.ReadWrite.IoSizeInBytes) {
- if ((Controller->SendStop != FALSE) &&
- ((Controller->HostCapabilities & SD_MODE_AUTO_CMD12) == 0)) {
- Controller->SendStop = FALSE;
- Child->Controller->IoCompletionRoutine = SdRk32DmaCompletion;
- Child->Controller->IoCompletionContext = Child;
- Status = SdSendStop(Controller, TRUE, TRUE);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- } else {
- IoCompleteIrp(SdRk32Driver, Irp, Status);
- }
- return;
- }
- IoOffset = Irp->U.ReadWrite.IoOffset + Irp->U.ReadWrite.IoBytesCompleted;
- BlockOffset = IoOffset >> Child->BlockShift;
- IoSize = Irp->U.ReadWrite.IoSizeInBytes -
- Irp->U.ReadWrite.IoBytesCompleted;
- BlockCount = IoSize >> Child->BlockShift;
- Write = FALSE;
- if (Irp->MinorCode == IrpMinorIoWrite) {
- Write = TRUE;
- }
- SdRk32BlockIoDma(Child->Parent,
- BlockOffset,
- BlockCount,
- Irp->U.ReadWrite.IoBuffer,
- Irp->U.ReadWrite.IoBytesCompleted,
- Write,
- SdRk32DmaCompletion,
- Child);
- return;
- }
- PSD_RK32_CHILD
- SdRk32pCreateChild (
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine creates an SD child context.
- Arguments:
- Device - Supplies a pointer to the parent device to which the child belongs.
- Return Value:
- Returns a pointer to the new child on success or NULL on failure.
- --*/
- {
- PSD_RK32_CHILD Child;
- Child = MmAllocateNonPagedPool(sizeof(SD_RK32_CHILD), SD_ALLOCATION_TAG);
- if (Child == NULL) {
- return NULL;
- }
- RtlZeroMemory(Child, sizeof(SD_RK32_CHILD));
- Child->Type = SdRk32Child;
- Child->Parent = Device;
- Child->Controller = Device->Controller;
- Child->ControllerLock = Device->Lock;
- Child->ReferenceCount = 1;
- return Child;
- }
- VOID
- SdRk32pDestroyChild (
- PSD_RK32_CHILD Child
- )
- /*++
- Routine Description:
- This routine destroys the given SD child device.
- Arguments:
- Child - Supplies a pointer to the SD child device to destroy.
- Return Value:
- None.
- --*/
- {
- ASSERT(Child->DiskInterface.DiskToken == NULL);
- ASSERT(Child->Irp == NULL);
- MmFreeNonPagedPool(Child);
- return;
- }
- VOID
- SdRk32pChildAddReference (
- PSD_RK32_CHILD Child
- )
- /*++
- Routine Description:
- This routine adds a reference to SD child device.
- Arguments:
- Child - Supplies a pointer to the SD child device.
- Return Value:
- None.
- --*/
- {
- ULONG OldReferenceCount;
- OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), 1);
- ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
- return;
- }
- VOID
- SdRk32pChildReleaseReference (
- PSD_RK32_CHILD Child
- )
- /*++
- Routine Description:
- This routine releases a reference from the SD child.
- Arguments:
- Child - Supplies a pointer to the SD child.
- Return Value:
- None.
- --*/
- {
- ULONG OldReferenceCount;
- OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), (ULONG)-1);
- ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
- if (OldReferenceCount == 1) {
- SdRk32pDestroyChild(Child);
- }
- return;
- }
- KSTATUS
- SdRk32ChildBlockIoReset (
- PVOID DiskToken
- )
- /*++
- Routine Description:
- This routine must be called immediately before using the block read and
- write routines in order to allow the disk to reset any I/O channels in
- preparation for imminent block I/O. This routine is called at high run
- level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CHILD Child;
- KSTATUS Status;
- ULONG Value;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_RK32_CHILD)DiskToken;
- //
- // Put the SD controller into critical execution mode.
- //
- SdSetCriticalMode(Child->Controller, TRUE);
- //
- // Abort any current transaction that might have been left incomplete
- // when the crash occurred.
- //
- Status = SdAbortTransaction(Child->Controller, FALSE);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Make sure the controller is not stuck in DMA transfer mode.
- //
- //
- // Make sure DMA mode is disabled.
- //
- Value = SD_DWC_READ_REGISTER(Child->Parent, SdDwcControl);
- if ((Value & SD_DWC_CONTROL_USE_INTERNAL_DMAC) != 0) {
- Value &= ~SD_DWC_CONTROL_USE_INTERNAL_DMAC;
- SD_DWC_WRITE_REGISTER(Child->Parent, SdDwcControl, Value);
- }
- return Status;
- }
- KSTATUS
- SdRk32ChildBlockIoRead (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- )
- /*++
- Routine Description:
- This routine reads the block contents from the disk into the given I/O
- buffer using polled I/O. It does so without acquiring any locks or
- allocating any resources, as this routine is used for crash dump support
- when the system is in a very fragile state. This routine must be called at
- high level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
- BlockAddress - Supplies the block index to read (for physical disk, this is
- the LBA).
- BlockCount - Supplies the number of blocks to read.
- BlocksCompleted - Supplies a pointer that receives the total number of
- blocks read.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CHILD Child;
- IRP_READ_WRITE IrpReadWrite;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_RK32_CHILD)DiskToken;
- IrpReadWrite.IoBuffer = IoBuffer;
- IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
- IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
- //
- // As this read routine is meant for critical code paths (crash dump),
- // indicate that the channel should not be locked when performing the I/O.
- // It may be that some other thread holds the lock, which would cause a
- // dead lock as all other processors and threads are likely frozen.
- //
- Status = SdRk32PerformIoPolled(&IrpReadWrite, Child, FALSE, FALSE);
- *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
- return Status;
- }
- KSTATUS
- SdRk32ChildBlockIoWrite (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- )
- /*++
- Routine Description:
- This routine writes the contents of the given I/O buffer to the disk using
- polled I/O. It does so without acquiring any locks or allocating any
- resources, as this routine is used for crash dump support when the system
- is in a very fragile state. This routine must be called at high level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- IoBuffer - Supplies a pointer to the I/O buffer containing the data to
- write.
- BlockAddress - Supplies the block index to write to (for physical disk,
- this is the LBA).
- BlockCount - Supplies the number of blocks to write.
- BlocksCompleted - Supplies a pointer that receives the total number of
- blocks written.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CHILD Child;
- IRP_READ_WRITE IrpReadWrite;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_RK32_CHILD)DiskToken;
- IrpReadWrite.IoBuffer = IoBuffer;
- IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
- IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
- //
- // As this write routine is meant for critical code paths (crash dump),
- // indicate that the channel should not be locked when performing the I/O.
- // It may be that some other thread holds the lock, which would cause a
- // dead lock as all other processors and threads are likely frozen.
- //
- Status = SdRk32PerformIoPolled(&IrpReadWrite, Child, TRUE, FALSE);
- *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
- return Status;
- }
- KSTATUS
- SdRk32PerformIoPolled (
- PIRP_READ_WRITE IrpReadWrite,
- PSD_RK32_CHILD Child,
- BOOL Write,
- BOOL LockRequired
- )
- /*++
- Routine Description:
- This routine performs polled I/O data transfers.
- Arguments:
- IrpReadWrite - Supplies a pointer to the IRP read/write context.
- Child - Supplies a pointer to the SD child device.
- Write - Supplies a boolean indicating if this is a read operation (TRUE) or
- a write operation (FALSE).
- LockRequired - Supplies a boolean indicating if this operation requires the
- child's controller lock to be acquired (TRUE) or not (FALSE).
- Return Value:
- None.
- --*/
- {
- UINTN BlockCount;
- ULONGLONG BlockOffset;
- UINTN BytesRemaining;
- UINTN BytesThisRound;
- KSTATUS CompletionStatus;
- PSD_CONTROLLER Controller;
- PIO_BUFFER_FRAGMENT Fragment;
- UINTN FragmentIndex;
- UINTN FragmentOffset;
- PIO_BUFFER IoBuffer;
- UINTN IoBufferOffset;
- ULONG IrpReadWriteFlags;
- BOOL LockHeld;
- BOOL ReadWriteIrpPrepared;
- KSTATUS Status;
- PVOID VirtualAddress;
- IrpReadWrite->IoBytesCompleted = 0;
- LockHeld = FALSE;
- ReadWriteIrpPrepared = FALSE;
- ASSERT(IrpReadWrite->IoBuffer != NULL);
- ASSERT(Child->Type == SdRk32Child);
- ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
- Controller = Child->Controller;
- //
- // Validate the supplied I/O buffer is aligned and big enough.
- //
- IrpReadWriteFlags = IRP_READ_WRITE_FLAG_POLLED;
- if (Write != FALSE) {
- IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
- }
- Status = IoPrepareReadWriteIrp(IrpReadWrite,
- 1 << Child->BlockShift,
- 0,
- MAX_ULONGLONG,
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- goto PerformBlockIoPolledEnd;
- }
- ReadWriteIrpPrepared = TRUE;
- //
- // Make sure the I/O buffer is mapped before use. SD depends on the buffer
- // being mapped.
- //
- IoBuffer = IrpReadWrite->IoBuffer;
- Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
- if (!KSUCCESS(Status)) {
- goto PerformBlockIoPolledEnd;
- }
- //
- // Find the starting fragment based on the current offset.
- //
- IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
- FragmentIndex = 0;
- FragmentOffset = 0;
- while (IoBufferOffset != 0) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- if (IoBufferOffset < Fragment->Size) {
- FragmentOffset = IoBufferOffset;
- break;
- }
- IoBufferOffset -= Fragment->Size;
- FragmentIndex += 1;
- }
- if (LockRequired != FALSE) {
- KeAcquireQueuedLock(Child->ControllerLock);
- LockHeld = TRUE;
- }
- if (((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
- ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0)) {
- Status = STATUS_NO_MEDIA;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Status = STATUS_MEDIA_CHANGED;
- }
- goto PerformBlockIoPolledEnd;
- }
- //
- // Loop reading in or writing out each fragment in the I/O buffer.
- //
- BytesRemaining = IrpReadWrite->IoSizeInBytes;
- ASSERT(IS_ALIGNED(BytesRemaining, 1 << Child->BlockShift) != FALSE);
- ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, 1 << Child->BlockShift) != FALSE);
- BlockOffset = IrpReadWrite->IoOffset >> Child->BlockShift;
- while (BytesRemaining != 0) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
- BytesThisRound = Fragment->Size - FragmentOffset;
- if (BytesRemaining < BytesThisRound) {
- BytesThisRound = BytesRemaining;
- }
- ASSERT(IS_ALIGNED(BytesThisRound, (1 << Child->BlockShift)) != FALSE);
- BlockCount = BytesThisRound >> Child->BlockShift;
- //
- // Make sure the system isn't trying to do I/O off the end of the disk.
- //
- ASSERT(BlockOffset < Child->BlockCount);
- ASSERT(BlockCount >= 1);
- Status = SdBlockIoPolled(Controller,
- BlockOffset,
- BlockCount,
- VirtualAddress,
- Write);
- if (!KSUCCESS(Status)) {
- goto PerformBlockIoPolledEnd;
- }
- BlockOffset += BlockCount;
- BytesRemaining -= BytesThisRound;
- IrpReadWrite->IoBytesCompleted += BytesThisRound;
- FragmentOffset += BytesThisRound;
- if (FragmentOffset >= Fragment->Size) {
- FragmentIndex += 1;
- FragmentOffset = 0;
- }
- }
- Status = STATUS_SUCCESS;
- PerformBlockIoPolledEnd:
- if (LockHeld != FALSE) {
- KeReleaseQueuedLock(Child->ControllerLock);
- }
- if (ReadWriteIrpPrepared != FALSE) {
- CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
- IrpReadWriteFlags);
- if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
- Status = CompletionStatus;
- }
- }
- IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
- IrpReadWrite->IoBytesCompleted;
- return Status;
- }
- KSTATUS
- SdRk32InitializeDma (
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine initializes DMA support in the RK32 host controller.
- Arguments:
- Device - Supplies a pointer to the RK32xx SD device.
- Return Value:
- Status code.
- --*/
- {
- PSD_CONTROLLER Controller;
- PSD_DWC_DMA_DESCRIPTOR Descriptor;
- ULONG IoBufferFlags;
- ULONG Value;
- Controller = Device->Controller;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- return STATUS_MEDIA_CHANGED;
- } else if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
- return STATUS_NO_MEDIA;
- }
- if ((Controller->HostCapabilities & SD_MODE_AUTO_CMD12) == 0) {
- return STATUS_NOT_SUPPORTED;
- }
- //
- // Create the DMA descriptor table if not already done.
- //
- if (Controller->DmaDescriptorTable == NULL) {
- IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS |
- IO_BUFFER_FLAG_MAP_NON_CACHED;
- Controller->DmaDescriptorTable = MmAllocateNonPagedIoBuffer(
- 0,
- MAX_ULONG,
- 4,
- SD_RK32_DMA_DESCRIPTOR_TABLE_SIZE,
- IoBufferFlags);
- if (Controller->DmaDescriptorTable == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- ASSERT(Controller->DmaDescriptorTable->FragmentCount == 1);
- }
- Descriptor = Controller->DmaDescriptorTable->Fragment[0].VirtualAddress;
- RtlZeroMemory(Descriptor, SD_RK32_DMA_DESCRIPTOR_TABLE_SIZE);
- //
- // Enable DMA in the control register.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value |= SD_DWC_CONTROL_DMA_ENABLE;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- //
- // Read it to make sure the write stuck.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- if ((Value & SD_DWC_CONTROL_DMA_ENABLE) == 0) {
- return STATUS_NOT_SUPPORTED;
- }
- //
- // Enable internal DMA in the bus mode register.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- Value |= SD_DWC_BUS_MODE_IDMAC_ENABLE;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- //
- // Read it to make sure the write stuck.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- if ((Value & SD_DWC_BUS_MODE_IDMAC_ENABLE) == 0) {
- return STATUS_NOT_SUPPORTED;
- }
- return STATUS_SUCCESS;
- }
- VOID
- SdRk32BlockIoDma (
- PSD_RK32_CONTEXT Device,
- ULONGLONG BlockOffset,
- UINTN BlockCount,
- PIO_BUFFER IoBuffer,
- UINTN IoBufferOffset,
- BOOL Write,
- PSD_IO_COMPLETION_ROUTINE CompletionRoutine,
- PVOID CompletionContext
- )
- /*++
- Routine Description:
- This routine performs a block I/O read or write using standard ADMA2.
- Arguments:
- Device - Supplies a pointer to the RK32xx controller device.
- BlockOffset - Supplies the logical block address of the I/O.
- BlockCount - Supplies the number of blocks to read or write.
- IoBuffer - Supplies a pointer to the buffer containing the data to write
- or where the read data should be returned.
- IoBufferOffset - Supplies the offset from the beginning of the I/O buffer
- where this I/O should begin. This is relative to the I/O buffer's
- current offset.
- Write - Supplies a boolean indicating if this is a read operation (FALSE)
- or a write operation.
- CompletionRoutine - Supplies a pointer to a function to call when the I/O
- completes.
- CompletionContext - Supplies a context pointer to pass as a parameter to
- the completion routine.
- Return Value:
- None. The status of the operation is returned when the completion routine
- is called, which may be during the execution of this function in the case
- of an early failure.
- --*/
- {
- ULONG BlockLength;
- SD_COMMAND Command;
- PSD_CONTROLLER Controller;
- ULONG DescriptorCount;
- PHYSICAL_ADDRESS DescriptorPhysical;
- UINTN DescriptorSize;
- PSD_DWC_DMA_DESCRIPTOR DmaDescriptor;
- PIO_BUFFER DmaDescriptorTable;
- PIO_BUFFER_FRAGMENT Fragment;
- UINTN FragmentIndex;
- UINTN FragmentOffset;
- PHYSICAL_ADDRESS PhysicalAddress;
- KSTATUS Status;
- ULONG TableAddress;
- UINTN TransferSize;
- UINTN TransferSizeRemaining;
- ULONG Value;
- ASSERT(BlockCount != 0);
- Controller = Device->Controller;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Status = STATUS_MEDIA_CHANGED;
- goto BlockIoDmaEnd;
- } else if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
- Status = STATUS_NO_MEDIA;
- goto BlockIoDmaEnd;
- }
- if (Write != FALSE) {
- if (BlockCount > 1) {
- Command.Command = SdCommandWriteMultipleBlocks;
- } else {
- Command.Command = SdCommandWriteSingleBlock;
- }
- BlockLength = Controller->WriteBlockLength;
- TransferSize = BlockCount * BlockLength;
- ASSERT(TransferSize != 0);
- } else {
- if (BlockCount > 1) {
- Command.Command = SdCommandReadMultipleBlocks;
- } else {
- Command.Command = SdCommandReadSingleBlock;
- }
- BlockLength = Controller->ReadBlockLength;
- TransferSize = BlockCount * BlockLength;
- ASSERT(TransferSize != 0);
- }
- //
- // Get to the correct spot in the I/O buffer.
- //
- IoBufferOffset += MmGetIoBufferCurrentOffset(IoBuffer);
- FragmentIndex = 0;
- FragmentOffset = 0;
- while (IoBufferOffset != 0) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- if (IoBufferOffset < Fragment->Size) {
- FragmentOffset = IoBufferOffset;
- break;
- }
- IoBufferOffset -= Fragment->Size;
- FragmentIndex += 1;
- }
- //
- // Do a DMA reset.
- //
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value |= SD_DWC_CONTROL_DMA_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- } while ((Value & SD_DWC_CONTROL_DMA_RESET) != 0);
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- Value |= SD_DWC_BUS_MODE_INTERNAL_DMA_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- //
- // Fill out the DMA descriptors.
- //
- DmaDescriptorTable = Controller->DmaDescriptorTable;
- DmaDescriptor = DmaDescriptorTable->Fragment[0].VirtualAddress;
- DescriptorPhysical = DmaDescriptorTable->Fragment[0].PhysicalAddress;
- DescriptorCount = 0;
- TransferSizeRemaining = TransferSize;
- while ((TransferSizeRemaining != 0) &&
- (DescriptorCount < SD_RK32_DMA_DESCRIPTOR_COUNT - 1)) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- //
- // This descriptor size is going to the the minimum of the total
- // remaining size, the size that can fit in a DMA descriptor, and the
- // remaining size of the fragment.
- //
- DescriptorSize = TransferSizeRemaining;
- if (DescriptorSize > SD_DWC_DMA_DESCRIPTOR_MAX_BUFFER_SIZE) {
- DescriptorSize = SD_DWC_DMA_DESCRIPTOR_MAX_BUFFER_SIZE;
- }
- if (DescriptorSize > (Fragment->Size - FragmentOffset)) {
- DescriptorSize = Fragment->Size - FragmentOffset;
- }
- TransferSizeRemaining -= DescriptorSize;
- PhysicalAddress = Fragment->PhysicalAddress + FragmentOffset;
- //
- // Assert that the buffer is within the first 4GB.
- //
- ASSERT(((ULONG)PhysicalAddress == PhysicalAddress) &&
- ((ULONG)(PhysicalAddress + DescriptorSize) ==
- PhysicalAddress + DescriptorSize));
- DmaDescriptor->Address = PhysicalAddress;
- DmaDescriptor->Size = DescriptorSize;
- DmaDescriptor->Control =
- SD_DWC_DMA_DESCRIPTOR_CONTROL_OWN |
- SD_DWC_DMA_DESCRIPTOR_CONTROL_SECOND_ADDRESS_CHAINED |
- SD_DWC_DMA_DESCRIPTOR_CONTROL_DISABLE_INTERRUPT_ON_COMPLETION;
- if (DescriptorCount == 0) {
- DmaDescriptor->Control |=
- SD_DWC_DMA_DESCRIPTOR_CONTROL_FIRST_DESCRIPTOR;
- }
- DescriptorPhysical += sizeof(SD_DWC_DMA_DESCRIPTOR);
- DmaDescriptor->NextDescriptor = DescriptorPhysical;
- DmaDescriptor += 1;
- DescriptorCount += 1;
- FragmentOffset += DescriptorSize;
- if (FragmentOffset >= Fragment->Size) {
- FragmentIndex += 1;
- FragmentOffset = 0;
- }
- }
- //
- // Mark the last DMA descriptor as the end of the transfer.
- //
- DmaDescriptor -= 1;
- DmaDescriptor->Control &=
- ~(SD_DWC_DMA_DESCRIPTOR_CONTROL_SECOND_ADDRESS_CHAINED |
- SD_DWC_DMA_DESCRIPTOR_CONTROL_DISABLE_INTERRUPT_ON_COMPLETION);
- DmaDescriptor->Control |= SD_DWC_DMA_DESCRIPTOR_CONTROL_LAST_DESCRIPTOR;
- DmaDescriptor->NextDescriptor = 0;
- RtlMemoryBarrier();
- Command.ResponseType = SD_RESPONSE_R1;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_HIGH_CAPACITY) != 0) {
- Command.CommandArgument = BlockOffset;
- } else {
- Command.CommandArgument = BlockOffset * BlockLength;
- }
- ASSERT((TransferSize - TransferSizeRemaining) <= MAX_ULONG);
- Command.BufferSize = (ULONG)(TransferSize - TransferSizeRemaining);
- Command.BufferVirtual = NULL;
- Command.BufferPhysical = INVALID_PHYSICAL_ADDRESS;
- Command.Write = Write;
- Command.Dma = TRUE;
- Controller->IoCompletionRoutine = CompletionRoutine;
- Controller->IoCompletionContext = CompletionContext;
- Controller->IoRequestSize = Command.BufferSize;
- //
- // Write the table base, enable DMA, and write the poll demand to get it
- // moving.
- //
- TableAddress = (ULONG)(DmaDescriptorTable->Fragment[0].PhysicalAddress);
- SD_DWC_WRITE_REGISTER(Device, SdDwcDescriptorBaseAddress, TableAddress);
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value |= SD_DWC_CONTROL_USE_INTERNAL_DMAC | SD_DWC_CONTROL_DMA_ENABLE;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- Value |= SD_DWC_BUS_MODE_IDMAC_ENABLE | SD_DWC_BUS_MODE_FIXED_BURST;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- SD_DWC_WRITE_REGISTER(Device, SdDwcPollDemand, 1);
- Status = Controller->FunctionTable.SendCommand(Controller,
- Controller->ConsumerContext,
- &Command);
- if (!KSUCCESS(Status)) {
- Controller->IoCompletionRoutine = NULL;
- Controller->IoCompletionContext = NULL;
- Controller->IoRequestSize = 0;
- goto BlockIoDmaEnd;
- }
- Status = STATUS_SUCCESS;
- BlockIoDmaEnd:
- //
- // If this routine failed, call the completion routine back immediately.
- //
- if (!KSUCCESS(Status)) {
- CompletionRoutine(Controller, CompletionContext, 0, Status);
- }
- return;
- }
- KSTATUS
- SdRk32InitializeController (
- PSD_CONTROLLER Controller,
- PVOID Context,
- ULONG Phase
- )
- /*++
- Routine Description:
- This routine performs any controller specific initialization steps.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Phase - Supplies the phase of initialization. Phase 0 happens after the
- initial software reset and Phase 1 happens after the bus width has been
- set to 1 and the speed to 400KHz.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CONTEXT Device;
- ULONG Mask;
- KSTATUS Status;
- ULONG Value;
- ULONG Voltage;
- Device = (PSD_RK32_CONTEXT)Context;
- //
- // Phase 0 is an early initialization phase that happens after the
- // controller has been reset. It is used to gather capabilities and set
- // certain parameters in the hardware.
- //
- if (Phase == 0) {
- Mask = SD_DWC_CONTROL_FIFO_RESET | SD_DWC_CONTROL_CONTROLLER_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Mask);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- } while ((Value & Mask) != 0);
- //
- // Set the default burst length.
- //
- Value = (SD_DWC_BUS_MODE_BURST_LENGTH_16 <<
- SD_DWC_BUS_MODE_BURST_LENGTH_SHIFT) |
- SD_DWC_BUS_MODE_FIXED_BURST;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- //
- // Set the default FIFO threshold.
- //
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcFifoThreshold,
- SD_DWC_FIFO_THRESHOLD_DEFAULT);
- //
- // Set the default timeout.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcTimeout, SD_DWC_TIMEOUT_DEFAULT);
- //
- // Set the voltages based on the supported values supplied when the
- // controller was created.
- //
- Voltage = SD_DWC_READ_REGISTER(Device, SdDwcUhs);
- Voltage &= ~SD_DWC_UHS_VOLTAGE_MASK;
- if ((Controller->Voltages & (SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34)) ==
- (SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34)) {
- Voltage |= SD_DWC_UHS_VOLTAGE_3V3;
- } else if ((Controller->Voltages &
- (SD_VOLTAGE_165_195 | SD_VOLTAGE_18)) != 0) {
- Voltage |= SD_DWC_UHS_VOLTAGE_1V8;
- } else {
- Status = STATUS_DEVICE_NOT_CONNECTED;
- goto InitializeControllerEnd;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcUhs, Voltage);
- //
- // Phase 1 happens right before the initialization command sequence is
- // about to begin. The clock and bus width have been program and the device
- // is just about read to go.
- //
- } else if (Phase == 1) {
- //
- // Turn on the power.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcPower, SD_DWC_POWER_ENABLE);
- //
- // Set the interrupt mask, clear any pending state, and enable the
- // interrupts.
- //
- Controller->EnabledInterrupts = SD_DWC_INTERRUPT_DEFAULT_MASK;
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptMask,
- SD_DWC_INTERRUPT_DEFAULT_MASK);
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_ALL_MASK);
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value |= SD_DWC_CONTROL_INTERRUPT_ENABLE;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- }
- Status = STATUS_SUCCESS;
- InitializeControllerEnd:
- return Status;
- }
- KSTATUS
- SdRk32ResetController (
- PSD_CONTROLLER Controller,
- PVOID Context,
- ULONG Flags
- )
- /*++
- Routine Description:
- This routine performs a soft reset of the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Flags - Supplies a bitmask of reset flags. See SD_RESET_FLAG_* for
- definitions.
- Return Value:
- Status code.
- --*/
- {
- ULONG BusMode;
- ULONG CardType;
- ULONG Control;
- PSD_RK32_CONTEXT Device;
- ULONGLONG Frequency;
- ULONG ResetMask;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Device = (PSD_RK32_CONTEXT)Context;
- Device->InVoltageSwitch = FALSE;
- Frequency = HlQueryTimeCounterFrequency();
- ResetMask = SD_DWC_CONTROL_FIFO_RESET |
- SD_DWC_CONTROL_DMA_RESET |
- SD_DWC_CONTROL_CONTROLLER_RESET;
- if ((Flags & SD_RESET_FLAG_ALL) != 0) {
- //
- // Power cycle the card.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcPower, 0);
- HlBusySpin(10000);
- SdRk32SetRegulatorVoltage(Device, FALSE);
- SD_DWC_WRITE_REGISTER(Device, SdDwcPower, SD_DWC_POWER_ENABLE);
- HlBusySpin(10000);
- }
- CardType = SD_DWC_READ_REGISTER(Device, SdDwcCardType);
- Control = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value = (Control | ResetMask) &
- ~(SD_DWC_CONTROL_DMA_ENABLE |
- SD_DWC_CONTROL_USE_INTERNAL_DMAC);
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- Status = STATUS_TIMEOUT;
- Timeout = SdQueryTimeCounter(Controller) + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- if ((Value & ResetMask) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcInterruptStatus, 0xFFFFFFFF);
- //
- // Wait for the DMA status to clear.
- //
- Status = STATUS_TIMEOUT;
- Timeout = SdQueryTimeCounter(Controller) + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & SD_DWC_STATUS_DMA_REQUEST) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Reset the FIFO again.
- //
- ResetMask = SD_DWC_CONTROL_FIFO_RESET;
- Device = (PSD_RK32_CONTEXT)Context;
- Value = (Control | ResetMask) &
- ~(SD_DWC_CONTROL_DMA_ENABLE |
- SD_DWC_CONTROL_USE_INTERNAL_DMAC);
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- Status = STATUS_TIMEOUT;
- Timeout = SdQueryTimeCounter(Controller) + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- if ((Value & ResetMask) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Reset the internal DMA.
- //
- BusMode = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- Value = BusMode &
- ~(SD_DWC_BUS_MODE_FIXED_BURST | SD_DWC_BUS_MODE_IDMAC_ENABLE);
- Value |= SD_DWC_BUS_MODE_INTERNAL_DMA_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, Value);
- Status = STATUS_TIMEOUT;
- Timeout = SdQueryTimeCounter(Controller) + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcBusMode);
- if ((Value & SD_DWC_BUS_MODE_INTERNAL_DMA_RESET) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcBusMode, BusMode);
- //
- // Restore the original control, and update the clock.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Control);
- SD_DWC_WRITE_REGISTER(Device, SdDwcCardType, CardType);
- Status = SdRk32SetClockSpeed(Device, Controller->ClockSpeed);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Value = (Controller->ReadBlockLength <<
- SD_DWC_CARD_READ_THRESHOLD_SIZE_SHIFT) |
- SD_DWC_CARD_READ_THRESHOLD_ENABLE;
- SD_DWC_WRITE_REGISTER(Device, SdDwcCardThresholdControl, Value);
- return STATUS_SUCCESS;
- }
- KSTATUS
- SdRk32SendCommand (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PSD_COMMAND Command
- )
- /*++
- Routine Description:
- This routine sends the given command to the card.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Command - Supplies a pointer to the command parameters.
- Return Value:
- Status code.
- --*/
- {
- ULONG CommandValue;
- PSD_RK32_CONTEXT Device;
- ULONG Flags;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Device = (PSD_RK32_CONTEXT)Context;
- //
- // Clear any old interrupt status.
- //
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_ALL_MASK);
- SdRk32SetDmaInterrupts(Controller,
- Device,
- Command->Dma,
- Command->BufferSize);
- //
- // If the stop command is being sent, add the flag to make sure the current
- // data transfer stops and that this command does not wait for the previous
- // data to complete. Otherwise, wait for the previous data to complete.
- //
- if ((Command->Command == SdCommandStopTransmission) &&
- (Command->ResponseType != SD_RESPONSE_R1B)) {
- Flags = SD_DWC_COMMAND_STOP_ABORT;
- } else {
- Flags = SD_DWC_COMMAND_WAIT_PREVIOUS_DATA_COMPLETE;
- if (Command->Command == SdCommandReset) {
- Flags |= SD_DWC_COMMAND_SEND_INITIALIZATION;
- //
- // For the voltage switch command, disable low power clock mode and set
- // the required flag in the CMD register.
- //
- } else if (Command->Command == SdCommandVoltageSwitch) {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcClockEnable);
- Value &= ~SD_DWC_CLOCK_ENABLE_LOW_POWER;
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockEnable, Value);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- Device->InVoltageSwitch = TRUE;
- Flags |= SD_DWC_COMMAND_VOLT_SWITCH;
- }
- //
- // Wait for the FIFO to become empty command to complete.
- //
- Timeout = 0;
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & SD_DWC_STATUS_FIFO_EMPTY) == 0) {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- Value |= SD_DWC_CONTROL_FIFO_RESET;
- SD_DWC_WRITE_REGISTER(Device, SdDwcControl, Value);
- Status = STATUS_TIMEOUT;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcControl);
- if ((Value & SD_DWC_CONTROL_FIFO_RESET) == 0) {
- Status = STATUS_SUCCESS;
- break;
- } else if (Timeout == 0) {
- Timeout = SdQueryTimeCounter(Controller) +
- Controller->Timeout;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- }
- //
- // Also wait for the controller to stop being busy from the last
- // command. This comes into play on writes that use internal DMA. The
- // state machine remains busy despite the transfer completion
- // interrupt.
- //
- if ((Value & SD_DWC_STATUS_DATA_BUSY) != 0) {
- Status = STATUS_TIMEOUT;
- Timeout = SdQueryTimeCounter(Controller) + Controller->Timeout;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & SD_DWC_STATUS_DATA_BUSY) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- }
- }
- //
- // Set up the response flags.
- //
- if ((Command->ResponseType & SD_RESPONSE_PRESENT) != 0) {
- if ((Command->ResponseType & SD_RESPONSE_136_BIT) != 0) {
- Flags |= SD_DWC_COMMAND_LONG_RESPONSE;
- }
- Flags |= SD_DWC_COMMAND_RESPONSE_EXPECTED;
- }
- //
- // Set up the remainder of the command flags.
- //
- if ((Command->ResponseType & SD_RESPONSE_VALID_CRC) != 0) {
- Flags |= SD_DWC_COMMAND_CHECK_RESPONSE_CRC;
- }
- //
- // If there's a data buffer, program the block count.
- //
- if (Command->BufferSize != 0) {
- Flags |= SD_DWC_COMMAND_DATA_EXPECTED;
- if (Command->Write != FALSE) {
- Flags |= SD_DWC_COMMAND_WRITE;
- } else {
- Flags |= SD_DWC_COMMAND_READ;
- }
- //
- // If reading or writing multiple blocks, the block size register
- // should be set to the default block size and the byte count should be
- // a multiple of the block size.
- //
- if ((Command->Command == SdCommandReadMultipleBlocks) ||
- (Command->Command == SdCommandWriteMultipleBlocks)) {
- if (((Controller->HostCapabilities & SD_MODE_AUTO_CMD12) != 0) &&
- (Controller->SendStop != FALSE)) {
- Flags |= SD_DWC_COMMAND_SEND_AUTO_STOP;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcBlockSize, SD_RK32_BLOCK_SIZE);
- SD_DWC_WRITE_REGISTER(Device, SdDwcByteCount, Command->BufferSize);
- //
- // Otherwise set the block size to total number of bytes to be
- // processed.
- //
- } else {
- SD_DWC_WRITE_REGISTER(Device, SdDwcBlockSize, Command->BufferSize);
- SD_DWC_WRITE_REGISTER(Device, SdDwcByteCount, Command->BufferSize);
- }
- }
- //
- // Internal DMA better be enabled if this is a DMA command.
- //
- ASSERT((Command->Dma == FALSE) ||
- (Command->BufferSize == 0) ||
- (((SD_DWC_READ_REGISTER(Device, SdDwcBusMode) &
- SD_DWC_BUS_MODE_IDMAC_ENABLE) != 0) &&
- ((SD_DWC_READ_REGISTER(Device, SdDwcControl) &
- SD_DWC_CONTROL_USE_INTERNAL_DMAC) != 0)));
- SD_DWC_WRITE_REGISTER(Device, SdDwcTimeout, 0xFFFFFFFF);
- //
- // Write the command argument.
- //
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcCommandArgument,
- Command->CommandArgument);
- //
- // Set the command and wait for it to be accepted.
- //
- CommandValue = (Command->Command << SD_DWC_COMMAND_INDEX_SHIFT) &
- SD_DWC_COMMAND_INDEX_MASK;
- CommandValue |= SD_DWC_COMMAND_START |
- SD_DWC_COMMAND_USE_HOLD_REGISTER |
- Flags;
- SD_DWC_WRITE_REGISTER(Device, SdDwcCommand, CommandValue);
- //
- // If this was a DMA command, just let it sail away.
- //
- if (Command->Dma != FALSE) {
- Status = STATUS_SUCCESS;
- goto SendCommandEnd;
- }
- ASSERT(Controller->EnabledInterrupts == SD_DWC_INTERRUPT_DEFAULT_MASK);
- Status = STATUS_TIMEOUT;
- Timeout = 0;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcCommand);
- if ((Value & SD_DWC_COMMAND_START) == 0) {
- Status = STATUS_SUCCESS;
- break;
- } else if (Timeout == 0) {
- Timeout = SdQueryTimeCounter(Controller) + Controller->Timeout;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- //
- // Check the interrupt status. Voltage switch commands set a specific
- // status bit, all other commands set command done.
- //
- Status = STATUS_TIMEOUT;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if (Command->Command == SdCommandVoltageSwitch) {
- if ((Value & SD_DWC_INTERRUPT_STATUS_VOLT_SWITCH) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } else if ((Value & SD_DWC_INTERRUPT_STATUS_COMMAND_DONE) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- if (Timeout == 0) {
- Timeout = SdQueryTimeCounter(Controller) + Controller->Timeout;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- if ((Value & SD_DWC_INTERRUPT_STATUS_ERROR_RESPONSE_TIMEOUT) != 0) {
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_ALL_MASK);
- SdRk32ResetController(Controller,
- Context,
- SD_RESET_FLAG_COMMAND_LINE);
- Status = STATUS_TIMEOUT;
- goto SendCommandEnd;
- } else if ((Value & SD_DWC_INTERRUPT_STATUS_COMMAND_ERROR_MASK) != 0) {
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_ALL_MASK);
- Status = STATUS_DEVICE_IO_ERROR;
- goto SendCommandEnd;
- }
- //
- // Acknowledge the completed command.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcInterruptStatus, Value);
- //
- // Get the response if there is one.
- //
- if ((Command->ResponseType & SD_RESPONSE_PRESENT) != 0) {
- if ((Command->ResponseType & SD_RESPONSE_136_BIT) != 0) {
- Command->Response[3] = SD_DWC_READ_REGISTER(Device, SdDwcResponse0);
- Command->Response[2] = SD_DWC_READ_REGISTER(Device, SdDwcResponse1);
- Command->Response[1] = SD_DWC_READ_REGISTER(Device, SdDwcResponse2);
- Command->Response[0] = SD_DWC_READ_REGISTER(Device, SdDwcResponse3);
- if ((Controller->HostCapabilities &
- SD_MODE_RESPONSE136_SHIFTED) != 0) {
- Command->Response[0] = (Command->Response[0] << 8) |
- ((Command->Response[1] >> 24) & 0xFF);
- Command->Response[1] = (Command->Response[1] << 8) |
- ((Command->Response[2] >> 24) & 0xFF);
- Command->Response[2] = (Command->Response[2] << 8) |
- ((Command->Response[3] >> 24) & 0xFF);
- Command->Response[3] = Command->Response[3] << 8;
- }
- } else {
- Command->Response[0] = SD_DWC_READ_REGISTER(Device, SdDwcResponse0);
- }
- }
- //
- // Read/write the data.
- //
- if (Command->BufferSize != 0) {
- if (Command->Write != FALSE) {
- Status = SdRk32WriteData(Controller,
- Context,
- Command->BufferVirtual,
- Command->BufferSize);
- } else {
- Status = SdRk32ReadData(Controller,
- Context,
- Command->BufferVirtual,
- Command->BufferSize);
- }
- if (!KSUCCESS(Status)) {
- goto SendCommandEnd;
- }
- }
- Status = STATUS_SUCCESS;
- SendCommandEnd:
- return Status;
- }
- KSTATUS
- SdRk32GetSetBusWidth (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- )
- /*++
- Routine Description:
- This routine gets or sets the controller's bus width. The bus width is
- stored in the controller structure.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Set - Supplies a boolean indicating whether the bus width should be queried
- or set.
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CONTEXT Device;
- ULONG Value;
- Device = (PSD_RK32_CONTEXT)Context;
- if (Set != FALSE) {
- switch (Controller->BusWidth) {
- case 1:
- Value = SD_DWC_CARD_TYPE_1_BIT_WIDTH;
- break;
- case 4:
- Value = SD_DWC_CARD_TYPE_4_BIT_WIDTH;
- break;
- case 8:
- Value = SD_DWC_CARD_TYPE_8_BIT_WIDTH;
- break;
- default:
- RtlDebugPrint("SDRK32: Invalid bus width %d.\n",
- Controller->BusWidth);
- ASSERT(FALSE);
- return STATUS_INVALID_CONFIGURATION;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcCardType, Value);
- } else {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcCardType);
- if ((Value & SD_DWC_CARD_TYPE_8_BIT_WIDTH) != 0) {
- Controller->BusWidth = 8;
- } else if ((Value & SD_DWC_CARD_TYPE_4_BIT_WIDTH) != 0) {
- Controller->BusWidth = 4;
- } else {
- Controller->BusWidth = 1;
- }
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- SdRk32GetSetClockSpeed (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- )
- /*++
- Routine Description:
- This routine gets or sets the controller's clock speed. The clock speed is
- stored in the controller structure.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Set - Supplies a boolean indicating whether the clock speed should be
- queried (FALSE) or set (TRUE).
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CONTEXT Device;
- Device = (PSD_RK32_CONTEXT)Context;
- if (Device->FundamentalClock == 0) {
- return STATUS_INVALID_CONFIGURATION;
- }
- //
- // Getting the clock speed is not implemented as the divisor math might not
- // work out precisely in reverse.
- //
- if (Set == FALSE) {
- return STATUS_NOT_SUPPORTED;
- }
- return SdRk32SetClockSpeed(Device, Controller->ClockSpeed);
- }
- KSTATUS
- SdRk32GetSetVoltage (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- )
- /*++
- Routine Description:
- This routine gets or sets the bus voltage. The bus voltage is
- stored in the controller structure.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Set - Supplies a boolean indicating whether the bus voltage should be
- queried (FALSE) or set (TRUE).
- Return Value:
- Status code.
- --*/
- {
- PSD_RK32_CONTEXT Device;
- ULONG Mask;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Device = Context;
- if (Set == FALSE) {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcUhs);
- if ((Value & SD_DWC_UHS_VOLTAGE_1V8) != 0) {
- Controller->CurrentVoltage = SdVoltage1V8;
- } else {
- Controller->CurrentVoltage = SdVoltage3V3;
- }
- return STATUS_SUCCESS;
- }
- //
- // When the standard SD library sent CMD11, the following happened inside
- // send command:
- // * Low power clocking was disabled.
- // * The volt switch interrupt was waited on and cleared.
- // Now stop the SD clock.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockEnable, 0);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- if (Controller->CurrentVoltage != SdVoltage1V8) {
- Status = SdRk32SetRegulatorVoltage(Device, FALSE);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- HlBusySpin(10000);
- Value = SD_DWC_CLOCK_ENABLE_ON | SD_DWC_CLOCK_ENABLE_LOW_POWER;
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockEnable, Value);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- return STATUS_SUCCESS;
- }
- ASSERT(Device->InVoltageSwitch != FALSE);
- //
- // Switch the voltage.
- //
- Status = SdRk32SetRegulatorVoltage(Device, TRUE);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- //
- // Wait at least 5ms as per spec.
- //
- HlBusySpin(10000);
- //
- // Re-enable the clock.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockEnable, SD_DWC_CLOCK_ENABLE_ON);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- //
- // Wait another millisecond as per spec.
- //
- HlBusySpin(2000);
- //
- // The controller should have generated a volt switch and command done
- // interrupt if DAT[3:0] went high for a millisecond.
- //
- Timeout = 0;
- Mask = SD_DWC_INTERRUPT_STATUS_VOLT_SWITCH |
- SD_DWC_INTERRUPT_STATUS_COMMAND_DONE;
- Status = STATUS_TIMEOUT;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if ((Value & Mask) == Mask) {
- Status = STATUS_SUCCESS;
- break;
- } else if (Timeout == 0) {
- Timeout = SdQueryTimeCounter(Controller) +
- HlQueryTimeCounterFrequency();
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- SD_DWC_WRITE_REGISTER(Device, SdDwcInterruptStatus, Value);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- Mask = SD_RESET_FLAG_COMMAND_LINE | SD_RESET_FLAG_DATA_LINE;
- Status = SdRk32ResetController(Controller, Device, Mask);
- if (!KSUCCESS(Status)) {
- goto GetSetVoltageEnd;
- }
- Status = STATUS_SUCCESS;
- GetSetVoltageEnd:
- Device->InVoltageSwitch = FALSE;
- return Status;
- }
- KSTATUS
- SdRk32ReadData (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PVOID Data,
- ULONG Size
- )
- /*++
- Routine Description:
- This routine reads polled data from the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Data - Supplies a pointer to the buffer where the data will be read into.
- Size - Supplies the size in bytes. This must be a multiple of four bytes.
- Return Value:
- Status code.
- --*/
- {
- PULONG Buffer32;
- ULONG BusyMask;
- ULONG Count;
- ULONG DataReadyMask;
- BOOL DataTransferOver;
- PSD_RK32_CONTEXT Device;
- ULONG Interrupts;
- ULONG IoIndex;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONGLONG TimeoutTicks;
- ULONG Value;
- ASSERT(IS_ALIGNED(Size, sizeof(ULONG)) != FALSE);
- Device = (PSD_RK32_CONTEXT)Context;
- DataTransferOver = FALSE;
- Buffer32 = (PULONG)Data;
- Size /= sizeof(ULONG);
- TimeoutTicks = HlQueryTimeCounterFrequency() * SD_RK32_TIMEOUT;
- while (Size != 0) {
- //
- // Get the interrupt status register.
- //
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Interrupts = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if (Interrupts != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Reset the controller if any error bits are set.
- //
- if ((Interrupts & SD_DWC_INTERRUPT_STATUS_DATA_ERROR_MASK) != 0) {
- SdRk32ResetController(Controller, Context, SD_RESET_FLAG_DATA_LINE);
- return STATUS_DEVICE_IO_ERROR;
- }
- //
- // Check for received data status. If data is ready, the status
- // register holds the number of 32-bit elements to be read.
- //
- DataReadyMask = SD_DWC_INTERRUPT_STATUS_RECEIVE_FIFO_DATA_REQUEST;
- if ((Interrupts & DataReadyMask) != 0) {
- Count = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- Count = (Count & SD_DWC_STATUS_FIFO_COUNT_MASK) >>
- SD_DWC_STATUS_FIFO_COUNT_SHIFT;
- if (Count > Size) {
- Count = Size;
- }
- for (IoIndex = 0; IoIndex < Count; IoIndex += 1) {
- *Buffer32 = SD_DWC_READ_REGISTER(Device, SdDwcFifoBase);
- Buffer32 += 1;
- }
- Size -= Count;
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- DataReadyMask);
- }
- //
- // Check for the transfer over bit. If it is set, then read the rest of
- // the bytes from the FIFO.
- //
- if ((Interrupts & SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER) != 0) {
- for (IoIndex = 0; IoIndex < Size; IoIndex += 1) {
- *Buffer32 = SD_DWC_READ_REGISTER(Device, SdDwcFifoBase);
- Buffer32 += 1;
- }
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER);
- Size = 0;
- DataTransferOver = TRUE;
- break;
- }
- }
- //
- // If the data transfer over interrupt has not yet been seen, wait for it
- // to be asserted.
- //
- if (DataTransferOver == FALSE) {
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Interrupts = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if ((Interrupts &
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER);
- }
- //
- // Wait until the state machine and data stop being busy.
- //
- BusyMask = SD_DWC_STATUS_DATA_STATE_MACHINE_BUSY |
- SD_DWC_STATUS_DATA_BUSY;
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & BusyMask) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- SdRk32WriteData (
- PSD_CONTROLLER Controller,
- PVOID Context,
- PVOID Data,
- ULONG Size
- )
- /*++
- Routine Description:
- This routine writes polled data to the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Data - Supplies a pointer to the buffer containing the data to write.
- Size - Supplies the size in bytes. This must be a multiple of 4 bytes.
- Return Value:
- Status code.
- --*/
- {
- PULONG Buffer32;
- ULONG BusyMask;
- ULONG Count;
- ULONG DataRequestMask;
- BOOL DataTransferOver;
- PSD_RK32_CONTEXT Device;
- ULONG Interrupts;
- ULONG IoIndex;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONGLONG TimeoutTicks;
- ULONG Value;
- ASSERT(IS_ALIGNED(Size, sizeof(ULONG)) != FALSE);
- Device = (PSD_RK32_CONTEXT)Context;
- DataTransferOver = FALSE;
- Buffer32 = (PULONG)Data;
- Size /= sizeof(ULONG);
- TimeoutTicks = HlQueryTimeCounterFrequency() * SD_RK32_TIMEOUT;
- while (Size != 0) {
- //
- // Get the interrupt status register.
- //
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Interrupts = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if (Interrupts != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Reset the controller if any error bits are set.
- //
- if ((Interrupts & SD_DWC_INTERRUPT_STATUS_DATA_ERROR_MASK) != 0) {
- SdRk32ResetController(Controller, Context, SD_RESET_FLAG_DATA_LINE);
- return STATUS_DEVICE_IO_ERROR;
- }
- //
- // If the controller is ready for data to be written, the number of
- // 4-byte elements consumed in the FIFO is stored in the status
- // register. The available bytes is the total FIFO size minus that
- // amount.
- //
- DataRequestMask = SD_DWC_INTERRUPT_STATUS_TRANSMIT_FIFO_DATA_REQUEST;
- if ((Interrupts & DataRequestMask) != 0) {
- Count = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- Count = (Count & SD_DWC_STATUS_FIFO_COUNT_MASK) >>
- SD_DWC_STATUS_FIFO_COUNT_SHIFT;
- Count = (SD_DWC_FIFO_DEPTH / sizeof(ULONG)) - Count;
- if (Count > Size) {
- Count = Size;
- }
- for (IoIndex = 0; IoIndex < Count; IoIndex += 1) {
- SD_DWC_WRITE_REGISTER(Device, SdDwcFifoBase, *Buffer32);
- Buffer32 += 1;
- }
- Size -= Count;
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- DataRequestMask);
- }
- //
- // Check for the transfer over bit. If it is set, then exit.
- //
- if ((Interrupts & SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER) != 0) {
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER);
- Size = 0;
- DataTransferOver = TRUE;
- break;
- }
- }
- //
- // If the data transfer over interrupt has not yet been seen, wait for it
- // to be asserted.
- //
- if (DataTransferOver == FALSE) {
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Interrupts = SD_DWC_READ_REGISTER(Device, SdDwcInterruptStatus);
- if ((Interrupts &
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptStatus,
- SD_DWC_INTERRUPT_STATUS_DATA_TRANSFER_OVER);
- }
- //
- // Wait until the state machine and data stop being busy.
- //
- BusyMask = SD_DWC_STATUS_DATA_STATE_MACHINE_BUSY |
- SD_DWC_STATUS_DATA_BUSY;
- Status = STATUS_SUCCESS;
- Timeout = SdQueryTimeCounter(Controller) + TimeoutTicks;
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & BusyMask) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (SdQueryTimeCounter(Controller) <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_SUCCESS;
- }
- KSTATUS
- SdRk32SetClockSpeed (
- PSD_RK32_CONTEXT Device,
- SD_CLOCK_SPEED ClockSpeed
- )
- /*++
- Routine Description:
- This routine sets the controller's clock speed. This function is RockChip
- specific.
- Arguments:
- Device - Supplies a pointer to this SD RK32xx device.
- ClockSpeed - Supplies the desired clock speed in Hertz.
- Return Value:
- Status code.
- --*/
- {
- ULONG Divisor;
- ULONGLONG Frequency;
- ULONG InputClock;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- //
- // TODO: Figure out why the RockChip SD fails occasionally and needs to be
- // slowed down here.
- //
- if (ClockSpeed > SdClock25MHz) {
- ClockSpeed = SdClock25MHz;
- }
- if (Device->FundamentalClock == 0) {
- return STATUS_INVALID_CONFIGURATION;
- }
- Frequency = HlQueryTimeCounterFrequency();
- //
- // Wait for the card to not be busy.
- //
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcStatus);
- if ((Value & SD_DWC_STATUS_DATA_BUSY) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Disable all clocks.
- //
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockEnable, 0);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Use the 24MHz clock if a really slow speed is desired.
- //
- InputClock = Device->FundamentalClock;
- if (ClockSpeed < (InputClock / (RK32_CRU_MAX_MMC_DIVISOR + 1))) {
- //
- // Select the raw 24MHz source, and set the DesignWare divider to 1 to
- // divide by 2.
- //
- InputClock = RK32_SDMMC_FREQUENCY_24MHZ / 2;
- ASSERT(ClockSpeed <= InputClock);
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockDivider, 1);
- Value = (RK32_CRU_CLOCK_SELECT_24MHZ <<
- RK32_CRU_CLOCK_SELECT_CLOCK_SHIFT);
- //
- // Use the general PLL.
- //
- } else {
- SD_DWC_WRITE_REGISTER(Device, SdDwcClockDivider, 0);
- Value = (RK32_CRU_CLOCK_SELECT_GENERAL_PLL <<
- RK32_CRU_CLOCK_SELECT_CLOCK_SHIFT);
- }
- Divisor = InputClock / ClockSpeed;
- if (InputClock / Divisor > ClockSpeed) {
- Divisor += 1;
- }
- ASSERT(Divisor <= RK32_CRU_MAX_MMC_DIVISOR);
- //
- // Bits 16 and up must be set for the write to take effect. This is also
- // why read-modify-write is not needed.
- //
- Value |= (RK32_CRU_CLOCK_SELECT_CLOCK_MASK |
- RK32_CRU_CLOCK_SELECT_DIVIDER_MASK) <<
- RK32_CRU_CLOCK_SELECT_PROTECT_SHIFT;
- Value |= Divisor;
- Value <<= Device->VendorData->ClockSelectShift;
- SD_RK32_WRITE_CRU(Device, Device->VendorData->ClockSelectOffset, Value);
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcClockSource,
- SD_DWC_CLOCK_SOURCE_DIVIDER_0);
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Enable the clocks in lower power mode.
- //
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcClockEnable,
- (SD_DWC_CLOCK_ENABLE_LOW_POWER |
- SD_DWC_CLOCK_ENABLE_ON));
- Status = SdRk32UpdateClock(Device);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_SUCCESS;
- }
- VOID
- SdRk32SetDmaInterrupts (
- PSD_CONTROLLER Controller,
- PSD_RK32_CONTEXT Device,
- BOOL Enable,
- ULONG BufferSize
- )
- /*++
- Routine Description:
- This routine enables or disables interrupts necessary to perform block I/O
- via DMA. It is assumed that the caller has synchronized disk access on this
- controller and there are currently no DMA or polled operations in flight.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Device - Supplies a pointer to the RK32xx SD device context.
- Enable - Supplies a boolean indicating if the DMA interrupts are to be
- enabled (TRUE) or disabled (FALSE).
- BufferSize - Supplies the length of the DMA buffer.
- Return Value:
- None.
- --*/
- {
- ULONG Value;
- //
- // Enable the interrupts for transfer completion so that DMA operations
- // can complete asynchronously. Unless, of course, the DMA interrupts are
- // already enabled.
- //
- if (Enable != FALSE) {
- Value = Controller->EnabledInterrupts | SD_DWC_INTERRUPT_ERROR_MASK;
- Value &= ~(SD_DWC_INTERRUPT_MASK_DATA_TRANSFER_OVER |
- SD_DWC_INTERRUPT_MASK_COMMAND_DONE);
- if (BufferSize != 0) {
- Value |= SD_DWC_INTERRUPT_MASK_DATA_TRANSFER_OVER;
- } else {
- Value |= SD_DWC_INTERRUPT_MASK_COMMAND_DONE;
- }
- //
- // Disable the DMA interrupts so that they do not interfere with polled I/O
- // attempts to check the transfer status. Do nothing if the DMA interrupts
- // are disabled.
- //
- } else {
- Value = Controller->EnabledInterrupts &
- ~(SD_DWC_INTERRUPT_MASK_DATA_TRANSFER_OVER |
- SD_DWC_INTERRUPT_MASK_COMMAND_DONE |
- SD_DWC_INTERRUPT_ERROR_MASK);
- }
- if (Value != Controller->EnabledInterrupts) {
- Controller->EnabledInterrupts = Value;
- SD_DWC_WRITE_REGISTER(Device,
- SdDwcInterruptMask,
- Controller->EnabledInterrupts);
- }
- return;
- }
- KSTATUS
- SdRk32UpdateClock (
- PSD_RK32_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine performs a clock update, activating the configuration when
- the clock divisor, enable, or source registers are changed.
- Arguments:
- Device - Supplies a pointer to this SD RK32xx device.
- Return Value:
- Status code.
- --*/
- {
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Value = SD_DWC_COMMAND_START |
- SD_DWC_COMMAND_UPDATE_CLOCK_REGISTERS |
- SD_DWC_COMMAND_WAIT_PREVIOUS_DATA_COMPLETE;
- if (Device->InVoltageSwitch != FALSE) {
- Value |= SD_DWC_COMMAND_VOLT_SWITCH;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcCommand, Value);
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() +
- (HlQueryTimeCounterFrequency() * SD_RK32_TIMEOUT);
- do {
- Value = SD_DWC_READ_REGISTER(Device, SdDwcCommand);
- if ((Value & SD_DWC_COMMAND_START) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return Status;
- }
- VOID
- SdRk32Rk808InterfaceNotificationCallback (
- PVOID Context,
- PDEVICE Device,
- PVOID InterfaceBuffer,
- ULONG InterfaceBufferSize,
- BOOL Arrival
- )
- /*++
- Routine Description:
- This routine is called to notify listeners that an RK808 interface has
- arrived or departed.
- Arguments:
- Context - Supplies the caller's context pointer, supplied when the caller
- requested interface notifications.
- Device - Supplies a pointer to the device exposing or deleting the
- interface.
- InterfaceBuffer - Supplies a pointer to the interface buffer of the
- interface.
- InterfaceBufferSize - Supplies the buffer size.
- Arrival - Supplies TRUE if a new interface is arriving, or FALSE if an
- interface is departing.
- Return Value:
- None.
- --*/
- {
- PSD_RK32_CONTEXT SdDevice;
- SdDevice = Context;
- if (InterfaceBufferSize == sizeof(INTERFACE_RK808)) {
- if (Arrival != FALSE) {
- ASSERT(SdDevice->Rk808 == NULL);
- SdDevice->Rk808 = InterfaceBuffer;
- } else {
- SdDevice->Rk808 = NULL;
- }
- }
- return;
- }
- KSTATUS
- SdRk32SetRegulatorVoltage (
- PSD_RK32_CONTEXT Device,
- BOOL LowVoltage
- )
- /*++
- Routine Description:
- This routine sets the regulator voltage of the SD bus pins.
- Arguments:
- Device - Supplies a pointer to the device context.
- LowVoltage - Supplies a boolean indicating whether to set the bus voltage
- to 1.8V (TRUE) or 3.3V (FALSE).
- Return Value:
- Status code.
- --*/
- {
- RK808_LDO_CONFIGURATION Configuration;
- KSTATUS Status;
- ULONG Value;
- if ((Device->Ldo != 0) && (Device->Rk808 != NULL)) {
- RtlZeroMemory(&Configuration, sizeof(RK808_LDO_CONFIGURATION));
- Configuration.Flags = RK808_LDO_ENABLED | RK808_LDO_OFF_IN_SLEEP;
- Configuration.ActiveVoltage = 3300;
- if (LowVoltage != FALSE) {
- Configuration.ActiveVoltage = 1800;
- }
- Status = Device->Rk808->SetLdo(Device->Rk808,
- Device->Ldo,
- &Configuration);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- }
- Value = SD_DWC_READ_REGISTER(Device, SdDwcUhs);
- if (LowVoltage != FALSE) {
- Value |= SD_DWC_UHS_VOLTAGE_1V8;
- } else {
- Value = 0;
- }
- SD_DWC_WRITE_REGISTER(Device, SdDwcUhs, Value);
- return Status;
- }
|