dwhcihc.c 147 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dwhcihc.c
  5. Abstract:
  6. This module implements support for the DesignWare Hi-Speed USB 2.O
  7. On-The-Go (HS OTG) Host Controller.
  8. Copyright (C) 2004-2013 by Synopsis, Inc.
  9. Redistribution and use in source and binary forms, with or without
  10. modification, are permitted provided that the following conditions are met:
  11. 1. Redistributions of source code must retain the above copyright notice,
  12. this list of conditions, and the following disclaimer, without
  13. modification.
  14. 2. Redistributions in binary form must reproduce the above copyright
  15. notice, this list of conditions and the following disclaimer in the
  16. documentation and/or other materials provided with the distribution.
  17. 3. The names of the above-listed copyright holders may not be used to
  18. endorse or promote products derived from this software without specific
  19. prior written permission.
  20. This software is provided by the copyright holders and contributors "AS IS"
  21. and any express or implied warranties, including, by not limited to, the
  22. implied warranties or mechantability and fitness for a particular purpose
  23. are disclained. In no event shall the copyright owner or contributors be
  24. liable for any direct, indirect, incidental, special, exemplary, or
  25. consequential damages (including, but not limited to, procurement of
  26. substitue goods or services; loss of use, data, or profits; or business
  27. interruption) however caused and on any theory of liability, whether in
  28. contract, strict liability, or tort (including negligence or otherwise)
  29. arising in any way out of the use of this software, even if advised of the
  30. possibility of such damage.
  31. Author:
  32. Chris Stevens 38-Mar-2014
  33. Environment:
  34. Kernel
  35. --*/
  36. //
  37. // ------------------------------------------------------------------- Includes
  38. //
  39. #include <minoca/kernel/driver.h>
  40. #include <minoca/usb/usbhost.h>
  41. #include "dwhci.h"
  42. //
  43. // --------------------------------------------------------------------- Macros
  44. //
  45. //
  46. // These macros read from and write to a DWHCI host controller register. The
  47. // first argument is a PDWHCI_CONTROLLER, the second is a DWHCI_REGISTER. The
  48. // value on write is a ULONG.
  49. //
  50. #define DWHCI_READ_REGISTER(_Controller, _Register) \
  51. HlReadRegister32((_Controller)->RegisterBase + _Register)
  52. #define DWHCI_WRITE_REGISTER(_Controller, _Register, _Value) \
  53. HlWriteRegister32((_Controller)->RegisterBase + _Register, _Value)
  54. //
  55. // These macros read from and write to a DWHCI channel register. The first
  56. // argument is a PDWHCI_CONTROLLER, the second is a DWHCI_CHANNEL_REGISTER and
  57. // the third is a ULONG for the channel index. The value on write is a ULONG.
  58. //
  59. #define DWHCI_READ_CHANNEL_REGISTER(_Controller, _Register, _Channel) \
  60. HlReadRegister32((_Controller)->RegisterBase + \
  61. DwhciRegisterChannelBase + \
  62. (DwhciChannelRegistersSize * _Channel) + \
  63. _Register)
  64. #define DWHCI_WRITE_CHANNEL_REGISTER(_Controller, _Register, _Channel, _Value) \
  65. HlWriteRegister32(((_Controller)->RegisterBase + \
  66. DwhciRegisterChannelBase + \
  67. (DwhciChannelRegistersSize * _Channel) + \
  68. _Register), \
  69. _Value)
  70. //
  71. // This macro reads the frame number.
  72. //
  73. #define DWHCI_READ_FRAME_NUMBER(_Controller) \
  74. (((DWHCI_READ_REGISTER((_Controller), DwhciRegisterFrameNumber) & \
  75. DWHCI_FRAME_NUMBER_MASK) >> \
  76. DWHCI_FRAME_NUMBER_SHIFT) & \
  77. DWHCI_FRAME_NUMBER_MAX)
  78. //
  79. // This macro evaluates whether two frame numbers are in descending order,
  80. // taking wrapping into account.
  81. //
  82. #define DWHCI_FRAME_GREATER_THAN_OR_EQUAL(_Frame1, _Frame2) \
  83. (((((_Frame1) - (_Frame2)) & DWHCI_FRAME_NUMBER_MAX) & \
  84. DWHCI_FRAME_NUMBER_HIGH_BIT) == 0)
  85. //
  86. // This macro evaluates whether two frame numbers are in ascending order,
  87. // taking wrapping into account.
  88. //
  89. #define DWHCI_FRAME_LESS_THAN(_Frame1, _Frame2) \
  90. (((((_Frame1) - (_Frame2)) & DWHCI_FRAME_NUMBER_MAX) & \
  91. DWHCI_FRAME_NUMBER_HIGH_BIT) != 0)
  92. //
  93. // ---------------------------------------------------------------- Definitions
  94. //
  95. //
  96. // Define the maximum number of channels that can exist in the host controller.
  97. //
  98. #define DWHCI_MAX_CHANNELS 16
  99. //
  100. // Define the default start frame offset for periodic transfers
  101. //
  102. #define DWHCI_DEFAULT_FRAME_OFFSET 15
  103. //
  104. // Define the maximum number of errors allowed on a split transfer.
  105. //
  106. #define DWHCI_SPLIT_ERROR_MAX 3
  107. //
  108. // Define the maximum number of complete splits allowed.
  109. //
  110. #define DWHCI_COMPLETE_SPLIT_MAX 3
  111. //
  112. // Define the mask to OR onto each interrupt split's next frame.
  113. //
  114. #define DWHCI_INTERRUPT_SPLIT_FRAME_MASK 0x7
  115. //
  116. // Define the number of microframes per frame.
  117. //
  118. #define DWHCI_MICROFRAMES_PER_FRAME 8
  119. #define DWHCI_MICROFRAMES_PER_FRAME_SHIFT 3
  120. //
  121. // Define the required alignment for DMA buffers.
  122. //
  123. #define DWHCI_DMA_ALIGNMENT 0x8
  124. //
  125. // Define the size of the control status buffer used as a bit bucket.
  126. //
  127. #define DWHCI_CONTROL_STATUS_BUFFER_SIZE 64
  128. //
  129. // Define the initial set of interrupts that the host controller is interested
  130. // in.
  131. //
  132. #define DWHCI_INITIAL_CORE_INTERRUPT_MASK \
  133. (DWHCI_CORE_INTERRUPT_DISCONNECT | \
  134. DWHCI_CORE_INTERRUPT_PORT | \
  135. DWHCI_CORE_INTERRUPT_HOST_CHANNEL)
  136. //
  137. // Define flags for DWHCI debugging.
  138. //
  139. #define DWHCI_DEBUG_FLAG_PORTS 0x1
  140. #define DWHCI_DEBUG_FLAG_TRANSFERS 0x2
  141. //
  142. // Define the value for an invalid frame.
  143. //
  144. #define DWHCI_INVALID_FRAME 0xFFFF
  145. //
  146. // Define the size of the window in which complete splits must finish, in
  147. // microframes. The start frame is recorded, and the start split actually
  148. // executes in the next microframe (1). Then there is a rest microframe (2),
  149. // followed by three microframes in which the complete split can finish (5).
  150. //
  151. #define DWHCI_SPLIT_NOT_YET_FRAME_WINDOW 5
  152. //
  153. // Define the DWHCI host controller revision that first handled automatic PING
  154. // processing for bulk and control transfers.
  155. //
  156. #define DWHCI_AUTOMATIC_PING_REVISION_MININUM 0x4f54271a
  157. //
  158. // ------------------------------------------------------ Data Type Definitions
  159. //
  160. //
  161. // ----------------------------------------------- Internal Function Prototypes
  162. //
  163. KSTATUS
  164. DwhcipCreateEndpoint (
  165. PVOID HostControllerContext,
  166. PUSB_HOST_ENDPOINT_CREATION_REQUEST Endpoint,
  167. PVOID *EndpointContext
  168. );
  169. VOID
  170. DwhcipResetEndpoint (
  171. PVOID HostControllerContext,
  172. PVOID EndpointContext,
  173. ULONG MaxPacketSize
  174. );
  175. VOID
  176. DwhcipDestroyEndpoint (
  177. PVOID HostControllerContext,
  178. PVOID EndpointContext
  179. );
  180. KSTATUS
  181. DwhcipCreateTransfer (
  182. PVOID HostControllerContext,
  183. PVOID EndpointContext,
  184. ULONG MaxBufferSize,
  185. ULONG Flags,
  186. PVOID *TransferContext
  187. );
  188. VOID
  189. DwhcipDestroyTransfer (
  190. PVOID HostControllerContext,
  191. PVOID EndpointContext,
  192. PVOID TransferContext
  193. );
  194. KSTATUS
  195. DwhcipSubmitTransfer (
  196. PVOID HostControllerContext,
  197. PVOID EndpointContext,
  198. PUSB_TRANSFER_INTERNAL Transfer,
  199. PVOID TransferContext
  200. );
  201. KSTATUS
  202. DwhcipCancelTransfer (
  203. PVOID HostControllerContext,
  204. PVOID EndpointContext,
  205. PUSB_TRANSFER_INTERNAL Transfer,
  206. PVOID TransferContext
  207. );
  208. KSTATUS
  209. DwhcipGetRootHubStatus (
  210. PVOID HostControllerContext,
  211. PUSB_HUB_STATUS HubStatus
  212. );
  213. KSTATUS
  214. DwhcipSetRootHubStatus (
  215. PVOID HostControllerContext,
  216. PUSB_HUB_STATUS NewStatus
  217. );
  218. RUNLEVEL
  219. DwhcipAcquireControllerLock (
  220. PDWHCI_CONTROLLER Controller
  221. );
  222. VOID
  223. DwhcipReleaseControllerLock (
  224. PDWHCI_CONTROLLER Controller,
  225. RUNLEVEL OldRunLevel
  226. );
  227. VOID
  228. DwhcipInterruptServiceDpc (
  229. PDPC Dpc
  230. );
  231. VOID
  232. DwhcipProcessInterrupt (
  233. PVOID Context
  234. );
  235. VOID
  236. DwhcipProcessStartOfFrameInterrupt (
  237. PDWHCI_CONTROLLER Controller
  238. );
  239. VOID
  240. DwhcipSaveChannelInterrupts (
  241. PDWHCI_CONTROLLER Controller
  242. );
  243. VOID
  244. DwhcipProcessChannelInterrupt (
  245. PDWHCI_CONTROLLER Controller,
  246. PULONG ChannelInterruptBits
  247. );
  248. VOID
  249. DwhcipProcessPotentiallyCompletedTransfer (
  250. PDWHCI_CONTROLLER Controller,
  251. PDWHCI_TRANSFER Transfer,
  252. ULONG Interrupts,
  253. PBOOL RemoveSet,
  254. PBOOL AdvanceEndpoint
  255. );
  256. VOID
  257. DwhcipRemoveTransferSet (
  258. PDWHCI_CONTROLLER Controller,
  259. PDWHCI_TRANSFER_SET TransferSet
  260. );
  261. VOID
  262. DwhcipProcessSplitEndpoint (
  263. PDWHCI_CONTROLLER Controller,
  264. PDWHCI_ENDPOINT Endpoint,
  265. PULONG Interrupts
  266. );
  267. VOID
  268. DwhcipProcessPingEndpoint (
  269. PDWHCI_CONTROLLER Controller,
  270. PDWHCI_ENDPOINT Endpoint,
  271. PULONG Interrupts
  272. );
  273. VOID
  274. DwhcipFillOutTransferDescriptor (
  275. PDWHCI_CONTROLLER Controller,
  276. PDWHCI_TRANSFER_SET TransferSet,
  277. PDWHCI_TRANSFER DwhciTransfer,
  278. ULONG Offset,
  279. ULONG Length,
  280. BOOL LastTransfer
  281. );
  282. VOID
  283. DwhcipProcessSchedule (
  284. PDWHCI_CONTROLLER Controller,
  285. BOOL PeriodicOnly
  286. );
  287. KSTATUS
  288. DwhcipAllocateChannel (
  289. PDWHCI_CONTROLLER Controller,
  290. PDWHCI_ENDPOINT Endpoint
  291. );
  292. VOID
  293. DwhcipFreeChannel (
  294. PDWHCI_CONTROLLER Controller,
  295. PDWHCI_CHANNEL Channel
  296. );
  297. VOID
  298. DwhcipScheduleTransfer (
  299. PDWHCI_CONTROLLER Controller,
  300. PDWHCI_ENDPOINT Endpoint
  301. );
  302. VOID
  303. DwhcipAdvanceEndpoint (
  304. PDWHCI_CONTROLLER Controller,
  305. PDWHCI_ENDPOINT Endpoint
  306. );
  307. PDWHCI_TRANSFER
  308. DwhcipGetEndpointTransfer (
  309. PDWHCI_ENDPOINT Endpoint
  310. );
  311. KSTATUS
  312. DwhcipSoftReset (
  313. PDWHCI_CONTROLLER Controller
  314. );
  315. KSTATUS
  316. DwhcipInitializePhy (
  317. PDWHCI_CONTROLLER Controller
  318. );
  319. KSTATUS
  320. DwhcipInitializeUsb (
  321. PDWHCI_CONTROLLER Controller,
  322. ULONG UsbMode
  323. );
  324. KSTATUS
  325. DwhcipInitializeHostMode (
  326. PDWHCI_CONTROLLER Controller,
  327. ULONG ReceiveFifoSize,
  328. ULONG NonPeriodicTransmitFifoSize,
  329. ULONG PeriodicTransmitFifoSize
  330. );
  331. VOID
  332. DwhcipFlushFifo (
  333. PDWHCI_CONTROLLER Controller,
  334. BOOL TransmitFifo,
  335. ULONG TransmitFifoMask
  336. );
  337. KSTATUS
  338. DwhcipResetChannel (
  339. PDWHCI_CONTROLLER Controller,
  340. ULONG ChannelNumber
  341. );
  342. BOOL
  343. DwhcipHaltChannel (
  344. PDWHCI_CONTROLLER Controller,
  345. PDWHCI_CHANNEL Channel
  346. );
  347. //
  348. // -------------------------------------------------------------------- Globals
  349. //
  350. //
  351. // Define a bitfield of debug flags that enable various print messages for
  352. // DWHCI. See DWHCI_DEBUG_* definitions.
  353. //
  354. ULONG DwhciDebugFlags = 0x0;
  355. //
  356. // ------------------------------------------------------------------ Functions
  357. //
  358. PDWHCI_CONTROLLER
  359. DwhcipInitializeControllerState (
  360. PVOID RegisterBase,
  361. ULONG ChannelCount,
  362. USB_DEVICE_SPEED Speed,
  363. ULONG MaxTransferSize,
  364. ULONG MaxPacketCount,
  365. ULONG Revision
  366. )
  367. /*++
  368. Routine Description:
  369. This routine initializes the state and variables needed to start up a DWHCI
  370. host controller.
  371. Arguments:
  372. RegisterBase - Supplies the virtual address of the base of the registers.
  373. ChannelCount - Supplies the number of host controller channels.
  374. Speed - Supplies the speed of the DWHCI host controller.
  375. MaxTransferSize - Supplies the maximum transfer size for the DWHCI host
  376. controller.
  377. MaxPacketCount - Supplies the maximum packet count for the DWHCI host
  378. controller.
  379. Revision - Supplies the revision of the DWHCI host controller.
  380. Return Value:
  381. Returns a pointer to the DWHCI controller state object on success.
  382. NULL on failure.
  383. --*/
  384. {
  385. ULONG AllocationSize;
  386. PDWHCI_CHANNEL Channels;
  387. PDWHCI_CONTROLLER Controller;
  388. ULONG Index;
  389. ULONG IoBufferFlags;
  390. KSTATUS Status;
  391. //
  392. // Allocate the controller structure and fill it in.
  393. //
  394. AllocationSize = sizeof(DWHCI_CONTROLLER) +
  395. ((ChannelCount - 1) * sizeof(DWHCI_CHANNEL));
  396. Controller = MmAllocateNonPagedPool(AllocationSize, DWHCI_ALLOCATION_TAG);
  397. if (Controller == NULL) {
  398. Status = STATUS_INSUFFICIENT_RESOURCES;
  399. goto InitializeControllerStateEnd;
  400. }
  401. RtlZeroMemory(Controller, AllocationSize);
  402. Controller->RegisterBase = RegisterBase;
  403. Controller->UsbCoreHandle = INVALID_HANDLE;
  404. Controller->InterruptHandle = INVALID_HANDLE;
  405. INITIALIZE_LIST_HEAD(&(Controller->PeriodicActiveListHead));
  406. INITIALIZE_LIST_HEAD(&(Controller->PeriodicInactiveListHead));
  407. INITIALIZE_LIST_HEAD(&(Controller->PeriodicReadyListHead));
  408. INITIALIZE_LIST_HEAD(&(Controller->NonPeriodicActiveListHead));
  409. INITIALIZE_LIST_HEAD(&(Controller->NonPeriodicReadyListHead));
  410. INITIALIZE_LIST_HEAD(&(Controller->FreeChannelListHead));
  411. KeInitializeSpinLock(&(Controller->Lock));
  412. KeInitializeSpinLock(&(Controller->InterruptLock));
  413. Controller->PortCount = DWHCI_HOST_PORT_COUNT;
  414. Controller->Revision = Revision;
  415. Controller->Speed = Speed;
  416. Controller->MaxTransferSize = MaxTransferSize;
  417. Controller->MaxPacketCount = MaxPacketCount;
  418. Controller->NextFrame = DWHCI_INVALID_FRAME;
  419. Controller->InterruptDpc = KeCreateDpc(DwhcipInterruptServiceDpc,
  420. Controller);
  421. if (Controller->InterruptDpc == NULL) {
  422. Status = STATUS_INSUFFICIENT_RESOURCES;
  423. goto InitializeControllerStateEnd;
  424. }
  425. Controller->BlockAllocator = MmCreateBlockAllocator(
  426. sizeof(DWHCI_TRANSFER),
  427. DWHCI_BLOCK_ALLOCATOR_ALIGNMENT,
  428. DWHCI_BLOCK_ALLOCATOR_EXPANSION_COUNT,
  429. BLOCK_ALLOCATOR_FLAG_NON_PAGED,
  430. DWHCI_BLOCK_ALLOCATION_TAG);
  431. if (Controller->BlockAllocator == NULL) {
  432. Status = STATUS_INSUFFICIENT_RESOURCES;
  433. goto InitializeControllerStateEnd;
  434. }
  435. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  436. Controller->ControlStatusBuffer = MmAllocateNonPagedIoBuffer(
  437. 0,
  438. MAX_ULONG,
  439. DWHCI_DMA_ALIGNMENT,
  440. DWHCI_CONTROL_STATUS_BUFFER_SIZE,
  441. IoBufferFlags);
  442. if (Controller->ControlStatusBuffer == NULL) {
  443. Status = STATUS_INSUFFICIENT_RESOURCES;
  444. goto InitializeControllerStateEnd;
  445. }
  446. //
  447. // Initialize the channels.
  448. //
  449. Controller->ChannelCount = ChannelCount;
  450. Channels = (PDWHCI_CHANNEL)(Controller->Channel);
  451. for (Index = 0; Index < ChannelCount; Index += 1) {
  452. Channels[Index].ChannelNumber = Index;
  453. }
  454. Status = STATUS_SUCCESS;
  455. InitializeControllerStateEnd:
  456. if (!KSUCCESS(Status)) {
  457. if (Controller != NULL) {
  458. DwhcipDestroyControllerState(Controller);
  459. Controller = NULL;
  460. }
  461. }
  462. return Controller;
  463. }
  464. VOID
  465. DwhcipDestroyControllerState (
  466. PDWHCI_CONTROLLER Controller
  467. )
  468. /*++
  469. Routine Description:
  470. This routine destroys the memory associated with a DWHCI controller.
  471. Arguments:
  472. Controller - Supplies a pointer to the DWHCI controller state to release.
  473. Return Value:
  474. None.
  475. --*/
  476. {
  477. ASSERT(LIST_EMPTY(&(Controller->PeriodicActiveListHead)) != FALSE);
  478. ASSERT(LIST_EMPTY(&(Controller->PeriodicReadyListHead)) != FALSE);
  479. ASSERT(LIST_EMPTY(&(Controller->NonPeriodicActiveListHead)) != FALSE);
  480. ASSERT(LIST_EMPTY(&(Controller->NonPeriodicReadyListHead)) != FALSE);
  481. if (Controller->InterruptDpc != NULL) {
  482. KeDestroyDpc(Controller->InterruptDpc);
  483. }
  484. if (Controller->UsbCoreHandle != INVALID_HANDLE) {
  485. UsbHostDestroyControllerState(Controller->UsbCoreHandle);
  486. }
  487. if (Controller->BlockAllocator != NULL) {
  488. MmDestroyBlockAllocator(Controller->BlockAllocator);
  489. }
  490. if (Controller->ControlStatusBuffer != NULL) {
  491. MmFreeIoBuffer(Controller->ControlStatusBuffer);
  492. }
  493. MmFreeNonPagedPool(Controller);
  494. return;
  495. }
  496. KSTATUS
  497. DwhcipRegisterController (
  498. PDWHCI_CONTROLLER Controller,
  499. PDEVICE Device
  500. )
  501. /*++
  502. Routine Description:
  503. This routine registers the started DWHCI controller with the core USB
  504. library.
  505. Arguments:
  506. Controller - Supplies a pointer to the DWHCI controller state of the
  507. controller to register.
  508. Device - Supplies a pointer to the device object.
  509. Return Value:
  510. Status code.
  511. --*/
  512. {
  513. USB_HOST_CONTROLLER_INTERFACE Interface;
  514. KSTATUS Status;
  515. //
  516. // Fill out the functions that the USB core library will use to control
  517. // the DWHCI controller.
  518. //
  519. RtlZeroMemory(&Interface, sizeof(USB_HOST_CONTROLLER_INTERFACE));
  520. Interface.Version = USB_HOST_CONTROLLER_INTERFACE_VERSION;
  521. Interface.DriverObject = DwhciDriver;
  522. Interface.DeviceObject = Device;
  523. Interface.HostControllerContext = Controller;
  524. Interface.Speed = Controller->Speed;
  525. Interface.DebugPortSubType = -1;
  526. Interface.RootHubPortCount = Controller->PortCount;
  527. Interface.CreateEndpoint = DwhcipCreateEndpoint;
  528. Interface.ResetEndpoint = DwhcipResetEndpoint;
  529. Interface.DestroyEndpoint = DwhcipDestroyEndpoint;
  530. Interface.CreateTransfer = DwhcipCreateTransfer;
  531. Interface.DestroyTransfer = DwhcipDestroyTransfer;
  532. Interface.SubmitTransfer = DwhcipSubmitTransfer;
  533. Interface.CancelTransfer = DwhcipCancelTransfer;
  534. Interface.GetRootHubStatus = DwhcipGetRootHubStatus;
  535. Interface.SetRootHubStatus = DwhcipSetRootHubStatus;
  536. Status = UsbHostRegisterController(&Interface,
  537. &(Controller->UsbCoreHandle));
  538. if (!KSUCCESS(Status)) {
  539. goto RegisterControllerEnd;
  540. }
  541. RegisterControllerEnd:
  542. return Status;
  543. }
  544. KSTATUS
  545. DwhcipInitializeController (
  546. PDWHCI_CONTROLLER Controller
  547. )
  548. /*++
  549. Routine Description:
  550. This routine initializes and starts the DWHCI controller.
  551. Arguments:
  552. Controller - Supplies a pointer to the DWHCI controller state of the
  553. controller to reset.
  554. Return Value:
  555. Status code.
  556. --*/
  557. {
  558. ULONG AhbConfiguration;
  559. ULONG BurstLength;
  560. ULONG CoreInterruptMask;
  561. ULONG Hardware2;
  562. ULONG Hardware4;
  563. ULONG HostConfiguration;
  564. ULONG NonPeriodicTransmitFifoSize;
  565. ULONG PeriodicTransmitFifoSize;
  566. ULONG ReceiveFifoSize;
  567. KSTATUS Status;
  568. ULONG UsbCapabilities;
  569. ULONG UsbConfiguration;
  570. //
  571. // Before resetting the controller, save the FIFO sizes that may have been
  572. // programmed by ACPI. The reset will undo any of the work done by ACPI.
  573. //
  574. ReceiveFifoSize = DWHCI_READ_REGISTER(Controller,
  575. DwhciRegisterReceiveFifoSize);
  576. NonPeriodicTransmitFifoSize = DWHCI_READ_REGISTER(
  577. Controller,
  578. DwhciRegisterNonPeriodicFifoSize);
  579. PeriodicTransmitFifoSize = DWHCI_READ_REGISTER(
  580. Controller,
  581. DwhciRegisterPeriodicFifoSize);
  582. //
  583. // Save the burst length configured by ACPI in the AHB register and disable
  584. // global interrupts.
  585. //
  586. AhbConfiguration = DWHCI_READ_REGISTER(Controller,
  587. DwhciRegisterAhbConfiguration);
  588. BurstLength = (AhbConfiguration &
  589. DWHCI_AHB_CONFIGURATION_AXI_BURST_LENGTH_MASK);
  590. AhbConfiguration &= ~DWHCI_AHB_CONFIGURATION_INTERRUPT_ENABLE;
  591. DWHCI_WRITE_REGISTER(Controller,
  592. DwhciRegisterAhbConfiguration,
  593. AhbConfiguration);
  594. //
  595. // Clear the ULPI External VBUS and TS D-LINE pulse enable bits.
  596. //
  597. UsbConfiguration = DWHCI_READ_REGISTER(Controller,
  598. DwhciRegisterUsbConfiguration);
  599. //
  600. // Save the USB capability bits in the USB configuration register. These do
  601. // not always agree with the mode set in the hardware 2 register.
  602. //
  603. UsbCapabilities = UsbConfiguration & (DWHCI_USB_CONFIGURATION_SRP_CAPABLE |
  604. DWHCI_USB_CONFIGURATION_HNP_CAPABLE);
  605. UsbConfiguration &= ~DWHCI_USB_CONFIGURATION_ULPI_DRIVER_EXTERNAL_VBUS;
  606. UsbConfiguration &= ~DWHCI_USB_CONFIGURATION_TS_DLINE_PULSE_ENABLE;
  607. DWHCI_WRITE_REGISTER(Controller,
  608. DwhciRegisterUsbConfiguration,
  609. UsbConfiguration);
  610. //
  611. // Perform a soft reset of the DWHCI core.
  612. //
  613. Status = DwhcipSoftReset(Controller);
  614. if (!KSUCCESS(Status)) {
  615. goto InitializeControllerEnd;
  616. }
  617. //
  618. // Initialize the physical layer.
  619. //
  620. Status = DwhcipInitializePhy(Controller);
  621. if (!KSUCCESS(Status)) {
  622. goto InitializeControllerEnd;
  623. }
  624. //
  625. // The host controller driver currently only supports internal DMA modes.
  626. //
  627. Hardware2 = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware2);
  628. if ((Hardware2 & DWHCI_HARDWARE2_ARCHITECTURE_MASK) !=
  629. DWHCI_HARDWARE2_ARCHITECTURE_INTERNAL_DMA) {
  630. Status = STATUS_NOT_SUPPORTED;
  631. goto InitializeControllerEnd;
  632. }
  633. //
  634. // The controller currently only supports non-descriptor DMA mode.
  635. //
  636. Hardware4 = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware4);
  637. if ((Hardware4 & DWHCI_HARDWARE4_DMA_DESCRIPTOR_MODE) != 0) {
  638. HostConfiguration = DWHCI_READ_REGISTER(Controller,
  639. DwhciRegisterHostConfiguration);
  640. HostConfiguration &= ~DWHCI_HOST_CONFIGURATION_ENABLE_DMA_DESCRIPTOR;
  641. DWHCI_WRITE_REGISTER(Controller,
  642. DwhciRegisterHostConfiguration,
  643. HostConfiguration);
  644. }
  645. //
  646. // Enable DMA mode.
  647. //
  648. AhbConfiguration = DWHCI_READ_REGISTER(Controller,
  649. DwhciRegisterAhbConfiguration);
  650. AhbConfiguration |= DWHCI_AHB_CONFIGURATION_DMA_ENABLE;
  651. AhbConfiguration &= ~DWHCI_AHB_CONFIGURATION_DMA_REMAINDER_MODE_MASK;
  652. AhbConfiguration |= DWHCI_AHB_CONFIGURATION_DMA_REMAINDER_MODE_INCREMENTAL;
  653. AhbConfiguration |= BurstLength;
  654. DWHCI_WRITE_REGISTER(Controller,
  655. DwhciRegisterAhbConfiguration,
  656. AhbConfiguration);
  657. //
  658. // Perform the necessary steps to initialize the USB configuration.
  659. //
  660. Status = DwhcipInitializeUsb(Controller, UsbCapabilities);
  661. if (!KSUCCESS(Status)) {
  662. goto InitializeControllerEnd;
  663. }
  664. //
  665. // The DWHCI can operate in one of two modes. Host mode or device mode.
  666. // Configure the controller to run in host mode.
  667. //
  668. Status = DwhcipInitializeHostMode(Controller,
  669. ReceiveFifoSize,
  670. NonPeriodicTransmitFifoSize,
  671. PeriodicTransmitFifoSize);
  672. if (!KSUCCESS(Status)) {
  673. goto InitializeControllerEnd;
  674. }
  675. //
  676. // Enable interrupts for the core and channels. Do not enable global
  677. // interrupts until the interrupt handle is initialized.
  678. //
  679. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterOtgInterrupt, 0xFFFFFFFF);
  680. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterCoreInterrupt, 0xFFFFFFFF);
  681. CoreInterruptMask = DWHCI_INITIAL_CORE_INTERRUPT_MASK;
  682. DWHCI_WRITE_REGISTER(Controller,
  683. DwhciRegisterCoreInterruptMask,
  684. CoreInterruptMask);
  685. //
  686. // Re-enable the global interrupts.
  687. //
  688. AhbConfiguration = DWHCI_READ_REGISTER(Controller,
  689. DwhciRegisterAhbConfiguration);
  690. AhbConfiguration |= DWHCI_AHB_CONFIGURATION_INTERRUPT_ENABLE;
  691. DWHCI_WRITE_REGISTER(Controller,
  692. DwhciRegisterAhbConfiguration,
  693. AhbConfiguration);
  694. InitializeControllerEnd:
  695. return Status;
  696. }
  697. INTERRUPT_STATUS
  698. DwhcipInterruptService (
  699. PVOID Context
  700. )
  701. /*++
  702. Routine Description:
  703. This routine implements the DWHCI interrupt service routine.
  704. Arguments:
  705. Context - Supplies the context pointer given to the system when the
  706. interrupt was connected. In this case, this points to the DWHCI
  707. controller.
  708. Return Value:
  709. Interrupt status.
  710. --*/
  711. {
  712. PDWHCI_CONTROLLER Controller;
  713. ULONG FrameNumber;
  714. ULONG Interrupts;
  715. ULONG InterruptsMask;
  716. INTERRUPT_STATUS InterruptStatus;
  717. ULONG OriginalInterrupts;
  718. ULONG OriginalPendingInterrupts;
  719. ULONG PortInterrupts;
  720. Controller = (PDWHCI_CONTROLLER)Context;
  721. InterruptStatus = InterruptStatusNotClaimed;
  722. //
  723. // Read the interrupt register. If there are interesting interrupts, then
  724. // handle them.
  725. //
  726. Interrupts = DWHCI_READ_REGISTER(Controller, DwhciRegisterCoreInterrupt);
  727. InterruptsMask = DWHCI_READ_REGISTER(Controller,
  728. DwhciRegisterCoreInterruptMask);
  729. Interrupts &= InterruptsMask;
  730. if (Interrupts != 0) {
  731. OriginalInterrupts = Interrupts;
  732. PortInterrupts = 0;
  733. InterruptStatus = InterruptStatusClaimed;
  734. KeAcquireSpinLock(&(Controller->InterruptLock));
  735. //
  736. // In order to clear the core host port interrupt, the host port
  737. // interrupt status must read and cleared.
  738. //
  739. if ((Interrupts & DWHCI_CORE_INTERRUPT_PORT) != 0) {
  740. PortInterrupts = DWHCI_READ_REGISTER(Controller,
  741. DwhciRegisterHostPort);
  742. //
  743. // If none of the change bits are set, then ignore this host port
  744. // interrupt.
  745. //
  746. if ((PortInterrupts & DWHCI_HOST_PORT_INTERRUPT_MASK) == 0) {
  747. Interrupts &= ~DWHCI_CORE_INTERRUPT_PORT;
  748. PortInterrupts = 0;
  749. } else {
  750. PortInterrupts = (PortInterrupts &
  751. ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK) |
  752. (PortInterrupts &
  753. DWHCI_HOST_PORT_INTERRUPT_MASK);
  754. }
  755. }
  756. //
  757. // If there is a channel interrupt, then each channel's interrupt bits
  758. // needs to be saved and cleared in order to clear the core interrupt.
  759. //
  760. if ((Interrupts & DWHCI_CORE_INTERRUPT_HOST_CHANNEL) != 0) {
  761. DwhcipSaveChannelInterrupts(Controller);
  762. }
  763. //
  764. // On start of frame interrupts, check the current frame against the
  765. // next targeted start of frame. If it is less, then skip this start of
  766. // frame interrupt.
  767. //
  768. if ((Interrupts & DWHCI_CORE_INTERRUPT_START_OF_FRAME) != 0) {
  769. FrameNumber = DWHCI_READ_FRAME_NUMBER(Controller);
  770. if ((Controller->NextFrame == DWHCI_INVALID_FRAME) ||
  771. DWHCI_FRAME_LESS_THAN(FrameNumber, Controller->NextFrame)) {
  772. Interrupts &= ~DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  773. }
  774. }
  775. //
  776. // If there were no pending interrupts to begin with and there are
  777. // interrupts left to process, then a DPC needs to be queued to process
  778. // these interrupts.
  779. //
  780. OriginalPendingInterrupts = Controller->PendingInterruptBits;
  781. Controller->PendingInterruptBits |= Interrupts;
  782. if ((OriginalPendingInterrupts == 0) && (Interrupts != 0)) {
  783. KeQueueDpc(Controller->InterruptDpc);
  784. }
  785. //
  786. // The host port register needs to be cleared of any change bits in
  787. // order to remove the core host port interrupt.
  788. //
  789. if (PortInterrupts != 0) {
  790. DWHCI_WRITE_REGISTER(Controller,
  791. DwhciRegisterHostPort,
  792. PortInterrupts);
  793. }
  794. //
  795. // Clear the bits in the core interrupt register to acknowledge the
  796. // interrupts.
  797. //
  798. DWHCI_WRITE_REGISTER(Controller,
  799. DwhciRegisterCoreInterrupt,
  800. OriginalInterrupts);
  801. KeReleaseSpinLock(&(Controller->InterruptLock));
  802. }
  803. return InterruptStatus;
  804. }
  805. VOID
  806. DwhcipSetInterruptHandle (
  807. PDWHCI_CONTROLLER Controller,
  808. HANDLE InterruptHandle
  809. )
  810. /*++
  811. Routine Description:
  812. This routine saves the handle of the connected interrupt in the DWHCI
  813. controller.
  814. Arguments:
  815. Controller - Supplies a pointer to the DWHCI controller state.
  816. InterruptHandle - Supplies the connected interrupt handle.
  817. Return Value:
  818. None.
  819. --*/
  820. {
  821. Controller->InterruptHandle = InterruptHandle;
  822. return;
  823. }
  824. //
  825. // --------------------------------------------------------- Internal Functions
  826. //
  827. KSTATUS
  828. DwhcipCreateEndpoint (
  829. PVOID HostControllerContext,
  830. PUSB_HOST_ENDPOINT_CREATION_REQUEST Endpoint,
  831. PVOID *EndpointContext
  832. )
  833. /*++
  834. Routine Description:
  835. This routine is called by the USB core when a new endpoint is being opened.
  836. It allows the host controller to create and store any context needed to
  837. support a new endpoint (such as a queue head).
  838. Arguments:
  839. HostControllerContext - Supplies the context pointer passed to the USB core
  840. when the controller was created. This is used to identify the USB host
  841. controller to the host controller driver.
  842. Endpoint - Supplies a pointer containing information about the endpoint
  843. being created. The host controller cannot count on this buffer sticking
  844. around after the function returns. If it needs this information it
  845. should make a copy of it.
  846. EndpointContext - Supplies a pointer where the host controller can store a
  847. context pointer identifying the endpoint created.
  848. Return Value:
  849. STATUS_SUCCESS if the endpoint can be successfully accommodated.
  850. Failing status code if the endpoint cannot be opened.
  851. --*/
  852. {
  853. ULONG ChannelControl;
  854. PDWHCI_CONTROLLER Controller;
  855. ULONG HubAddress;
  856. PDWHCI_ENDPOINT NewEndpoint;
  857. ULONG PortAddress;
  858. KSTATUS Status;
  859. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  860. NewEndpoint = MmAllocateNonPagedPool(sizeof(DWHCI_ENDPOINT),
  861. DWHCI_ALLOCATION_TAG);
  862. if (NewEndpoint == NULL) {
  863. Status = STATUS_INSUFFICIENT_RESOURCES;
  864. goto CreateEndpointEnd;
  865. }
  866. RtlZeroMemory(NewEndpoint, sizeof(DWHCI_ENDPOINT));
  867. INITIALIZE_LIST_HEAD(&(NewEndpoint->TransferSetListHead));
  868. NewEndpoint->TransferType = Endpoint->Type;
  869. //
  870. // The endpoint speed better be appropriate for the controller.
  871. //
  872. ASSERT((Controller->Speed != UsbDeviceSpeedHigh) ||
  873. ((Endpoint->Speed == UsbDeviceSpeedLow) ||
  874. (Endpoint->Speed == UsbDeviceSpeedFull) ||
  875. (Endpoint->Speed == UsbDeviceSpeedHigh)));
  876. ASSERT((Controller->Speed != UsbDeviceSpeedFull) ||
  877. ((Endpoint->Speed == UsbDeviceSpeedLow) ||
  878. (Endpoint->Speed == UsbDeviceSpeedFull)));
  879. NewEndpoint->Speed = Endpoint->Speed;
  880. NewEndpoint->DataToggle = DWHCI_PID_CODE_DATA_0;
  881. NewEndpoint->PollRate = Endpoint->PollRate;
  882. ASSERT(Endpoint->MaxPacketSize != 0);
  883. //
  884. // If the endpoint is a full or low speed endpoint, then the poll rate is
  885. // in milliseconds. But if the controller is high speed, it operates in 125
  886. // microsecond frames. Do the conversion - multiply by 8.
  887. //
  888. if ((Controller->Speed == UsbDeviceSpeedHigh) &&
  889. ((NewEndpoint->Speed == UsbDeviceSpeedLow) ||
  890. (NewEndpoint->Speed == UsbDeviceSpeedFull))) {
  891. NewEndpoint->PollRate <<= DWHCI_MICROFRAMES_PER_FRAME_SHIFT;
  892. NewEndpoint->PollRate &= DWHCI_FRAME_NUMBER_MAX;
  893. }
  894. //
  895. // If this is a high speed bulk OUT endpoint, then always start with the
  896. // PING protocol.
  897. //
  898. NewEndpoint->PingRequired = FALSE;
  899. if ((Endpoint->Type == UsbTransferTypeBulk) &&
  900. (Endpoint->Speed == UsbDeviceSpeedHigh) &&
  901. (Endpoint->Direction == UsbTransferDirectionOut)) {
  902. NewEndpoint->PingRequired = TRUE;
  903. }
  904. //
  905. // If this is a low or full speed endpoint on a high speed controller, then
  906. // initialize the split control with the hub port and hub address.
  907. //
  908. ASSERT(NewEndpoint->SplitControl == 0);
  909. if ((Controller->Speed == UsbDeviceSpeedHigh) &&
  910. (Endpoint->HubAddress != 0) &&
  911. ((NewEndpoint->Speed == UsbDeviceSpeedLow) ||
  912. (NewEndpoint->Speed == UsbDeviceSpeedFull))) {
  913. ASSERT(Endpoint->HubPortNumber != 0);
  914. PortAddress = (Endpoint->HubPortNumber <<
  915. DWHCI_CHANNEL_SPLIT_CONTROL_PORT_ADDRESS_SHIFT) &
  916. DWHCI_CHANNEL_SPLIT_CONTROL_PORT_ADDRESS_MASK;
  917. HubAddress = (Endpoint->HubAddress <<
  918. DWHCI_CHANNEL_SPLIT_CONTROL_HUB_ADDRESS_SHIFT) &
  919. DWHCI_CHANNEL_SPLIT_CONTROL_HUB_ADDRESS_MASK;
  920. NewEndpoint->SplitControl = PortAddress | HubAddress;
  921. //
  922. // TODO: The isochronous split schedule should be more precise.
  923. //
  924. NewEndpoint->SplitControl |= DWHCI_CHANNEL_SPLIT_CONTROL_POSITION_ALL;
  925. NewEndpoint->SplitControl |= DWHCI_CHANNEL_SPLIT_CONTROL_ENABLE;
  926. }
  927. NewEndpoint->MaxPacketSize = Endpoint->MaxPacketSize;
  928. NewEndpoint->EndpointNumber = Endpoint->EndpointNumber;
  929. //
  930. // Save the maximum number of packets that can be sent over this endpoint
  931. // in a single transfer and the maximum size of each transfer.
  932. //
  933. NewEndpoint->MaxPacketCount = Controller->MaxTransferSize /
  934. NewEndpoint->MaxPacketSize;
  935. if (NewEndpoint->MaxPacketCount > Controller->MaxPacketCount) {
  936. NewEndpoint->MaxPacketCount = Controller->MaxPacketCount;
  937. }
  938. NewEndpoint->MaxTransferSize = NewEndpoint->MaxPacketCount *
  939. NewEndpoint->MaxPacketSize;
  940. ASSERT(NewEndpoint->MaxPacketCount <= DWHCI_MAX_PACKET_COUNT);
  941. ASSERT(NewEndpoint->MaxTransferSize <= DWHCI_MAX_TRANSFER_SIZE);
  942. //
  943. // High-bandwidth multiple count packets are not supported.
  944. //
  945. ASSERT((NewEndpoint->MaxPacketSize &
  946. ~DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_MASK) == 0);
  947. //
  948. // Initialize the endpoints's channel control.
  949. //
  950. ChannelControl = (NewEndpoint->EndpointNumber <<
  951. DWHCI_CHANNEL_CONTROL_ENDPOINT_SHIFT) &
  952. DWHCI_CHANNEL_CONTROL_ENDPOINT_MASK;
  953. ChannelControl |= (NewEndpoint->MaxPacketSize <<
  954. DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_SHIFT) &
  955. DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_MASK;
  956. switch (NewEndpoint->TransferType) {
  957. case UsbTransferTypeControl:
  958. ChannelControl |= DWHCI_CHANNEL_CONTROL_ENDPOINT_CONTROL;
  959. break;
  960. case UsbTransferTypeInterrupt:
  961. ChannelControl |= DWHCI_CHANNEL_CONTROL_ENDPOINT_INTERRUPT;
  962. break;
  963. case UsbTransferTypeBulk:
  964. ChannelControl |= DWHCI_CHANNEL_CONTROL_ENDPOINT_BULK;
  965. break;
  966. case UsbTransferTypeIsochronous:
  967. ChannelControl |= DWHCI_CHANNEL_CONTROL_ENDPOINT_ISOCHRONOUS;
  968. break;
  969. default:
  970. ASSERT(FALSE);
  971. break;
  972. }
  973. if (NewEndpoint->Speed == UsbDeviceSpeedLow) {
  974. ChannelControl |= DWHCI_CHANNEL_CONTROL_LOW_SPEED;
  975. }
  976. ChannelControl |= (0x1 << DWHCI_CHANNEL_CONTROL_PACKETS_PER_FRAME_SHIFT) &
  977. DWHCI_CHANNEL_CONTROL_PACKETS_PER_FRAME_MASK;
  978. ChannelControl |= DWHCI_CHANNEL_CONTROL_ENABLE;
  979. ASSERT((ChannelControl & DWHCI_CHANNEL_CONTROL_DISABLE) == 0);
  980. NewEndpoint->ChannelControl = ChannelControl;
  981. Status = STATUS_SUCCESS;
  982. CreateEndpointEnd:
  983. if (!KSUCCESS(Status)) {
  984. if (NewEndpoint != NULL) {
  985. MmFreeNonPagedPool(NewEndpoint);
  986. NewEndpoint = NULL;
  987. }
  988. }
  989. *EndpointContext = NewEndpoint;
  990. return Status;
  991. }
  992. VOID
  993. DwhcipResetEndpoint (
  994. PVOID HostControllerContext,
  995. PVOID EndpointContext,
  996. ULONG MaxPacketSize
  997. )
  998. /*++
  999. Routine Description:
  1000. This routine is called by the USB core when an endpoint needs to be reset.
  1001. Arguments:
  1002. HostControllerContext - Supplies the context pointer passed to the USB core
  1003. when the controller was created. This is used to identify the USB host
  1004. controller to the host controller driver.
  1005. EndpointContext - Supplies a pointer to the context returned by the host
  1006. controller when the endpoint was created.
  1007. MaxPacketSize - Supplies the maximum transfer size of the endpoint.
  1008. Return Value:
  1009. None.
  1010. --*/
  1011. {
  1012. ULONG ChannelControl;
  1013. PDWHCI_CONTROLLER Controller;
  1014. PDWHCI_ENDPOINT Endpoint;
  1015. Endpoint = (PDWHCI_ENDPOINT)EndpointContext;
  1016. Endpoint->DataToggle = DWHCI_PID_CODE_DATA_0;
  1017. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1018. if (MaxPacketSize != Endpoint->MaxPacketSize) {
  1019. Endpoint->MaxPacketSize = MaxPacketSize;
  1020. ChannelControl = Endpoint->ChannelControl &
  1021. ~DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_MASK;
  1022. ChannelControl |= (Endpoint->MaxPacketSize <<
  1023. DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_SHIFT) &
  1024. DWHCI_CHANNEL_CONTROL_MAX_PACKET_SIZE_MASK;
  1025. Endpoint->ChannelControl = ChannelControl;
  1026. Endpoint->MaxPacketCount = Controller->MaxTransferSize / MaxPacketSize;
  1027. if (Endpoint->MaxPacketCount > Controller->MaxPacketCount) {
  1028. Endpoint->MaxPacketCount = Controller->MaxPacketCount;
  1029. }
  1030. Endpoint->MaxTransferSize = Endpoint->MaxPacketCount * MaxPacketSize;
  1031. }
  1032. return;
  1033. }
  1034. VOID
  1035. DwhcipDestroyEndpoint (
  1036. PVOID HostControllerContext,
  1037. PVOID EndpointContext
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine tears down and destroys an endpoint created with the endpoint
  1042. creation routine.
  1043. Arguments:
  1044. HostControllerContext - Supplies the context pointer passed to the USB core
  1045. when the controller was created. This is used to identify the USB host
  1046. controller to the host controller driver.
  1047. EndpointContext - Supplies a pointer to the context returned by the host
  1048. controller when the endpoint was created.
  1049. Return Value:
  1050. None.
  1051. --*/
  1052. {
  1053. PDWHCI_ENDPOINT Endpoint;
  1054. Endpoint = (PDWHCI_ENDPOINT)EndpointContext;
  1055. ASSERT(LIST_EMPTY(&(Endpoint->TransferSetListHead)) != FALSE);
  1056. MmFreeNonPagedPool(Endpoint);
  1057. return;
  1058. }
  1059. KSTATUS
  1060. DwhcipCreateTransfer (
  1061. PVOID HostControllerContext,
  1062. PVOID EndpointContext,
  1063. ULONG MaxBufferSize,
  1064. ULONG Flags,
  1065. PVOID *TransferContext
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This routine allocates structures needed for the USB host controller to
  1070. support a transfer.
  1071. Arguments:
  1072. HostControllerContext - Supplies the context pointer passed to the USB core
  1073. when the controller was created. This is used to identify the USB host
  1074. controller to the host controller driver.
  1075. EndpointContext - Supplies a pointer to the host controller's context of
  1076. the endpoint that this transfer will eventually be submitted to.
  1077. MaxBufferSize - Supplies the maximum buffer length, in bytes, of the
  1078. transfer when it is submitted. It is assumed that the host controller
  1079. will set up as many transfer descriptors as are needed to support a
  1080. transfer of this size.
  1081. Flags - Supplies a bitfield of flags regarding the transaction. See
  1082. USB_TRANSFER_FLAG_* definitions.
  1083. TransferContext - Supplies a pointer where the host controller can store a
  1084. context pointer containing any needed structures for the transfer.
  1085. Return Value:
  1086. None.
  1087. --*/
  1088. {
  1089. ULONG AllocationSize;
  1090. PDWHCI_CONTROLLER Controller;
  1091. PDWHCI_ENDPOINT Endpoint;
  1092. BOOL ForceShortTransfer;
  1093. KSTATUS Status;
  1094. PDWHCI_TRANSFER Transfer;
  1095. PDWHCI_TRANSFER *TransferArray;
  1096. ULONG TransferCount;
  1097. ULONG TransferIndex;
  1098. PDWHCI_TRANSFER_SET TransferSet;
  1099. ASSERT(TransferContext != NULL);
  1100. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1101. Endpoint = (PDWHCI_ENDPOINT)EndpointContext;
  1102. TransferArray = NULL;
  1103. ForceShortTransfer = FALSE;
  1104. if ((Flags & USB_TRANSFER_FLAG_FORCE_SHORT_TRANSFER) != 0) {
  1105. ForceShortTransfer = TRUE;
  1106. }
  1107. //
  1108. // Figure out the number of transfers needed. The first 8 bytes of a
  1109. // control transfer (the setup packet) are always on their own. Control
  1110. // transfers also have a status stage at the end.
  1111. //
  1112. TransferCount = 0;
  1113. if (Endpoint->TransferType == UsbTransferTypeControl) {
  1114. ASSERT(MaxBufferSize >= sizeof(USB_SETUP_PACKET));
  1115. MaxBufferSize -= sizeof(USB_SETUP_PACKET);
  1116. //
  1117. // Account for both the setup and status stage here.
  1118. //
  1119. TransferCount += 2;
  1120. }
  1121. //
  1122. // Try to fit as many packets into each transfer as possible. Low speed
  1123. // endpoints on high speed controllers requiring split transfers can only
  1124. // execute one max packet size per transfer.
  1125. //
  1126. if (MaxBufferSize != 0) {
  1127. if (Endpoint->SplitControl == 0) {
  1128. TransferCount += MaxBufferSize / Endpoint->MaxTransferSize;
  1129. if ((MaxBufferSize % Endpoint->MaxTransferSize) != 0) {
  1130. TransferCount += 1;
  1131. }
  1132. } else {
  1133. TransferCount += MaxBufferSize / Endpoint->MaxPacketSize;
  1134. if ((MaxBufferSize % Endpoint->MaxPacketSize) != 0) {
  1135. TransferCount += 1;
  1136. }
  1137. }
  1138. //
  1139. // If this transfer needs to indicate completion with a short packet,
  1140. // make sure another transfer is available. This is only necessary if
  1141. // the last packet might not be a short packet. Unfortunately the
  1142. // terminating zero length packet cannot be added to the end of a
  1143. // multi-packet transfer, so it needs its own.
  1144. //
  1145. if ((ForceShortTransfer != FALSE) &&
  1146. (MaxBufferSize >= Endpoint->MaxPacketSize)) {
  1147. TransferCount += 1;
  1148. }
  1149. //
  1150. // Account for a USB transfer that will only send zero length packets and
  1151. // for control transfers that need to force a zero length packet in the
  1152. // data phase.
  1153. //
  1154. } else if ((ForceShortTransfer != FALSE) ||
  1155. (Endpoint->TransferType != UsbTransferTypeControl)) {
  1156. TransferCount += 1;
  1157. }
  1158. //
  1159. // Allocate the transfer set structure.
  1160. //
  1161. AllocationSize = sizeof(DWHCI_TRANSFER_SET);
  1162. if (TransferCount > 1) {
  1163. AllocationSize += sizeof(PDWHCI_TRANSFER) * (TransferCount - 1);
  1164. }
  1165. TransferSet = MmAllocateNonPagedPool(AllocationSize, DWHCI_ALLOCATION_TAG);
  1166. if (TransferSet == NULL) {
  1167. Status = STATUS_INSUFFICIENT_RESOURCES;
  1168. goto CreateTransferEnd;
  1169. }
  1170. RtlZeroMemory(TransferSet, AllocationSize);
  1171. INITIALIZE_LIST_HEAD(&(TransferSet->TransferListHead));
  1172. TransferSet->TransferCount = TransferCount;
  1173. TransferSet->Endpoint = Endpoint;
  1174. TransferArray = (PDWHCI_TRANSFER *)(TransferSet->Transfer);
  1175. //
  1176. // Create the new transfers.
  1177. //
  1178. for (TransferIndex = 0; TransferIndex < TransferCount; TransferIndex += 1) {
  1179. Transfer = MmAllocateBlock(Controller->BlockAllocator, NULL);
  1180. if (Transfer == NULL) {
  1181. Status = STATUS_INSUFFICIENT_RESOURCES;
  1182. goto CreateTransferEnd;
  1183. }
  1184. RtlZeroMemory(Transfer, sizeof(DWHCI_TRANSFER));
  1185. TransferArray[TransferIndex] = Transfer;
  1186. }
  1187. Status = STATUS_SUCCESS;
  1188. CreateTransferEnd:
  1189. if (!KSUCCESS(Status)) {
  1190. if (TransferSet != NULL) {
  1191. for (TransferIndex = 0;
  1192. TransferIndex < TransferCount;
  1193. TransferIndex += 1) {
  1194. Transfer = TransferArray[TransferIndex];
  1195. if (Transfer != NULL) {
  1196. MmFreeBlock(Controller->BlockAllocator, Transfer);
  1197. }
  1198. }
  1199. MmFreeNonPagedPool(TransferSet);
  1200. TransferSet = NULL;
  1201. }
  1202. }
  1203. *TransferContext = TransferSet;
  1204. return Status;
  1205. }
  1206. VOID
  1207. DwhcipDestroyTransfer (
  1208. PVOID HostControllerContext,
  1209. PVOID EndpointContext,
  1210. PVOID TransferContext
  1211. )
  1212. /*++
  1213. Routine Description:
  1214. This routine destroys host controller structures associated with a USB
  1215. transfer.
  1216. Arguments:
  1217. HostControllerContext - Supplies the context pointer passed to the USB core
  1218. when the controller was created. This is used to identify the USB host
  1219. controller to the host controller driver.
  1220. EndpointContext - Supplies a pointer to the host controller context for the
  1221. endpoint this transfer belonged to.
  1222. TransferContext - Supplies the pointer provided to the USB core by the host
  1223. controller when the transfer was created.
  1224. Return Value:
  1225. None.
  1226. --*/
  1227. {
  1228. PDWHCI_CONTROLLER Controller;
  1229. PDWHCI_TRANSFER Transfer;
  1230. PDWHCI_TRANSFER *TransferArray;
  1231. ULONG TransferIndex;
  1232. PDWHCI_TRANSFER_SET TransferSet;
  1233. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1234. TransferSet = (PDWHCI_TRANSFER_SET)TransferContext;
  1235. TransferArray = (PDWHCI_TRANSFER *)(TransferSet->Transfer);
  1236. //
  1237. // Free all transfers that were allocated.
  1238. //
  1239. for (TransferIndex = 0;
  1240. TransferIndex < TransferSet->TransferCount;
  1241. TransferIndex += 1) {
  1242. Transfer = TransferArray[TransferIndex];
  1243. ASSERT(Transfer != NULL);
  1244. MmFreeBlock(Controller->BlockAllocator, Transfer);
  1245. TransferArray[TransferIndex] = NULL;
  1246. }
  1247. MmFreeNonPagedPool(TransferSet);
  1248. return;
  1249. }
  1250. KSTATUS
  1251. DwhcipSubmitTransfer (
  1252. PVOID HostControllerContext,
  1253. PVOID EndpointContext,
  1254. PUSB_TRANSFER_INTERNAL Transfer,
  1255. PVOID TransferContext
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. This routine submits a transfer to the USB host controller for execution.
  1260. Arguments:
  1261. HostControllerContext - Supplies the context pointer passed to the USB core
  1262. when the controller was created. This is used to identify the USB host
  1263. controller to the host controller driver.
  1264. EndpointContext - Supplies the context pointer provided to the USB core by
  1265. the host controller when the endpoint was created.
  1266. Transfer - Supplies a pointer to the USB transfer to execute.
  1267. TransferContext - Supplies the pointer provided to the USB core by the host
  1268. controller when the transfer was created.
  1269. Return Value:
  1270. STATUS_SUCCESS if the transfer was successfully added to the hardware queue.
  1271. Failure codes if the transfer could not be added.
  1272. --*/
  1273. {
  1274. ULONG ChannelControl;
  1275. PDWHCI_CONTROLLER Controller;
  1276. BOOL ControlTransfer;
  1277. ULONG CoreInterruptMask;
  1278. PDWHCI_TRANSFER DwhciTransfer;
  1279. PDWHCI_ENDPOINT Endpoint;
  1280. UCHAR EndpointDeviceAddress;
  1281. BOOL ForceShortTransfer;
  1282. ULONG FrameNumber;
  1283. ULONG FrameOffset;
  1284. BOOL LastTransfer;
  1285. ULONG Length;
  1286. ULONG MaxTransferSize;
  1287. ULONG NextFrame;
  1288. ULONG Offset;
  1289. RUNLEVEL OldRunLevel;
  1290. ULONG TotalLength;
  1291. PDWHCI_TRANSFER *TransferArray;
  1292. ULONG TransferCount;
  1293. ULONG TransferIndex;
  1294. PDWHCI_TRANSFER_SET TransferSet;
  1295. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1296. ControlTransfer = FALSE;
  1297. Endpoint = (PDWHCI_ENDPOINT)EndpointContext;
  1298. TransferSet = (PDWHCI_TRANSFER_SET)TransferContext;
  1299. TransferArray = (PDWHCI_TRANSFER *)(TransferSet->Transfer);
  1300. DwhciTransfer = NULL;
  1301. //
  1302. // Assume that this is going to be a rousing success.
  1303. //
  1304. Transfer->Public.Status = STATUS_SUCCESS;
  1305. Transfer->Public.Error = UsbErrorNone;
  1306. TransferSet->UsbTransfer = Transfer;
  1307. //
  1308. // Before filling out and inserting transfers, take a look to see if the
  1309. // device address has changed. If it has, then it should still be in the
  1310. // enumeration phase, meaning there are no pending transfers floating
  1311. // around.
  1312. //
  1313. EndpointDeviceAddress = (Endpoint->ChannelControl &
  1314. DWHCI_CHANNEL_CONTROL_DEVICE_ADDRESS_MASK) >>
  1315. DWHCI_CHANNEL_CONTROL_DEVICE_ADDRESS_SHIFT;
  1316. if (Transfer->DeviceAddress != EndpointDeviceAddress) {
  1317. ASSERT(EndpointDeviceAddress == 0);
  1318. ASSERT(Transfer->DeviceAddress != 0);
  1319. ASSERT(LIST_EMPTY(&(Endpoint->TransferSetListHead)) != FALSE);
  1320. ChannelControl = (Transfer->DeviceAddress <<
  1321. DWHCI_CHANNEL_CONTROL_DEVICE_ADDRESS_SHIFT) &
  1322. DWHCI_CHANNEL_CONTROL_DEVICE_ADDRESS_MASK;
  1323. Endpoint->ChannelControl |= ChannelControl;
  1324. }
  1325. //
  1326. // Determine the number of transfers needed for this transfer, and loop
  1327. // filling them out. This is necessary because the number of transfers
  1328. // per transfer is not constant; the system may re-use a transfer and
  1329. // and change the length.
  1330. //
  1331. TransferCount = 0;
  1332. TotalLength = Transfer->Public.Length;
  1333. if (Endpoint->TransferType == UsbTransferTypeControl) {
  1334. ControlTransfer = TRUE;
  1335. ASSERT(TotalLength >= sizeof(USB_SETUP_PACKET));
  1336. TotalLength -= sizeof(USB_SETUP_PACKET);
  1337. //
  1338. // Account for both the setup and status transfers.
  1339. //
  1340. TransferCount += 2;
  1341. }
  1342. ForceShortTransfer = FALSE;
  1343. if ((Transfer->Public.Flags &
  1344. USB_TRANSFER_FLAG_FORCE_SHORT_TRANSFER) != 0) {
  1345. ForceShortTransfer = TRUE;
  1346. }
  1347. //
  1348. // Determine the number of transfers in this set. Low speed endpoints on
  1349. // high speed controllers requiring split transfers can only execute one
  1350. // max packet size per transfer.
  1351. //
  1352. if (Endpoint->SplitControl == 0) {
  1353. TransferCount += TotalLength / Endpoint->MaxTransferSize;
  1354. if ((TotalLength % Endpoint->MaxTransferSize) != 0) {
  1355. TransferCount += 1;
  1356. }
  1357. MaxTransferSize = Endpoint->MaxTransferSize;
  1358. } else {
  1359. TransferCount += TotalLength / Endpoint->MaxPacketSize;
  1360. if ((TotalLength % Endpoint->MaxPacketSize) != 0) {
  1361. TransferCount += 1;
  1362. }
  1363. MaxTransferSize = Endpoint->MaxPacketSize;
  1364. }
  1365. //
  1366. // Add an extra transfer if it is needed for more data or to force a short
  1367. // transfer. Make sure this accounts for non-control zero-length requests.
  1368. //
  1369. if (((ForceShortTransfer != FALSE) &&
  1370. ((TotalLength % Endpoint->MaxPacketSize) == 0)) ||
  1371. ((TotalLength == 0) &&
  1372. (Endpoint->TransferType != UsbTransferTypeControl)) ) {
  1373. TransferCount += 1;
  1374. }
  1375. ASSERT(TransferSet->TransferCount >= TransferCount);
  1376. //
  1377. // Initialize the DWHCI transfers required for this USB transfer and add
  1378. // them to the transfer set's list head.
  1379. //
  1380. Offset = 0;
  1381. LastTransfer = FALSE;
  1382. INITIALIZE_LIST_HEAD(&(TransferSet->TransferListHead));
  1383. for (TransferIndex = 0; TransferIndex < TransferCount; TransferIndex += 1) {
  1384. //
  1385. // Calculate the length for this transfer descriptor.
  1386. //
  1387. Length = MaxTransferSize;
  1388. if (Offset + Length > Transfer->Public.Length) {
  1389. Length = Transfer->Public.Length - Offset;
  1390. }
  1391. if (TransferIndex == (TransferCount - 1)) {
  1392. LastTransfer = TRUE;
  1393. }
  1394. if (ControlTransfer != FALSE) {
  1395. //
  1396. // The first part of a control transfer is the setup packet, which
  1397. // is always 8 bytes long.
  1398. //
  1399. if (Offset == 0) {
  1400. Length = sizeof(USB_SETUP_PACKET);
  1401. }
  1402. //
  1403. // The last part of a control transfer is the status phase and the
  1404. // length better be zero.
  1405. //
  1406. ASSERT((LastTransfer == FALSE) || (Length == 0));
  1407. }
  1408. ASSERT((Length != 0) ||
  1409. (LastTransfer != FALSE) ||
  1410. ((ForceShortTransfer != FALSE) && (ControlTransfer != FALSE)));
  1411. //
  1412. // Fill out this transfer descriptor.
  1413. //
  1414. DwhciTransfer = TransferArray[TransferIndex];
  1415. DwhcipFillOutTransferDescriptor(Controller,
  1416. TransferSet,
  1417. DwhciTransfer,
  1418. Offset,
  1419. Length,
  1420. LastTransfer);
  1421. //
  1422. // Advance the buffer position.
  1423. //
  1424. Offset += Length;
  1425. }
  1426. //
  1427. // Mark the current transfer as the last transfer.
  1428. //
  1429. DwhciTransfer->LastTransfer = TRUE;
  1430. //
  1431. // The controller lock is required for endpoint updates and schedule
  1432. // processing.
  1433. //
  1434. OldRunLevel = DwhcipAcquireControllerLock(Controller);
  1435. //
  1436. // The transfer set is ready to go. Insert it into the endpoint's list of
  1437. // transfer sets.
  1438. //
  1439. INSERT_BEFORE(&(TransferSet->EndpointListEntry),
  1440. &(Endpoint->TransferSetListHead));
  1441. //
  1442. // If the endpoint is not already inserted into the schedule, insert it.
  1443. //
  1444. if (Endpoint->ListEntry.Next == NULL) {
  1445. ASSERT(Endpoint->Scheduled == FALSE);
  1446. if ((Endpoint->TransferType == UsbTransferTypeControl) ||
  1447. (Endpoint->TransferType == UsbTransferTypeBulk)) {
  1448. INSERT_BEFORE(&(Endpoint->ListEntry),
  1449. &(Controller->NonPeriodicReadyListHead));
  1450. //
  1451. // There is now work on the non-periodic schedule that needs to be
  1452. // done. Try to schedule it.
  1453. //
  1454. DwhcipProcessSchedule(Controller, FALSE);
  1455. } else {
  1456. ASSERT((Endpoint->TransferType == UsbTransferTypeInterrupt) ||
  1457. (Endpoint->TransferType == UsbTransferTypeIsochronous));
  1458. //
  1459. // Schedule this endpoint for a (micro)frame shortly in the future
  1460. // to kick it off.
  1461. //
  1462. FrameNumber = DWHCI_READ_FRAME_NUMBER(Controller);
  1463. ASSERT(Endpoint->NextFrame == 0);
  1464. //
  1465. // Schedule for a future (micro)frame, but not further than the
  1466. // poll rate.
  1467. //
  1468. FrameOffset = DWHCI_DEFAULT_FRAME_OFFSET;
  1469. if (FrameOffset > Endpoint->PollRate) {
  1470. FrameOffset = Endpoint->PollRate;
  1471. }
  1472. NextFrame = (FrameNumber + FrameOffset) & DWHCI_FRAME_NUMBER_MAX;
  1473. //
  1474. // Start splits are not allowed to start in the 6th microframe and
  1475. // get less time for the complete splits the later they get
  1476. // scheduled within a frame. Schedule them all for the last
  1477. // microframe.
  1478. //
  1479. if ((Endpoint->SplitControl != 0) &&
  1480. (Endpoint->TransferType == UsbTransferTypeInterrupt)) {
  1481. NextFrame |= DWHCI_INTERRUPT_SPLIT_FRAME_MASK;
  1482. }
  1483. if ((Controller->NextFrame == DWHCI_INVALID_FRAME) ||
  1484. DWHCI_FRAME_LESS_THAN(NextFrame, Controller->NextFrame)) {
  1485. Controller->NextFrame = NextFrame;
  1486. }
  1487. Endpoint->NextFrame = NextFrame;
  1488. //
  1489. // These transfer need to wait for the start of the appropriate
  1490. // (micro)frame. Activate the start-of-frame interrupt if the
  1491. // periodic inactive list is currently empty.
  1492. //
  1493. if (LIST_EMPTY(&(Controller->PeriodicInactiveListHead)) != FALSE) {
  1494. CoreInterruptMask = DWHCI_READ_REGISTER(
  1495. Controller,
  1496. DwhciRegisterCoreInterruptMask);
  1497. CoreInterruptMask |= DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  1498. DWHCI_WRITE_REGISTER(Controller,
  1499. DwhciRegisterCoreInterruptMask,
  1500. CoreInterruptMask);
  1501. }
  1502. INSERT_BEFORE(&(Endpoint->ListEntry),
  1503. &(Controller->PeriodicInactiveListHead));
  1504. }
  1505. }
  1506. //
  1507. // All done. Release the lock and return.
  1508. //
  1509. DwhcipReleaseControllerLock(Controller, OldRunLevel);
  1510. return STATUS_SUCCESS;
  1511. }
  1512. KSTATUS
  1513. DwhcipCancelTransfer (
  1514. PVOID HostControllerContext,
  1515. PVOID EndpointContext,
  1516. PUSB_TRANSFER_INTERNAL Transfer,
  1517. PVOID TransferContext
  1518. )
  1519. /*++
  1520. Routine Description:
  1521. This routine submits attempts to cancel a transfer that was previously
  1522. submitted for execution.
  1523. Arguments:
  1524. HostControllerContext - Supplies the context pointer passed to the USB core
  1525. when the controller was created. This is used to identify the USB host
  1526. controller to the host controller driver.
  1527. EndpointContext - Supplies the context pointer provided to the USB core by
  1528. the host controller when the endpoint was created.
  1529. Transfer - Supplies a pointer to the USB transfer to execute.
  1530. TransferContext - Supplies the pointer provided to the USB core by the host
  1531. controller when the transfer was created.
  1532. Return Value:
  1533. STATUS_SUCCESS if the transfer was successfully removed from the hardware
  1534. queue.
  1535. STATUS_TOO_LATE if the transfer had already completed.
  1536. Other failure codes if the transfer could not be cancelled but has not yet
  1537. completed.
  1538. --*/
  1539. {
  1540. PDWHCI_CONTROLLER Controller;
  1541. PDWHCI_ENDPOINT Endpoint;
  1542. BOOL FirstSet;
  1543. PDWHCI_TRANSFER_SET FirstTransferSet;
  1544. BOOL Halted;
  1545. RUNLEVEL OldRunLevel;
  1546. BOOL RemoveSet;
  1547. KSTATUS Status;
  1548. PDWHCI_TRANSFER_SET TransferSet;
  1549. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1550. TransferSet = (PDWHCI_TRANSFER_SET)TransferContext;
  1551. ASSERT(TransferSet->UsbTransfer == Transfer);
  1552. //
  1553. // Lock the controller to manipulate the endpoint lists.
  1554. //
  1555. OldRunLevel = DwhcipAcquireControllerLock(Controller);
  1556. //
  1557. // If the transfer set was already taken off its endpoint list, then the
  1558. // transfer has already completed.
  1559. //
  1560. if (TransferSet->EndpointListEntry.Next == NULL) {
  1561. ASSERT(TransferSet->EndpointListEntry.Next == NULL);
  1562. Status = STATUS_TOO_LATE;
  1563. goto CancelTransferEnd;
  1564. }
  1565. //
  1566. // Isochronous transfers are handled differently.
  1567. //
  1568. if (Transfer->Type == UsbTransferTypeIsochronous) {
  1569. //
  1570. // TODO: Implement support for isochronous transfers.
  1571. //
  1572. ASSERT(FALSE);
  1573. Status = STATUS_NOT_IMPLEMENTED;
  1574. goto CancelTransferEnd;
  1575. }
  1576. Endpoint = TransferSet->Endpoint;
  1577. ASSERT(LIST_EMPTY(&(Endpoint->TransferSetListHead)) == FALSE);
  1578. //
  1579. // Only move the endpoint forward if removing the first transfer set.
  1580. //
  1581. FirstTransferSet = LIST_VALUE(Endpoint->TransferSetListHead.Next,
  1582. DWHCI_TRANSFER_SET,
  1583. EndpointListEntry);
  1584. FirstSet = FALSE;
  1585. if (TransferSet == FirstTransferSet) {
  1586. FirstSet = TRUE;
  1587. }
  1588. //
  1589. // Set the error state for the channel. It will either get pulled out of
  1590. // the schedule below or halted, in the case of an active transfer. Once
  1591. // the active transfer halts, it will see why based on this status.
  1592. //
  1593. Transfer->Public.Status = STATUS_OPERATION_CANCELLED;
  1594. Transfer->Public.Error = UsbErrorTransferCancelled;
  1595. //
  1596. // If the transfer set is active on the endpoint, the endpoint has been
  1597. // assigned a channel and the endpoint is actually scheduled on the channel,
  1598. // then halt the channel. Halting a channel is not supported if the root
  1599. // port is not connected. Just remove the transfer set.
  1600. //
  1601. RemoveSet = TRUE;
  1602. if ((Controller->PortConnected != FALSE) &&
  1603. (FirstSet != FALSE) &&
  1604. (Endpoint->Channel != NULL) &&
  1605. (Endpoint->Scheduled != FALSE)) {
  1606. Halted = DwhcipHaltChannel(Controller, Endpoint->Channel);
  1607. if (Halted == FALSE) {
  1608. RemoveSet = FALSE;
  1609. }
  1610. }
  1611. //
  1612. // If the transfer set can be removed because it was not active or the
  1613. // channel was successfully halted, do it. Also complete the transfer and
  1614. // advance the endpoint to the next transfer, if any.
  1615. //
  1616. if (RemoveSet != FALSE) {
  1617. DwhcipRemoveTransferSet(Controller, TransferSet);
  1618. UsbHostProcessCompletedTransfer(Transfer);
  1619. if (FirstSet != FALSE) {
  1620. DwhcipAdvanceEndpoint(Controller, Endpoint);
  1621. DwhcipProcessSchedule(Controller, FALSE);
  1622. }
  1623. Status = STATUS_SUCCESS;
  1624. } else {
  1625. Status = STATUS_TOO_LATE;
  1626. }
  1627. CancelTransferEnd:
  1628. DwhcipReleaseControllerLock(Controller, OldRunLevel);
  1629. return Status;
  1630. }
  1631. KSTATUS
  1632. DwhcipGetRootHubStatus (
  1633. PVOID HostControllerContext,
  1634. PUSB_HUB_STATUS HubStatus
  1635. )
  1636. /*++
  1637. Routine Description:
  1638. This routine queries the host controller for the status of the root hub.
  1639. Arguments:
  1640. HostControllerContext - Supplies the context pointer passed to the USB core
  1641. when the controller was created. This is used to identify the USB host
  1642. controller to the host controller driver.
  1643. HubStatus - Supplies a pointer where the host controller should fill out
  1644. the root hub status.
  1645. Return Value:
  1646. STATUS_SUCCESS if the hub status was successfully queried.
  1647. Failure codes if the status could not be queried.
  1648. --*/
  1649. {
  1650. ULONG AcknowledgeStatus;
  1651. USHORT ChangeBits;
  1652. PDWHCI_CONTROLLER Controller;
  1653. ULONG HardwareStatus;
  1654. PUSB_PORT_STATUS PortStatus;
  1655. USHORT SoftwareStatus;
  1656. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1657. ASSERT(Controller->PortCount == DWHCI_HOST_PORT_COUNT);
  1658. ASSERT(HubStatus->PortStatus != NULL);
  1659. HardwareStatus = DWHCI_READ_REGISTER(Controller, DwhciRegisterHostPort);
  1660. SoftwareStatus = 0;
  1661. //
  1662. // Set the software bits that correspond to the queried hardware bits.
  1663. //
  1664. if ((HardwareStatus & DWHCI_HOST_PORT_CONNECT_STATUS) != 0) {
  1665. SoftwareStatus |= USB_PORT_STATUS_CONNECTED;
  1666. switch (HardwareStatus & DWHCI_HOST_PORT_SPEED_MASK) {
  1667. case DWHCI_HOST_PORT_SPEED_LOW:
  1668. HubStatus->PortDeviceSpeed[0] = UsbDeviceSpeedLow;
  1669. break;
  1670. case DWHCI_HOST_PORT_SPEED_FULL:
  1671. HubStatus->PortDeviceSpeed[0] = UsbDeviceSpeedFull;
  1672. break;
  1673. case DWHCI_HOST_PORT_SPEED_HIGH:
  1674. HubStatus->PortDeviceSpeed[0] = UsbDeviceSpeedHigh;
  1675. break;
  1676. default:
  1677. ASSERT(FALSE);
  1678. break;
  1679. }
  1680. Controller->PortConnected = TRUE;
  1681. } else {
  1682. Controller->PortConnected = FALSE;
  1683. }
  1684. if ((HardwareStatus & DWHCI_HOST_PORT_ENABLE) != 0) {
  1685. SoftwareStatus |= USB_PORT_STATUS_ENABLED;
  1686. }
  1687. if ((HardwareStatus & DWHCI_HOST_PORT_RESET) != 0) {
  1688. SoftwareStatus |= USB_PORT_STATUS_RESET;
  1689. }
  1690. if ((HardwareStatus & DWHCI_HOST_PORT_OVER_CURRENT_ACTIVE) != 0) {
  1691. SoftwareStatus |= USB_PORT_STATUS_OVER_CURRENT;
  1692. }
  1693. //
  1694. // If the new software status is different from the current software
  1695. // status, record the change bits and set the new software status.
  1696. //
  1697. PortStatus = &(HubStatus->PortStatus[0]);
  1698. if (SoftwareStatus != PortStatus->Status) {
  1699. ChangeBits = SoftwareStatus ^ PortStatus->Status;
  1700. //
  1701. // Because the change bits correspond with the status bits 1-to-1, just
  1702. // OR in the change bits.
  1703. //
  1704. PortStatus->Change |= ChangeBits;
  1705. PortStatus->Status = SoftwareStatus;
  1706. }
  1707. //
  1708. // Acknowledge the over current change bit if it is set.
  1709. //
  1710. if ((HardwareStatus & DWHCI_HOST_PORT_OVER_CURRENT_CHANGE) != 0) {
  1711. PortStatus->Change |= USB_PORT_STATUS_OVER_CURRENT;
  1712. AcknowledgeStatus = HardwareStatus &
  1713. ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK;
  1714. AcknowledgeStatus |= DWHCI_HOST_PORT_OVER_CURRENT_CHANGE;
  1715. DWHCI_WRITE_REGISTER(Controller,
  1716. DwhciRegisterHostPort,
  1717. AcknowledgeStatus);
  1718. }
  1719. //
  1720. // Acknowledge the port connection status change in the hardware and set
  1721. // the bit in the software's port status change bits. It may be that the
  1722. // port transitioned from connected to connected and the above checks did
  1723. // not pick up the change.
  1724. //
  1725. if ((HardwareStatus & DWHCI_HOST_PORT_CONNECT_STATUS_CHANGE) != 0) {
  1726. PortStatus->Change |= USB_PORT_STATUS_CHANGE_CONNECTED;
  1727. //
  1728. // If the port is not in the middle of a reset, clear the connect
  1729. // status change bit in the hardware by setting it to 1. Resets clear
  1730. // the connect status changed bit.
  1731. //
  1732. if ((HardwareStatus & DWHCI_HOST_PORT_RESET) == 0) {
  1733. AcknowledgeStatus = HardwareStatus &
  1734. ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK;
  1735. AcknowledgeStatus |= DWHCI_HOST_PORT_CONNECT_STATUS_CHANGE;
  1736. DWHCI_WRITE_REGISTER(Controller,
  1737. DwhciRegisterHostPort,
  1738. AcknowledgeStatus);
  1739. }
  1740. }
  1741. if ((DwhciDebugFlags & DWHCI_DEBUG_FLAG_PORTS) != 0) {
  1742. RtlDebugPrint(
  1743. "DWHCI: Controller 0x%x Port %d Status 0x%x. Connected %d, "
  1744. "Enabled %d, Reset %d, Changed %d.\n",
  1745. Controller,
  1746. 0,
  1747. HardwareStatus,
  1748. (HardwareStatus & DWHCI_HOST_PORT_CONNECT_STATUS) != 0,
  1749. (HardwareStatus & DWHCI_HOST_PORT_ENABLE) != 0,
  1750. (HardwareStatus & DWHCI_HOST_PORT_RESET) != 0,
  1751. (HardwareStatus & DWHCI_HOST_PORT_CONNECT_STATUS_CHANGE) != 0);
  1752. }
  1753. return STATUS_SUCCESS;
  1754. }
  1755. KSTATUS
  1756. DwhcipSetRootHubStatus (
  1757. PVOID HostControllerContext,
  1758. PUSB_HUB_STATUS HubStatus
  1759. )
  1760. /*++
  1761. Routine Description:
  1762. This routine sets the state of the root hub in the USB host controller. It
  1763. looks at the status change bits for each port in order to determine what
  1764. needs to be set.
  1765. Arguments:
  1766. HostControllerContext - Supplies the context pointer passed to the USB core
  1767. when the controller was created. This is used to identify the USB host
  1768. controller to the host controller driver.
  1769. HubStatus - Supplies a pointer to the status that should be set in the root
  1770. hub.
  1771. Return Value:
  1772. STATUS_SUCCESS if the hub state was successfully programmed into the device.
  1773. Failure codes if the status could not be set.
  1774. --*/
  1775. {
  1776. PDWHCI_CONTROLLER Controller;
  1777. ULONG HardwareStatus;
  1778. ULONG OriginalHardwareStatus;
  1779. PUSB_PORT_STATUS PortStatus;
  1780. Controller = (PDWHCI_CONTROLLER)HostControllerContext;
  1781. ASSERT(Controller->PortCount == DWHCI_HOST_PORT_COUNT);
  1782. ASSERT(HubStatus->PortStatus != NULL);
  1783. PortStatus = &(HubStatus->PortStatus[0]);
  1784. if (PortStatus->Change == 0) {
  1785. return STATUS_SUCCESS;
  1786. }
  1787. HardwareStatus = DWHCI_READ_REGISTER(Controller, DwhciRegisterHostPort);
  1788. HardwareStatus &= ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK;
  1789. OriginalHardwareStatus = HardwareStatus;
  1790. //
  1791. // Clear out the bits that may potentially be adjusted.
  1792. //
  1793. HardwareStatus &= ~(DWHCI_HOST_PORT_ENABLE |
  1794. DWHCI_HOST_PORT_RESET |
  1795. DWHCI_HOST_PORT_SUSPEND);
  1796. //
  1797. // Set the hardware bits according to the software bits passed in.
  1798. //
  1799. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_ENABLED) != 0) {
  1800. //
  1801. // If the port is being enabled, power it on.
  1802. //
  1803. if ((PortStatus->Status & USB_PORT_STATUS_ENABLED) != 0) {
  1804. HardwareStatus |= DWHCI_HOST_PORT_POWER;
  1805. //
  1806. // Otherwise set the enable bit to disable.
  1807. //
  1808. } else {
  1809. HardwareStatus |= DWHCI_HOST_PORT_ENABLE;
  1810. }
  1811. //
  1812. // Acknowledge that the enable bit was handled.
  1813. //
  1814. PortStatus->Change &= ~ USB_PORT_STATUS_CHANGE_ENABLED;
  1815. }
  1816. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_RESET) != 0) {
  1817. if ((PortStatus->Status & USB_PORT_STATUS_RESET) != 0) {
  1818. HardwareStatus |= DWHCI_HOST_PORT_RESET | DWHCI_HOST_PORT_POWER;
  1819. }
  1820. //
  1821. // Acknowledge that the reset bit was handled.
  1822. //
  1823. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_RESET;
  1824. }
  1825. //
  1826. // Suspend the port if requested.
  1827. //
  1828. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_SUSPENDED) != 0) {
  1829. if ((PortStatus->Status & USB_PORT_STATUS_SUSPENDED) != 0) {
  1830. HardwareStatus |= DWHCI_HOST_PORT_SUSPEND;
  1831. }
  1832. //
  1833. // Acknowledge that the suspended bit was handled.
  1834. //
  1835. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_SUSPENDED;
  1836. }
  1837. //
  1838. // Write out the new value if it is different than the old one. If both the
  1839. // enable (i.e. disable) bit and the reset bit are set, disable the port
  1840. // first using the original hardware status.
  1841. //
  1842. if (HardwareStatus != OriginalHardwareStatus) {
  1843. if (((HardwareStatus & DWHCI_HOST_PORT_ENABLE) != 0) &&
  1844. ((HardwareStatus & DWHCI_HOST_PORT_RESET) != 0)) {
  1845. OriginalHardwareStatus |= DWHCI_HOST_PORT_ENABLE;
  1846. DWHCI_WRITE_REGISTER(Controller,
  1847. DwhciRegisterHostPort,
  1848. OriginalHardwareStatus);
  1849. HardwareStatus &= ~DWHCI_HOST_PORT_ENABLE;
  1850. }
  1851. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterHostPort, HardwareStatus);
  1852. }
  1853. //
  1854. // If reset was set, wait a bit and then clear the reset flag.
  1855. //
  1856. if ((HardwareStatus & DWHCI_HOST_PORT_RESET) != 0) {
  1857. KeDelayExecution(FALSE, FALSE, 50 * MICROSECONDS_PER_MILLISECOND);
  1858. HardwareStatus = DWHCI_READ_REGISTER(Controller, DwhciRegisterHostPort);
  1859. HardwareStatus &= ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK;
  1860. HardwareStatus &= ~DWHCI_HOST_PORT_RESET;
  1861. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterHostPort, HardwareStatus);
  1862. }
  1863. return STATUS_SUCCESS;
  1864. }
  1865. RUNLEVEL
  1866. DwhcipAcquireControllerLock (
  1867. PDWHCI_CONTROLLER Controller
  1868. )
  1869. /*++
  1870. Routine Description:
  1871. This routine acquires the given DWHCI controller's lock at dispatch level.
  1872. Arguments:
  1873. Controller - Supplies a pointer to the controller to lock.
  1874. Return Value:
  1875. Returns the previous run-level, which must be passed in when the controller
  1876. is unlocked.
  1877. --*/
  1878. {
  1879. RUNLEVEL OldRunLevel;
  1880. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  1881. KeAcquireSpinLock(&(Controller->Lock));
  1882. return OldRunLevel;
  1883. }
  1884. VOID
  1885. DwhcipReleaseControllerLock (
  1886. PDWHCI_CONTROLLER Controller,
  1887. RUNLEVEL OldRunLevel
  1888. )
  1889. /*++
  1890. Routine Description:
  1891. This routine releases the given DWHCI controller's lock, and returns the
  1892. run-level to its previous value.
  1893. Arguments:
  1894. Controller - Supplies a pointer to the controller to unlock.
  1895. OldRunLevel - Supplies the original run level returned when the lock was
  1896. acquired.
  1897. Return Value:
  1898. None.
  1899. --*/
  1900. {
  1901. KeReleaseSpinLock(&(Controller->Lock));
  1902. KeLowerRunLevel(OldRunLevel);
  1903. return;
  1904. }
  1905. VOID
  1906. DwhcipInterruptServiceDpc (
  1907. PDPC Dpc
  1908. )
  1909. /*++
  1910. Routine Description:
  1911. This routine implements the DWHCI DPC that is queued when an interrupt
  1912. fires.
  1913. Arguments:
  1914. Dpc - Supplies a pointer to the DPC that is running.
  1915. Return Value:
  1916. None.
  1917. --*/
  1918. {
  1919. ASSERT(KeGetRunLevel() == RunLevelDispatch);
  1920. DwhcipProcessInterrupt(Dpc->UserData);
  1921. return;
  1922. }
  1923. VOID
  1924. DwhcipProcessInterrupt (
  1925. PVOID Context
  1926. )
  1927. /*++
  1928. Routine Description:
  1929. This routine performs the work associated with receiving an DWHCI
  1930. interrupt. This routine runs at dispatch level.
  1931. Arguments:
  1932. Context - Supplies a pointer to the controller to service.
  1933. Return Value:
  1934. None.
  1935. --*/
  1936. {
  1937. ULONG ChannelInterruptBits[DWHCI_MAX_CHANNELS];
  1938. PDWHCI_CHANNEL Channels;
  1939. PDWHCI_CONTROLLER Controller;
  1940. ULONG Index;
  1941. ULONG InterruptBits;
  1942. RUNLEVEL OldRunLevel;
  1943. Controller = (PDWHCI_CONTROLLER)Context;
  1944. ASSERT(Controller->ChannelCount <= DWHCI_MAX_CHANNELS);
  1945. //
  1946. // Collect the pending interrupt bits and clear them to signal that another
  1947. // DPC will need to be queued for any subsequent interrupts. If the
  1948. // interrupt handle is not yet assigned, just raise to high. This will not
  1949. // result in a priority inversion problem as this code always run at
  1950. // dispatch, and thus cannot pre-empt the interrupt code while it has the
  1951. // lock.
  1952. //
  1953. if (Controller->InterruptHandle == INVALID_HANDLE) {
  1954. OldRunLevel = KeRaiseRunLevel(RunLevelHigh);
  1955. } else {
  1956. OldRunLevel = IoRaiseToInterruptRunLevel(Controller->InterruptHandle);
  1957. }
  1958. KeAcquireSpinLock(&(Controller->InterruptLock));
  1959. InterruptBits = Controller->PendingInterruptBits;
  1960. Controller->PendingInterruptBits = 0;
  1961. //
  1962. // Recording the pending interrupt bits for each channel.
  1963. //
  1964. if ((InterruptBits & DWHCI_CORE_INTERRUPT_HOST_CHANNEL) != 0) {
  1965. Channels = (PDWHCI_CHANNEL)(Controller->Channel);
  1966. for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
  1967. ChannelInterruptBits[Index] = Channels[Index].PendingInterruptBits;
  1968. Channels[Index].PendingInterruptBits = 0;
  1969. }
  1970. }
  1971. KeReleaseSpinLock(&(Controller->InterruptLock));
  1972. KeLowerRunLevel(OldRunLevel);
  1973. //
  1974. // Lock the controller and loop until this routine has caught up with the
  1975. // interrupts.
  1976. //
  1977. OldRunLevel = DwhcipAcquireControllerLock(Controller);
  1978. //
  1979. // If the start-of-frame interrupt fired, then try to schedule some of the
  1980. // periodic transfers.
  1981. //
  1982. if ((InterruptBits & DWHCI_CORE_INTERRUPT_START_OF_FRAME) != 0) {
  1983. DwhcipProcessStartOfFrameInterrupt(Controller);
  1984. }
  1985. //
  1986. // If the port interrupt or the disconnect interrupt fired, then the host
  1987. // port's status changed. Notify the USB core.
  1988. //
  1989. if (((InterruptBits & DWHCI_CORE_INTERRUPT_PORT) != 0) ||
  1990. ((InterruptBits & DWHCI_CORE_INTERRUPT_DISCONNECT) != 0)) {
  1991. UsbHostNotifyPortChange(Controller->UsbCoreHandle);
  1992. }
  1993. //
  1994. // If the host channel interrupt fired, then iterate over the channel
  1995. // interrupt array to determine which channels have work pending.
  1996. //
  1997. if ((InterruptBits & DWHCI_CORE_INTERRUPT_HOST_CHANNEL) != 0) {
  1998. DwhcipProcessChannelInterrupt(Controller, ChannelInterruptBits);
  1999. }
  2000. DwhcipReleaseControllerLock(Controller, OldRunLevel);
  2001. return;
  2002. }
  2003. VOID
  2004. DwhcipProcessStartOfFrameInterrupt (
  2005. PDWHCI_CONTROLLER Controller
  2006. )
  2007. /*++
  2008. Routine Description:
  2009. This routine processes the inactive periodic schedule to see if any
  2010. transfer's period has expired. This routine assumes that the controller's
  2011. lock is held.
  2012. Arguments:
  2013. Controller - Supplies a pointer to the state of the DWHCI controller who
  2014. has reached the start of a frame.
  2015. Return Value:
  2016. None.
  2017. --*/
  2018. {
  2019. ULONG CoreInterruptMask;
  2020. PLIST_ENTRY CurrentEntry;
  2021. PDWHCI_ENDPOINT Endpoint;
  2022. ULONG FrameNumber;
  2023. ULONG NextFrame;
  2024. BOOL ProcessSchedule;
  2025. //
  2026. // The start of frame interrupt could have come in the middle of disabling
  2027. // the interrupt. Check to make sure there is a valid next frame.
  2028. //
  2029. if (Controller->NextFrame == DWHCI_INVALID_FRAME) {
  2030. return;
  2031. }
  2032. //
  2033. // Iterate over the inactive periodic schedule looking for endpoints that
  2034. // have something to submit for the current frame or some frame in the past.
  2035. //
  2036. NextFrame = DWHCI_INVALID_FRAME;
  2037. ProcessSchedule = FALSE;
  2038. FrameNumber = DWHCI_READ_FRAME_NUMBER(Controller);
  2039. CurrentEntry = Controller->PeriodicInactiveListHead.Next;
  2040. while (CurrentEntry != &(Controller->PeriodicInactiveListHead)) {
  2041. Endpoint = LIST_VALUE(CurrentEntry, DWHCI_ENDPOINT, ListEntry);
  2042. CurrentEntry = CurrentEntry->Next;
  2043. //
  2044. // Skip any endpoints whose polling interval has not expired, but do
  2045. // record the next frame.
  2046. //
  2047. if (DWHCI_FRAME_LESS_THAN(FrameNumber, Endpoint->NextFrame)) {
  2048. if ((NextFrame == DWHCI_INVALID_FRAME) ||
  2049. DWHCI_FRAME_LESS_THAN(Endpoint->NextFrame, NextFrame)) {
  2050. NextFrame = Endpoint->NextFrame;
  2051. }
  2052. continue;
  2053. }
  2054. LIST_REMOVE(&(Endpoint->ListEntry));
  2055. INSERT_BEFORE(&(Endpoint->ListEntry),
  2056. &(Controller->PeriodicReadyListHead));
  2057. ProcessSchedule = TRUE;
  2058. }
  2059. //
  2060. // If the inactive list is empty, then disable the start-of-frame interrupt.
  2061. //
  2062. if (LIST_EMPTY(&(Controller->PeriodicInactiveListHead)) != FALSE) {
  2063. CoreInterruptMask = DWHCI_READ_REGISTER(Controller,
  2064. DwhciRegisterCoreInterruptMask);
  2065. CoreInterruptMask &= ~DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  2066. DWHCI_WRITE_REGISTER(Controller,
  2067. DwhciRegisterCoreInterruptMask,
  2068. CoreInterruptMask);
  2069. ASSERT(NextFrame == DWHCI_INVALID_FRAME);
  2070. }
  2071. //
  2072. // Update the controller's next start of frame to process. This is either
  2073. // the smallest frame number out of the inactive periodic transfers or the
  2074. // invalid frame number if there are no more inactive periodic transfers.
  2075. //
  2076. Controller->NextFrame = NextFrame;
  2077. //
  2078. // If something was switch from the inactive to the ready list, then kick
  2079. // off the schedule.
  2080. //
  2081. if (ProcessSchedule != FALSE) {
  2082. DwhcipProcessSchedule(Controller, TRUE);
  2083. }
  2084. return;
  2085. }
  2086. VOID
  2087. DwhcipSaveChannelInterrupts (
  2088. PDWHCI_CONTROLLER Controller
  2089. )
  2090. /*++
  2091. Routine Description:
  2092. This routine saves the current interupt status for each channel and clears
  2093. any pending interrupts.
  2094. Arguments:
  2095. Controller - Supplies a pointer to the state of the DWHCI controller whose
  2096. channel interrupts are to be saved.
  2097. Return Value:
  2098. None.
  2099. --*/
  2100. {
  2101. ULONG Channel;
  2102. ULONG ChannelBits;
  2103. BOOL ChannelChanged;
  2104. PDWHCI_CHANNEL Channels;
  2105. ULONG Interrupts;
  2106. //
  2107. // A bit is set in the channel interrupt register for every channel that
  2108. // needs attention.
  2109. //
  2110. ChannelBits = DWHCI_READ_REGISTER(Controller,
  2111. DwhciRegisterHostChannelInterrupt);
  2112. Channels = (PDWHCI_CHANNEL)(Controller->Channel);
  2113. for (Channel = 0; Channel < Controller->ChannelCount; Channel += 1) {
  2114. ChannelChanged = FALSE;
  2115. if ((ChannelBits & 0x1) != 0) {
  2116. ChannelChanged = TRUE;
  2117. }
  2118. ChannelBits = ChannelBits >> 1;
  2119. if (ChannelChanged == FALSE) {
  2120. continue;
  2121. }
  2122. Interrupts = DWHCI_READ_CHANNEL_REGISTER(Controller,
  2123. DwhciChannelRegisterInterrupt,
  2124. Channel);
  2125. //
  2126. // Acknowledge the interrupts.
  2127. //
  2128. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  2129. DwhciChannelRegisterInterrupt,
  2130. Channel,
  2131. Interrupts);
  2132. //
  2133. // If there is no endpoint assigned to this channel, then something is
  2134. // not quite right. The interrupts have been acknowledged, but don't
  2135. // record the pending status.
  2136. //
  2137. if (Channels[Channel].Endpoint == NULL) {
  2138. Channels[Channel].PendingInterruptBits = 0;
  2139. continue;
  2140. }
  2141. //
  2142. // Save the unmasked interrupts for this channel.
  2143. //
  2144. Channels[Channel].PendingInterruptBits |= Interrupts;
  2145. }
  2146. return;
  2147. }
  2148. VOID
  2149. DwhcipProcessChannelInterrupt (
  2150. PDWHCI_CONTROLLER Controller,
  2151. PULONG ChannelInterruptBits
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. This routine handles a channel interrupt detected in the core interrupt
  2156. register. It interates over the host channels processing any channel that
  2157. has pending status.
  2158. Arguments:
  2159. Controller - Supplies a pointer to the controller state of the DWHCI
  2160. host controller whose channel interrupt fired.
  2161. ChannelInterruptBits - Supplies an array of pending interrupt bits for
  2162. each channel.
  2163. Return Value:
  2164. None.
  2165. --*/
  2166. {
  2167. BOOL AdvanceEndpoint;
  2168. PDWHCI_CHANNEL Channels;
  2169. PDWHCI_ENDPOINT Endpoint;
  2170. ULONG Index;
  2171. ULONG Interrupts;
  2172. BOOL ProcessSchedule;
  2173. BOOL RemoveSet;
  2174. PDWHCI_TRANSFER Transfer;
  2175. //
  2176. // Iterate over all the channels, looking for pending interrupt bits.
  2177. //
  2178. Channels = (PDWHCI_CHANNEL)(Controller->Channel);
  2179. ProcessSchedule = FALSE;
  2180. for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
  2181. Interrupts = ChannelInterruptBits[Index];
  2182. if (Interrupts == 0) {
  2183. continue;
  2184. }
  2185. //
  2186. // If there is no endpoint assigned to this channel, then something is
  2187. // not quite right. Ignore the interrupts.
  2188. //
  2189. Endpoint = Channels[Index].Endpoint;
  2190. if (Endpoint == NULL) {
  2191. continue;
  2192. }
  2193. //
  2194. // Pre-process endpoints using split transfers. This may modify the
  2195. // interrupt state.
  2196. //
  2197. if (Endpoint->SplitControl != 0) {
  2198. DwhcipProcessSplitEndpoint(Controller, Endpoint, &Interrupts);
  2199. }
  2200. //
  2201. // Pre-process high speed bulk and control transfers to handle the
  2202. // PING protocol.
  2203. //
  2204. if ((Endpoint->Speed == UsbDeviceSpeedHigh) &&
  2205. ((Endpoint->TransferType == UsbTransferTypeBulk) ||
  2206. (Endpoint->TransferType == UsbTransferTypeControl))) {
  2207. DwhcipProcessPingEndpoint(Controller,
  2208. Endpoint,
  2209. &Interrupts);
  2210. }
  2211. //
  2212. // Get the first transfer for the endpoint. That is the one to which
  2213. // the interrupt status applies. Then process the endpoint.
  2214. //
  2215. Transfer = DwhcipGetEndpointTransfer(Endpoint);
  2216. ASSERT(Transfer != NULL);
  2217. DwhcipProcessPotentiallyCompletedTransfer(Controller,
  2218. Transfer,
  2219. Interrupts,
  2220. &RemoveSet,
  2221. &AdvanceEndpoint);
  2222. if (RemoveSet != FALSE) {
  2223. DwhcipRemoveTransferSet(Controller, Transfer->Set);
  2224. UsbHostProcessCompletedTransfer(Transfer->Set->UsbTransfer);
  2225. }
  2226. //
  2227. // Prepare the endpoint to move onto its next transfer.
  2228. //
  2229. if (AdvanceEndpoint != FALSE) {
  2230. DwhcipAdvanceEndpoint(Controller, Endpoint);
  2231. ProcessSchedule = TRUE;
  2232. }
  2233. }
  2234. //
  2235. // Try to pump other transfers through the schedule if some channels have
  2236. // become available.
  2237. //
  2238. if (ProcessSchedule != FALSE) {
  2239. DwhcipProcessSchedule(Controller, FALSE);
  2240. }
  2241. return;
  2242. }
  2243. VOID
  2244. DwhcipProcessPotentiallyCompletedTransfer (
  2245. PDWHCI_CONTROLLER Controller,
  2246. PDWHCI_TRANSFER Transfer,
  2247. ULONG Interrupts,
  2248. PBOOL RemoveSet,
  2249. PBOOL AdvanceEndpoint
  2250. )
  2251. /*++
  2252. Routine Description:
  2253. This routine processes a potentially completed transfer, adjusting the USB
  2254. transfer if the transfer errored out or completed.
  2255. Arguments:
  2256. Controller - Supplies a pointer to the controller state of the DWHCI host
  2257. controller who owns the potentially completed transfer.
  2258. Transfer - Supplies a pointer to the transfer to evaluate.
  2259. Interrupts - Supplies the interrupt status for this transfer's channel.
  2260. RemoveSet - Supplies a pointer to a boolean that receives TRUE if the
  2261. transfer's set should be removed from the active list due to completion
  2262. or failure, or FALSE otherwise.
  2263. AdvanceEndpoint - Supplies a pointer to a boolean that receives TRUE if the
  2264. transfer's endpoint should be advanced to the next transfer, or FALSE
  2265. otherwise.
  2266. Return Value:
  2267. None.
  2268. --*/
  2269. {
  2270. ULONG BytesRemaining;
  2271. PDWHCI_CHANNEL Channel;
  2272. PDWHCI_ENDPOINT Endpoint;
  2273. ULONG Errors;
  2274. BOOL Halted;
  2275. ULONG LengthTransferred;
  2276. BOOL RemoveTransfer;
  2277. PDWHCI_TRANSFER StatusTransfer;
  2278. ULONG Token;
  2279. PDWHCI_TRANSFER_SET TransferSet;
  2280. BOOL TransferShorted;
  2281. PUSB_TRANSFER UsbTransfer;
  2282. Channel = Transfer->Set->Endpoint->Channel;
  2283. Endpoint = Transfer->Set->Endpoint;
  2284. LengthTransferred = 0;
  2285. RemoveTransfer = FALSE;
  2286. *RemoveSet = FALSE;
  2287. *AdvanceEndpoint = TRUE;
  2288. TransferShorted = FALSE;
  2289. UsbTransfer = &(Transfer->Set->UsbTransfer->Public);
  2290. ASSERT(Channel != NULL);
  2291. //
  2292. // The transfer should not be removed if this routine is reached. Nor
  2293. // should it's transfer set.
  2294. //
  2295. ASSERT(Transfer->SetListEntry.Next != NULL);
  2296. ASSERT(Transfer->Set->EndpointListEntry.Next != NULL);
  2297. //
  2298. // Always read the transfer token to update the endpoint's data toggle.
  2299. //
  2300. Token = DWHCI_READ_CHANNEL_REGISTER(Controller,
  2301. DwhciChannelRegisterToken,
  2302. Channel->ChannelNumber);
  2303. Endpoint->DataToggle = (Token & DWHCI_CHANNEL_TOKEN_PID_MASK) >>
  2304. DWHCI_CHANNEL_TOKEN_PID_SHIFT;
  2305. //
  2306. // DATA2 may be returned, so if the toggle is not DATA0, just force it to
  2307. // DATA1.
  2308. //
  2309. if (Endpoint->DataToggle != DWHCI_PID_CODE_DATA_0) {
  2310. Endpoint->DataToggle = DWHCI_PID_CODE_DATA_1;
  2311. }
  2312. ASSERT(Endpoint->DataToggle != DWHCI_PID_CODE_MORE_DATA);
  2313. //
  2314. // If the transfer was already cancelled, then just remove the set and
  2315. // exit.
  2316. //
  2317. if (UsbTransfer->Error == UsbErrorTransferCancelled) {
  2318. ASSERT(UsbTransfer->Status == STATUS_OPERATION_CANCELLED);
  2319. *RemoveSet = TRUE;
  2320. goto ProcessPotentiallyCompletedTransferEnd;
  2321. }
  2322. //
  2323. // If a device I/O error is set in the transfer, then this is just the
  2324. // channel halt operation completing. The AHB error was already handled.
  2325. //
  2326. if (UsbTransfer->Error == UsbErrorTransferDeviceIo) {
  2327. *RemoveSet = TRUE;
  2328. goto ProcessPotentiallyCompletedTransferEnd;
  2329. }
  2330. //
  2331. // If there was an error on the channel, then update the USB transfer's
  2332. // error state.
  2333. //
  2334. Errors = Interrupts & DWHCI_CHANNEL_INTERRUPT_ERROR_MASK;
  2335. if (Errors != 0) {
  2336. *RemoveSet = TRUE;
  2337. UsbTransfer->Status = STATUS_DEVICE_IO_ERROR;
  2338. if ((Errors & DWHCI_CHANNEL_INTERRUPT_STALL) != 0) {
  2339. UsbTransfer->Error = UsbErrorTransferStalled;
  2340. } else if ((Errors & DWHCI_CHANNEL_INTERRUPT_TRANSACTION_ERROR) != 0) {
  2341. UsbTransfer->Error = UsbErrorTransferCrcOrTimeoutError;
  2342. } else if ((Errors & DWHCI_CHANNEL_INTERRUPT_BABBLE_ERROR) != 0) {
  2343. UsbTransfer->Error = UsbErrorTransferBabbleDetected;
  2344. } else if ((Errors &
  2345. DWHCI_CHANNEL_INTERRUPT_DMA_BUFFER_NOT_AVAILABLE) != 0) {
  2346. UsbTransfer->Error = UsbErrorTransferDataBuffer;
  2347. } else if ((Errors & DWHCI_CHANNEL_INTERRUPT_AHB_ERROR) != 0) {
  2348. UsbTransfer->Error = UsbErrorTransferDeviceIo;
  2349. Halted = DwhcipHaltChannel(Controller, Channel);
  2350. if (Halted == FALSE) {
  2351. *RemoveSet = FALSE;
  2352. *AdvanceEndpoint = FALSE;
  2353. }
  2354. }
  2355. }
  2356. //
  2357. // If the transfer completed, then update the USB transfer's size. It is
  2358. // only valid if the complete bit is set.
  2359. //
  2360. if ((Interrupts & DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE) != 0) {
  2361. //
  2362. // For IN transfes, the channel token contains the number of unwritten
  2363. // bytes in the transfer buffer.
  2364. //
  2365. if (Transfer->InTransfer != FALSE) {
  2366. BytesRemaining = (Token & DWHCI_CHANNEL_TOKEN_TRANSFER_SIZE_MASK) >>
  2367. DWHCI_CHANNEL_TOKEN_TRANSFER_SIZE_SHIFT;
  2368. LengthTransferred = Transfer->TransferLength - BytesRemaining;
  2369. //
  2370. // For completed OUT transfers, it is assumed that all the bytes were
  2371. // accepted. There are no bytes remaining.
  2372. //
  2373. } else {
  2374. LengthTransferred = Transfer->TransferLength;
  2375. }
  2376. UsbTransfer->LengthTransferred += LengthTransferred;
  2377. //
  2378. // If the whole set is not already scheduled for removal, process the
  2379. // completed status information to decided what happens to the transfer
  2380. // and/or its set.
  2381. //
  2382. if (*RemoveSet == FALSE) {
  2383. if (Transfer->LastTransfer != FALSE) {
  2384. *RemoveSet = TRUE;
  2385. } else if (LengthTransferred != Transfer->TransferLength) {
  2386. TransferShorted = TRUE;
  2387. } else {
  2388. RemoveTransfer = TRUE;
  2389. }
  2390. }
  2391. }
  2392. //
  2393. // For shorted transfers, either skip ahead to the status phase of a
  2394. // control transfer or just return that the whole set should be removed.
  2395. //
  2396. if (TransferShorted != FALSE) {
  2397. if (Endpoint->TransferType == UsbTransferTypeControl) {
  2398. *RemoveSet = FALSE;
  2399. //
  2400. // The last entry in the transfer set should be the status transfer.
  2401. //
  2402. TransferSet = Transfer->Set;
  2403. ASSERT(LIST_EMPTY(&(TransferSet->TransferListHead)) == FALSE);
  2404. StatusTransfer = LIST_VALUE(TransferSet->TransferListHead.Previous,
  2405. DWHCI_TRANSFER,
  2406. SetListEntry);
  2407. ASSERT(StatusTransfer->LastTransfer != FALSE);
  2408. //
  2409. // Remove everything from the list by simply re-initializing it and
  2410. // then re-insert the status transfer as the only transfer.
  2411. //
  2412. INITIALIZE_LIST_HEAD(&(TransferSet->TransferListHead));
  2413. INSERT_BEFORE(&(StatusTransfer->SetListEntry),
  2414. &(TransferSet->TransferListHead));
  2415. } else {
  2416. *RemoveSet = TRUE;
  2417. }
  2418. //
  2419. // Otherwise remove the single transfer if necessary.
  2420. //
  2421. } else if (RemoveTransfer != FALSE) {
  2422. LIST_REMOVE(&(Transfer->SetListEntry));
  2423. }
  2424. ProcessPotentiallyCompletedTransferEnd:
  2425. return;
  2426. }
  2427. VOID
  2428. DwhcipRemoveTransferSet (
  2429. PDWHCI_CONTROLLER Controller,
  2430. PDWHCI_TRANSFER_SET TransferSet
  2431. )
  2432. /*++
  2433. Routine Description:
  2434. This routine removes a transfer set from the schedule. This routine
  2435. assumes that the controller lock is already held.
  2436. Arguments:
  2437. Controller - Supplies a pointer to the controller being operated on.
  2438. TransferSet - Supplies a pointer to the set of transfers to remove.
  2439. Return Value:
  2440. None.
  2441. --*/
  2442. {
  2443. LIST_REMOVE(&(TransferSet->EndpointListEntry));
  2444. TransferSet->EndpointListEntry.Next = NULL;
  2445. return;
  2446. }
  2447. VOID
  2448. DwhcipProcessSplitEndpoint (
  2449. PDWHCI_CONTROLLER Controller,
  2450. PDWHCI_ENDPOINT Endpoint,
  2451. PULONG Interrupts
  2452. )
  2453. /*++
  2454. Routine Description:
  2455. This routine pre-processes a potentially completed transfer for an endpoint
  2456. that must use split transfers.
  2457. Arguments:
  2458. Controller - Supplies a pointer to the controller state of the DWHCI host
  2459. controller whose got a split endpoint with a potentially completed
  2460. transfer.
  2461. Endpoint - Supplies a pointer to an endpoint that sends split transfers.
  2462. Interrupts - Supplies a pointer to the interrupt state for the endpoint's
  2463. associated channel. This routine may modify the interrupt state.
  2464. Return Value:
  2465. None.
  2466. --*/
  2467. {
  2468. ULONG EndFrame;
  2469. ULONG Frame;
  2470. ULONG LocalInterrupts;
  2471. PDWHCI_TRANSFER Transfer;
  2472. ASSERT(Endpoint->SplitControl != 0);
  2473. LocalInterrupts = *Interrupts;
  2474. //
  2475. // Get the active transfer on this endpoint.
  2476. //
  2477. Transfer = DwhcipGetEndpointTransfer(Endpoint);
  2478. ASSERT(Transfer != NULL);
  2479. //
  2480. // If this is a start split there are three possible paths: NAK, ACK, or an
  2481. // error.
  2482. //
  2483. if (Transfer->CompleteSplitCount == 0) {
  2484. //
  2485. // A maximum of 3 errors are allowed. If the are fewer than three
  2486. // errors for this transfer, then mask out the errors and retry the
  2487. // start split.
  2488. //
  2489. if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_ERROR_MASK) != 0) {
  2490. Transfer->ErrorCount += 1;
  2491. if (Transfer->ErrorCount < DWHCI_SPLIT_ERROR_MAX) {
  2492. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_ERROR_MASK;
  2493. }
  2494. //
  2495. // An ACK on a start split rolls over to the complete split.
  2496. //
  2497. } else if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_ACK) != 0) {
  2498. Transfer->CompleteSplitCount = 1;
  2499. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE;
  2500. //
  2501. // A NAK on a start split should retry the start split.
  2502. //
  2503. } else if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NAK) != 0) {
  2504. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE;
  2505. }
  2506. //
  2507. // If this is a complete split, then there are five possible paths: NAK,
  2508. // ACK, stall, error, and 'not yet'.
  2509. //
  2510. } else {
  2511. //
  2512. // A stall should cause the transfer to just abort. Set the errors to
  2513. // the max.
  2514. //
  2515. if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_STALL) != 0) {
  2516. Transfer->ErrorCount = DWHCI_SPLIT_ERROR_MAX;
  2517. }
  2518. //
  2519. // A maximum of 3 errors are allowed. If the are fewer than three
  2520. // errors on this endpoint, then mask out the errors. Control and bulk
  2521. // data toggle errors cause the start split to be retried.
  2522. //
  2523. if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_ERROR_MASK) != 0) {
  2524. Transfer->ErrorCount += 1;
  2525. if (Transfer->ErrorCount < DWHCI_SPLIT_ERROR_MAX) {
  2526. if (((Endpoint->TransferType == UsbTransferTypeBulk) ||
  2527. (Endpoint->TransferType == UsbTransferTypeControl)) &&
  2528. ((LocalInterrupts &
  2529. DWHCI_CHANNEL_INTERRUPT_DATA_TOGGLE_ERROR) != 0)) {
  2530. Transfer->CompleteSplitCount = 0;
  2531. Transfer->ErrorCount = 0;
  2532. }
  2533. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_ERROR_MASK;
  2534. }
  2535. //
  2536. // An ACK on a complete split should finish the transfer.
  2537. //
  2538. } else if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_ACK) != 0) {
  2539. LocalInterrupts |= DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE;
  2540. //
  2541. // A NAK on the complete split causes the start split to be retried.
  2542. //
  2543. } else if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NAK) != 0) {
  2544. Transfer->CompleteSplitCount = 0;
  2545. Transfer->ErrorCount = 0;
  2546. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE;
  2547. //
  2548. // A NYET on the complete split should retry the complete split.
  2549. //
  2550. } else if ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NOT_YET) != 0) {
  2551. LocalInterrupts &= ~DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE;
  2552. //
  2553. // Interrupt endpoints are the exception. If this is not the last
  2554. // (3rd) complete split or the complete split window has not passed,
  2555. // then NYETs indicate that the complete split should be tried
  2556. // again. Otherwise NYETs count towards the error count and the
  2557. // start split is tried again if the maximum error is yet to be
  2558. // reached.
  2559. //
  2560. if (Endpoint->TransferType == UsbTransferTypeInterrupt) {
  2561. Frame = DWHCI_READ_FRAME_NUMBER(Controller);
  2562. EndFrame = (Endpoint->StartFrame +
  2563. DWHCI_SPLIT_NOT_YET_FRAME_WINDOW) &
  2564. DWHCI_FRAME_NUMBER_MAX;
  2565. if (DWHCI_FRAME_LESS_THAN(EndFrame, Frame) != FALSE) {
  2566. LocalInterrupts |=
  2567. DWHCI_CHANNEL_INTERRUPT_TRANSACTION_ERROR;
  2568. Transfer->CompleteSplitCount = 0;
  2569. } else if (Transfer->CompleteSplitCount >=
  2570. DWHCI_COMPLETE_SPLIT_MAX) {
  2571. Transfer->ErrorCount += 1;
  2572. if (Transfer->ErrorCount >= DWHCI_SPLIT_ERROR_MAX) {
  2573. LocalInterrupts |=
  2574. DWHCI_CHANNEL_INTERRUPT_TRANSACTION_ERROR;
  2575. }
  2576. Transfer->CompleteSplitCount = 0;
  2577. } else {
  2578. Transfer->CompleteSplitCount += 1;
  2579. }
  2580. }
  2581. }
  2582. }
  2583. *Interrupts = LocalInterrupts;
  2584. return;
  2585. }
  2586. VOID
  2587. DwhcipProcessPingEndpoint (
  2588. PDWHCI_CONTROLLER Controller,
  2589. PDWHCI_ENDPOINT Endpoint,
  2590. PULONG Interrupts
  2591. )
  2592. /*++
  2593. Routine Description:
  2594. This routine pre-processes a potentially completed transfer for an endpoint
  2595. that must use PING protocol.
  2596. Arguments:
  2597. Controller - Supplies a pointer to the controller state of the DWHCI host
  2598. controller whose got a high speed bulk or control endpoint with a
  2599. potentially completed transfer.
  2600. Endpoint - Supplies a pointer to an endpoint that implements the PING
  2601. protocol.
  2602. Interrupts - Supplies a pointer to the interrupt state for the endpoint's
  2603. associated channel. This routine may modify the interrupt state.
  2604. Return Value:
  2605. None.
  2606. --*/
  2607. {
  2608. ULONG LocalInterrupts;
  2609. PDWHCI_TRANSFER NextTransfer;
  2610. PDWHCI_TRANSFER Transfer;
  2611. PDWHCI_TRANSFER_SET TransferSet;
  2612. ASSERT(Endpoint->Speed == UsbDeviceSpeedHigh);
  2613. ASSERT((Endpoint->TransferType == UsbTransferTypeBulk) ||
  2614. (Endpoint->TransferType == UsbTransferTypeControl));
  2615. ASSERT(Endpoint->SplitControl == 0);
  2616. LocalInterrupts = *Interrupts;
  2617. //
  2618. // Get the active transfer on this endpoint.
  2619. //
  2620. Transfer = DwhcipGetEndpointTransfer(Endpoint);
  2621. ASSERT(Transfer != NULL);
  2622. TransferSet = Transfer->Set;
  2623. //
  2624. // IN endpoints do not implement the PING protocol.
  2625. //
  2626. if (TransferSet->UsbTransfer->Public.Direction == UsbTransferDirectionIn) {
  2627. return;
  2628. }
  2629. //
  2630. // Newer revisions do not require manual handling of the PING protocol.
  2631. //
  2632. if (Controller->Revision >= DWHCI_AUTOMATIC_PING_REVISION_MININUM) {
  2633. return;
  2634. }
  2635. ASSERT(Endpoint->PingRequired == FALSE);
  2636. //
  2637. // For OUT bulk transfers, NAKs and NYETs require that the PING protocol
  2638. // should be triggered on the next transfer for the endpoint.
  2639. //
  2640. if (Endpoint->TransferType == UsbTransferTypeBulk) {
  2641. if (((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NAK) != 0) ||
  2642. ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NOT_YET) != 0)) {
  2643. Endpoint->PingRequired = TRUE;
  2644. }
  2645. //
  2646. // For control transfers, the PING protocol is only required on OUT data or
  2647. // status phases so separate this between SETUP and not setup.
  2648. //
  2649. } else {
  2650. ASSERT(Endpoint->TransferType == UsbTransferTypeControl);
  2651. //
  2652. // The PING protocol is not supported for the SETUP phase. If this is
  2653. // the setup phase completing, then potentially set PING for the next
  2654. // transfer, if it is OUT.
  2655. //
  2656. if ((Transfer->Token & DWHCI_CHANNEL_TOKEN_PID_MASK) ==
  2657. DWHCI_CHANNEL_TOKEN_PID_CODE_SETUP) {
  2658. if ((LocalInterrupts &
  2659. DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE) != 0) {
  2660. ASSERT(Transfer->SetListEntry.Next !=
  2661. &(TransferSet->TransferListHead));
  2662. NextTransfer = LIST_VALUE(Transfer->SetListEntry.Next,
  2663. DWHCI_TRANSFER,
  2664. SetListEntry);
  2665. if (NextTransfer->InTransfer == FALSE) {
  2666. Endpoint->PingRequired = TRUE;
  2667. }
  2668. }
  2669. //
  2670. // Handle DATA transfers.
  2671. //
  2672. } else if (Transfer->LastTransfer == FALSE) {
  2673. //
  2674. // A DATA OUT that did not complete and sent NAK or NYET requires
  2675. // a PING when the transfer is resent. Completed DATA OUTs do not
  2676. // need to set the PING, because the status phase goes in the
  2677. // opposite direction.
  2678. //
  2679. if ((Transfer->InTransfer == FALSE) &&
  2680. (((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NAK) != 0) ||
  2681. ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NOT_YET) != 0))) {
  2682. ASSERT((LocalInterrupts &
  2683. DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE) == 0);
  2684. Endpoint->PingRequired = TRUE;
  2685. //
  2686. // Otherwise a completed DATA IN will transfer to the status phase,
  2687. // which should begin with the PING protocol, as it is an OUT
  2688. // transfer.
  2689. //
  2690. } else if ((Transfer->InTransfer != FALSE) &&
  2691. ((LocalInterrupts &
  2692. DWHCI_CHANNEL_INTERRUPT_TRANSFER_COMPLETE) != 0)) {
  2693. Endpoint->PingRequired = TRUE;
  2694. }
  2695. //
  2696. // Handle OUT status phases.
  2697. //
  2698. } else if ((Transfer->LastTransfer != FALSE) &&
  2699. (Transfer->InTransfer == FALSE)) {
  2700. //
  2701. // If the OUT status phase NAKs or NYETs, then the PING protocol
  2702. // needs to be invoked on the retry.
  2703. //
  2704. if (((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NAK) != 0) ||
  2705. ((LocalInterrupts & DWHCI_CHANNEL_INTERRUPT_NOT_YET) != 0)) {
  2706. Endpoint->PingRequired = TRUE;
  2707. }
  2708. }
  2709. }
  2710. return;
  2711. }
  2712. VOID
  2713. DwhcipFillOutTransferDescriptor (
  2714. PDWHCI_CONTROLLER Controller,
  2715. PDWHCI_TRANSFER_SET TransferSet,
  2716. PDWHCI_TRANSFER DwhciTransfer,
  2717. ULONG Offset,
  2718. ULONG Length,
  2719. BOOL LastTransfer
  2720. )
  2721. /*++
  2722. Routine Description:
  2723. This routine fills out an DWHCI transfer descriptor.
  2724. Arguments:
  2725. Controller - Supplies a pointer to the DWHCI controller.
  2726. TransferSet - Supplies a pointer to the transfer set this transfer belongs
  2727. to.
  2728. DwhciTransfer - Supplies a pointer to DWHCI's transfer descriptor
  2729. information.
  2730. Offset - Supplies the offset from the public transfer physical address that
  2731. this transfer descriptor should be initialize to.
  2732. Length - Supplies the length of the transfer, in bytes.
  2733. LastTransfer - Supplies a boolean indicating if this transfer descriptor
  2734. represents the last transfer in a set. For control transfers, this is
  2735. the status phase where the in/out is reversed and the length had better
  2736. be zero.
  2737. Return Value:
  2738. None.
  2739. --*/
  2740. {
  2741. PDWHCI_ENDPOINT Endpoint;
  2742. ULONG PacketCount;
  2743. UCHAR PidCode;
  2744. ULONG Token;
  2745. PUSB_TRANSFER_INTERNAL Transfer;
  2746. Endpoint = TransferSet->Endpoint;
  2747. Transfer = TransferSet->UsbTransfer;
  2748. DwhciTransfer->LastTransfer = FALSE;
  2749. DwhciTransfer->TransferLength = Length;
  2750. DwhciTransfer->Set = TransferSet;
  2751. DwhciTransfer->ErrorCount = 0;
  2752. DwhciTransfer->PhysicalAddress = Transfer->Public.BufferPhysicalAddress +
  2753. Offset;
  2754. //
  2755. // The first packet in a control transfer is always a setup packet and is
  2756. // not an IN transfer.
  2757. //
  2758. PidCode = 0;
  2759. if ((Endpoint->TransferType == UsbTransferTypeControl) && (Offset == 0)) {
  2760. PidCode = DWHCI_PID_CODE_SETUP;
  2761. DwhciTransfer->InTransfer = FALSE;
  2762. //
  2763. // Do it backwards if this is the status phase. Status phases always have
  2764. // a data toggle of 1 and the transfer direction is opposite that of the
  2765. // transfer. The exception is if there was no data phase for the control
  2766. // transfer - just the setup and status phases. In that case, the status
  2767. // phase is always in the IN direction.
  2768. //
  2769. } else if ((Endpoint->TransferType == UsbTransferTypeControl) &&
  2770. (LastTransfer != FALSE)) {
  2771. ASSERT(Length == 0);
  2772. PidCode = DWHCI_PID_CODE_DATA_1;
  2773. if (Offset == sizeof(USB_SETUP_PACKET)) {
  2774. DwhciTransfer->InTransfer = TRUE;
  2775. } else if (Transfer->Public.Direction == UsbTransferDirectionIn) {
  2776. DwhciTransfer->InTransfer = FALSE;
  2777. } else {
  2778. ASSERT(Transfer->Public.Direction == UsbTransferDirectionOut);
  2779. DwhciTransfer->InTransfer = TRUE;
  2780. }
  2781. DwhciTransfer->PhysicalAddress =
  2782. Controller->ControlStatusBuffer->Fragment[0].PhysicalAddress;
  2783. //
  2784. // Not setup and not status, fill this out like a normal descriptor.
  2785. //
  2786. } else {
  2787. if (Transfer->Public.Direction == UsbTransferDirectionIn) {
  2788. DwhciTransfer->InTransfer = TRUE;
  2789. } else {
  2790. ASSERT(Transfer->Public.Direction == UsbTransferDirectionOut);
  2791. DwhciTransfer->InTransfer = FALSE;
  2792. }
  2793. }
  2794. //
  2795. // Determine which channel interrupts to set.
  2796. //
  2797. switch (Endpoint->TransferType) {
  2798. case UsbTransferTypeIsochronous:
  2799. //
  2800. // TODO: Implement support for isochronous transfers.
  2801. //
  2802. ASSERT(FALSE);
  2803. break;
  2804. case UsbTransferTypeInterrupt:
  2805. case UsbTransferTypeControl:
  2806. case UsbTransferTypeBulk:
  2807. DwhciTransfer->InterruptMask = DWHCI_CHANNEL_INTERRUPT_HALTED |
  2808. DWHCI_CHANNEL_INTERRUPT_AHB_ERROR;
  2809. break;
  2810. default:
  2811. ASSERT(FALSE);
  2812. break;
  2813. }
  2814. //
  2815. // If this transfer uses the split procotol, it will always begin with the
  2816. // start split (i.e. a complete split count of zero).
  2817. //
  2818. DwhciTransfer->CompleteSplitCount = 0;
  2819. //
  2820. // Determine the number of packets in the transfer.
  2821. //
  2822. PacketCount = 1;
  2823. if (DwhciTransfer->TransferLength > Endpoint->MaxPacketSize) {
  2824. PacketCount = DwhciTransfer->TransferLength / Endpoint->MaxPacketSize;
  2825. if ((DwhciTransfer->TransferLength % Endpoint->MaxPacketSize) != 0) {
  2826. PacketCount += 1;
  2827. }
  2828. }
  2829. ASSERT(PacketCount <= Endpoint->MaxPacketCount);
  2830. //
  2831. // Initialize the token that is to be written to a channel's transfer setup
  2832. // register when submitting this transfer.
  2833. //
  2834. Token = (PacketCount << DWHCI_CHANNEL_TOKEN_PACKET_COUNT_SHIFT) &
  2835. DWHCI_CHANNEL_TOKEN_PACKET_COUNT_MASK;
  2836. Token |= (PidCode << DWHCI_CHANNEL_TOKEN_PID_SHIFT) &
  2837. DWHCI_CHANNEL_TOKEN_PID_MASK;
  2838. Token |= (DwhciTransfer->TransferLength <<
  2839. DWHCI_CHANNEL_TOKEN_TRANSFER_SIZE_SHIFT) &
  2840. DWHCI_CHANNEL_TOKEN_TRANSFER_SIZE_MASK;
  2841. DwhciTransfer->Token = Token;
  2842. //
  2843. // Add the transfer into the transfer set's queue.
  2844. //
  2845. INSERT_BEFORE(&(DwhciTransfer->SetListEntry),
  2846. &(TransferSet->TransferListHead));
  2847. if ((DwhciDebugFlags & DWHCI_DEBUG_FLAG_TRANSFERS) != 0) {
  2848. RtlDebugPrint("DWHCI: Adding transfer (0x%08x) to endpoint (0x%08x): "
  2849. "TOKEN 0x%x, IN 0x%x, LAST 0x%x, INT 0x%08x, "
  2850. "LENGTH 0x%x.\n",
  2851. DwhciTransfer,
  2852. Endpoint,
  2853. DwhciTransfer->Token,
  2854. DwhciTransfer->InTransfer,
  2855. DwhciTransfer->LastTransfer,
  2856. DwhciTransfer->InterruptMask,
  2857. DwhciTransfer->TransferLength);
  2858. }
  2859. return;
  2860. }
  2861. VOID
  2862. DwhcipProcessSchedule (
  2863. PDWHCI_CONTROLLER Controller,
  2864. BOOL PeriodicOnly
  2865. )
  2866. /*++
  2867. Routine Description:
  2868. This routine processes any pending activity on the given host controller's
  2869. periodic and non-periodic schedules. If there are channels available to
  2870. schedule work on, then work will be scheduled. This routine expects the
  2871. controller lock to be held.
  2872. Arguments:
  2873. Controller - Supplies a pointer to the state for the DWHCI controller
  2874. whose schedule needs to be processed.
  2875. PeriodicOnly - Supplies a boolean indicating whether or not to only schedule
  2876. periodic transfers.
  2877. Return Value:
  2878. None.
  2879. --*/
  2880. {
  2881. PLIST_ENTRY CurrentEntry;
  2882. PDWHCI_ENDPOINT Endpoint;
  2883. KSTATUS Status;
  2884. //
  2885. // If there are any periodic endpoints waiting to be assigned a channel,
  2886. // then try to move the endpoints from the ready list to the active list.
  2887. //
  2888. while (LIST_EMPTY(&(Controller->PeriodicReadyListHead)) == FALSE) {
  2889. Endpoint = LIST_VALUE(Controller->PeriodicReadyListHead.Next,
  2890. DWHCI_ENDPOINT,
  2891. ListEntry);
  2892. //
  2893. // Initialize the channel to accept transfers from this endpoint.
  2894. //
  2895. Status = DwhcipAllocateChannel(Controller, Endpoint);
  2896. if (!KSUCCESS(Status)) {
  2897. break;
  2898. }
  2899. LIST_REMOVE(&(Endpoint->ListEntry));
  2900. INSERT_BEFORE(&(Endpoint->ListEntry),
  2901. &(Controller->PeriodicActiveListHead));
  2902. }
  2903. //
  2904. // Process the active periodic endpoint list to try to push them through
  2905. // the periodic queue.
  2906. //
  2907. CurrentEntry = Controller->PeriodicActiveListHead.Next;
  2908. while (CurrentEntry != &(Controller->PeriodicActiveListHead)) {
  2909. Endpoint = LIST_VALUE(CurrentEntry, DWHCI_ENDPOINT, ListEntry);
  2910. CurrentEntry = CurrentEntry->Next;
  2911. if (Endpoint->Scheduled != FALSE) {
  2912. continue;
  2913. }
  2914. DwhcipScheduleTransfer(Controller, Endpoint);
  2915. }
  2916. //
  2917. // If only the periodic schedule was requested to be processed, then exit
  2918. // immediately.
  2919. //
  2920. if (PeriodicOnly != FALSE) {
  2921. return;
  2922. }
  2923. //
  2924. // If there are any non-periodic endpoints waiting to be assigned a
  2925. // channel, then try to move the endpoints from the ready list to the
  2926. // active list.
  2927. //
  2928. while (LIST_EMPTY(&(Controller->NonPeriodicReadyListHead)) == FALSE) {
  2929. Endpoint = LIST_VALUE(Controller->NonPeriodicReadyListHead.Next,
  2930. DWHCI_ENDPOINT,
  2931. ListEntry);
  2932. //
  2933. // Initialize the channel to accept transfers from this endpoint.
  2934. //
  2935. Status = DwhcipAllocateChannel(Controller, Endpoint);
  2936. if (!KSUCCESS(Status)) {
  2937. break;
  2938. }
  2939. LIST_REMOVE(&(Endpoint->ListEntry));
  2940. INSERT_BEFORE(&(Endpoint->ListEntry),
  2941. &(Controller->NonPeriodicActiveListHead));
  2942. }
  2943. //
  2944. // Process the active non-periodic endpoint list to try to push them
  2945. // through the non-periodic queue.
  2946. //
  2947. CurrentEntry = Controller->NonPeriodicActiveListHead.Next;
  2948. while (CurrentEntry != &(Controller->NonPeriodicActiveListHead)) {
  2949. Endpoint = LIST_VALUE(CurrentEntry, DWHCI_ENDPOINT, ListEntry);
  2950. CurrentEntry = CurrentEntry->Next;
  2951. if (Endpoint->Scheduled != FALSE) {
  2952. continue;
  2953. }
  2954. DwhcipScheduleTransfer(Controller, Endpoint);
  2955. }
  2956. return;
  2957. }
  2958. KSTATUS
  2959. DwhcipAllocateChannel (
  2960. PDWHCI_CONTROLLER Controller,
  2961. PDWHCI_ENDPOINT Endpoint
  2962. )
  2963. /*++
  2964. Routine Description:
  2965. This routine allocates a channel for use by the given endpoint.
  2966. Arguments:
  2967. Controller - Supplies a pointer to the state of the DWHCI controller from
  2968. which to allocate a channel.
  2969. Endpoint - Supplies a pointer to the DWHCI endpoint that is to be assigned
  2970. to the channel.
  2971. Return Value:
  2972. Status code.
  2973. --*/
  2974. {
  2975. PDWHCI_CHANNEL Channel;
  2976. //
  2977. // If the free channel list is empty, then exit immediately.
  2978. //
  2979. if (LIST_EMPTY(&(Controller->FreeChannelListHead)) != FALSE) {
  2980. return STATUS_RESOURCE_IN_USE;
  2981. }
  2982. //
  2983. // If this is a periodic endpoint and there is only one channel left, exit,
  2984. // allowing the non-periodic endpoints some guaranteed progress.
  2985. //
  2986. if ((Controller->FreeChannelListHead.Next ==
  2987. Controller->FreeChannelListHead.Previous) &&
  2988. ((Endpoint->TransferType == UsbTransferTypeInterrupt) ||
  2989. (Endpoint->TransferType == UsbTransferTypeIsochronous))) {
  2990. return STATUS_RESOURCE_IN_USE;
  2991. }
  2992. //
  2993. // Allocate the first channel in the free list.
  2994. //
  2995. Channel = LIST_VALUE(Controller->FreeChannelListHead.Next,
  2996. DWHCI_CHANNEL,
  2997. FreeListEntry);
  2998. LIST_REMOVE(&(Channel->FreeListEntry));
  2999. ASSERT(Channel->Endpoint == NULL);
  3000. //
  3001. // Associate the allocated channel with the given endpoint.
  3002. //
  3003. Channel->Endpoint = Endpoint;
  3004. Endpoint->Channel = Channel;
  3005. return STATUS_SUCCESS;
  3006. }
  3007. VOID
  3008. DwhcipFreeChannel (
  3009. PDWHCI_CONTROLLER Controller,
  3010. PDWHCI_CHANNEL Channel
  3011. )
  3012. /*++
  3013. Routine Description:
  3014. This routine frees the given channel from use by an endpoint.
  3015. Arguments:
  3016. Controller - Supplies a pointer to the state of the DWHCI controller from
  3017. which to allocate a channel.
  3018. Channel - Supplies a pointer to the DWHCI channel that is to be released.
  3019. Return Value:
  3020. None.
  3021. --*/
  3022. {
  3023. ASSERT(Channel->Endpoint != NULL);
  3024. Channel->Endpoint->Channel = NULL;
  3025. Channel->Endpoint = NULL;
  3026. INSERT_BEFORE(&(Channel->FreeListEntry),
  3027. &(Controller->FreeChannelListHead));
  3028. return;
  3029. }
  3030. VOID
  3031. DwhcipScheduleTransfer (
  3032. PDWHCI_CONTROLLER Controller,
  3033. PDWHCI_ENDPOINT Endpoint
  3034. )
  3035. /*++
  3036. Routine Description:
  3037. This routine schedules the next transfer for the given endpoint.
  3038. Arguments:
  3039. Controller - Supplies a pointer to the state of the DWHCI controller to
  3040. which the endpoint belongs.
  3041. Endpoint - Supplies a pointer to the endpoint whose next transfer is to be
  3042. scheduled.
  3043. Return Value:
  3044. None.
  3045. --*/
  3046. {
  3047. PDWHCI_CHANNEL Channel;
  3048. ULONG Control;
  3049. ULONG Frame;
  3050. ULONG Interrupts;
  3051. ULONG SplitControl;
  3052. KSTATUS Status;
  3053. ULONG Token;
  3054. PDWHCI_TRANSFER Transfer;
  3055. ASSERT(Endpoint->Channel != NULL);
  3056. Channel = Endpoint->Channel;
  3057. //
  3058. // Find the next transfer for this endpoint. This transfer is the first
  3059. // transfer in the first transfer set.
  3060. //
  3061. Transfer = DwhcipGetEndpointTransfer(Endpoint);
  3062. ASSERT(Transfer != NULL);
  3063. //
  3064. // Initialize the host channel for use by the endpoint. Start by clearing
  3065. // any interrupts on the channel.
  3066. //
  3067. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3068. DwhciChannelRegisterInterrupt,
  3069. Channel->ChannelNumber,
  3070. 0xFFFFFFFF);
  3071. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3072. DwhciChannelRegisterInterruptMask,
  3073. Channel->ChannelNumber,
  3074. Transfer->InterruptMask);
  3075. //
  3076. // Enable host level interrupts for this channel.
  3077. //
  3078. Interrupts = DWHCI_READ_REGISTER(Controller,
  3079. DwhciRegisterHostChannelInterruptMask);
  3080. Interrupts |= (1 << Channel->ChannelNumber);
  3081. DWHCI_WRITE_REGISTER(Controller,
  3082. DwhciRegisterHostChannelInterruptMask,
  3083. Interrupts);
  3084. //
  3085. // If this is a full or low-speed device, then configure the split register.
  3086. //
  3087. Token = Transfer->Token;
  3088. SplitControl = Endpoint->SplitControl;
  3089. if (SplitControl != 0) {
  3090. ASSERT((Endpoint->Speed == UsbDeviceSpeedLow) ||
  3091. (Endpoint->Speed == UsbDeviceSpeedFull));
  3092. ASSERT((SplitControl & DWHCI_CHANNEL_SPLIT_CONTROL_ENABLE) != 0);
  3093. if (Transfer->CompleteSplitCount != 0) {
  3094. if (Transfer->InTransfer == FALSE) {
  3095. Token &= ~DWHCI_CHANNEL_TOKEN_TRANSFER_SIZE_MASK;
  3096. }
  3097. SplitControl |= DWHCI_CHANNEL_SPLIT_CONTROL_COMPLETE_SPLIT;
  3098. //
  3099. // Interrupt start splits are not allowed to be started in the 6th
  3100. // microframe.
  3101. //
  3102. } else if (Endpoint->TransferType == UsbTransferTypeInterrupt) {
  3103. Frame = DWHCI_READ_FRAME_NUMBER(Controller);
  3104. if ((Frame & 0x7) == 0x6) {
  3105. Status = STATUS_TRY_AGAIN;
  3106. goto ScheduleTransferEnd;
  3107. }
  3108. Endpoint->StartFrame = Frame;
  3109. }
  3110. }
  3111. //
  3112. // Setup up the transfer register based on the transfer token. This
  3113. // includes information on the transfer length, the PID, and number of
  3114. // packets. If the PID is preset in the token, then use what is there,
  3115. // otherwise use the current toggle pid stored in the endpoint.
  3116. //
  3117. if ((Transfer->Token & DWHCI_CHANNEL_TOKEN_PID_MASK) == 0) {
  3118. Token |= (Endpoint->DataToggle << DWHCI_CHANNEL_TOKEN_PID_SHIFT) &
  3119. DWHCI_CHANNEL_TOKEN_PID_MASK;
  3120. } else {
  3121. ASSERT(Endpoint->TransferType == UsbTransferTypeControl);
  3122. }
  3123. //
  3124. // Set the PING protocol bit in the token if required.
  3125. //
  3126. if (Endpoint->PingRequired != FALSE) {
  3127. ASSERT(Transfer->InTransfer == FALSE);
  3128. ASSERT(Endpoint->Speed == UsbDeviceSpeedHigh);
  3129. ASSERT((Endpoint->TransferType == UsbTransferTypeBulk) ||
  3130. (Endpoint->TransferType == UsbTransferTypeControl));
  3131. ASSERT((Endpoint->TransferType != UsbTransferTypeControl) ||
  3132. ((Token & DWHCI_CHANNEL_TOKEN_PID_MASK) !=
  3133. DWHCI_CHANNEL_TOKEN_PID_CODE_SETUP));
  3134. Token |= DWHCI_CHANNEL_TOKEN_PING;
  3135. //
  3136. // Let the status of this transfer determine if another PING is
  3137. // required.
  3138. //
  3139. Endpoint->PingRequired = FALSE;
  3140. }
  3141. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3142. DwhciChannelRegisterToken,
  3143. Channel->ChannelNumber,
  3144. Token);
  3145. //
  3146. // Program the DMA register.
  3147. //
  3148. ASSERT(Transfer->PhysicalAddress == (ULONG)Transfer->PhysicalAddress);
  3149. ASSERT(IS_ALIGNED(Transfer->PhysicalAddress, DWHCI_DMA_ALIGNMENT) != FALSE);
  3150. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3151. DwhciChannelRegisterDmaAddress,
  3152. Channel->ChannelNumber,
  3153. (ULONG)Transfer->PhysicalAddress);
  3154. //
  3155. // Program the split control register.
  3156. //
  3157. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3158. DwhciChannelRegisterSplitControl,
  3159. Channel->ChannelNumber,
  3160. SplitControl);
  3161. //
  3162. // Execute the final steps, enabling the channel to handle the transfer.
  3163. //
  3164. Control = Endpoint->ChannelControl;
  3165. if (Transfer->InTransfer != FALSE) {
  3166. Control |= DWHCI_CHANNEL_CONTROL_ENDPOINT_DIRECTION_IN;
  3167. }
  3168. switch (Endpoint->TransferType) {
  3169. case UsbTransferTypeIsochronous:
  3170. case UsbTransferTypeInterrupt:
  3171. //
  3172. // Set the odd frame bit if the current frame is even.
  3173. //
  3174. Frame = DWHCI_READ_FRAME_NUMBER(Controller);
  3175. if ((Frame & 0x1) == 0) {
  3176. Control |= DWHCI_CHANNEL_CONTROL_ODD_FRAME;
  3177. }
  3178. break;
  3179. case UsbTransferTypeControl:
  3180. case UsbTransferTypeBulk:
  3181. break;
  3182. default:
  3183. ASSERT(FALSE);
  3184. break;
  3185. }
  3186. ASSERT((Control & DWHCI_CHANNEL_CONTROL_ENABLE) != 0);
  3187. ASSERT((Control & DWHCI_CHANNEL_CONTROL_DISABLE) == 0);
  3188. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3189. DwhciChannelRegisterControl,
  3190. Channel->ChannelNumber,
  3191. Control);
  3192. Endpoint->Scheduled = TRUE;
  3193. Status = STATUS_SUCCESS;
  3194. ScheduleTransferEnd:
  3195. if (!KSUCCESS(Status)) {
  3196. //
  3197. // Disable interrupts for this channel.
  3198. //
  3199. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3200. DwhciChannelRegisterInterruptMask,
  3201. Channel->ChannelNumber,
  3202. 0);
  3203. Interrupts = DWHCI_READ_REGISTER(Controller,
  3204. DwhciRegisterHostChannelInterruptMask);
  3205. Interrupts &= ~(1 << Channel->ChannelNumber);
  3206. DWHCI_WRITE_REGISTER(Controller,
  3207. DwhciRegisterHostChannelInterruptMask,
  3208. Interrupts);
  3209. //
  3210. // This should be an interrupt endpoint and it needs to try again. Just
  3211. // move it back to the inactive list and trigger the start-of-frame
  3212. // interrupt. Release the channel as well.
  3213. //
  3214. ASSERT(Status == STATUS_TRY_AGAIN);
  3215. ASSERT(Endpoint->TransferType == UsbTransferTypeInterrupt);
  3216. LIST_REMOVE(&(Endpoint->ListEntry));
  3217. if (LIST_EMPTY(&(Controller->PeriodicInactiveListHead)) != FALSE) {
  3218. Interrupts = DWHCI_READ_REGISTER(Controller,
  3219. DwhciRegisterCoreInterruptMask);
  3220. Interrupts |= DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  3221. DWHCI_WRITE_REGISTER(Controller,
  3222. DwhciRegisterCoreInterruptMask,
  3223. Interrupts);
  3224. }
  3225. INSERT_BEFORE(&(Endpoint->ListEntry),
  3226. &(Controller->PeriodicInactiveListHead));
  3227. DwhcipFreeChannel(Controller, Endpoint->Channel);
  3228. Endpoint->Scheduled = FALSE;
  3229. }
  3230. return;
  3231. }
  3232. VOID
  3233. DwhcipAdvanceEndpoint (
  3234. PDWHCI_CONTROLLER Controller,
  3235. PDWHCI_ENDPOINT Endpoint
  3236. )
  3237. /*++
  3238. Routine Description:
  3239. This routine prepares the given endpoint for its next transfer. This may
  3240. or may not release the channel. This routine assumes that the caller
  3241. will process the host controller's schedule shortly after calling this
  3242. routine.
  3243. Arguments:
  3244. Controller - Supplies a pointer to the state of the DWHCI controller that
  3245. owns the given endpoint.
  3246. Endpoint - Supplies a pointer to the endpoint that needs to be advanced
  3247. to its next transfer.
  3248. Return Value:
  3249. Returns TRUE if the endpoint had been using a channel and this routine
  3250. released it. Returns FALSE otherwise.
  3251. --*/
  3252. {
  3253. ULONG Base;
  3254. PDWHCI_CHANNEL Channel;
  3255. ULONG CoreInterruptMask;
  3256. ULONG Delta;
  3257. ULONG FrameNumber;
  3258. BOOL FreeChannel;
  3259. ULONG Interrupts;
  3260. ULONG NextFrame;
  3261. BOOL PeriodicInactiveWasEmpty;
  3262. PDWHCI_TRANSFER Transfer;
  3263. Channel = Endpoint->Channel;
  3264. FreeChannel = FALSE;
  3265. //
  3266. // Disable and clear all interrupts on the current channel.
  3267. //
  3268. if (Channel != NULL) {
  3269. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3270. DwhciChannelRegisterInterruptMask,
  3271. Channel->ChannelNumber,
  3272. 0);
  3273. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3274. DwhciChannelRegisterInterrupt,
  3275. Channel->ChannelNumber,
  3276. 0xFFFFFFFF);
  3277. //
  3278. // Disable host level interrupts for this channel.
  3279. //
  3280. Interrupts = DWHCI_READ_REGISTER(Controller,
  3281. DwhciRegisterHostChannelInterruptMask);
  3282. Interrupts &= ~(1 << Channel->ChannelNumber);
  3283. DWHCI_WRITE_REGISTER(Controller,
  3284. DwhciRegisterHostChannelInterruptMask,
  3285. Interrupts);
  3286. //
  3287. // Assume that the channel will become available for other transfers.
  3288. //
  3289. FreeChannel = TRUE;
  3290. }
  3291. //
  3292. // Before the endpoint is removed, determine the state of the periodic
  3293. // inactive list.
  3294. //
  3295. PeriodicInactiveWasEmpty = FALSE;
  3296. if (LIST_EMPTY(&(Controller->PeriodicInactiveListHead)) != FALSE) {
  3297. PeriodicInactiveWasEmpty = TRUE;
  3298. }
  3299. //
  3300. // Completely remove the endpoint from the schedule.
  3301. //
  3302. LIST_REMOVE(&(Endpoint->ListEntry));
  3303. //
  3304. // If there is more work left to do on this endpoint, then add it back to
  3305. // the appropriate list.
  3306. //
  3307. if (LIST_EMPTY(&(Endpoint->TransferSetListHead)) == FALSE) {
  3308. if ((Endpoint->TransferType == UsbTransferTypeControl) ||
  3309. (Endpoint->TransferType == UsbTransferTypeBulk)) {
  3310. INSERT_BEFORE(&(Endpoint->ListEntry),
  3311. &(Controller->NonPeriodicReadyListHead));
  3312. } else {
  3313. ASSERT((Endpoint->TransferType == UsbTransferTypeInterrupt) ||
  3314. (Endpoint->TransferType == UsbTransferTypeIsochronous));
  3315. Transfer = DwhcipGetEndpointTransfer(Endpoint);
  3316. ASSERT(Transfer != NULL);
  3317. FrameNumber = DWHCI_READ_FRAME_NUMBER(Controller);
  3318. //
  3319. // When scheduling a complete split, schedule just ahead of the
  3320. // start split's microframe.
  3321. //
  3322. if (Transfer->CompleteSplitCount != 0) {
  3323. ASSERT(Endpoint->StartFrame != DWHCI_INVALID_FRAME);
  3324. Base = Endpoint->StartFrame;
  3325. Delta = 1 + Transfer->CompleteSplitCount;
  3326. //
  3327. // Otherwise the next (micro)frame is based on the current frame
  3328. // and the poll rate, which is stored in (micro)frames.
  3329. //
  3330. } else {
  3331. Base = FrameNumber;
  3332. Delta = Endpoint->PollRate;
  3333. }
  3334. NextFrame = (Base + Delta) & DWHCI_FRAME_NUMBER_MAX;
  3335. //
  3336. // Start splits are not allowed to start in the 6th microframe and
  3337. // get less time for the complete splits the later they get
  3338. // scheduled within a frame. Schedule them all for the last
  3339. // microframe.
  3340. //
  3341. if ((Endpoint->SplitControl != 0) &&
  3342. (Endpoint->TransferType == UsbTransferTypeInterrupt) &&
  3343. (Transfer->CompleteSplitCount == 0)) {
  3344. NextFrame |= DWHCI_INTERRUPT_SPLIT_FRAME_MASK;
  3345. }
  3346. Endpoint->NextFrame = NextFrame;
  3347. //
  3348. // If the next frame has already come to pass and a channel is
  3349. // assigned to the endpoint, then put the endpoint back on the
  3350. // active list and do not free the channel.
  3351. //
  3352. if ((Channel != NULL) &&
  3353. DWHCI_FRAME_GREATER_THAN_OR_EQUAL(FrameNumber, NextFrame)) {
  3354. INSERT_BEFORE(&(Endpoint->ListEntry),
  3355. &(Controller->PeriodicActiveListHead));
  3356. FreeChannel = FALSE;
  3357. //
  3358. // Otherwise the endpoint must wait for the start of the
  3359. // appropriate (micro)frame.
  3360. //
  3361. } else {
  3362. if ((Controller->NextFrame == DWHCI_INVALID_FRAME) ||
  3363. DWHCI_FRAME_LESS_THAN(NextFrame, Controller->NextFrame)) {
  3364. Controller->NextFrame = NextFrame;
  3365. }
  3366. //
  3367. // Activate the start-of-frame interrupt if the periodic
  3368. // inactive list was empty when checked above.
  3369. //
  3370. if (PeriodicInactiveWasEmpty != FALSE) {
  3371. CoreInterruptMask = DWHCI_READ_REGISTER(
  3372. Controller,
  3373. DwhciRegisterCoreInterruptMask);
  3374. CoreInterruptMask |= DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  3375. DWHCI_WRITE_REGISTER(Controller,
  3376. DwhciRegisterCoreInterruptMask,
  3377. CoreInterruptMask);
  3378. }
  3379. INSERT_BEFORE(&(Endpoint->ListEntry),
  3380. &(Controller->PeriodicInactiveListHead));
  3381. }
  3382. }
  3383. //
  3384. // Otherwise keep the endpoint off of all lists.
  3385. //
  3386. } else {
  3387. Endpoint->NextFrame = 0;
  3388. Endpoint->StartFrame = 0;
  3389. Endpoint->ListEntry.Next = NULL;
  3390. }
  3391. //
  3392. // Release the channel if the endpoint no longer needs it.
  3393. //
  3394. if ((Channel != NULL) && (FreeChannel != FALSE)) {
  3395. DwhcipFreeChannel(Controller, Channel);
  3396. }
  3397. //
  3398. // If this caused the inactive periodic list to become empty, then disable
  3399. // the start-of-frame interrupts.
  3400. //
  3401. if ((PeriodicInactiveWasEmpty == FALSE) &&
  3402. (LIST_EMPTY(&(Controller->PeriodicInactiveListHead)) != FALSE)) {
  3403. CoreInterruptMask = DWHCI_READ_REGISTER(Controller,
  3404. DwhciRegisterCoreInterruptMask);
  3405. CoreInterruptMask &= ~DWHCI_CORE_INTERRUPT_START_OF_FRAME;
  3406. DWHCI_WRITE_REGISTER(Controller,
  3407. DwhciRegisterCoreInterruptMask,
  3408. CoreInterruptMask);
  3409. Controller->NextFrame = DWHCI_INVALID_FRAME;
  3410. }
  3411. //
  3412. // Note that the endpoint is not scheduled, so that it gets picked up the
  3413. // next time the schedule is processed.
  3414. //
  3415. Endpoint->Scheduled = FALSE;
  3416. return;
  3417. }
  3418. PDWHCI_TRANSFER
  3419. DwhcipGetEndpointTransfer (
  3420. PDWHCI_ENDPOINT Endpoint
  3421. )
  3422. /*++
  3423. Routine Description:
  3424. This routine returns the first transfer in the given endpoint's queue.
  3425. Arguments:
  3426. Endpoint - Supplies a pointer to an endpoint.
  3427. Return Value:
  3428. Returns a pointer to the first transfer on the endpoint or NULL if no such
  3429. transfer exists.
  3430. --*/
  3431. {
  3432. PDWHCI_TRANSFER Transfer;
  3433. PDWHCI_TRANSFER_SET TransferSet;
  3434. //
  3435. // Find the next transfer for this endpoint. This transfer is the first
  3436. // transfer in the first transfer set.
  3437. //
  3438. if (LIST_EMPTY(&(Endpoint->TransferSetListHead)) != FALSE) {
  3439. return NULL;
  3440. }
  3441. TransferSet = LIST_VALUE(Endpoint->TransferSetListHead.Next,
  3442. DWHCI_TRANSFER_SET,
  3443. EndpointListEntry);
  3444. if (LIST_EMPTY(&(TransferSet->TransferListHead)) != FALSE) {
  3445. return NULL;
  3446. }
  3447. Transfer = LIST_VALUE(TransferSet->TransferListHead.Next,
  3448. DWHCI_TRANSFER,
  3449. SetListEntry);
  3450. return Transfer;
  3451. }
  3452. KSTATUS
  3453. DwhcipSoftReset (
  3454. PDWHCI_CONTROLLER Controller
  3455. )
  3456. /*++
  3457. Routine Description:
  3458. This routine performs a soft reset of the DWHCI controller.
  3459. Arguments:
  3460. Controller - Supplies a pointer to the DWHCI controller state of the
  3461. controller to reset.
  3462. Return Value:
  3463. Status code.
  3464. --*/
  3465. {
  3466. ULONG CoreReset;
  3467. //
  3468. // Wait for the core reset register to report that the AHB is idle.
  3469. //
  3470. while (TRUE) {
  3471. CoreReset = DWHCI_READ_REGISTER(Controller, DwhciRegisterCoreReset);
  3472. if ((CoreReset & DWHCI_CORE_RESET_AHB_MASTER_IDLE) != 0) {
  3473. break;
  3474. }
  3475. KeDelayExecution(FALSE, FALSE, 20 * MICROSECONDS_PER_MILLISECOND);
  3476. }
  3477. //
  3478. // Execute the core soft reset by writing the soft reset bit to the
  3479. // register.
  3480. //
  3481. CoreReset |= DWHCI_CORE_RESET_CORE_SOFT_RESET;
  3482. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterCoreReset, CoreReset);
  3483. //
  3484. // Now wait for the bit to clear.
  3485. //
  3486. while (TRUE) {
  3487. CoreReset = DWHCI_READ_REGISTER(Controller, DwhciRegisterCoreReset);
  3488. if ((CoreReset & DWHCI_CORE_RESET_CORE_SOFT_RESET) == 0) {
  3489. break;
  3490. }
  3491. KeDelayExecution(FALSE, FALSE, 20 * MICROSECONDS_PER_MILLISECOND);
  3492. }
  3493. //
  3494. // Execute a long delay to keep the DWHCI core in host mode.
  3495. //
  3496. KeDelayExecution(FALSE, FALSE, 200 * MICROSECONDS_PER_MILLISECOND);
  3497. return STATUS_SUCCESS;
  3498. }
  3499. KSTATUS
  3500. DwhcipInitializePhy (
  3501. PDWHCI_CONTROLLER Controller
  3502. )
  3503. /*++
  3504. Routine Description:
  3505. This routine initializes the USB physical layer.
  3506. Arguments:
  3507. Controller - Supplies a pointer to the DWHCI controller state of the
  3508. controller whose physical layer is to be initialized.
  3509. Return Value:
  3510. Status code.
  3511. --*/
  3512. {
  3513. ULONG FullSpeedType;
  3514. ULONG Hardware2;
  3515. ULONG HighSpeedType;
  3516. ULONG HostConfiguration;
  3517. KSTATUS Status;
  3518. ULONG UsbConfiguration;
  3519. ULONG UsbFlags;
  3520. ULONG UtmiWidth;
  3521. //
  3522. // Get the high speed type and the full speed type.
  3523. //
  3524. Hardware2 = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware2);
  3525. HighSpeedType = Hardware2 & DWHCI_HARDWARE2_HIGH_SPEED_MASK;
  3526. FullSpeedType = Hardware2 & DWHCI_HARDWARE2_FULL_SPEED_MASK;
  3527. //
  3528. // If this is a full speed controller, then initialize portions of physical
  3529. // layer that are specific to full speed.
  3530. //
  3531. if (Controller->Speed == UsbDeviceSpeedFull) {
  3532. //
  3533. // Set the PHY select bit in the USB configuration register.
  3534. //
  3535. UsbConfiguration = DWHCI_READ_REGISTER(Controller,
  3536. DwhciRegisterUsbConfiguration);
  3537. UsbConfiguration |= DWHCI_USB_CONFIGURATION_PHY_SELECT;
  3538. DWHCI_WRITE_REGISTER(Controller,
  3539. DwhciRegisterUsbConfiguration,
  3540. UsbConfiguration);
  3541. //
  3542. // Perform a soft reset.
  3543. //
  3544. Status = DwhcipSoftReset(Controller);
  3545. if (!KSUCCESS(Status)) {
  3546. goto InitializePhysicalLayerEnd;
  3547. }
  3548. //
  3549. // Set the full speed clock to 48 MHz in the host configuration
  3550. // register.
  3551. //
  3552. HostConfiguration = DWHCI_READ_REGISTER(Controller,
  3553. DwhciRegisterHostConfiguration);
  3554. HostConfiguration &= ~DWHCI_HOST_CONFIGURATION_CLOCK_RATE_MASK;
  3555. HostConfiguration |= (DWHCI_HOST_CONFIGURATION_CLOCK_48_MHZ <<
  3556. DWHCI_HOST_CONFIGURATION_CLOCK_RATE_SHIFT);
  3557. DWHCI_WRITE_REGISTER(Controller,
  3558. DwhciRegisterHostConfiguration,
  3559. HostConfiguration);
  3560. //
  3561. // Otherwise, this is a high speed controller. Initialize high speed mode
  3562. // in the physical layer.
  3563. //
  3564. } else {
  3565. ASSERT(Controller->Speed == UsbDeviceSpeedHigh);
  3566. ASSERT(HighSpeedType != DWHCI_HARDWARE2_HIGH_SPEED_NOT_SUPPORTED);
  3567. //
  3568. // Configure the USB based on the high speed type.
  3569. //
  3570. UsbConfiguration = DWHCI_READ_REGISTER(Controller,
  3571. DwhciRegisterUsbConfiguration);
  3572. if (HighSpeedType == DWHCI_HARDWARE2_HIGH_SPEED_ULPI) {
  3573. UsbConfiguration &= ~(DWHCI_USB_CONFIGURATION_PHY_INTERFACE_16 |
  3574. DWHCI_USB_CONFIGURATION_DDR_SELECT |
  3575. DWHCI_USB_CONFIGURATION_MODE_SELECT_MASK);
  3576. UsbConfiguration |= DWHCI_USB_CONFIGURATION_MODE_SELECT_ULPI;
  3577. } else {
  3578. ASSERT((HighSpeedType == DWHCI_HARDWARE2_HIGH_SPEED_UTMI) ||
  3579. (HighSpeedType == DWHCI_HARDWARE2_HIGH_SPEED_UTMI_ULPI));
  3580. UsbConfiguration &= ~(DWHCI_USB_CONFIGURATION_MODE_SELECT_MASK |
  3581. DWHCI_USB_CONFIGURATION_PHY_INTERFACE_16);
  3582. UsbConfiguration |= DWHCI_USB_CONFIGURATION_MODE_SELECT_UTMI;
  3583. //
  3584. // Enable the physical interface 16 if the UTMI width is not 8 bit.
  3585. //
  3586. UtmiWidth = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware4);
  3587. UtmiWidth &= ~DWHCI_HARDWARE4_UTMI_PHYSICAL_DATA_WIDTH_MASK;
  3588. if (UtmiWidth != DWHCI_HARDWARE4_UTMI_PHYSICAL_DATA_WIDTH_8_BIT) {
  3589. UsbConfiguration |= DWHCI_USB_CONFIGURATION_PHY_INTERFACE_16;
  3590. }
  3591. }
  3592. DWHCI_WRITE_REGISTER(Controller,
  3593. DwhciRegisterUsbConfiguration,
  3594. UsbConfiguration);
  3595. //
  3596. // Perform a soft reset.
  3597. //
  3598. Status = DwhcipSoftReset(Controller);
  3599. if (!KSUCCESS(Status)) {
  3600. goto InitializePhysicalLayerEnd;
  3601. }
  3602. //
  3603. // Set the high speed clock to 30-60 MHz in the host configuration
  3604. // register.
  3605. //
  3606. HostConfiguration = DWHCI_READ_REGISTER(Controller,
  3607. DwhciRegisterHostConfiguration);
  3608. HostConfiguration &= ~DWHCI_HOST_CONFIGURATION_CLOCK_RATE_MASK;
  3609. HostConfiguration |= (DWHCI_HOST_CONFIGURATION_CLOCK_30_60_MHZ <<
  3610. DWHCI_HOST_CONFIGURATION_CLOCK_RATE_SHIFT);
  3611. DWHCI_WRITE_REGISTER(Controller,
  3612. DwhciRegisterHostConfiguration,
  3613. HostConfiguration);
  3614. }
  3615. //
  3616. // Perform operations that are common to high and full speed.
  3617. //
  3618. UsbConfiguration = DWHCI_READ_REGISTER(Controller,
  3619. DwhciRegisterUsbConfiguration);
  3620. UsbFlags = DWHCI_USB_CONFIGURATION_ULPI_FULL_SPEED_LOW_SPEED_SELECT |
  3621. DWHCI_USB_CONFIGURATION_ULPI_CLOCK_SUSPEND_MODE;
  3622. if ((HighSpeedType == DWHCI_HARDWARE2_HIGH_SPEED_ULPI) &&
  3623. (FullSpeedType == DWHCI_HARDWARE2_FULL_SPEED_DEDICATED)) {
  3624. UsbConfiguration |= UsbFlags;
  3625. } else {
  3626. UsbConfiguration &= ~UsbFlags;
  3627. }
  3628. DWHCI_WRITE_REGISTER(Controller,
  3629. DwhciRegisterUsbConfiguration,
  3630. UsbConfiguration);
  3631. InitializePhysicalLayerEnd:
  3632. return Status;
  3633. }
  3634. KSTATUS
  3635. DwhcipInitializeUsb (
  3636. PDWHCI_CONTROLLER Controller,
  3637. ULONG UsbCapabilities
  3638. )
  3639. /*++
  3640. Routine Description:
  3641. This routine initialize the USB register for the DWHCI host controller.
  3642. Arguments:
  3643. Controller - Supplies a pointer to the DWHCI controller state of the
  3644. controller whose USB register is to be initialized.
  3645. UsbCapabilities - Supplies USB capability bits saved from the USB
  3646. configuration register before the reset.
  3647. Return Value:
  3648. Status code.
  3649. --*/
  3650. {
  3651. ULONG Hardware2;
  3652. ULONG Mask;
  3653. ULONG Mode;
  3654. KSTATUS Status;
  3655. ULONG UsbConfiguration;
  3656. Mask = DWHCI_USB_CONFIGURATION_HNP_CAPABLE |
  3657. DWHCI_USB_CONFIGURATION_SRP_CAPABLE;
  3658. ASSERT((UsbCapabilities & ~Mask) == 0);
  3659. UsbConfiguration = DWHCI_READ_REGISTER(Controller,
  3660. DwhciRegisterUsbConfiguration);
  3661. UsbConfiguration &= ~Mask;
  3662. Hardware2 = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware2);
  3663. Mode = Hardware2 & DWHCI_HARDWARE2_MODE_MASK;
  3664. Status = STATUS_SUCCESS;
  3665. switch (Mode) {
  3666. //
  3667. // Not all controllers are made equal. Some that advertise HNP/SRP do
  3668. // not actually support it and these bits must remain zero. Leave it up
  3669. // to ACPI to set these bits. The supplied capabilities should hold the
  3670. // values set by ACPI.
  3671. //
  3672. case DWHCI_HARDWARE2_MODE_HNP_SRP:
  3673. UsbConfiguration |= UsbCapabilities;
  3674. break;
  3675. case DWHCI_HARDWARE2_MODE_SRP_ONLY:
  3676. case DWHCI_HARDWARE2_MODE_SRP_DEVICE:
  3677. case DWHCI_HARDWARE2_MODE_SRP_HOST:
  3678. UsbConfiguration |= DWHCI_USB_CONFIGURATION_SRP_CAPABLE;
  3679. break;
  3680. case DWHCI_HARDWARE2_MODE_NO_HNP_SRP:
  3681. case DWHCI_HARDWARE2_MODE_NO_SRP_DEVICE:
  3682. case DWHCI_HARDWARE2_MODE_NO_SRP_HOST:
  3683. break;
  3684. default:
  3685. ASSERT(FALSE);
  3686. Status = STATUS_INVALID_CONFIGURATION;
  3687. break;
  3688. }
  3689. if (KSUCCESS(Status)) {
  3690. DWHCI_WRITE_REGISTER(Controller,
  3691. DwhciRegisterUsbConfiguration,
  3692. UsbConfiguration);
  3693. }
  3694. return Status;
  3695. }
  3696. KSTATUS
  3697. DwhcipInitializeHostMode (
  3698. PDWHCI_CONTROLLER Controller,
  3699. ULONG ReceiveFifoSize,
  3700. ULONG NonPeriodicTransmitFifoSize,
  3701. ULONG PeriodicTransmitFifoSize
  3702. )
  3703. /*++
  3704. Routine Description:
  3705. This routine initializes the DWHCI controller in host mode.
  3706. Arguments:
  3707. Controller - Supplies a pointer to the DWHCI controller state of the
  3708. controller whose USB register is to be initialized.
  3709. ReceiveFifoSize - Supplies the receive FIFO size to set if the FIFO's are
  3710. dynamic.
  3711. NonPeriodicTransmitFifoSize - Supplies the non-periodic transmit FIFO size
  3712. to set if the FIFO's are dynamic. This includes the FIFO offset.
  3713. PeriodicTransmitFifoSize - Supplies the periodic transmit FIFO size to
  3714. set if the FIFO's are dynamic. This includes the FIFO offset.
  3715. Return Value:
  3716. Status code.
  3717. --*/
  3718. {
  3719. PDWHCI_CHANNEL Channels;
  3720. ULONG Control;
  3721. ULONG Hardware2;
  3722. ULONG HostConfiguration;
  3723. ULONG Index;
  3724. ULONG OtgControl;
  3725. ULONG PortStatus;
  3726. KSTATUS Status;
  3727. //
  3728. // Restart the PHY clock.
  3729. //
  3730. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterPowerAndClock, 0);
  3731. //
  3732. // Initialize the speed of the host controller.
  3733. //
  3734. if (Controller->Speed == UsbDeviceSpeedFull) {
  3735. HostConfiguration = DWHCI_READ_REGISTER(Controller,
  3736. DwhciRegisterHostConfiguration);
  3737. HostConfiguration |= DWHCI_HOST_CONFIGURATION_FULL_SPEED_LOW_SPEED_ONLY;
  3738. DWHCI_WRITE_REGISTER(Controller,
  3739. DwhciRegisterHostConfiguration,
  3740. HostConfiguration);
  3741. }
  3742. //
  3743. // If dynamic FIFO sizing is allowed, then set the FIFO sizes and
  3744. // starting addresses using the provided values. Otherwise use what is
  3745. // programmed in the registers.
  3746. //
  3747. Hardware2 = DWHCI_READ_REGISTER(Controller, DwhciRegisterHardware2);
  3748. if ((Hardware2 & DWHCI_HARDWARE2_DYNAMIC_FIFO) != 0) {
  3749. DWHCI_WRITE_REGISTER(Controller,
  3750. DwhciRegisterReceiveFifoSize,
  3751. ReceiveFifoSize);
  3752. DWHCI_WRITE_REGISTER(Controller,
  3753. DwhciRegisterNonPeriodicFifoSize,
  3754. NonPeriodicTransmitFifoSize);
  3755. DWHCI_WRITE_REGISTER(Controller,
  3756. DwhciRegisterPeriodicFifoSize,
  3757. PeriodicTransmitFifoSize);
  3758. }
  3759. //
  3760. // Clear the Host Set HNP Enable in the OTG Control Register.
  3761. //
  3762. OtgControl = DWHCI_READ_REGISTER(Controller, DwhciRegisterOtgControl);
  3763. OtgControl &= ~DWHCI_OTG_CONTROL_HOST_SET_HNP_ENABLE;
  3764. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterOtgControl, OtgControl);
  3765. //
  3766. // Flush the FIFOs.
  3767. //
  3768. DwhcipFlushFifo(Controller, TRUE, DWHCI_CORE_RESET_TRANSMIT_FIFO_FLUSH_ALL);
  3769. DwhcipFlushFifo(Controller, FALSE, 0);
  3770. //
  3771. // First disable all the channels.
  3772. //
  3773. for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
  3774. Control = DWHCI_READ_CHANNEL_REGISTER(Controller,
  3775. DwhciChannelRegisterControl,
  3776. Index);
  3777. Control &= ~(DWHCI_CHANNEL_CONTROL_ENDPOINT_DIRECTION_IN |
  3778. DWHCI_CHANNEL_CONTROL_ENABLE);
  3779. Control |= DWHCI_CHANNEL_CONTROL_DISABLE;
  3780. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3781. DwhciChannelRegisterControl,
  3782. Index,
  3783. Control);
  3784. }
  3785. //
  3786. // Reset every channel and add them to the list of free channels.
  3787. //
  3788. Channels = (PDWHCI_CHANNEL)(Controller->Channel);
  3789. for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
  3790. Status = DwhcipResetChannel(Controller, Index);
  3791. if (!KSUCCESS(Status)) {
  3792. goto InitializeHostModeEnd;
  3793. }
  3794. //
  3795. // Since the channel was just disabled, add it to the free list.
  3796. //
  3797. ASSERT(Channels[Index].Endpoint == NULL);
  3798. INSERT_BEFORE(&(Channels[Index].FreeListEntry),
  3799. &(Controller->FreeChannelListHead));
  3800. }
  3801. //
  3802. // Initialize the power for the host controller.
  3803. //
  3804. PortStatus = DWHCI_READ_REGISTER(Controller, DwhciRegisterHostPort);
  3805. if ((PortStatus & DWHCI_HOST_PORT_POWER) == 0) {
  3806. PortStatus |= DWHCI_HOST_PORT_POWER;
  3807. PortStatus &= ~DWHCI_HOST_PORT_WRITE_TO_CLEAR_MASK;
  3808. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterHostPort, PortStatus);
  3809. }
  3810. //
  3811. // Disable all channel interrupts.
  3812. //
  3813. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterHostChannelInterruptMask, 0);
  3814. InitializeHostModeEnd:
  3815. return Status;
  3816. }
  3817. VOID
  3818. DwhcipFlushFifo (
  3819. PDWHCI_CONTROLLER Controller,
  3820. BOOL TransmitFifo,
  3821. ULONG TransmitFifoMask
  3822. )
  3823. /*++
  3824. Routine Description:
  3825. This routine flushes either the one receive FIFO or the specified transmit
  3826. FIFO.
  3827. Arguments:
  3828. Controller - Supplies a pointer to the DWHCI controller state of the
  3829. controller whose FIFO is to be flushed.
  3830. TransmitFifo - Supplies a boolean indicating whether or not the flush is
  3831. for a transmit FIFO.
  3832. TransmitFifoMask - Supplies a bitmask of transmission FIFOs to flush. See
  3833. DWHCI_CORE_RESET_TRAMSIT_FIFO_FLUSH_* for available options.
  3834. Return Value:
  3835. None.
  3836. --*/
  3837. {
  3838. ULONG CoreResetMask;
  3839. ULONG CoreResetValue;
  3840. //
  3841. // Write the core reset register to initiate the FIFO flush.
  3842. //
  3843. if (TransmitFifo == FALSE) {
  3844. CoreResetValue = DWHCI_CORE_RESET_RECEIVE_FIFO_FLUSH;
  3845. CoreResetMask = CoreResetValue;
  3846. } else {
  3847. ASSERT((TransmitFifoMask &
  3848. ~DWHCI_CORE_RESET_TRANSMIT_FIFO_FLUSH_MASK) ==
  3849. 0);
  3850. CoreResetValue = TransmitFifoMask;
  3851. CoreResetMask = DWHCI_CORE_RESET_TRANSMIT_FIFO_FLUSH;
  3852. }
  3853. DWHCI_WRITE_REGISTER(Controller, DwhciRegisterCoreReset, CoreResetValue);
  3854. //
  3855. // Wait for the mask to go to zero.
  3856. //
  3857. while (TRUE) {
  3858. CoreResetValue = DWHCI_READ_REGISTER(Controller,
  3859. DwhciRegisterCoreReset);
  3860. if ((CoreResetValue & CoreResetMask) == 0) {
  3861. break;
  3862. }
  3863. KeDelayExecution(FALSE, FALSE, 10);
  3864. }
  3865. KeDelayExecution(FALSE, FALSE, 10);
  3866. return;
  3867. }
  3868. KSTATUS
  3869. DwhcipResetChannel (
  3870. PDWHCI_CONTROLLER Controller,
  3871. ULONG ChannelNumber
  3872. )
  3873. /*++
  3874. Routine Description:
  3875. This routine resets the given channel for the supplied DWHCI controller.
  3876. Arguments:
  3877. Controller - Supplies a pointer to the controller state of the DWHCI
  3878. controller whose channel is to be reset.
  3879. ChannelNumber - Supplies the number of the channel to be reset.
  3880. Return Value:
  3881. Status code.
  3882. --*/
  3883. {
  3884. ULONG Control;
  3885. //
  3886. // Reset the channel by setting both the enable and disable bits and then
  3887. // wait for the enable bit to clear.
  3888. //
  3889. Control = DWHCI_READ_CHANNEL_REGISTER(Controller,
  3890. DwhciChannelRegisterControl,
  3891. ChannelNumber);
  3892. Control &= ~DWHCI_CHANNEL_CONTROL_ENDPOINT_DIRECTION_IN;
  3893. Control |= (DWHCI_CHANNEL_CONTROL_ENABLE |
  3894. DWHCI_CHANNEL_CONTROL_DISABLE);
  3895. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3896. DwhciChannelRegisterControl,
  3897. ChannelNumber,
  3898. Control);
  3899. while (TRUE) {
  3900. Control = DWHCI_READ_CHANNEL_REGISTER(Controller,
  3901. DwhciChannelRegisterControl,
  3902. ChannelNumber);
  3903. if ((Control & DWHCI_CHANNEL_CONTROL_ENABLE) == 0) {
  3904. break;
  3905. }
  3906. KeDelayExecution(FALSE, FALSE, 10);
  3907. }
  3908. return STATUS_SUCCESS;
  3909. }
  3910. BOOL
  3911. DwhcipHaltChannel (
  3912. PDWHCI_CONTROLLER Controller,
  3913. PDWHCI_CHANNEL Channel
  3914. )
  3915. /*++
  3916. Routine Description:
  3917. This routine halts the given channel that belongs to the specified host
  3918. controller.
  3919. Arguments:
  3920. Controller - Supplies a pointer to the controller state of the DWHCI
  3921. controller whose channel is to be halted.
  3922. Channel - Supplies a pointer to the channel to be halted.
  3923. Return Value:
  3924. Returns TRUE if the channel was successfully halted, or FALSE if an
  3925. asynchronous halt was scheduled.
  3926. --*/
  3927. {
  3928. ULONG ChannelControl;
  3929. ULONG Interrupts;
  3930. ASSERT(Channel->Endpoint != NULL);
  3931. //
  3932. // Make sure that the channel will only interrupt if it is halted.
  3933. //
  3934. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3935. DwhciChannelRegisterInterruptMask,
  3936. Channel->ChannelNumber,
  3937. DWHCI_CHANNEL_INTERRUPT_HALTED);
  3938. //
  3939. // Clear any other interrupts.
  3940. //
  3941. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3942. DwhciChannelRegisterInterrupt,
  3943. Channel->ChannelNumber,
  3944. ~DWHCI_CHANNEL_INTERRUPT_HALTED);
  3945. //
  3946. // If the channel is not currently enabled, then it is not active. There
  3947. // should be no need to halt it.
  3948. //
  3949. ChannelControl = DWHCI_READ_CHANNEL_REGISTER(Controller,
  3950. DwhciChannelRegisterControl,
  3951. Channel->ChannelNumber);
  3952. if ((ChannelControl & DWHCI_CHANNEL_CONTROL_ENABLE) == 0) {
  3953. return TRUE;
  3954. }
  3955. //
  3956. // Enable host level interrupts for this channel.
  3957. //
  3958. Interrupts = DWHCI_READ_REGISTER(Controller,
  3959. DwhciRegisterHostChannelInterruptMask);
  3960. Interrupts |= (1 << Channel->ChannelNumber);
  3961. DWHCI_WRITE_REGISTER(Controller,
  3962. DwhciRegisterHostChannelInterruptMask,
  3963. Interrupts);
  3964. //
  3965. // Reset the channel by enabling and disabling it.
  3966. //
  3967. ChannelControl |= DWHCI_CHANNEL_CONTROL_DISABLE |
  3968. DWHCI_CHANNEL_CONTROL_ENABLE;
  3969. DWHCI_WRITE_CHANNEL_REGISTER(Controller,
  3970. DwhciChannelRegisterControl,
  3971. Channel->ChannelNumber,
  3972. ChannelControl);
  3973. return FALSE;
  3974. }