dwhcihc.c 147 KB

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