usbmass.c 135 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. usbmass.c
  5. Abstract:
  6. This module implements support for the USB Mass Storage driver.
  7. Author:
  8. Evan Green 27-Jan-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include <minoca/intrface/disk.h>
  17. #include <minoca/usb/usb.h>
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. #define CONVERT_BIG_ENDIAN_TO_CPU32(_Value) \
  22. ((((_Value) << 24) & 0xFF000000) | \
  23. (((_Value) << 8) & 0x00FF0000) | \
  24. (((_Value) >> 8) & 0x0000FF00) | \
  25. (((_Value) >> 24) & 0x000000FF))
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // Define the allocation tag used throughout the mass storage driver.
  31. //
  32. #define USB_MASS_ALLOCATION_TAG 0x4D627355 // 'MbsU'
  33. //
  34. // Define the interface protocol numbers used by Mass Storage.
  35. //
  36. #define USB_MASS_BULK_ONLY_PROTOCOL 0x50
  37. //
  38. // Define the class-specific mass storage request codes.
  39. //
  40. #define USB_MASS_REQUEST_GET_MAX_LUN 0xFE
  41. #define USB_MASS_REQUEST_RESET_DEVICE 0xFF
  42. //
  43. // Define the maximum size of the buffer used for command headers and data
  44. // transfers.
  45. //
  46. #define USB_MASS_COMMAND_BUFFER_SIZE 0x200
  47. #define USB_MASS_MAX_DATA_TRANSFER (64 * 1024)
  48. //
  49. // Define the limit of how many times the status transfer can be sent when the
  50. // IN endpoint is stalling.
  51. //
  52. #define USB_MASS_STATUS_TRANSFER_ATTEMPT_LIMIT 2
  53. //
  54. // Define the number of times to retry an I/O request before giving up on the
  55. // IRP.
  56. //
  57. #define USB_MASS_IO_REQUEST_RETRY_COUNT 3
  58. //
  59. // Define the SCSI command block and command status signatures.
  60. //
  61. #define SCSI_COMMAND_BLOCK_SIGNATURE 0x43425355
  62. #define SCSI_COMMAND_STATUS_SIGNATURE 0x53425355
  63. //
  64. // Define SCSI result status codes returned in the command status wrapper.
  65. //
  66. #define SCSI_STATUS_SUCCESS 0x00
  67. #define SCSI_STATUS_FAILED 0x01
  68. #define SCSI_STATUS_PHASE_ERROR 0x02
  69. //
  70. // Define the number of bits the LUN is shifted in most SCSI commands.
  71. //
  72. #define SCSI_COMMAND_LUN_SHIFT 5
  73. //
  74. // Define the flags in the command block wrapper.
  75. //
  76. #define SCSI_COMMAND_BLOCK_FLAG_DATA_IN 0x80
  77. //
  78. // Define SCSI commands.
  79. //
  80. #define SCSI_COMMAND_TEST_UNIT_READY 0x00
  81. #define SCSI_COMMAND_REQUEST_SENSE 0x03
  82. #define SCSI_COMMAND_INQUIRY 0x12
  83. #define SCSI_COMMAND_MODE_SENSE_6 0x1A
  84. #define SCSI_COMMAND_READ_FORMAT_CAPACITIES 0x23
  85. #define SCSI_COMMAND_READ_CAPACITY 0x25
  86. #define SCSI_COMMAND_READ_10 0x28
  87. #define SCSI_COMMAND_WRITE_10 0x2A
  88. //
  89. // Define command sizes.
  90. //
  91. #define SCSI_COMMAND_TEST_UNIT_READY_SIZE 12
  92. #define SCSI_COMMAND_REQUEST_SENSE_SIZE 12
  93. #define SCSI_COMMAND_INQUIRY_SIZE 12
  94. #define SCSI_COMMAND_MODE_SENSE_6_SIZE 6
  95. #define SCSI_COMMAND_READ_FORMAT_CAPACITIES_SIZE 10
  96. #define SCSI_COMMAND_READ_CAPACITY_SIZE 10
  97. #define SCSI_COMMAND_READ_10_SIZE 12
  98. #define SCSI_COMMAND_WRITE_10_SIZE 12
  99. //
  100. // Define command data sizes.
  101. //
  102. #define SCSI_COMMAND_REQUEST_SENSE_DATA_SIZE 18
  103. #define SCSI_COMMAND_READ_FORMAT_CAPACITIES_DATA_SIZE 0xFC
  104. #define SCSI_COMMAND_MODE_SENSE_6_DATA_SIZE 0xC0
  105. //
  106. // Define USB Mass storage driver errors that can be reported back to the
  107. // system.
  108. //
  109. #define USB_MASS_ERROR_FAILED_RESET_RECOVERY 0x00000001
  110. //
  111. // Set this flag if the USB mass storage device has claimed an interface.
  112. //
  113. #define USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED 0x00000001
  114. //
  115. // Set this flag if the USB mass storage device owns the paging disk and has
  116. // prepared the USB core for handling paging.
  117. //
  118. #define USB_MASS_STORAGE_FLAG_PAGING_ENABLED 0x00000002
  119. //
  120. // Define the number of times a command is repeated.
  121. //
  122. #define USB_MASS_RETRY_COUNT 3
  123. //
  124. // Define the number of seconds to wait for the unit to become ready.
  125. //
  126. #define USB_MASS_UNIT_READY_TIMEOUT 30
  127. //
  128. // ------------------------------------------------------ Data Type Definitions
  129. //
  130. typedef enum _USB_MASS_STORAGE_TYPE {
  131. UsbMassStorageInvalid,
  132. UsbMassStorageDevice,
  133. UsbMassStorageLogicalDisk
  134. } USB_MASS_STORAGE_TYPE, *PUSB_MASS_STORAGE_TYPE;
  135. /*++
  136. Structure Description:
  137. This structure defines the set of buffers and transfers required to send
  138. USB mass storage requests.
  139. Members:
  140. CommandBuffer - Stores a pointer to an I/O buffer used as scratch space
  141. for status and command transfers and small data transfers.
  142. StatusTransfer - Stores a pointer to the IN USB transfer used for SCSI
  143. command status results.
  144. CommandTransfer - Stores a pointer to the OUT USB transfer used for SCSI
  145. commands.
  146. DataInTransfer - Stores a pointer to the USB transfer used when a
  147. command needs to read additional data from the device.
  148. DataOutTransfer - Stores a pointer to the USB transfer used to write data
  149. out to the disk.
  150. --*/
  151. typedef struct _USB_MASS_STORAGE_TRANSFERS {
  152. PIO_BUFFER CommandBuffer;
  153. PUSB_TRANSFER StatusTransfer;
  154. PUSB_TRANSFER CommandTransfer;
  155. PUSB_TRANSFER DataInTransfer;
  156. PUSB_TRANSFER DataOutTransfer;
  157. } USB_MASS_STORAGE_TRANSFERS, *PUSB_MASS_STORAGE_TRANSFERS;
  158. /*++
  159. Structure Description:
  160. This structure stores the state necessary to complete polled I/O to a USB
  161. mass storage device. It is meant to be used at high run level during
  162. critical code paths (e.g. system failure).
  163. Members:
  164. IoTransfers - Stores a pointer to the set of transfers used to complete
  165. I/O requests in polled mode.
  166. ControlTransfer - Stores a pointer to a control transfer that can be used
  167. in polled mode.
  168. ResetRequired - Stores a boolean indicating if a reset is required on all
  169. endpoints before executing polled transfers.
  170. --*/
  171. typedef struct _USB_MASS_STORAGE_POLLED_IO_STATE {
  172. USB_MASS_STORAGE_TRANSFERS IoTransfers;
  173. PUSB_TRANSFER ControlTransfer;
  174. BOOL ResetRequired;
  175. } USB_MASS_STORAGE_POLLED_IO_STATE, *PUSB_MASS_STORAGE_POLLED_IO_STATE;
  176. /*++
  177. Structure Description:
  178. This structure stores context about a USB Mass storage device.
  179. Members:
  180. Type - Stores a tag used to differentiate devices from disks.
  181. ReferenceCount - Stores a reference count for the device.
  182. UsbCoreHandle - Stores the handle to the device as identified by the USB
  183. core library.
  184. Lock - Stores a pointer to a lock that synchronizes the LUNs' access to the
  185. device, and serializes transfers.
  186. LogicalDiskList - Stores the list of logical disks on this device.
  187. PolledIoState - Stores a pointer to an optional I/O state used for polled
  188. I/O communications with the USB mass storage device during critical
  189. code paths.
  190. LunCount - Stores the maximum number of LUNs on this device.
  191. InEndpoint - Stores the endpoint number for the bulk IN endpoint.
  192. OutEndpoint - Stores the endpointer number for the bulk OUT endpoint.
  193. InterfaceNumber - Stores the USB Mass Storage interface number that this
  194. driver instance is attached to.
  195. Flags - Stores a bitmask of flags for this device.
  196. See USB_MASS_STORAGE_FLAG_* for definitions.
  197. --*/
  198. typedef struct _USB_MASS_STORAGE_DEVICE {
  199. USB_MASS_STORAGE_TYPE Type;
  200. volatile ULONG ReferenceCount;
  201. HANDLE UsbCoreHandle;
  202. PQUEUED_LOCK Lock;
  203. LIST_ENTRY LogicalDiskList;
  204. volatile PUSB_MASS_STORAGE_POLLED_IO_STATE PolledIoState;
  205. UCHAR LunCount;
  206. UCHAR InEndpoint;
  207. UCHAR OutEndpoint;
  208. UCHAR InterfaceNumber;
  209. ULONG Flags;
  210. } USB_MASS_STORAGE_DEVICE, *PUSB_MASS_STORAGE_DEVICE;
  211. /*++
  212. Structure Description:
  213. This structure stores context about a USB Mass storage logical disk.
  214. Members:
  215. Type - Stores a tag used to differentiate devices from disks.
  216. ReferenceCount - Stores a reference count for the disk.
  217. ListEntry - Stores pointers to the next and previous logical disks in the
  218. device.
  219. OsDevice - Stores a pointer to the OS device.
  220. Transfers - Stores the default set of transfers used to communicate with
  221. the USB mass storage device.
  222. LunNumber - Stores this logical disk's LUN number (a SCSI term).
  223. Device - Stores a pointer back to the device that this logical disk lives
  224. on.
  225. IoRequestAttempts - Stores the number of attempts that have been made
  226. to complete the current I/O request.
  227. StatusTransferAttempts - Stores the number of attempts that have been made
  228. to receive the status transfer.
  229. Event - Stores a pointer to an event to wait for in the case of
  230. synchronous commands.
  231. Irp - Stores a pointer to the IRP that the disk is currently serving.
  232. Whether this is NULL or non-NULL also serves to tell the callback
  233. routine whether to signal the IRP or the event.
  234. BlockCount - Stores the maximum number of blocks in the device.
  235. BlockShift - Stores the number of bits to shift to convert from bytes to
  236. blocks. This means the block size must be a power of two.
  237. CurrentFragment - Stores the current fragment number in a long transfer.
  238. CurrentFragmentOffset - Stores the offset (in bytes) into the current
  239. fragment in a long transfer.
  240. CurrentBytesTransferred - Stores the number of bytes that have been
  241. tranferred on behalf of the current I/O IRP.
  242. Connected - Stores a boolean indicating the disk's connection status.
  243. DiskInterface - Stores the disk interface published for this disk.
  244. --*/
  245. typedef struct _USB_DISK {
  246. USB_MASS_STORAGE_TYPE Type;
  247. volatile ULONG ReferenceCount;
  248. LIST_ENTRY ListEntry;
  249. PDEVICE OsDevice;
  250. UCHAR LunNumber;
  251. PUSB_MASS_STORAGE_DEVICE Device;
  252. USB_MASS_STORAGE_TRANSFERS Transfers;
  253. ULONG IoRequestAttempts;
  254. ULONG StatusTransferAttempts;
  255. PKEVENT Event;
  256. PIRP Irp;
  257. ULONG BlockCount;
  258. ULONG BlockShift;
  259. UINTN CurrentFragment;
  260. UINTN CurrentFragmentOffset;
  261. UINTN CurrentBytesTransferred;
  262. BOOL Connected;
  263. DISK_INTERFACE DiskInterface;
  264. } USB_DISK, *PUSB_DISK;
  265. /*++
  266. Structure Description:
  267. This structure defines a SCSI Command Block Wrapper (CBW), which contains
  268. the command format used to communicate with disks.
  269. Members:
  270. Signature - Stores a magic constant value. Use SCSI_COMMAND_BLOCK_SIGNATURE.
  271. Tag - Stores a unique value used to identify this command among others. The
  272. tag value in the ending command status word will be set to this value to
  273. signify which command is being acknowledged. The hardware does not
  274. interpret this value other than to copy it into the CSW at the end.
  275. DataTransferLength - Store the number of bytes the host expects to transfer
  276. on the Bulk-In or Bulk-Out endpoint (as indicated by the direction bit)
  277. during the execution of this command. If this field is zero, the device
  278. and host shall transfer no data between the CBW and CSW, and the device
  279. shall ignore the value of the Direction bit in the flags.
  280. Flags - Stores pretty much just one flag, the direction of the transfer
  281. (in or out).
  282. LunNumber - Stores the Logical Unit Number (disk index) to which the
  283. command block is being sent.
  284. CommandLength - Stores the valid length of the Command portion in bytes. The
  285. only legcal values are 1 through 16.
  286. --*/
  287. typedef struct _SCSI_COMMAND_BLOCK {
  288. ULONG Signature;
  289. ULONG Tag;
  290. ULONG DataTransferLength;
  291. UCHAR Flags;
  292. UCHAR LunNumber;
  293. UCHAR CommandLength;
  294. UCHAR Command[16];
  295. } PACKED SCSI_COMMAND_BLOCK, *PSCSI_COMMAND_BLOCK;
  296. /*++
  297. Structure Description:
  298. This structure defines a SCSI Command Status Wrapper (CSW), which is sent
  299. by the disk to contain the ending status of the command just sent.
  300. Members:
  301. Signature - Stores a magic constant value. Use
  302. SCSI_COMMAND_STATUS_SIGNATURE.
  303. Tag - Stores the unique tag value supplied by the host when the command
  304. was issued. This allows the host to match up statuses with their
  305. corresponding commands
  306. DataResidue - Stores a value for Data-Out transfers that represents the
  307. difference between the amount of data expected as stated in the
  308. data transfer length and the actual amount of data processed by the
  309. device. For Data-In the device shall report the difference between the
  310. amount of data expected as stated in the data transfer length field of
  311. the command and the actual amount of relevant data sent by the device.
  312. This shall not exceed the value sent in the transfer length.
  313. Status - Stores the status code representing the result of the procedure.
  314. See SCSI_STATUS_* definitions.
  315. --*/
  316. typedef struct _SCSI_COMMAND_STATUS {
  317. ULONG Signature;
  318. ULONG Tag;
  319. ULONG DataResidue;
  320. UCHAR Status;
  321. } PACKED SCSI_COMMAND_STATUS, *PSCSI_COMMAND_STATUS;
  322. /*++
  323. Structure Description:
  324. This structure defines tHe result returned from the device of an INQUIRY
  325. command for page 0.
  326. Members:
  327. PeripheralDeviceType - Stores the device currently connected to the logical
  328. unit.
  329. RemovableFlag - Stores a flag indicating if the device is removable (0x80
  330. if removable).
  331. VersionInformation - Stores the ISO, ECMA, and ANSI versions.
  332. ResponseDataFormat - Stores the response data format.
  333. AdditionalLength - Stores 31, the number of additional bytes in the
  334. information.
  335. Reserved - Stores reserved fields that should be set to 0.
  336. VendorInformation - Stores the vendor ID string.
  337. ProductInformation - Stores the product ID string.
  338. ProductRevision - Stores the product revision string, which should be in an
  339. "n.nn" type format.
  340. VendorData - Stores the first byte of the vendor-specific data. Disks like
  341. to transmit at least 36 bytes, and get fussy when they can't.
  342. --*/
  343. typedef struct _SCSI_INQUIRY_PAGE0 {
  344. UCHAR PeripheralDeviceType;
  345. UCHAR RemovableFlag;
  346. UCHAR VersionInformation;
  347. UCHAR ResponseDataFormat;
  348. UCHAR AdditionalLength;
  349. UCHAR Reserved[2];
  350. UCHAR VendorInformation[8];
  351. UCHAR ProductInformation[16];
  352. UCHAR ProductRevision[4];
  353. UCHAR VendorData;
  354. } PACKED SCSI_INQUIRY_PAGE0, *PSCSI_INQUIRY_PAGE0;
  355. /*++
  356. Structure Description:
  357. This structure defines tje result returned from the device of a READ
  358. FORMAT CAPACITIES command.
  359. Members:
  360. Reserved - Stores three unused bytes.
  361. CapacityListLength - Stores the size of the remaining structure (not
  362. counting this byte). This value should be at least 8 to contain the
  363. rest of this structure.
  364. BlockCount - Stores the number of blocks on the device.
  365. DescriptorCode - Stores whether this descriptor defines the maximum
  366. formattable capacity for this cartridge, the current media capacity, or
  367. the maximum formattable capacity for any cartridge.
  368. BlockLength - Stores the length of one block, in bytes. This value is
  369. commonly 512.
  370. --*/
  371. typedef struct _SCSI_FORMAT_CAPACITIES {
  372. UCHAR Reserved[3];
  373. UCHAR CapacityListLength;
  374. ULONG BlockCount;
  375. UCHAR DescriptorCode;
  376. ULONG BlockLength;
  377. } PACKED SCSI_FORMAT_CAPACITIES, *PSCSI_FORMAT_CAPACITIES;
  378. /*++
  379. Structure Description:
  380. This structure defines tje result returned from the device of a READ
  381. CAPACITY command.
  382. Members:
  383. LastValidBlockAddress - Stores the last valid logical block address for
  384. media access commands.
  385. BlockLength - Stores the length of one block, in bytes. This value is
  386. commonly 512.
  387. --*/
  388. typedef struct _SCSI_CAPACITY {
  389. ULONG LastValidBlockAddress;
  390. ULONG BlockLength;
  391. } PACKED SCSI_CAPACITY, *PSCSI_CAPACITY;
  392. //
  393. // ----------------------------------------------- Internal Function Prototypes
  394. //
  395. KSTATUS
  396. UsbMassAddDevice (
  397. PVOID Driver,
  398. PSTR DeviceId,
  399. PSTR ClassId,
  400. PSTR CompatibleIds,
  401. PVOID DeviceToken
  402. );
  403. VOID
  404. UsbMassDispatchStateChange (
  405. PIRP Irp,
  406. PVOID DeviceContext,
  407. PVOID IrpContext
  408. );
  409. VOID
  410. UsbMassDispatchOpen (
  411. PIRP Irp,
  412. PVOID DeviceContext,
  413. PVOID IrpContext
  414. );
  415. VOID
  416. UsbMassDispatchClose (
  417. PIRP Irp,
  418. PVOID DeviceContext,
  419. PVOID IrpContext
  420. );
  421. VOID
  422. UsbMassDispatchIo (
  423. PIRP Irp,
  424. PVOID DeviceContext,
  425. PVOID IrpContext
  426. );
  427. VOID
  428. UsbMassDispatchSystemControl (
  429. PIRP Irp,
  430. PVOID DeviceContext,
  431. PVOID IrpContext
  432. );
  433. KSTATUS
  434. UsbMasspStartDevice (
  435. PIRP Irp,
  436. PUSB_MASS_STORAGE_DEVICE Device
  437. );
  438. VOID
  439. UsbMasspEnumerateChildren (
  440. PIRP Irp,
  441. PUSB_MASS_STORAGE_DEVICE Device
  442. );
  443. KSTATUS
  444. UsbMasspEnablePaging (
  445. PUSB_MASS_STORAGE_DEVICE Device
  446. );
  447. VOID
  448. UsbMasspRemoveDevice (
  449. PIRP Irp,
  450. PUSB_MASS_STORAGE_DEVICE Device
  451. );
  452. VOID
  453. UsbMasspDestroyDevice (
  454. PUSB_MASS_STORAGE_DEVICE Device
  455. );
  456. VOID
  457. UsbMasspDeviceAddReference (
  458. PUSB_MASS_STORAGE_DEVICE Device
  459. );
  460. VOID
  461. UsbMasspDeviceReleaseReference (
  462. PUSB_MASS_STORAGE_DEVICE Device
  463. );
  464. KSTATUS
  465. UsbMasspSetUpUsbDevice (
  466. PIRP Irp,
  467. PUSB_MASS_STORAGE_DEVICE Device
  468. );
  469. KSTATUS
  470. UsbMasspGetLunCount (
  471. PUSB_MASS_STORAGE_DEVICE Device,
  472. PUCHAR LunCount
  473. );
  474. KSTATUS
  475. UsbMasspCreateLogicalDisks (
  476. PUSB_MASS_STORAGE_DEVICE Device,
  477. ULONG DiskCount
  478. );
  479. VOID
  480. UsbMasspDestroyLogicalDisks (
  481. PUSB_MASS_STORAGE_DEVICE Device
  482. );
  483. PUSB_MASS_STORAGE_POLLED_IO_STATE
  484. UsbMasspCreatePolledIoState (
  485. PUSB_MASS_STORAGE_DEVICE Device
  486. );
  487. VOID
  488. UsbMasspDestroyPolledIoState (
  489. PUSB_MASS_STORAGE_POLLED_IO_STATE PolledIoState
  490. );
  491. KSTATUS
  492. UsbMasspCreateTransfers (
  493. PUSB_MASS_STORAGE_DEVICE Device,
  494. PUSB_MASS_STORAGE_TRANSFERS Transfers,
  495. PVOID UserData,
  496. PUSB_TRANSFER_CALLBACK CallbackRoutine
  497. );
  498. VOID
  499. UsbMasspDestroyTransfers (
  500. PUSB_MASS_STORAGE_TRANSFERS Transfers
  501. );
  502. KSTATUS
  503. UsbMasspStartDisk (
  504. PUSB_DISK Disk
  505. );
  506. VOID
  507. UsbMasspRemoveDisk (
  508. PUSB_DISK Disk
  509. );
  510. VOID
  511. UsbMasspDestroyDisk (
  512. PUSB_DISK Disk
  513. );
  514. VOID
  515. UsbMasspDiskAddReference (
  516. PUSB_DISK Disk
  517. );
  518. VOID
  519. UsbMasspDiskReleaseReference (
  520. PUSB_DISK Disk
  521. );
  522. KSTATUS
  523. UsbMasspSendInquiry (
  524. PUSB_DISK Disk,
  525. UCHAR Page,
  526. PVOID *ResultBuffer,
  527. PULONG ResultBufferSize
  528. );
  529. KSTATUS
  530. UsbMasspTestUnitReady (
  531. PUSB_DISK Disk
  532. );
  533. KSTATUS
  534. UsbMasspRequestSense (
  535. PUSB_DISK Disk
  536. );
  537. KSTATUS
  538. UsbMasspModeSense (
  539. PUSB_DISK Disk
  540. );
  541. KSTATUS
  542. UsbMasspReadFormatCapacities (
  543. PUSB_DISK Disk
  544. );
  545. KSTATUS
  546. UsbMasspReadCapacity (
  547. PUSB_DISK Disk
  548. );
  549. PVOID
  550. UsbMasspSetupCommand (
  551. PUSB_DISK Disk,
  552. ULONG Tag,
  553. ULONG DataLength,
  554. UCHAR CommandLength,
  555. BOOL DataIn,
  556. BOOL PolledIo,
  557. PVOID TransferVirtualAddress,
  558. PHYSICAL_ADDRESS TransferPhysicalAddress
  559. );
  560. KSTATUS
  561. UsbMasspSendCommand (
  562. PUSB_DISK Disk
  563. );
  564. VOID
  565. UsbMasspTransferCompletionCallback (
  566. PUSB_TRANSFER Transfer
  567. );
  568. KSTATUS
  569. UsbMasspEvaluateCommandStatus (
  570. PUSB_DISK Disk,
  571. BOOL PolledIo,
  572. BOOL DisableRecovery,
  573. PULONG BytesTransferred
  574. );
  575. KSTATUS
  576. UsbMasspSendNextIoRequest (
  577. PUSB_DISK Disk
  578. );
  579. KSTATUS
  580. UsbMasspResetRecovery (
  581. PUSB_MASS_STORAGE_DEVICE Device,
  582. BOOL PolledIo
  583. );
  584. KSTATUS
  585. UsbMasspReset (
  586. PUSB_MASS_STORAGE_DEVICE Device,
  587. BOOL PolledIo
  588. );
  589. KSTATUS
  590. UsbMasspClearHalts (
  591. PUSB_MASS_STORAGE_DEVICE Device,
  592. BOOL PolledIo
  593. );
  594. KSTATUS
  595. UsbMasspClearEndpoint (
  596. PUSB_MASS_STORAGE_DEVICE Device,
  597. UCHAR Endpoint,
  598. BOOL PolledIo
  599. );
  600. KSTATUS
  601. UsbMasspBlockIoInitialize (
  602. PVOID DiskToken
  603. );
  604. KSTATUS
  605. UsbMasspBlockIoRead (
  606. PVOID DiskToken,
  607. PIO_BUFFER IoBuffer,
  608. ULONGLONG BlockAddress,
  609. UINTN BlockCount,
  610. PUINTN BlocksCompleted
  611. );
  612. KSTATUS
  613. UsbMasspBlockIoWrite (
  614. PVOID DiskToken,
  615. PIO_BUFFER IoBuffer,
  616. ULONGLONG BlockAddress,
  617. UINTN BlockCount,
  618. PUINTN BlocksCompleted
  619. );
  620. KSTATUS
  621. UsbMasspPerformPolledIo (
  622. PIRP_READ_WRITE IrpReadWrite,
  623. PUSB_DISK Disk,
  624. BOOL Write
  625. );
  626. KSTATUS
  627. UsbMasspSendPolledIoCommand (
  628. PUSB_DISK Disk,
  629. PULONG BytesCompleted
  630. );
  631. KSTATUS
  632. UsbMasspResetForPolledIo (
  633. PUSB_MASS_STORAGE_DEVICE Device
  634. );
  635. KSTATUS
  636. UsbMasspSendPolledIoControlTransfer (
  637. PUSB_MASS_STORAGE_DEVICE Device,
  638. USB_TRANSFER_DIRECTION TransferDirection,
  639. PUSB_SETUP_PACKET SetupPacket
  640. );
  641. //
  642. // -------------------------------------------------------------------- Globals
  643. //
  644. PDRIVER UsbMassDriver = NULL;
  645. UUID UsbMassDiskInterfaceUuid = UUID_DISK_INTERFACE;
  646. DISK_INTERFACE UsbMassDiskInterfaceTemplate = {
  647. DISK_INTERFACE_VERSION,
  648. NULL,
  649. 0,
  650. 0,
  651. UsbMasspBlockIoInitialize,
  652. NULL,
  653. UsbMasspBlockIoRead,
  654. UsbMasspBlockIoWrite
  655. };
  656. //
  657. // ------------------------------------------------------------------ Functions
  658. //
  659. KSTATUS
  660. DriverEntry (
  661. PDRIVER Driver
  662. )
  663. /*++
  664. Routine Description:
  665. This routine is the entry point for the USB Mass Storage driver. It
  666. registers the other dispatch functions, and performs driver-wide
  667. initialization.
  668. Arguments:
  669. Driver - Supplies a pointer to the driver object.
  670. Return Value:
  671. STATUS_SUCCESS on success.
  672. Failure code on error.
  673. --*/
  674. {
  675. DRIVER_FUNCTION_TABLE FunctionTable;
  676. KSTATUS Status;
  677. UsbMassDriver = Driver;
  678. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  679. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  680. FunctionTable.AddDevice = UsbMassAddDevice;
  681. FunctionTable.DispatchStateChange = UsbMassDispatchStateChange;
  682. FunctionTable.DispatchOpen = UsbMassDispatchOpen;
  683. FunctionTable.DispatchClose = UsbMassDispatchClose;
  684. FunctionTable.DispatchIo = UsbMassDispatchIo;
  685. FunctionTable.DispatchSystemControl = UsbMassDispatchSystemControl;
  686. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  687. return Status;
  688. }
  689. //
  690. // --------------------------------------------------------- Internal Functions
  691. //
  692. KSTATUS
  693. UsbMassAddDevice (
  694. PVOID Driver,
  695. PSTR DeviceId,
  696. PSTR ClassId,
  697. PSTR CompatibleIds,
  698. PVOID DeviceToken
  699. )
  700. /*++
  701. Routine Description:
  702. This routine is called when a device is detected for which the USB Mass
  703. Storage driver acts as the function driver. The driver will attach itself
  704. to the stack.
  705. Arguments:
  706. Driver - Supplies a pointer to the driver being called.
  707. DeviceId - Supplies a pointer to a string with the device ID.
  708. ClassId - Supplies a pointer to a string containing the device's class ID.
  709. CompatibleIds - Supplies a pointer to a string containing device IDs
  710. that would be compatible with this device.
  711. DeviceToken - Supplies an opaque token that the driver can use to identify
  712. the device in the system. This token should be used when attaching to
  713. the stack.
  714. Return Value:
  715. STATUS_SUCCESS on success.
  716. Failure code if the driver was unsuccessful in attaching itself.
  717. --*/
  718. {
  719. PUSB_MASS_STORAGE_DEVICE NewDevice;
  720. KSTATUS Status;
  721. //
  722. // Create the device context and attach to the device.
  723. //
  724. NewDevice = MmAllocateNonPagedPool(sizeof(USB_MASS_STORAGE_DEVICE),
  725. USB_MASS_ALLOCATION_TAG);
  726. if (NewDevice == NULL) {
  727. return STATUS_INSUFFICIENT_RESOURCES;
  728. }
  729. RtlZeroMemory(NewDevice, sizeof(USB_MASS_STORAGE_DEVICE));
  730. NewDevice->Type = UsbMassStorageDevice;
  731. NewDevice->ReferenceCount = 1;
  732. NewDevice->UsbCoreHandle = INVALID_HANDLE;
  733. INITIALIZE_LIST_HEAD(&(NewDevice->LogicalDiskList));
  734. NewDevice->Lock = KeCreateQueuedLock();
  735. if (NewDevice->Lock == NULL) {
  736. Status = STATUS_INSUFFICIENT_RESOURCES;
  737. goto AddDeviceEnd;
  738. }
  739. //
  740. // Attempt to attach to the USB core.
  741. //
  742. Status = UsbDriverAttach(DeviceToken,
  743. UsbMassDriver,
  744. &(NewDevice->UsbCoreHandle));
  745. if (!KSUCCESS(Status)) {
  746. goto AddDeviceEnd;
  747. }
  748. ASSERT(NewDevice->UsbCoreHandle != INVALID_HANDLE);
  749. Status = IoAttachDriverToDevice(Driver, DeviceToken, NewDevice);
  750. AddDeviceEnd:
  751. if (!KSUCCESS(Status)) {
  752. if (NewDevice != NULL) {
  753. //
  754. // Release the reference, closing the USB core handle and
  755. // destroying the device.
  756. //
  757. UsbMasspDeviceReleaseReference(NewDevice);
  758. }
  759. }
  760. return Status;
  761. }
  762. VOID
  763. UsbMassDispatchStateChange (
  764. PIRP Irp,
  765. PVOID DeviceContext,
  766. PVOID IrpContext
  767. )
  768. /*++
  769. Routine Description:
  770. This routine handles State Change IRPs.
  771. Arguments:
  772. Irp - Supplies a pointer to the I/O request packet.
  773. DeviceContext - Supplies the context pointer supplied by the driver when it
  774. attached itself to the driver stack. Presumably this pointer contains
  775. driver-specific device context.
  776. IrpContext - Supplies the context pointer supplied by the driver when
  777. the IRP was created.
  778. Return Value:
  779. None.
  780. --*/
  781. {
  782. PUSB_MASS_STORAGE_DEVICE Device;
  783. PUSB_DISK Disk;
  784. KSTATUS Status;
  785. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  786. Device = (PUSB_MASS_STORAGE_DEVICE)DeviceContext;
  787. if (Device->Type == UsbMassStorageDevice) {
  788. switch (Irp->MinorCode) {
  789. case IrpMinorQueryResources:
  790. if (Irp->Direction == IrpUp) {
  791. IoCompleteIrp(UsbMassDriver, Irp, STATUS_SUCCESS);
  792. }
  793. break;
  794. case IrpMinorStartDevice:
  795. //
  796. // Attempt to fire the thing up if the bus has already started it.
  797. //
  798. if (Irp->Direction == IrpUp) {
  799. Status = UsbMasspStartDevice(Irp, Device);
  800. if (!KSUCCESS(Status)) {
  801. IoCompleteIrp(UsbMassDriver, Irp, Status);
  802. }
  803. }
  804. break;
  805. case IrpMinorQueryChildren:
  806. if (Irp->Direction == IrpUp) {
  807. UsbMasspEnumerateChildren(Irp, Device);
  808. }
  809. break;
  810. case IrpMinorRemoveDevice:
  811. if (Irp->Direction == IrpUp) {
  812. UsbMasspRemoveDevice(Irp, Device);
  813. }
  814. break;
  815. //
  816. // For all other IRPs, do nothing.
  817. //
  818. default:
  819. break;
  820. }
  821. } else {
  822. Disk = (PUSB_DISK)DeviceContext;
  823. ASSERT(Disk->Type == UsbMassStorageLogicalDisk);
  824. switch (Irp->MinorCode) {
  825. case IrpMinorStartDevice:
  826. if (Irp->Direction == IrpUp) {
  827. Status = UsbMasspStartDisk(Disk);
  828. IoCompleteIrp(UsbMassDriver, Irp, Status);
  829. }
  830. break;
  831. case IrpMinorQueryResources:
  832. case IrpMinorQueryChildren:
  833. if (Irp->Direction == IrpUp) {
  834. IoCompleteIrp(UsbMassDriver, Irp, STATUS_SUCCESS);
  835. }
  836. break;
  837. case IrpMinorRemoveDevice:
  838. if (Irp->Direction == IrpUp) {
  839. UsbMasspRemoveDisk(Disk);
  840. IoCompleteIrp(UsbMassDriver, Irp, STATUS_SUCCESS);
  841. }
  842. break;
  843. default:
  844. break;
  845. }
  846. }
  847. return;
  848. }
  849. VOID
  850. UsbMassDispatchOpen (
  851. PIRP Irp,
  852. PVOID DeviceContext,
  853. PVOID IrpContext
  854. )
  855. /*++
  856. Routine Description:
  857. This routine handles Open IRPs.
  858. Arguments:
  859. Irp - Supplies a pointer to the I/O request packet.
  860. DeviceContext - Supplies the context pointer supplied by the driver when it
  861. attached itself to the driver stack. Presumably this pointer contains
  862. driver-specific device context.
  863. IrpContext - Supplies the context pointer supplied by the driver when
  864. the IRP was created.
  865. Return Value:
  866. None.
  867. --*/
  868. {
  869. PUSB_DISK Disk;
  870. KSTATUS Status;
  871. Disk = (PUSB_DISK)DeviceContext;
  872. if (Disk->Type != UsbMassStorageLogicalDisk) {
  873. return;
  874. }
  875. ASSERT(Disk->Connected != FALSE);
  876. //
  877. // If this is an open for the paging device then enable paging on this
  878. // device.
  879. //
  880. if ((Irp->U.Open.OpenFlags & OPEN_FLAG_PAGING_DEVICE) != 0) {
  881. Status = UsbMasspEnablePaging(Disk->Device);
  882. if (!KSUCCESS(Status)) {
  883. goto DispatchOpenEnd;
  884. }
  885. }
  886. UsbMasspDiskAddReference(Disk);
  887. Irp->U.Open.DeviceContext = NULL;
  888. Status = STATUS_SUCCESS;
  889. DispatchOpenEnd:
  890. IoCompleteIrp(UsbMassDriver, Irp, Status);
  891. return;
  892. }
  893. VOID
  894. UsbMassDispatchClose (
  895. PIRP Irp,
  896. PVOID DeviceContext,
  897. PVOID IrpContext
  898. )
  899. /*++
  900. Routine Description:
  901. This routine handles Close IRPs.
  902. Arguments:
  903. Irp - Supplies a pointer to the I/O request packet.
  904. DeviceContext - Supplies the context pointer supplied by the driver when it
  905. attached itself to the driver stack. Presumably this pointer contains
  906. driver-specific device context.
  907. IrpContext - Supplies the context pointer supplied by the driver when
  908. the IRP was created.
  909. Return Value:
  910. None.
  911. --*/
  912. {
  913. PUSB_DISK Disk;
  914. Disk = (PUSB_DISK)DeviceContext;
  915. if (Disk->Type != UsbMassStorageLogicalDisk) {
  916. return;
  917. }
  918. UsbMasspDiskReleaseReference(Disk);
  919. IoCompleteIrp(UsbMassDriver, Irp, STATUS_SUCCESS);
  920. return;
  921. }
  922. VOID
  923. UsbMassDispatchIo (
  924. PIRP Irp,
  925. PVOID DeviceContext,
  926. PVOID IrpContext
  927. )
  928. /*++
  929. Routine Description:
  930. This routine handles I/O IRPs.
  931. Arguments:
  932. Irp - Supplies a pointer to the I/O request packet.
  933. DeviceContext - Supplies the context pointer supplied by the driver when it
  934. attached itself to the driver stack. Presumably this pointer contains
  935. driver-specific device context.
  936. IrpContext - Supplies the context pointer supplied by the driver when
  937. the IRP was created.
  938. Return Value:
  939. None.
  940. --*/
  941. {
  942. BOOL CompleteIrp;
  943. PUSB_DISK Disk;
  944. PIO_BUFFER_FRAGMENT Fragment;
  945. UINTN FragmentIndex;
  946. UINTN FragmentOffset;
  947. PIO_BUFFER IoBuffer;
  948. UINTN IoBufferOffset;
  949. ULONG IrpReadWriteFlags;
  950. BOOL LockHeld;
  951. BOOL ReadWriteIrpPrepared;
  952. KSTATUS Status;
  953. CompleteIrp = TRUE;
  954. Disk = (PUSB_DISK)DeviceContext;
  955. LockHeld = FALSE;
  956. ReadWriteIrpPrepared = FALSE;
  957. ASSERT(Disk->Type == UsbMassStorageLogicalDisk);
  958. //
  959. // Set the read/write flags for preparation. As USB mass storage does not
  960. // do DMA directly, nor does it do polled I/O, don't set either flag.
  961. //
  962. IrpReadWriteFlags = 0;
  963. if (Irp->MinorCode == IrpMinorIoWrite) {
  964. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  965. }
  966. //
  967. // If the IRP is on the way up, then clean up after the DMA as this IRP is
  968. // still sitting in the channel. An IRP going up is already complete.
  969. //
  970. if (Irp->Direction != IrpDown) {
  971. CompleteIrp = FALSE;
  972. ASSERT(Irp == Disk->Irp);
  973. Disk->Irp = NULL;
  974. KeReleaseQueuedLock(Disk->Device->Lock);
  975. Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  976. if (!KSUCCESS(Status)) {
  977. IoUpdateIrpStatus(Irp, Status);
  978. }
  979. } else {
  980. ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
  981. //
  982. // Before acquiring the device's lock and starting the transfer,
  983. // prepare the I/O context for USB Mass Storage (i.e. it must use
  984. // physical addresses that are less than 4GB and be cache aligned).
  985. //
  986. Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
  987. 1 << Disk->BlockShift,
  988. 0,
  989. MAX_ULONG,
  990. IrpReadWriteFlags);
  991. if (!KSUCCESS(Status)) {
  992. goto DispatchIoEnd;
  993. }
  994. ReadWriteIrpPrepared = TRUE;
  995. IoBuffer = Irp->U.ReadWrite.IoBuffer;
  996. //
  997. // Map the I/O buffer.
  998. //
  999. // TODO: Make sure USB Mass does not need the I/O buffer mapped.
  1000. //
  1001. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
  1002. if (!KSUCCESS(Status)) {
  1003. goto DispatchIoEnd;
  1004. }
  1005. //
  1006. // Find the starting fragment based on the current offset.
  1007. //
  1008. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  1009. FragmentIndex = 0;
  1010. FragmentOffset = 0;
  1011. while (IoBufferOffset != 0) {
  1012. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1013. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1014. if (IoBufferOffset < Fragment->Size) {
  1015. FragmentOffset = IoBufferOffset;
  1016. break;
  1017. }
  1018. IoBufferOffset -= Fragment->Size;
  1019. FragmentIndex += 1;
  1020. }
  1021. //
  1022. // Lock the disk to serialize all I/O access to the device.
  1023. //
  1024. KeAcquireQueuedLock(Disk->Device->Lock);
  1025. LockHeld = TRUE;
  1026. if (Disk->Connected == FALSE) {
  1027. Status = STATUS_DEVICE_NOT_CONNECTED;
  1028. goto DispatchIoEnd;
  1029. }
  1030. //
  1031. // Otherwise start the I/O on a connected device.
  1032. //
  1033. Disk->CurrentFragment = FragmentIndex;
  1034. Disk->CurrentFragmentOffset = FragmentOffset;
  1035. Disk->CurrentBytesTransferred = 0;
  1036. Disk->Irp = Irp;
  1037. ASSERT(Irp->U.ReadWrite.IoSizeInBytes != 0);
  1038. ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoSizeInBytes,
  1039. (1 << Disk->BlockShift)));
  1040. ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoOffset, (1 << Disk->BlockShift)));
  1041. //
  1042. // Pend the IRP first so that the request can't complete in between
  1043. // submitting it and marking it pended.
  1044. //
  1045. CompleteIrp = FALSE;
  1046. IoPendIrp(UsbMassDriver, Irp);
  1047. //
  1048. // Fire the first I/O request off to the disk. If this fails, expect to
  1049. // get called on the way up, as the IRP has already been pended. Thus,
  1050. // act like the lock is not held and the context was not prepared.
  1051. //
  1052. Disk->IoRequestAttempts = 0;
  1053. Status = UsbMasspSendNextIoRequest(Disk);
  1054. if (!KSUCCESS(Status)) {
  1055. CompleteIrp = TRUE;
  1056. LockHeld = FALSE;
  1057. ReadWriteIrpPrepared = FALSE;
  1058. goto DispatchIoEnd;
  1059. }
  1060. }
  1061. DispatchIoEnd:
  1062. if (CompleteIrp != FALSE) {
  1063. if (LockHeld != FALSE) {
  1064. KeReleaseQueuedLock(Disk->Device->Lock);
  1065. }
  1066. if (ReadWriteIrpPrepared != FALSE) {
  1067. IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  1068. }
  1069. IoCompleteIrp(UsbMassDriver, Irp, Status);
  1070. }
  1071. return;
  1072. }
  1073. VOID
  1074. UsbMassDispatchSystemControl (
  1075. PIRP Irp,
  1076. PVOID DeviceContext,
  1077. PVOID IrpContext
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. This routine handles System Control IRPs.
  1082. Arguments:
  1083. Irp - Supplies a pointer to the I/O request packet.
  1084. DeviceContext - Supplies the context pointer supplied by the driver when it
  1085. attached itself to the driver stack. Presumably this pointer contains
  1086. driver-specific device context.
  1087. IrpContext - Supplies the context pointer supplied by the driver when
  1088. the IRP was created.
  1089. Return Value:
  1090. None.
  1091. --*/
  1092. {
  1093. PVOID Context;
  1094. PUSB_DISK Disk;
  1095. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  1096. ULONGLONG FileSize;
  1097. PSYSTEM_CONTROL_LOOKUP Lookup;
  1098. PFILE_PROPERTIES Properties;
  1099. ULONGLONG PropertiesFileSize;
  1100. KSTATUS Status;
  1101. //
  1102. // Do nothing for non-logical disks.
  1103. //
  1104. Disk = (PUSB_DISK)DeviceContext;
  1105. if (Disk->Type != UsbMassStorageLogicalDisk) {
  1106. return;
  1107. }
  1108. //
  1109. // System control IRPs should only be arriving if the disk is connected.
  1110. //
  1111. ASSERT(Disk->Connected != FALSE);
  1112. //
  1113. // Handle the IRP for logical disks.
  1114. //
  1115. Context = Irp->U.SystemControl.SystemContext;
  1116. switch (Irp->MinorCode) {
  1117. case IrpMinorSystemControlLookup:
  1118. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  1119. Status = STATUS_PATH_NOT_FOUND;
  1120. if (Lookup->Root != FALSE) {
  1121. //
  1122. // Enable opening of the root as a single file.
  1123. //
  1124. Properties = &(Lookup->Properties);
  1125. Properties->FileId = 0;
  1126. Properties->Type = IoObjectBlockDevice;
  1127. Properties->HardLinkCount = 1;
  1128. ASSERT(((1 << Disk->BlockShift) != 0) && (Disk->BlockCount != 0));
  1129. Properties->BlockSize = 1 << Disk->BlockShift;
  1130. Properties->BlockCount = Disk->BlockCount;
  1131. FileSize = (ULONGLONG)Disk->BlockCount <<
  1132. (ULONGLONG)Disk->BlockShift;
  1133. WRITE_INT64_SYNC(&(Properties->FileSize), FileSize);
  1134. Status = STATUS_SUCCESS;
  1135. }
  1136. IoCompleteIrp(UsbMassDriver, Irp, Status);
  1137. break;
  1138. //
  1139. // Writes to the disk's properties are not allowed. Fail if the data
  1140. // has changed.
  1141. //
  1142. case IrpMinorSystemControlWriteFileProperties:
  1143. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  1144. Properties = FileOperation->FileProperties;
  1145. READ_INT64_SYNC(&(Properties->FileSize), &PropertiesFileSize);
  1146. FileSize = (ULONGLONG)Disk->BlockCount << (ULONGLONG)Disk->BlockShift;
  1147. if ((Properties->FileId != 0) ||
  1148. (Properties->Type != IoObjectBlockDevice) ||
  1149. (Properties->HardLinkCount != 1) ||
  1150. (Properties->BlockSize != (1 << Disk->BlockShift)) ||
  1151. (Properties->BlockCount != Disk->BlockCount) ||
  1152. (PropertiesFileSize != FileSize)) {
  1153. Status = STATUS_NOT_SUPPORTED;
  1154. } else {
  1155. Status = STATUS_SUCCESS;
  1156. }
  1157. IoCompleteIrp(UsbMassDriver, Irp, Status);
  1158. break;
  1159. //
  1160. // Do not support USB mass storage device truncation.
  1161. //
  1162. case IrpMinorSystemControlTruncate:
  1163. IoCompleteIrp(UsbMassDriver, Irp, STATUS_NOT_SUPPORTED);
  1164. break;
  1165. //
  1166. // Gather and return device information.
  1167. //
  1168. case IrpMinorSystemControlDeviceInformation:
  1169. break;
  1170. case IrpMinorSystemControlSynchronize:
  1171. IoCompleteIrp(UsbMassDriver, Irp, STATUS_SUCCESS);
  1172. break;
  1173. //
  1174. // Ignore everything unrecognized.
  1175. //
  1176. default:
  1177. ASSERT(FALSE);
  1178. break;
  1179. }
  1180. return;
  1181. }
  1182. KSTATUS
  1183. UsbMasspStartDevice (
  1184. PIRP Irp,
  1185. PUSB_MASS_STORAGE_DEVICE Device
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This routine starts up the USB Mass Storage device.
  1190. Arguments:
  1191. Irp - Supplies a pointer to the I/O request packet.
  1192. Device - Supplies a pointer to this mass storage device.
  1193. Return Value:
  1194. Status code.
  1195. --*/
  1196. {
  1197. UCHAR LunCount;
  1198. KSTATUS Status;
  1199. ASSERT(Device->Type == UsbMassStorageDevice);
  1200. //
  1201. // Claim the interface.
  1202. //
  1203. Status = UsbMasspSetUpUsbDevice(Irp, Device);
  1204. if (!KSUCCESS(Status)) {
  1205. goto StartDeviceEnd;
  1206. }
  1207. if (Device->LunCount == 0) {
  1208. Status = UsbMasspGetLunCount(Device, &LunCount);
  1209. if (!KSUCCESS(Status)) {
  1210. goto StartDeviceEnd;
  1211. }
  1212. //
  1213. // Fire up all those little disks.
  1214. //
  1215. Status = UsbMasspCreateLogicalDisks(Device, LunCount);
  1216. if (!KSUCCESS(Status)) {
  1217. goto StartDeviceEnd;
  1218. }
  1219. Device->LunCount = LunCount;
  1220. }
  1221. StartDeviceEnd:
  1222. return Status;
  1223. }
  1224. KSTATUS
  1225. UsbMasspEnablePaging (
  1226. PUSB_MASS_STORAGE_DEVICE Device
  1227. )
  1228. /*++
  1229. Routine Description:
  1230. This routine enables paging on the given USB mass storage device. It
  1231. converts all transfers for all disks to paging device transfers, which USB
  1232. core will handle separately from other non-critical transfers.
  1233. Arguments:
  1234. Device - Supplies a pointer to a USB mass storage device.
  1235. Return Value:
  1236. Status code.
  1237. --*/
  1238. {
  1239. PLIST_ENTRY CurrentEntry;
  1240. PUSB_DISK Disk;
  1241. BOOL LockHeld;
  1242. KSTATUS Status;
  1243. PUSB_MASS_STORAGE_TRANSFERS Transfers;
  1244. LockHeld = FALSE;
  1245. //
  1246. // If the device has already been enabled for paging, then work here is
  1247. // done.
  1248. //
  1249. if ((Device->Flags & USB_MASS_STORAGE_FLAG_PAGING_ENABLED) != 0) {
  1250. return STATUS_SUCCESS;
  1251. }
  1252. //
  1253. // Notify USB core that a paging device has arrived and that it would like
  1254. // its transfers to be serviced on their own work queue.
  1255. //
  1256. Status = UsbInitializePagingDeviceTransfers();
  1257. if (!KSUCCESS(Status)) {
  1258. goto InitializePagingEnd;
  1259. }
  1260. //
  1261. // Now acquire the device's lock to synchronize with transfer submissions
  1262. // and try to convert this device's transfer to be paging transfers.
  1263. //
  1264. KeAcquireQueuedLock(Device->Lock);
  1265. LockHeld = TRUE;
  1266. if ((Device->Flags & USB_MASS_STORAGE_FLAG_PAGING_ENABLED) != 0) {
  1267. Status = STATUS_SUCCESS;
  1268. goto InitializePagingEnd;
  1269. }
  1270. //
  1271. // Iterate over all transfers for all the disks, converting them to be
  1272. // paging device transfers. Because all disks share the same device lock,
  1273. // all disks need to start using the paging path, even if a disk is not
  1274. // involved in paging.
  1275. //
  1276. CurrentEntry = Device->LogicalDiskList.Next;
  1277. while (CurrentEntry != &(Device->LogicalDiskList)) {
  1278. Disk = LIST_VALUE(CurrentEntry, USB_DISK, ListEntry);
  1279. Transfers = &(Disk->Transfers);
  1280. Transfers->CommandTransfer->Flags |= USB_TRANSFER_FLAG_PAGING_DEVICE;
  1281. Transfers->StatusTransfer->Flags |= USB_TRANSFER_FLAG_PAGING_DEVICE;
  1282. Transfers->DataInTransfer->Flags |= USB_TRANSFER_FLAG_PAGING_DEVICE;
  1283. Transfers->DataOutTransfer->Flags |= USB_TRANSFER_FLAG_PAGING_DEVICE;
  1284. CurrentEntry = CurrentEntry->Next;
  1285. }
  1286. Device->Flags |= USB_MASS_STORAGE_FLAG_PAGING_ENABLED;
  1287. KeReleaseQueuedLock(Device->Lock);
  1288. LockHeld = FALSE;
  1289. Status = STATUS_SUCCESS;
  1290. InitializePagingEnd:
  1291. if (LockHeld != FALSE) {
  1292. KeReleaseQueuedLock(Device->Lock);
  1293. }
  1294. return Status;
  1295. }
  1296. VOID
  1297. UsbMasspEnumerateChildren (
  1298. PIRP Irp,
  1299. PUSB_MASS_STORAGE_DEVICE Device
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. This routine enumerates the USB Mass Storage device's children.
  1304. Arguments:
  1305. Irp - Supplies a pointer to the I/O request packet.
  1306. Device - Supplies a pointer to this mass storage device.
  1307. Return Value:
  1308. None.
  1309. --*/
  1310. {
  1311. ULONG ChildCount;
  1312. ULONG ChildIndex;
  1313. PDEVICE *Children;
  1314. PLIST_ENTRY CurrentEntry;
  1315. PUSB_DISK Disk;
  1316. KSTATUS Status;
  1317. ASSERT(Device->Type == UsbMassStorageDevice);
  1318. ChildCount = Device->LunCount;
  1319. Children = NULL;
  1320. if (Device->LunCount == 0) {
  1321. Status = STATUS_SUCCESS;
  1322. goto EnumerateChildrenEnd;
  1323. }
  1324. Children = MmAllocatePagedPool(sizeof(PDEVICE) * ChildCount,
  1325. USB_MASS_ALLOCATION_TAG);
  1326. if (Children == NULL) {
  1327. Status = STATUS_INSUFFICIENT_RESOURCES;
  1328. goto EnumerateChildrenEnd;
  1329. }
  1330. RtlZeroMemory(Children, sizeof(PDEVICE) * ChildCount);
  1331. //
  1332. // Loop through and add every disk.
  1333. //
  1334. ChildIndex = 0;
  1335. CurrentEntry = Device->LogicalDiskList.Next;
  1336. while (CurrentEntry != &(Device->LogicalDiskList)) {
  1337. Disk = LIST_VALUE(CurrentEntry, USB_DISK, ListEntry);
  1338. CurrentEntry = CurrentEntry->Next;
  1339. if (Disk->OsDevice == NULL) {
  1340. Status = IoCreateDevice(UsbMassDriver,
  1341. Disk,
  1342. Irp->Device,
  1343. "UsbDisk",
  1344. DISK_CLASS_ID,
  1345. NULL,
  1346. &(Disk->OsDevice));
  1347. if (!KSUCCESS(Status)) {
  1348. goto EnumerateChildrenEnd;
  1349. }
  1350. }
  1351. if (Disk->OsDevice != NULL) {
  1352. Disk->Connected = TRUE;
  1353. Children[ChildIndex] = Disk->OsDevice;
  1354. ChildIndex += 1;
  1355. }
  1356. }
  1357. ChildCount = ChildIndex;
  1358. Status = STATUS_SUCCESS;
  1359. EnumerateChildrenEnd:
  1360. if (!KSUCCESS(Status)) {
  1361. if (Children != NULL) {
  1362. MmFreePagedPool(Children);
  1363. Children = NULL;
  1364. ChildCount = 0;
  1365. }
  1366. }
  1367. ASSERT((Irp->U.QueryChildren.Children == NULL) &&
  1368. (Irp->U.QueryChildren.ChildCount == 0));
  1369. Irp->U.QueryChildren.Children = Children;
  1370. Irp->U.QueryChildren.ChildCount = ChildCount;
  1371. IoCompleteIrp(UsbMassDriver, Irp, Status);
  1372. return;
  1373. }
  1374. VOID
  1375. UsbMasspRemoveDevice (
  1376. PIRP Irp,
  1377. PUSB_MASS_STORAGE_DEVICE Device
  1378. )
  1379. /*++
  1380. Routine Description:
  1381. This routine removes the USB Mass Storage device.
  1382. Arguments:
  1383. Irp - Supplies a pointer to the I/O request packet.
  1384. Device - Supplies a pointer to this mass storage device.
  1385. Return Value:
  1386. None.
  1387. --*/
  1388. {
  1389. ASSERT(Device->Type == UsbMassStorageDevice);
  1390. //
  1391. // Detach the device from USB core. This marks it as disconnected and
  1392. // cancels all transfers associated with the device.
  1393. //
  1394. // N.B. Since all the logical disks have already received a remove IRP,
  1395. // the transfers should be inactive already.
  1396. //
  1397. UsbDetachDevice(Device->UsbCoreHandle);
  1398. //
  1399. // The logical disk list for this device should be empty if the device
  1400. // successfully completed enumeration. That is, all the logical disk
  1401. // should have received a removal IRP that this driver handled, acting as
  1402. // the bus driver. If it is not empty, then the device never made it to
  1403. // enumeration, or one logical disk failed to enumerate, and the disks need
  1404. // to be cleaned up.
  1405. //
  1406. UsbMasspDestroyLogicalDisks(Device);
  1407. //
  1408. // Release the interface used for the USB mass storage device.
  1409. //
  1410. if ((Device->Flags & USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED) != 0) {
  1411. UsbReleaseInterface(Device->UsbCoreHandle, Device->InterfaceNumber);
  1412. Device->Flags &= ~USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED;
  1413. }
  1414. //
  1415. // Release the reference taken during device add. Logical disks may still
  1416. // have references on the device and USB core.
  1417. //
  1418. UsbMasspDeviceReleaseReference(Device);
  1419. return;
  1420. }
  1421. VOID
  1422. UsbMasspDestroyDevice (
  1423. PUSB_MASS_STORAGE_DEVICE Device
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. This routine destroys a USB mass storage device.
  1428. Arguments:
  1429. Device - Supplies a pointer to the USB mass storage device.
  1430. Return Value:
  1431. None.
  1432. --*/
  1433. {
  1434. //
  1435. // The device should have already received the removal IRP or have never
  1436. // made it off the ground before it gets destroyed, so assert that there
  1437. // are no references, its logical disk list is empty and the interface is
  1438. // not claimed.
  1439. //
  1440. ASSERT(Device->ReferenceCount == 0);
  1441. ASSERT(LIST_EMPTY(&(Device->LogicalDiskList)) != FALSE);
  1442. ASSERT((Device->Flags & USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED) == 0);
  1443. //
  1444. // Destroy the polled I/O state if it exists.
  1445. //
  1446. if (Device->PolledIoState != NULL) {
  1447. UsbMasspDestroyPolledIoState(Device->PolledIoState);
  1448. }
  1449. //
  1450. // Release the USB core handle. The USB core device does not get dropped
  1451. // until all of its transfers are destroyed. As a result, this handle
  1452. // remains open until the last logical disk reference is dropped, making it
  1453. // pointless to put this close in the device removal routine.
  1454. //
  1455. UsbDeviceClose(Device->UsbCoreHandle);
  1456. //
  1457. // Destroy the lock if necessary.
  1458. //
  1459. if (Device->Lock != NULL) {
  1460. ASSERT(KeIsQueuedLockHeld(Device->Lock) == FALSE);
  1461. KeDestroyQueuedLock(Device->Lock);
  1462. }
  1463. //
  1464. // Release the device itself.
  1465. //
  1466. MmFreeNonPagedPool(Device);
  1467. return;
  1468. }
  1469. VOID
  1470. UsbMasspDeviceAddReference (
  1471. PUSB_MASS_STORAGE_DEVICE Device
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. This routine adds a reference to USB mass storage device.
  1476. Arguments:
  1477. Device - Supplies a pointer to the USB mass storage device.
  1478. Return Value:
  1479. None.
  1480. --*/
  1481. {
  1482. ULONG OldReferenceCount;
  1483. OldReferenceCount = RtlAtomicAdd32(&(Device->ReferenceCount), 1);
  1484. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1485. return;
  1486. }
  1487. VOID
  1488. UsbMasspDeviceReleaseReference (
  1489. PUSB_MASS_STORAGE_DEVICE Device
  1490. )
  1491. /*++
  1492. Routine Description:
  1493. This routine releases a reference from the USB mass storage device.
  1494. Arguments:
  1495. Device - Supplies a pointer to the USB mass storage device.
  1496. Return Value:
  1497. None.
  1498. --*/
  1499. {
  1500. ULONG OldReferenceCount;
  1501. OldReferenceCount = RtlAtomicAdd32(&(Device->ReferenceCount), (ULONG)-1);
  1502. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1503. if (OldReferenceCount == 1) {
  1504. UsbMasspDestroyDevice(Device);
  1505. }
  1506. return;
  1507. }
  1508. KSTATUS
  1509. UsbMasspSetUpUsbDevice (
  1510. PIRP Irp,
  1511. PUSB_MASS_STORAGE_DEVICE Device
  1512. )
  1513. /*++
  1514. Routine Description:
  1515. This routine claims the mass storage interface for the given device.
  1516. Arguments:
  1517. Irp - Supplies a pointer to the I/O request packet.
  1518. Device - Supplies a pointer to this mass storage device.
  1519. Return Value:
  1520. Status code.
  1521. --*/
  1522. {
  1523. PUSB_CONFIGURATION_DESCRIPTION Configuration;
  1524. PLIST_ENTRY CurrentEntry;
  1525. USB_TRANSFER_DIRECTION Direction;
  1526. PUSB_ENDPOINT_DESCRIPTION Endpoint;
  1527. UCHAR EndpointType;
  1528. BOOL InEndpointFound;
  1529. PUSB_INTERFACE_DESCRIPTION Interface;
  1530. BOOL OutEndpointFound;
  1531. KSTATUS Status;
  1532. ASSERT(Device->Type == UsbMassStorageDevice);
  1533. if ((Device->Flags & USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED) != 0) {
  1534. Status = STATUS_SUCCESS;
  1535. goto SetUpUsbDeviceEnd;
  1536. }
  1537. //
  1538. // If the configuration isn't yet set, set the first one.
  1539. //
  1540. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  1541. if (Configuration == NULL) {
  1542. Status = UsbSetConfiguration(Device->UsbCoreHandle, 0, TRUE);
  1543. if (!KSUCCESS(Status)) {
  1544. goto SetUpUsbDeviceEnd;
  1545. }
  1546. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  1547. ASSERT(Configuration != NULL);
  1548. }
  1549. //
  1550. // Get and verify the interface.
  1551. //
  1552. Interface = UsbGetDesignatedInterface(Irp->Device, Device->UsbCoreHandle);
  1553. if (Interface == NULL) {
  1554. Status = STATUS_NO_INTERFACE;
  1555. goto SetUpUsbDeviceEnd;
  1556. }
  1557. if (Interface->Descriptor.Class != UsbInterfaceClassMassStorage) {
  1558. Status = STATUS_NO_INTERFACE;
  1559. goto SetUpUsbDeviceEnd;
  1560. }
  1561. if (Interface->Descriptor.Protocol != USB_MASS_BULK_ONLY_PROTOCOL) {
  1562. RtlDebugPrint("USB Mass Storage Error: Unsupported protocol 0x%x. Only "
  1563. "the Bulk-Only protocol (0x50) is supported.\n");
  1564. ASSERT(FALSE);
  1565. Status = STATUS_NOT_SUPPORTED;
  1566. goto SetUpUsbDeviceEnd;
  1567. }
  1568. //
  1569. // Locate the IN and OUT bulk endpoints.
  1570. //
  1571. InEndpointFound = FALSE;
  1572. OutEndpointFound = FALSE;
  1573. CurrentEntry = Interface->EndpointListHead.Next;
  1574. while (CurrentEntry != &(Interface->EndpointListHead)) {
  1575. Endpoint = LIST_VALUE(CurrentEntry,
  1576. USB_ENDPOINT_DESCRIPTION,
  1577. ListEntry);
  1578. CurrentEntry = CurrentEntry->Next;
  1579. //
  1580. // Deconstruct the components of the endpoint descriptor.
  1581. //
  1582. EndpointType = Endpoint->Descriptor.Attributes &
  1583. USB_ENDPOINT_ATTRIBUTES_TYPE_MASK;
  1584. if ((Endpoint->Descriptor.EndpointAddress &
  1585. USB_ENDPOINT_ADDRESS_DIRECTION_IN) != 0) {
  1586. Direction = UsbTransferDirectionIn;
  1587. } else {
  1588. Direction = UsbTransferDirectionOut;
  1589. }
  1590. //
  1591. // Look to match the endpoint up to one of the required ones.
  1592. //
  1593. if (EndpointType == USB_ENDPOINT_ATTRIBUTES_TYPE_BULK) {
  1594. if ((InEndpointFound == FALSE) &&
  1595. (Direction == UsbTransferDirectionIn)) {
  1596. InEndpointFound = TRUE;
  1597. Device->InEndpoint = Endpoint->Descriptor.EndpointAddress;
  1598. } else if ((OutEndpointFound == FALSE) &&
  1599. (Direction == UsbTransferDirectionOut)) {
  1600. OutEndpointFound = TRUE;
  1601. Device->OutEndpoint = Endpoint->Descriptor.EndpointAddress;
  1602. }
  1603. }
  1604. if ((InEndpointFound != FALSE) && (OutEndpointFound != FALSE)) {
  1605. break;
  1606. }
  1607. }
  1608. if ((InEndpointFound == FALSE) || (OutEndpointFound == FALSE)) {
  1609. Status = STATUS_INVALID_CONFIGURATION;
  1610. goto SetUpUsbDeviceEnd;
  1611. }
  1612. //
  1613. // Everything's all ready, claim the interface.
  1614. //
  1615. Status = UsbClaimInterface(Device->UsbCoreHandle,
  1616. Interface->Descriptor.InterfaceNumber);
  1617. if (!KSUCCESS(Status)) {
  1618. goto SetUpUsbDeviceEnd;
  1619. }
  1620. Device->InterfaceNumber = Interface->Descriptor.InterfaceNumber;
  1621. Device->Flags |= USB_MASS_STORAGE_FLAG_INTERFACE_CLAIMED;
  1622. Status = STATUS_SUCCESS;
  1623. SetUpUsbDeviceEnd:
  1624. return Status;
  1625. }
  1626. KSTATUS
  1627. UsbMasspGetLunCount (
  1628. PUSB_MASS_STORAGE_DEVICE Device,
  1629. PUCHAR LunCount
  1630. )
  1631. /*++
  1632. Routine Description:
  1633. This routine returns the maximum number of logical disks contained in this
  1634. mass storage device.
  1635. Arguments:
  1636. Device - Supplies a pointer to this mass storage device.
  1637. LunCount - Supplies a pointer where the number of devices will be
  1638. returned on success.
  1639. Return Value:
  1640. Status code.
  1641. --*/
  1642. {
  1643. ULONG Alignment;
  1644. PIO_BUFFER IoBuffer;
  1645. ULONG IoBufferFlags;
  1646. ULONG MaxTransferLength;
  1647. PUSB_SETUP_PACKET Setup;
  1648. KSTATUS Status;
  1649. PUSB_TRANSFER Transfer;
  1650. PVOID TransferBuffer;
  1651. ULONG TransferLength;
  1652. Transfer = NULL;
  1653. //
  1654. // Create the I/O buffer that will be used for the transfer.
  1655. //
  1656. Alignment = MmGetIoBufferAlignment();
  1657. TransferLength = sizeof(USB_SETUP_PACKET) + sizeof(UCHAR);
  1658. MaxTransferLength = ALIGN_RANGE_UP(TransferLength, Alignment);
  1659. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  1660. IoBuffer = MmAllocateNonPagedIoBuffer(0,
  1661. MAX_ULONG,
  1662. Alignment,
  1663. MaxTransferLength,
  1664. IoBufferFlags);
  1665. if (IoBuffer == NULL) {
  1666. Status = STATUS_INSUFFICIENT_RESOURCES;
  1667. goto GetMaxLunEnd;
  1668. }
  1669. ASSERT(IoBuffer->FragmentCount == 1);
  1670. TransferBuffer = IoBuffer->Fragment[0].VirtualAddress;
  1671. Setup = (PUSB_SETUP_PACKET)TransferBuffer;
  1672. Setup->RequestType = USB_SETUP_REQUEST_TO_HOST |
  1673. USB_SETUP_REQUEST_CLASS |
  1674. USB_SETUP_REQUEST_INTERFACE_RECIPIENT;
  1675. Setup->Request = USB_MASS_REQUEST_GET_MAX_LUN;
  1676. Setup->Value = 0;
  1677. Setup->Index = Device->InterfaceNumber;
  1678. Setup->Length = sizeof(UCHAR);
  1679. //
  1680. // Create a USB transfer.
  1681. //
  1682. Transfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  1683. 0,
  1684. MaxTransferLength,
  1685. 0);
  1686. if (Transfer == NULL) {
  1687. Status = STATUS_INSUFFICIENT_RESOURCES;
  1688. goto GetMaxLunEnd;
  1689. }
  1690. Transfer->Direction = UsbTransferDirectionIn;
  1691. Transfer->Length = TransferLength;
  1692. Transfer->Buffer = IoBuffer->Fragment[0].VirtualAddress;
  1693. Transfer->BufferPhysicalAddress = IoBuffer->Fragment[0].PhysicalAddress;
  1694. Transfer->BufferActualLength = IoBuffer->Fragment[0].Size;
  1695. //
  1696. // Submit the transfer and wait for it to complete. The spec says that
  1697. // devices that don't support multiple LUNs may stall the transfer.
  1698. //
  1699. Status = UsbSubmitSynchronousTransfer(Transfer);
  1700. if ((Status == STATUS_DEVICE_IO_ERROR) &&
  1701. (Transfer->Error == UsbErrorTransferStalled)) {
  1702. //
  1703. // Clear the halt condition of endpoint zero. One might think that this
  1704. // is not possible, but indeed it is.
  1705. //
  1706. Status = UsbMasspClearEndpoint(Device, 0, FALSE);
  1707. if (!KSUCCESS(Status)) {
  1708. goto GetMaxLunEnd;
  1709. }
  1710. *LunCount = 1;
  1711. goto GetMaxLunEnd;
  1712. }
  1713. if (!KSUCCESS(Status)) {
  1714. goto GetMaxLunEnd;
  1715. }
  1716. ASSERT(KSUCCESS(Transfer->Status));
  1717. if (Transfer->LengthTransferred != TransferLength) {
  1718. Status = STATUS_DATA_LENGTH_MISMATCH;
  1719. goto GetMaxLunEnd;
  1720. }
  1721. *LunCount = *((PUCHAR)Transfer->Buffer +
  1722. sizeof(USB_SETUP_PACKET));
  1723. //
  1724. // Add 1 since the data value was a "max index", but the caller wants a
  1725. // count.
  1726. //
  1727. *LunCount += 1;
  1728. Status = STATUS_SUCCESS;
  1729. GetMaxLunEnd:
  1730. if (Transfer != NULL) {
  1731. UsbDestroyTransfer(Transfer);
  1732. }
  1733. if (IoBuffer != NULL) {
  1734. MmFreeIoBuffer(IoBuffer);
  1735. }
  1736. return Status;
  1737. }
  1738. KSTATUS
  1739. UsbMasspCreateLogicalDisks (
  1740. PUSB_MASS_STORAGE_DEVICE Device,
  1741. ULONG DiskCount
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. This routine creates a number of logical disks to live under the given
  1746. mass storage device. These disks will be added to the device.
  1747. Arguments:
  1748. Device - Supplies a pointer to this mass storage device.
  1749. DiskCount - Supplies the number of logical disks to create.
  1750. Return Value:
  1751. Status code.
  1752. --*/
  1753. {
  1754. PUSB_DISK Disk;
  1755. ULONG DiskIndex;
  1756. KSTATUS Status;
  1757. ASSERT(LIST_EMPTY(&(Device->LogicalDiskList)) != FALSE);
  1758. Disk = NULL;
  1759. for (DiskIndex = 0; DiskIndex < DiskCount; DiskIndex += 1) {
  1760. Disk = MmAllocateNonPagedPool(sizeof(USB_DISK),
  1761. USB_MASS_ALLOCATION_TAG);
  1762. if (Disk == NULL) {
  1763. Status = STATUS_INSUFFICIENT_RESOURCES;
  1764. goto CreateLogicalDisksEnd;
  1765. }
  1766. RtlZeroMemory(Disk, sizeof(USB_DISK));
  1767. Disk->Type = UsbMassStorageLogicalDisk;
  1768. Disk->ReferenceCount = 1;
  1769. Disk->LunNumber = DiskIndex;
  1770. Disk->Device = Device;
  1771. UsbMasspDeviceAddReference(Device);
  1772. //
  1773. // Create the event for synchronous transfers.
  1774. //
  1775. Disk->Event = KeCreateEvent(NULL);
  1776. if (Disk->Event == NULL) {
  1777. Status = STATUS_INSUFFICIENT_RESOURCES;
  1778. goto CreateLogicalDisksEnd;
  1779. }
  1780. //
  1781. // Create the set of default transfers for this disk.
  1782. //
  1783. Status = UsbMasspCreateTransfers(Device,
  1784. &(Disk->Transfers),
  1785. Disk,
  1786. UsbMasspTransferCompletionCallback);
  1787. if (!KSUCCESS(Status)) {
  1788. goto CreateLogicalDisksEnd;
  1789. }
  1790. ASSERT(Disk->Connected == FALSE);
  1791. //
  1792. // Add the new disk to the list.
  1793. //
  1794. INSERT_BEFORE(&(Disk->ListEntry), &(Device->LogicalDiskList));
  1795. Disk = NULL;
  1796. }
  1797. Status = STATUS_SUCCESS;
  1798. CreateLogicalDisksEnd:
  1799. if (!KSUCCESS(Status)) {
  1800. if (Disk != NULL) {
  1801. UsbMasspDiskReleaseReference(Disk);
  1802. }
  1803. UsbMasspDestroyLogicalDisks(Device);
  1804. }
  1805. return Status;
  1806. }
  1807. VOID
  1808. UsbMasspDestroyLogicalDisks (
  1809. PUSB_MASS_STORAGE_DEVICE Device
  1810. )
  1811. /*++
  1812. Routine Description:
  1813. This routine destroys all logical disks associated with the given mass
  1814. storage device.
  1815. Arguments:
  1816. Device - Supplies a pointer to this mass storage device.
  1817. Return Value:
  1818. None.
  1819. --*/
  1820. {
  1821. PUSB_DISK Disk;
  1822. while (LIST_EMPTY(&(Device->LogicalDiskList)) == FALSE) {
  1823. Disk = LIST_VALUE(Device->LogicalDiskList.Next, USB_DISK, ListEntry);
  1824. LIST_REMOVE(&(Disk->ListEntry));
  1825. //
  1826. // The mass storage driver should only need to call this on disks that
  1827. // never completed enumeration.
  1828. //
  1829. ASSERT(Disk->OsDevice == NULL);
  1830. ASSERT(Disk->Connected == FALSE);
  1831. ASSERT(Disk->ReferenceCount == 1);
  1832. UsbMasspDiskReleaseReference(Disk);
  1833. }
  1834. return;
  1835. }
  1836. PUSB_MASS_STORAGE_POLLED_IO_STATE
  1837. UsbMasspCreatePolledIoState (
  1838. PUSB_MASS_STORAGE_DEVICE Device
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. This routine creates polled I/O state for the given USB mass storage device.
  1843. Arguments:
  1844. Device - Supplies a pointer to the USB device that is to be the target of
  1845. the polled I/O.
  1846. Return Value:
  1847. Returns a pointer to a polled I/O state for the device.
  1848. --*/
  1849. {
  1850. ULONG AllocationSize;
  1851. PUSB_TRANSFER ControlTransfer;
  1852. PUSB_MASS_STORAGE_POLLED_IO_STATE PolledIoState;
  1853. KSTATUS Status;
  1854. AllocationSize = sizeof(USB_MASS_STORAGE_POLLED_IO_STATE);
  1855. PolledIoState = MmAllocateNonPagedPool(AllocationSize,
  1856. USB_MASS_ALLOCATION_TAG);
  1857. if (PolledIoState == NULL) {
  1858. return NULL;
  1859. }
  1860. RtlZeroMemory(PolledIoState, AllocationSize);
  1861. //
  1862. // Create the I/O transfers for the newly minted polled I/O state. Since
  1863. // these transfers will be used with polled I/O, they lack a callback
  1864. // routine and user data.
  1865. //
  1866. Status = UsbMasspCreateTransfers(Device,
  1867. &(PolledIoState->IoTransfers),
  1868. NULL,
  1869. NULL);
  1870. if (!KSUCCESS(Status)) {
  1871. goto CreatePolledIoStateEnd;
  1872. }
  1873. //
  1874. // Allocate a control transfer that will be used to perform reset recovery.
  1875. // It only ever needs to send a setup packet.
  1876. //
  1877. ControlTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  1878. 0,
  1879. sizeof(USB_SETUP_PACKET),
  1880. 0);
  1881. if (ControlTransfer == NULL) {
  1882. Status = STATUS_INSUFFICIENT_RESOURCES;
  1883. goto CreatePolledIoStateEnd;
  1884. }
  1885. PolledIoState->ControlTransfer = ControlTransfer;
  1886. //
  1887. // Before polled I/O is used for the first time, assumably in a very
  1888. // critical scenario (e.g. crash dump), then mass storage endpoints will
  1889. // need to be reset.
  1890. //
  1891. PolledIoState->ResetRequired = TRUE;
  1892. CreatePolledIoStateEnd:
  1893. if (!KSUCCESS(Status)) {
  1894. if (PolledIoState != NULL) {
  1895. UsbMasspDestroyPolledIoState(PolledIoState);
  1896. PolledIoState = NULL;
  1897. }
  1898. }
  1899. return PolledIoState;
  1900. }
  1901. VOID
  1902. UsbMasspDestroyPolledIoState (
  1903. PUSB_MASS_STORAGE_POLLED_IO_STATE PolledIoState
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. This routine destroys the given polled I/O state.
  1908. Arguments:
  1909. PolledIoState - Supplies a pointer to the polled I/O state to destroy.
  1910. Return Value:
  1911. None.
  1912. --*/
  1913. {
  1914. ASSERT(PolledIoState != NULL);
  1915. UsbMasspDestroyTransfers(&(PolledIoState->IoTransfers));
  1916. if (PolledIoState->ControlTransfer != NULL) {
  1917. UsbDestroyTransfer(PolledIoState->ControlTransfer);
  1918. }
  1919. MmFreeNonPagedPool(PolledIoState);
  1920. return;
  1921. }
  1922. KSTATUS
  1923. UsbMasspCreateTransfers (
  1924. PUSB_MASS_STORAGE_DEVICE Device,
  1925. PUSB_MASS_STORAGE_TRANSFERS Transfers,
  1926. PVOID UserData,
  1927. PUSB_TRANSFER_CALLBACK CallbackRoutine
  1928. )
  1929. /*++
  1930. Routine Description:
  1931. This routine initializes a set of USB disk transfers by creating the
  1932. command, status, and data transfers as well as any necessary buffers.
  1933. Arguments:
  1934. Device - Supplies a pointer to the USB device to which the transfers
  1935. belong.
  1936. Transfers - Supplies a pointer to the USB disk transfers structure to be
  1937. initialized.
  1938. UserData - Supplies an optional pointer to the private user data with which
  1939. the transfers will be initialized.
  1940. CallbackRoutine - Supplies an optional pointer to the USB transfer
  1941. callback routine with which the transfers will be initialized.
  1942. Return Value:
  1943. Status code.
  1944. --*/
  1945. {
  1946. ULONG Alignment;
  1947. PIO_BUFFER CommandBuffer;
  1948. PUSB_TRANSFER CommandTransfer;
  1949. PUSB_TRANSFER DataOutTransfer;
  1950. ULONG IoBufferFlags;
  1951. ULONG MaxCommandBlockSize;
  1952. ULONG MaxCommandBufferSize;
  1953. ULONG MaxCommandStatusSize;
  1954. PHYSICAL_ADDRESS PhysicalAddress;
  1955. KSTATUS Status;
  1956. PUSB_TRANSFER StatusTransfer;
  1957. //
  1958. // Create the I/O buffer used for commands.
  1959. //
  1960. Alignment = MmGetIoBufferAlignment();
  1961. MaxCommandBufferSize = ALIGN_RANGE_UP(USB_MASS_COMMAND_BUFFER_SIZE,
  1962. Alignment);
  1963. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  1964. Transfers->CommandBuffer = MmAllocateNonPagedIoBuffer(0,
  1965. MAX_ULONG,
  1966. Alignment,
  1967. MaxCommandBufferSize,
  1968. IoBufferFlags);
  1969. if (Transfers->CommandBuffer == NULL) {
  1970. Status = STATUS_INSUFFICIENT_RESOURCES;
  1971. goto CreateDiskTransfersEnd;
  1972. }
  1973. ASSERT(Transfers->CommandBuffer->FragmentCount == 1);
  1974. //
  1975. // Create a USB transfer to the get the Command Status Wrapper at the
  1976. // end of a transfer.
  1977. //
  1978. StatusTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  1979. Device->InEndpoint,
  1980. sizeof(SCSI_COMMAND_STATUS),
  1981. 0);
  1982. if (StatusTransfer == NULL) {
  1983. Status = STATUS_INSUFFICIENT_RESOURCES;
  1984. goto CreateDiskTransfersEnd;
  1985. }
  1986. StatusTransfer->Direction = UsbTransferDirectionIn;
  1987. StatusTransfer->Length = sizeof(SCSI_COMMAND_STATUS);
  1988. StatusTransfer->CallbackRoutine = CallbackRoutine;
  1989. StatusTransfer->UserData = UserData;
  1990. Transfers->StatusTransfer = StatusTransfer;
  1991. //
  1992. // The buffer's virtual and physical address is calculated for each
  1993. // request, but there should always be exactly the same amount of
  1994. // memory used for the status transfer.
  1995. //
  1996. MaxCommandStatusSize = ALIGN_RANGE_UP(sizeof(SCSI_COMMAND_STATUS),
  1997. Alignment);
  1998. Transfers->StatusTransfer->BufferActualLength = MaxCommandStatusSize;
  1999. //
  2000. // Create the command transfer for sending the Command Block Wrapper.
  2001. //
  2002. CommandTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  2003. Device->OutEndpoint,
  2004. sizeof(SCSI_COMMAND_BLOCK),
  2005. 0);
  2006. if (CommandTransfer == NULL) {
  2007. Status = STATUS_INSUFFICIENT_RESOURCES;
  2008. goto CreateDiskTransfersEnd;
  2009. }
  2010. CommandTransfer->Direction = UsbTransferDirectionOut;
  2011. CommandTransfer->Length = sizeof(SCSI_COMMAND_BLOCK);
  2012. CommandBuffer = Transfers->CommandBuffer;
  2013. CommandTransfer->Buffer = CommandBuffer->Fragment[0].VirtualAddress;
  2014. PhysicalAddress = CommandBuffer->Fragment[0].PhysicalAddress;
  2015. CommandTransfer->BufferPhysicalAddress = PhysicalAddress;
  2016. MaxCommandBlockSize = ALIGN_RANGE_UP(sizeof(SCSI_COMMAND_BLOCK), Alignment);
  2017. CommandTransfer->BufferActualLength = MaxCommandBlockSize;
  2018. CommandTransfer->CallbackRoutine = CallbackRoutine;
  2019. CommandTransfer->UserData = UserData;
  2020. Transfers->CommandTransfer = CommandTransfer;
  2021. //
  2022. // Create the data in transfer for receiving data from an incoming
  2023. // command.
  2024. //
  2025. Transfers->DataInTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  2026. Device->InEndpoint,
  2027. USB_MASS_MAX_DATA_TRANSFER,
  2028. 0);
  2029. if (Transfers->DataInTransfer == NULL) {
  2030. Status = STATUS_INSUFFICIENT_RESOURCES;
  2031. goto CreateDiskTransfersEnd;
  2032. }
  2033. Transfers->DataInTransfer->Direction = UsbTransferDirectionIn;
  2034. Transfers->DataInTransfer->CallbackRoutine = CallbackRoutine;
  2035. Transfers->DataInTransfer->UserData = UserData;
  2036. //
  2037. // Create the data out transfer for sending data to the disk.
  2038. //
  2039. DataOutTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  2040. Device->OutEndpoint,
  2041. USB_MASS_MAX_DATA_TRANSFER,
  2042. 0);
  2043. if (DataOutTransfer == NULL) {
  2044. Status = STATUS_INSUFFICIENT_RESOURCES;
  2045. goto CreateDiskTransfersEnd;
  2046. }
  2047. DataOutTransfer->Direction = UsbTransferDirectionOut;
  2048. DataOutTransfer->CallbackRoutine = CallbackRoutine;
  2049. DataOutTransfer->UserData = UserData;
  2050. Transfers->DataOutTransfer = DataOutTransfer;
  2051. Status = STATUS_SUCCESS;
  2052. CreateDiskTransfersEnd:
  2053. return Status;
  2054. }
  2055. VOID
  2056. UsbMasspDestroyTransfers (
  2057. PUSB_MASS_STORAGE_TRANSFERS Transfers
  2058. )
  2059. /*++
  2060. Routine Description:
  2061. This routine destroys a USB logical disk's transfers. It does not destroy
  2062. the structure intself.
  2063. Arguments:
  2064. Transfers - Supplies a pointer to a USB disk tranfers structure.
  2065. Return Value:
  2066. None.
  2067. --*/
  2068. {
  2069. if (Transfers->DataOutTransfer != NULL) {
  2070. UsbDestroyTransfer(Transfers->DataOutTransfer);
  2071. }
  2072. if (Transfers->DataInTransfer != NULL) {
  2073. UsbDestroyTransfer(Transfers->DataInTransfer);
  2074. }
  2075. if (Transfers->CommandTransfer != NULL) {
  2076. UsbDestroyTransfer(Transfers->CommandTransfer);
  2077. }
  2078. if (Transfers->StatusTransfer != NULL) {
  2079. UsbDestroyTransfer(Transfers->StatusTransfer);
  2080. }
  2081. if (Transfers->CommandBuffer != NULL) {
  2082. MmFreeIoBuffer(Transfers->CommandBuffer);
  2083. }
  2084. return;
  2085. }
  2086. KSTATUS
  2087. UsbMasspStartDisk (
  2088. PUSB_DISK Disk
  2089. )
  2090. /*++
  2091. Routine Description:
  2092. This routine attempts to fire up a USB logical disk.
  2093. Arguments:
  2094. Disk - Supplies a pointer to the disk.
  2095. Return Value:
  2096. None.
  2097. --*/
  2098. {
  2099. ULONG BufferSize;
  2100. PSCSI_INQUIRY_PAGE0 Page0;
  2101. BOOL PolledIoSupported;
  2102. KSTATUS Status;
  2103. ULONGLONG Timeout;
  2104. ULONG Try;
  2105. KeAcquireQueuedLock(Disk->Device->Lock);
  2106. //
  2107. // Send the INQUIRY for page 0 as a friendly "hello!".
  2108. //
  2109. BufferSize = sizeof(SCSI_INQUIRY_PAGE0);
  2110. Status = UsbMasspSendInquiry(Disk, 0, (PVOID)&Page0, &BufferSize);
  2111. if (!KSUCCESS(Status)) {
  2112. goto StartDiskEnd;
  2113. }
  2114. BufferSize = sizeof(SCSI_INQUIRY_PAGE0);
  2115. Status = UsbMasspSendInquiry(Disk, 0, (PVOID)&Page0, &BufferSize);
  2116. if (!KSUCCESS(Status)) {
  2117. goto StartDiskEnd;
  2118. }
  2119. //
  2120. // Get the block device parameters of the disk.
  2121. //
  2122. for (Try = 0; Try < USB_MASS_RETRY_COUNT; Try += 1) {
  2123. Status = UsbMasspReadFormatCapacities(Disk);
  2124. if (KSUCCESS(Status)) {
  2125. break;
  2126. }
  2127. Status = UsbMasspRequestSense(Disk);
  2128. if (!KSUCCESS(Status)) {
  2129. goto StartDiskEnd;
  2130. }
  2131. }
  2132. for (Try = 0; Try < USB_MASS_RETRY_COUNT; Try += 1) {
  2133. Status = UsbMasspReadCapacity(Disk);
  2134. if (KSUCCESS(Status)) {
  2135. break;
  2136. }
  2137. if (!KSUCCESS(UsbMasspRequestSense(Disk))) {
  2138. goto StartDiskEnd;
  2139. }
  2140. }
  2141. if (!KSUCCESS(Status)) {
  2142. goto StartDiskEnd;
  2143. }
  2144. Timeout = KeGetRecentTimeCounter() +
  2145. (HlQueryTimeCounterFrequency() * USB_MASS_UNIT_READY_TIMEOUT);
  2146. do {
  2147. Status = UsbMasspTestUnitReady(Disk);
  2148. if (KSUCCESS(Status)) {
  2149. break;
  2150. }
  2151. Status = UsbMasspRequestSense(Disk);
  2152. if (!KSUCCESS(Status)) {
  2153. goto StartDiskEnd;
  2154. }
  2155. Status = STATUS_TIMEOUT;
  2156. } while (KeGetRecentTimeCounter() <= Timeout);
  2157. if (!KSUCCESS(Status)) {
  2158. goto StartDiskEnd;
  2159. }
  2160. //
  2161. // Determine if polled I/O is supported, and create the disk interface if
  2162. // so.
  2163. //
  2164. if (Disk->DiskInterface.DiskToken == NULL) {
  2165. PolledIoSupported = UsbIsPolledIoSupported(Disk->Device->UsbCoreHandle);
  2166. if (PolledIoSupported != FALSE) {
  2167. RtlCopyMemory(&(Disk->DiskInterface),
  2168. &UsbMassDiskInterfaceTemplate,
  2169. sizeof(DISK_INTERFACE));
  2170. Disk->DiskInterface.DiskToken = Disk;
  2171. Disk->DiskInterface.BlockSize = 1 << Disk->BlockShift;
  2172. Disk->DiskInterface.BlockCount = Disk->BlockCount;
  2173. Status = IoCreateInterface(&UsbMassDiskInterfaceUuid,
  2174. Disk->OsDevice,
  2175. &(Disk->DiskInterface),
  2176. sizeof(DISK_INTERFACE));
  2177. if (!KSUCCESS(Status)) {
  2178. Disk->DiskInterface.DiskToken = NULL;
  2179. goto StartDiskEnd;
  2180. }
  2181. }
  2182. }
  2183. StartDiskEnd:
  2184. KeReleaseQueuedLock(Disk->Device->Lock);
  2185. return Status;
  2186. }
  2187. VOID
  2188. UsbMasspRemoveDisk (
  2189. PUSB_DISK Disk
  2190. )
  2191. /*++
  2192. Routine Description:
  2193. This routine attempts to remove a USB logical disk.
  2194. Arguments:
  2195. Disk - Supplies a pointer to the disk.
  2196. Return Value:
  2197. None.
  2198. --*/
  2199. {
  2200. PUSB_MASS_STORAGE_DEVICE Device;
  2201. //
  2202. // Tear down the disk interface if it was brought up.
  2203. //
  2204. if (Disk->DiskInterface.DiskToken != NULL) {
  2205. IoDestroyInterface(&UsbMassDiskInterfaceUuid,
  2206. Disk->OsDevice,
  2207. &(Disk->DiskInterface));
  2208. Disk->DiskInterface.DiskToken = NULL;
  2209. }
  2210. //
  2211. // Acquire the lock. Once the lock is held, the device will be no longer
  2212. // be in the middle of any transfers. This guarantees any pending IRPs will
  2213. // finish before the device is torn down.
  2214. //
  2215. Device = Disk->Device;
  2216. KeAcquireQueuedLock(Device->Lock);
  2217. //
  2218. // Assert that there is no active IRP.
  2219. //
  2220. ASSERT(Disk->Irp == NULL);
  2221. //
  2222. // Mark the disk as removed to prevent further IO.
  2223. //
  2224. Disk->Connected = FALSE;
  2225. //
  2226. // Remove the disk from the parents device list while holding the lock.
  2227. //
  2228. LIST_REMOVE(&(Disk->ListEntry));
  2229. KeReleaseQueuedLock(Device->Lock);
  2230. //
  2231. // Release the reference on the disk taken during creation. The disk will
  2232. // be destroyed once all the open handles are closed.
  2233. //
  2234. UsbMasspDiskReleaseReference(Disk);
  2235. return;
  2236. }
  2237. VOID
  2238. UsbMasspDestroyDisk (
  2239. PUSB_DISK Disk
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. This routine destroys a logical disk.
  2244. Arguments:
  2245. Disk - Supplies a pointer to the USB mass storage device.
  2246. Return Value:
  2247. None.
  2248. --*/
  2249. {
  2250. //
  2251. // The reference count should be zero.
  2252. //
  2253. ASSERT(Disk->ReferenceCount == 0);
  2254. //
  2255. // Destroy all structures that were created.
  2256. //
  2257. UsbMasspDestroyTransfers(&(Disk->Transfers));
  2258. if (Disk->Event != NULL) {
  2259. KeDestroyEvent(Disk->Event);
  2260. }
  2261. //
  2262. // Release the reference taken on the parent during disk creation.
  2263. //
  2264. UsbMasspDeviceReleaseReference(Disk->Device);
  2265. //
  2266. // Destroy the device structure.
  2267. //
  2268. MmFreeNonPagedPool(Disk);
  2269. return;
  2270. }
  2271. VOID
  2272. UsbMasspDiskAddReference (
  2273. PUSB_DISK Disk
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. This routine adds a reference to USB mass storage logical disk.
  2278. Arguments:
  2279. Disk - Supplies a pointer to the USB mass storage device.
  2280. Return Value:
  2281. None.
  2282. --*/
  2283. {
  2284. ULONG OldReferenceCount;
  2285. OldReferenceCount = RtlAtomicAdd32(&(Disk->ReferenceCount), 1);
  2286. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  2287. return;
  2288. }
  2289. VOID
  2290. UsbMasspDiskReleaseReference (
  2291. PUSB_DISK Disk
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. This routine releases a reference from the USB mass storage logical disk.
  2296. Arguments:
  2297. Disk - Supplies a pointer to the USB mass storage device.
  2298. Return Value:
  2299. None.
  2300. --*/
  2301. {
  2302. ULONG OldReferenceCount;
  2303. OldReferenceCount = RtlAtomicAdd32(&(Disk->ReferenceCount), (ULONG)-1);
  2304. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  2305. if (OldReferenceCount == 1) {
  2306. UsbMasspDestroyDisk(Disk);
  2307. }
  2308. return;
  2309. }
  2310. KSTATUS
  2311. UsbMasspSendInquiry (
  2312. PUSB_DISK Disk,
  2313. UCHAR Page,
  2314. PVOID *ResultBuffer,
  2315. PULONG ResultBufferSize
  2316. )
  2317. /*++
  2318. Routine Description:
  2319. This routine sends an inquiry to the USB disk device. This routine assumes
  2320. the mass storage device lock is already held.
  2321. Arguments:
  2322. Disk - Supplies a pointer to the disk to inquire to.
  2323. Page - Supplies the information page number to retrieve.
  2324. ResultBuffer - Supplies a pointer where the buffer containing the
  2325. information will be returned on success. This buffer will be pointing
  2326. into the disk's command buffer.
  2327. ResultBufferSize - Supplies a pointer pointing to an integer that on input
  2328. contains the expected size of the buffer. On output, contains the number
  2329. of bytes transferred.
  2330. Return Value:
  2331. Status code.
  2332. --*/
  2333. {
  2334. ULONG BytesTransferred;
  2335. PUCHAR InquiryCommand;
  2336. KSTATUS Status;
  2337. ASSERT(Disk->Irp == NULL);
  2338. BytesTransferred = 0;
  2339. *ResultBuffer = NULL;
  2340. //
  2341. // Set up the standard portion of the command block wrapper.
  2342. //
  2343. InquiryCommand = UsbMasspSetupCommand(Disk,
  2344. 0,
  2345. *ResultBufferSize,
  2346. SCSI_COMMAND_INQUIRY_SIZE,
  2347. TRUE,
  2348. FALSE,
  2349. NULL,
  2350. 0);
  2351. //
  2352. // Set up the command portion for an inquiry command.
  2353. //
  2354. *InquiryCommand = SCSI_COMMAND_INQUIRY;
  2355. ASSERT(Disk->LunNumber <= 7);
  2356. *(InquiryCommand + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2357. *(InquiryCommand + 4) = *ResultBufferSize;
  2358. Disk->Transfers.DataInTransfer->Length = *ResultBufferSize;
  2359. //
  2360. // Send the command.
  2361. //
  2362. Status = UsbMasspSendCommand(Disk);
  2363. if (!KSUCCESS(Status)) {
  2364. goto SendInquiryEnd;
  2365. }
  2366. Status = UsbMasspEvaluateCommandStatus(Disk,
  2367. FALSE,
  2368. FALSE,
  2369. &BytesTransferred);
  2370. if (!KSUCCESS(Status)) {
  2371. goto SendInquiryEnd;
  2372. }
  2373. if (BytesTransferred > *ResultBufferSize) {
  2374. Status = STATUS_BUFFER_TOO_SMALL;
  2375. goto SendInquiryEnd;
  2376. }
  2377. *ResultBuffer = Disk->Transfers.DataInTransfer->Buffer;
  2378. SendInquiryEnd:
  2379. *ResultBufferSize = BytesTransferred;
  2380. return Status;
  2381. }
  2382. KSTATUS
  2383. UsbMasspTestUnitReady (
  2384. PUSB_DISK Disk
  2385. )
  2386. /*++
  2387. Routine Description:
  2388. This routine sends a "test unit ready" command to the USB disk. This
  2389. routine assumes the mass storage device lock is already held.
  2390. Arguments:
  2391. Disk - Supplies a pointer to the disk to send the command to.
  2392. Return Value:
  2393. STATUS_SUCCESS if the device is ready.
  2394. STATUS_NOT_READY if the device is not ready.
  2395. Other error codes on failure.
  2396. --*/
  2397. {
  2398. ULONG BytesTransferred;
  2399. KSTATUS Status;
  2400. PUCHAR TestUnitReadyCommand;
  2401. ASSERT(Disk->Irp == NULL);
  2402. BytesTransferred = 0;
  2403. //
  2404. // Set up the standard portion of the command block wrapper.
  2405. //
  2406. TestUnitReadyCommand = UsbMasspSetupCommand(
  2407. Disk,
  2408. 0,
  2409. 0,
  2410. SCSI_COMMAND_TEST_UNIT_READY_SIZE,
  2411. TRUE,
  2412. FALSE,
  2413. NULL,
  2414. 0);
  2415. //
  2416. // Set up the command portion for an inquiry command.
  2417. //
  2418. *TestUnitReadyCommand = SCSI_COMMAND_TEST_UNIT_READY;
  2419. ASSERT(Disk->LunNumber <= 7);
  2420. *(TestUnitReadyCommand + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2421. *(TestUnitReadyCommand + 4) = 0;
  2422. Disk->Transfers.DataInTransfer->Length = 0;
  2423. //
  2424. // Send the command.
  2425. //
  2426. Status = UsbMasspSendCommand(Disk);
  2427. if (!KSUCCESS(Status)) {
  2428. goto TestUnitReadyEnd;
  2429. }
  2430. Status = UsbMasspEvaluateCommandStatus(Disk,
  2431. FALSE,
  2432. FALSE,
  2433. &BytesTransferred);
  2434. if (!KSUCCESS(Status)) {
  2435. Status = STATUS_NOT_READY;
  2436. goto TestUnitReadyEnd;
  2437. }
  2438. TestUnitReadyEnd:
  2439. return Status;
  2440. }
  2441. KSTATUS
  2442. UsbMasspRequestSense (
  2443. PUSB_DISK Disk
  2444. )
  2445. /*++
  2446. Routine Description:
  2447. This routine sends a "request sense data" command to the USB disk. This
  2448. routine assumes the mass storage device lock is already held.
  2449. Arguments:
  2450. Disk - Supplies a pointer to the disk to inquire to.
  2451. Return Value:
  2452. STATUS_SUCCESS if the device is ready.
  2453. STATUS_NOT_READY if the device is not ready.
  2454. Other error codes on failure.
  2455. --*/
  2456. {
  2457. ULONG BytesTransferred;
  2458. PUCHAR RequestSenseCommand;
  2459. KSTATUS Status;
  2460. ASSERT(Disk->Irp == NULL);
  2461. BytesTransferred = 0;
  2462. //
  2463. // Set up the standard portion of the command block wrapper.
  2464. //
  2465. RequestSenseCommand = UsbMasspSetupCommand(
  2466. Disk,
  2467. 0,
  2468. SCSI_COMMAND_REQUEST_SENSE_DATA_SIZE,
  2469. SCSI_COMMAND_REQUEST_SENSE_SIZE,
  2470. TRUE,
  2471. FALSE,
  2472. NULL,
  2473. 0);
  2474. //
  2475. // Set up the command portion for an inquiry command.
  2476. //
  2477. *RequestSenseCommand = SCSI_COMMAND_REQUEST_SENSE;
  2478. ASSERT(Disk->LunNumber <= 7);
  2479. *(RequestSenseCommand + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2480. *(RequestSenseCommand + 4) = SCSI_COMMAND_REQUEST_SENSE_DATA_SIZE;
  2481. Disk->Transfers.DataInTransfer->Length =
  2482. SCSI_COMMAND_REQUEST_SENSE_DATA_SIZE;
  2483. //
  2484. // Send the command.
  2485. //
  2486. Status = UsbMasspSendCommand(Disk);
  2487. if (!KSUCCESS(Status)) {
  2488. goto RequestSenseEnd;
  2489. }
  2490. Status = UsbMasspEvaluateCommandStatus(Disk,
  2491. FALSE,
  2492. FALSE,
  2493. &BytesTransferred);
  2494. if (!KSUCCESS(Status)) {
  2495. goto RequestSenseEnd;
  2496. }
  2497. RequestSenseEnd:
  2498. return Status;
  2499. }
  2500. KSTATUS
  2501. UsbMasspModeSense (
  2502. PUSB_DISK Disk
  2503. )
  2504. /*++
  2505. Routine Description:
  2506. This routine sends a "mode sense" command to the USB disk. This routine
  2507. assumes the mass storage device lock is already held.
  2508. Arguments:
  2509. Disk - Supplies a pointer to the disk to inquire to.
  2510. Return Value:
  2511. STATUS_SUCCESS if the device is ready.
  2512. STATUS_NOT_READY if the device is not ready.
  2513. Other error codes on failure.
  2514. --*/
  2515. {
  2516. ULONG BytesTransferred;
  2517. PUCHAR RequestSenseCommand;
  2518. KSTATUS Status;
  2519. ASSERT(Disk->Irp == NULL);
  2520. BytesTransferred = 0;
  2521. //
  2522. // Set up the standard portion of the command block wrapper.
  2523. //
  2524. RequestSenseCommand = UsbMasspSetupCommand(
  2525. Disk,
  2526. 0,
  2527. SCSI_COMMAND_MODE_SENSE_6_DATA_SIZE,
  2528. SCSI_COMMAND_MODE_SENSE_6_SIZE,
  2529. TRUE,
  2530. FALSE,
  2531. NULL,
  2532. 0);
  2533. //
  2534. // Set up the command portion for an inquiry command.
  2535. //
  2536. *RequestSenseCommand = SCSI_COMMAND_MODE_SENSE_6;
  2537. ASSERT(Disk->LunNumber <= 7);
  2538. *(RequestSenseCommand + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2539. *(RequestSenseCommand + 2) = 0x1C;
  2540. *(RequestSenseCommand + 4) = SCSI_COMMAND_MODE_SENSE_6_DATA_SIZE;
  2541. Disk->Transfers.DataInTransfer->Length =
  2542. SCSI_COMMAND_MODE_SENSE_6_DATA_SIZE;
  2543. //
  2544. // Send the command.
  2545. //
  2546. Status = UsbMasspSendCommand(Disk);
  2547. if (!KSUCCESS(Status)) {
  2548. goto ModeSenseEnd;
  2549. }
  2550. Status = UsbMasspEvaluateCommandStatus(Disk,
  2551. FALSE,
  2552. FALSE,
  2553. &BytesTransferred);
  2554. if (!KSUCCESS(Status)) {
  2555. goto ModeSenseEnd;
  2556. }
  2557. ModeSenseEnd:
  2558. return Status;
  2559. }
  2560. KSTATUS
  2561. UsbMasspReadFormatCapacities (
  2562. PUSB_DISK Disk
  2563. )
  2564. /*++
  2565. Routine Description:
  2566. This routine reads the capacity into the device using the "read format
  2567. capacities" command. The results will be written into the disk structure on
  2568. success. This routine assumes the mass storage device lock is already held.
  2569. Arguments:
  2570. Disk - Supplies a pointer to the disk to query.
  2571. Return Value:
  2572. Status code.
  2573. --*/
  2574. {
  2575. ULONG BlockSize;
  2576. ULONG BytesTransferred;
  2577. PSCSI_FORMAT_CAPACITIES Capacities;
  2578. PUCHAR Command;
  2579. PUSB_TRANSFER DataInTransfer;
  2580. KSTATUS Status;
  2581. ASSERT(Disk->Irp == NULL);
  2582. Command = UsbMasspSetupCommand(
  2583. Disk,
  2584. 0,
  2585. SCSI_COMMAND_READ_FORMAT_CAPACITIES_DATA_SIZE,
  2586. SCSI_COMMAND_READ_FORMAT_CAPACITIES_SIZE,
  2587. TRUE,
  2588. FALSE,
  2589. NULL,
  2590. 0);
  2591. //
  2592. // Set up the command portion for a read format capacities command.
  2593. //
  2594. *Command = SCSI_COMMAND_READ_FORMAT_CAPACITIES;
  2595. ASSERT(Disk->LunNumber <= 7);
  2596. *(Command + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2597. *(Command + 8) = SCSI_COMMAND_READ_FORMAT_CAPACITIES_DATA_SIZE;
  2598. DataInTransfer = Disk->Transfers.DataInTransfer;
  2599. DataInTransfer->Length = SCSI_COMMAND_READ_FORMAT_CAPACITIES_DATA_SIZE;
  2600. //
  2601. // Send the command.
  2602. //
  2603. Status = UsbMasspSendCommand(Disk);
  2604. if (!KSUCCESS(Status)) {
  2605. goto ReadFormatCapacitiesEnd;
  2606. }
  2607. Status = UsbMasspEvaluateCommandStatus(Disk,
  2608. FALSE,
  2609. FALSE,
  2610. &BytesTransferred);
  2611. if (!KSUCCESS(Status)) {
  2612. goto ReadFormatCapacitiesEnd;
  2613. }
  2614. if (BytesTransferred < sizeof(SCSI_FORMAT_CAPACITIES)) {
  2615. Status = STATUS_DATA_LENGTH_MISMATCH;
  2616. goto ReadFormatCapacitiesEnd;
  2617. }
  2618. Capacities = (PSCSI_FORMAT_CAPACITIES)DataInTransfer->Buffer;
  2619. Disk->BlockCount = CONVERT_BIG_ENDIAN_TO_CPU32(Capacities->BlockCount) + 1;
  2620. BlockSize = CONVERT_BIG_ENDIAN_TO_CPU32(Capacities->BlockLength);
  2621. if ((Disk->BlockCount == 0) || (BlockSize == 0)) {
  2622. Status = STATUS_INVALID_CONFIGURATION;
  2623. goto ReadFormatCapacitiesEnd;
  2624. }
  2625. if (POWER_OF_2(BlockSize) == FALSE) {
  2626. RtlDebugPrint("USB MASS: Invalid block size 0x%08x for device 0x%08x\n",
  2627. BlockSize,
  2628. Disk->OsDevice);
  2629. Status = STATUS_INVALID_CONFIGURATION;
  2630. goto ReadFormatCapacitiesEnd;
  2631. }
  2632. Disk->BlockShift = RtlCountTrailingZeros32(BlockSize);
  2633. ReadFormatCapacitiesEnd:
  2634. return Status;
  2635. }
  2636. KSTATUS
  2637. UsbMasspReadCapacity (
  2638. PUSB_DISK Disk
  2639. )
  2640. /*++
  2641. Routine Description:
  2642. This routine reads the capacity into the device. The results will be
  2643. written into the disk structure on success. This routine assumes the mass
  2644. storage device lock is already held.
  2645. Arguments:
  2646. Disk - Supplies a pointer to the disk to query.
  2647. Return Value:
  2648. Status code.
  2649. --*/
  2650. {
  2651. ULONG BlockSize;
  2652. ULONG BytesTransferred;
  2653. PSCSI_CAPACITY Capacity;
  2654. PUCHAR Command;
  2655. KSTATUS Status;
  2656. ASSERT(Disk->Irp == NULL);
  2657. Command = UsbMasspSetupCommand(Disk,
  2658. 0,
  2659. sizeof(SCSI_CAPACITY),
  2660. SCSI_COMMAND_READ_CAPACITY_SIZE,
  2661. TRUE,
  2662. FALSE,
  2663. NULL,
  2664. 0);
  2665. //
  2666. // Set up the command portion for a read capacity command.
  2667. //
  2668. *Command = SCSI_COMMAND_READ_CAPACITY;
  2669. ASSERT(Disk->LunNumber <= 7);
  2670. *(Command + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  2671. Disk->Transfers.DataInTransfer->Length = sizeof(SCSI_CAPACITY);
  2672. //
  2673. // Send the command.
  2674. //
  2675. Status = UsbMasspSendCommand(Disk);
  2676. if (!KSUCCESS(Status)) {
  2677. goto ReadCapacityEnd;
  2678. }
  2679. Status = UsbMasspEvaluateCommandStatus(Disk,
  2680. FALSE,
  2681. FALSE,
  2682. &BytesTransferred);
  2683. if (!KSUCCESS(Status)) {
  2684. goto ReadCapacityEnd;
  2685. }
  2686. if (BytesTransferred < sizeof(SCSI_CAPACITY)) {
  2687. Status = STATUS_DATA_LENGTH_MISMATCH;
  2688. goto ReadCapacityEnd;
  2689. }
  2690. Capacity = (PSCSI_CAPACITY)Disk->Transfers.DataInTransfer->Buffer;
  2691. Disk->BlockCount =
  2692. CONVERT_BIG_ENDIAN_TO_CPU32(Capacity->LastValidBlockAddress) + 1;
  2693. BlockSize = CONVERT_BIG_ENDIAN_TO_CPU32(Capacity->BlockLength);
  2694. if ((Disk->BlockCount == 0) || (BlockSize == 0)) {
  2695. Status = STATUS_INVALID_CONFIGURATION;
  2696. goto ReadCapacityEnd;
  2697. }
  2698. if (POWER_OF_2(BlockSize) == FALSE) {
  2699. RtlDebugPrint("USB MASS: Invalid block size 0x%08x for device 0x%08x\n",
  2700. BlockSize,
  2701. Disk->OsDevice);
  2702. Status = STATUS_INVALID_CONFIGURATION;
  2703. goto ReadCapacityEnd;
  2704. }
  2705. Disk->BlockShift = RtlCountTrailingZeros32(BlockSize);
  2706. ReadCapacityEnd:
  2707. return Status;
  2708. }
  2709. PVOID
  2710. UsbMasspSetupCommand (
  2711. PUSB_DISK Disk,
  2712. ULONG Tag,
  2713. ULONG DataLength,
  2714. UCHAR CommandLength,
  2715. BOOL DataIn,
  2716. BOOL PolledIo,
  2717. PVOID TransferVirtualAddress,
  2718. PHYSICAL_ADDRESS TransferPhysicalAddress
  2719. )
  2720. /*++
  2721. Routine Description:
  2722. This routine prepares to send a command to a disk by setting up the command
  2723. block wrapper and command status wrapper. This routine assumes the mass
  2724. storage device lock is already held.
  2725. Arguments:
  2726. Disk - Supplies a pointer to the disk that the command will be sent to.
  2727. Tag - Supplies an optional tag value to use, which can be useful in matching
  2728. up responses to requests.
  2729. DataLength - Supplies the length of the non-command portion of the transfer.
  2730. CommandLength - Supplies the length of the remaining free-form command
  2731. part of the Command Block Wrapper.
  2732. DataIn - Supplies a boolean indicating if the command is coming into the
  2733. host (TRUE) or going out to the device (FALSE).
  2734. PolledIo - Supplies a boolean indicating if the command is using the polled
  2735. I/O transfers (TRUE) or the default transfers (FALSE).
  2736. TransferVirtualAddress - Supplies a pointer to an optional buffer to use
  2737. for the data transfer.
  2738. TransferPhysicalAddress - Supplies the base physical address of the
  2739. transfer buffer. This parameter is optional but is required if the
  2740. transfer buffer is supplied.
  2741. Return Value:
  2742. Returns a pointer to the first free-form command byte in the Command Block
  2743. Wrapper.
  2744. --*/
  2745. {
  2746. ULONG AlignedDataLength;
  2747. ULONG BufferAlignment;
  2748. PSCSI_COMMAND_BLOCK Command;
  2749. PUSB_TRANSFER CommandTransfer;
  2750. PUSB_TRANSFER StatusTransfer;
  2751. PUSB_MASS_STORAGE_TRANSFERS Transfers;
  2752. if (PolledIo != FALSE) {
  2753. ASSERT(Disk->Device->PolledIoState != NULL);
  2754. Transfers = &(Disk->Device->PolledIoState->IoTransfers);
  2755. } else {
  2756. Transfers = &(Disk->Transfers);
  2757. }
  2758. CommandTransfer = Transfers->CommandTransfer;
  2759. StatusTransfer = Transfers->StatusTransfer;
  2760. //
  2761. // Set up the Command Block Wrapper (CBW).
  2762. //
  2763. Command = CommandTransfer->Buffer;
  2764. RtlZeroMemory(Command, sizeof(SCSI_COMMAND_BLOCK));
  2765. Command->Signature = SCSI_COMMAND_BLOCK_SIGNATURE;
  2766. Command->Tag = Tag;
  2767. Command->DataTransferLength = DataLength;
  2768. if (DataIn != FALSE) {
  2769. Command->Flags = SCSI_COMMAND_BLOCK_FLAG_DATA_IN;
  2770. } else {
  2771. Command->Flags = 0;
  2772. }
  2773. Command->LunNumber = Disk->LunNumber;
  2774. ASSERT(CommandLength <= 0x10);
  2775. Command->CommandLength = CommandLength;
  2776. //
  2777. // If no transfer buffer is supplied, then the transfer will use the
  2778. // command buffer. Set the status buffer after the data.
  2779. //
  2780. BufferAlignment = MmGetIoBufferAlignment();
  2781. if (TransferVirtualAddress == NULL) {
  2782. AlignedDataLength = ALIGN_RANGE_UP(DataLength, BufferAlignment);
  2783. //
  2784. // If a transfer buffer is supplied, the status buffer can start right
  2785. // after the command.
  2786. //
  2787. } else {
  2788. AlignedDataLength = 0;
  2789. }
  2790. ASSERT((CommandTransfer->BufferActualLength +
  2791. StatusTransfer->BufferActualLength +
  2792. AlignedDataLength) <=
  2793. ALIGN_RANGE_UP(USB_MASS_COMMAND_BUFFER_SIZE, BufferAlignment));
  2794. ASSERT(IS_ALIGNED((UINTN)CommandTransfer->Buffer, BufferAlignment));
  2795. ASSERT(IS_ALIGNED(CommandTransfer->BufferPhysicalAddress, BufferAlignment));
  2796. //
  2797. // Set the location and zero out the CSW.
  2798. //
  2799. StatusTransfer->Buffer = CommandTransfer->Buffer +
  2800. CommandTransfer->BufferActualLength +
  2801. AlignedDataLength;
  2802. StatusTransfer->BufferPhysicalAddress =
  2803. CommandTransfer->BufferPhysicalAddress +
  2804. CommandTransfer->BufferActualLength +
  2805. AlignedDataLength;
  2806. RtlZeroMemory(StatusTransfer->Buffer, sizeof(SCSI_COMMAND_STATUS));
  2807. ASSERT(IS_ALIGNED((UINTN)StatusTransfer->Buffer, BufferAlignment));
  2808. ASSERT(IS_ALIGNED(StatusTransfer->BufferPhysicalAddress, BufferAlignment));
  2809. //
  2810. // Set up the data in transfer to point immediately after the command block
  2811. // or to the supplied buffer.
  2812. //
  2813. if (TransferVirtualAddress == NULL) {
  2814. DataLength = AlignedDataLength;
  2815. TransferVirtualAddress = CommandTransfer->Buffer +
  2816. CommandTransfer->BufferActualLength;
  2817. TransferPhysicalAddress = CommandTransfer->BufferPhysicalAddress +
  2818. CommandTransfer->BufferActualLength;
  2819. }
  2820. ASSERT(TransferPhysicalAddress != INVALID_PHYSICAL_ADDRESS);
  2821. Transfers->DataInTransfer->Length = 0;
  2822. Transfers->DataInTransfer->Buffer = TransferVirtualAddress;
  2823. Transfers->DataInTransfer->BufferPhysicalAddress = TransferPhysicalAddress;
  2824. Transfers->DataInTransfer->BufferActualLength = DataLength;
  2825. Transfers->DataOutTransfer->Length = 0;
  2826. Transfers->DataOutTransfer->Buffer = TransferVirtualAddress;
  2827. Transfers->DataOutTransfer->BufferPhysicalAddress = TransferPhysicalAddress;
  2828. Transfers->DataOutTransfer->BufferActualLength = DataLength;
  2829. return &(Command->Command);
  2830. }
  2831. KSTATUS
  2832. UsbMasspSendCommand (
  2833. PUSB_DISK Disk
  2834. )
  2835. /*++
  2836. Routine Description:
  2837. This routine sends the command that's primed up in the command buffer of
  2838. the given USB disk. This routine assumes the mass storage device lock is
  2839. already held.
  2840. Arguments:
  2841. Disk - Supplies a pointer to the disk that the command will be sent to.
  2842. Irp - Supplies a pointer to an I/O IRP to continue when the transfer
  2843. completes. If this is NULL, the transfer will be completed
  2844. synchronously.
  2845. Return Value:
  2846. Status code. This status code may represent a failure to send, communicate,
  2847. or the disk failing the operation in the CSW. If the Command Status Wrapper
  2848. returns a phase error, this routine will reset the disk.
  2849. --*/
  2850. {
  2851. KSTATUS Status;
  2852. ASSERT(KeIsQueuedLockHeld(Disk->Device->Lock) != FALSE);
  2853. if (Disk->Irp == NULL) {
  2854. KeSignalEvent(Disk->Event, SignalOptionUnsignal);
  2855. }
  2856. Disk->StatusTransferAttempts = 0;
  2857. //
  2858. // Send the Command Block Wrapper.
  2859. //
  2860. Status = UsbSubmitTransfer(Disk->Transfers.CommandTransfer);
  2861. if (!KSUCCESS(Status)) {
  2862. goto SendCommandEnd;
  2863. }
  2864. //
  2865. // If there's an IRP, return immediately.
  2866. //
  2867. if (Disk->Irp != NULL) {
  2868. Status = STATUS_SUCCESS;
  2869. goto SendCommandEnd;
  2870. }
  2871. //
  2872. // This is a synchronous transfer. Mark that all transfers have been
  2873. // submitted, and wait for them to come back.
  2874. //
  2875. KeWaitForEvent(Disk->Event, FALSE, WAIT_TIME_INDEFINITE);
  2876. Status = STATUS_SUCCESS;
  2877. SendCommandEnd:
  2878. return Status;
  2879. }
  2880. VOID
  2881. UsbMasspTransferCompletionCallback (
  2882. PUSB_TRANSFER Transfer
  2883. )
  2884. /*++
  2885. Routine Description:
  2886. This routine is called when a USB transfer completes for mass storage.
  2887. Arguments:
  2888. Transfer - Supplies a pointer to the transfer that completed.
  2889. Return Value:
  2890. None.
  2891. --*/
  2892. {
  2893. ULONG BytesTransferred;
  2894. BOOL CompleteIrp;
  2895. PUSB_DISK Disk;
  2896. UCHAR Endpoint;
  2897. PIRP Irp;
  2898. KSTATUS Status;
  2899. BOOL SubmitStatusTransfer;
  2900. PUSB_MASS_STORAGE_TRANSFERS Transfers;
  2901. BOOL TransferSent;
  2902. CompleteIrp = FALSE;
  2903. Disk = (PUSB_DISK)Transfer->UserData;
  2904. Irp = Disk->Irp;
  2905. SubmitStatusTransfer = FALSE;
  2906. Transfers = &(Disk->Transfers);
  2907. TransferSent = FALSE;
  2908. ASSERT((Disk != NULL) && (Disk->Type == UsbMassStorageLogicalDisk));
  2909. ASSERT(KeIsQueuedLockHeld(Disk->Device->Lock) != FALSE);
  2910. //
  2911. // Handle stall failures according to the transfer type. All other failures
  2912. // should just roll through until the command status transfer is returned.
  2913. //
  2914. if ((Transfer != Transfers->CommandTransfer) &&
  2915. !KSUCCESS(Transfer->Status) &&
  2916. (Transfer->Error == UsbErrorTransferStalled)) {
  2917. //
  2918. // Pick the correct endpoint to clear. The status and data IN transfers
  2919. // clear the IN endpoint. The data OUT transfer clears the out endpoint.
  2920. //
  2921. Endpoint = Disk->Device->InEndpoint;
  2922. if (Transfer == Transfers->DataOutTransfer) {
  2923. Endpoint = Disk->Device->OutEndpoint;
  2924. }
  2925. UsbMasspClearEndpoint(Disk->Device, Endpoint, FALSE);
  2926. //
  2927. // Attempt to receive another command status wrapper if allowed.
  2928. //
  2929. if ((Transfer == Transfers->StatusTransfer) &&
  2930. (Disk->StatusTransferAttempts <
  2931. USB_MASS_STATUS_TRANSFER_ATTEMPT_LIMIT)) {
  2932. SubmitStatusTransfer = TRUE;
  2933. }
  2934. }
  2935. //
  2936. // If this is a successful command transfer completing, then fire off the
  2937. // next transfer in the set. If the command transfer fails, this I/O
  2938. // request is toast.
  2939. //
  2940. if (Transfer == Transfers->CommandTransfer) {
  2941. if (KSUCCESS(Transfer->Status)) {
  2942. //
  2943. // If there's data, submit the appropriate data transfer.
  2944. //
  2945. Disk->Transfers.DataInTransfer->Error = UsbErrorNone;
  2946. Disk->Transfers.DataOutTransfer->Error = UsbErrorNone;
  2947. if (Disk->Transfers.DataInTransfer->Length != 0) {
  2948. ASSERT(Disk->Transfers.DataOutTransfer->Length == 0);
  2949. TransferSent = TRUE;
  2950. Status = UsbSubmitTransfer(Disk->Transfers.DataInTransfer);
  2951. if (!KSUCCESS(Status)) {
  2952. TransferSent = FALSE;
  2953. }
  2954. } else if (Disk->Transfers.DataOutTransfer->Length != 0) {
  2955. TransferSent = TRUE;
  2956. Status = UsbSubmitTransfer(Disk->Transfers.DataOutTransfer);
  2957. if (!KSUCCESS(Status)) {
  2958. TransferSent = FALSE;
  2959. }
  2960. //
  2961. // Otherwise submit the transfer for the status word. If there is
  2962. // data then the status transfer will be submitted when the data
  2963. // portion is done.
  2964. //
  2965. } else {
  2966. ASSERT((Disk->Transfers.DataInTransfer->Length == 0) &&
  2967. (Disk->Transfers.DataOutTransfer->Length == 0));
  2968. SubmitStatusTransfer = TRUE;
  2969. }
  2970. }
  2971. //
  2972. // If the data IN or data OUT portion completed, submit the status transfer.
  2973. // The status transfer needs to be received even if the data transfer
  2974. // failed (or was cancelled). If the submission fails, it will be handled
  2975. // below with a reset. If a device I/O error occurred during the data
  2976. // portion, just skip the status transfer; the endpoint will go through
  2977. // reset recovery.
  2978. //
  2979. } else if ((Transfer != Transfers->StatusTransfer) &&
  2980. (Transfer->Error != UsbErrorTransferDeviceIo)) {
  2981. ASSERT((Transfer == Transfers->DataInTransfer) ||
  2982. (Transfer == Transfers->DataOutTransfer));
  2983. SubmitStatusTransfer = TRUE;
  2984. }
  2985. //
  2986. // If the status transfer needs to be submitted or resubmitted, fire it off.
  2987. //
  2988. if (SubmitStatusTransfer != FALSE) {
  2989. TransferSent = TRUE;
  2990. Disk->StatusTransferAttempts += 1;
  2991. Status = UsbSubmitTransfer(Disk->Transfers.StatusTransfer);
  2992. if (!KSUCCESS(Status)) {
  2993. Disk->StatusTransferAttempts -= 1;
  2994. TransferSent = FALSE;
  2995. }
  2996. }
  2997. //
  2998. // Do not do any processing if another transfer was sent.
  2999. //
  3000. if (TransferSent != FALSE) {
  3001. return;
  3002. }
  3003. //
  3004. // If the IRP is NULL, this must have been a synchronous transfer. If so,
  3005. // signal the event and let it handle the processing.
  3006. //
  3007. if (Irp == NULL) {
  3008. KeSignalEvent(Disk->Event, SignalOptionSignalAll);
  3009. return;
  3010. }
  3011. //
  3012. // Evaluate the result of the transfer and continue the IRP.
  3013. //
  3014. Status = UsbMasspEvaluateCommandStatus(Disk,
  3015. FALSE,
  3016. FALSE,
  3017. &BytesTransferred);
  3018. Disk->CurrentFragmentOffset += BytesTransferred;
  3019. Disk->CurrentBytesTransferred += BytesTransferred;
  3020. ASSERT(Disk->CurrentBytesTransferred <= Irp->U.ReadWrite.IoSizeInBytes);
  3021. //
  3022. // If the command succeeded and all the bytes have been transferred, then
  3023. // complete the IRP.
  3024. //
  3025. if (KSUCCESS(Status)) {
  3026. if (Disk->CurrentBytesTransferred == Irp->U.ReadWrite.IoSizeInBytes) {
  3027. CompleteIrp = TRUE;
  3028. goto TransferCompletionCallbackEnd;
  3029. }
  3030. Disk->IoRequestAttempts = 0;
  3031. //
  3032. // If it failed, prep to try the command again, unless it has been
  3033. // attempted too many times.
  3034. //
  3035. } else {
  3036. Disk->IoRequestAttempts += 1;
  3037. if (Disk->IoRequestAttempts > USB_MASS_IO_REQUEST_RETRY_COUNT) {
  3038. CompleteIrp = TRUE;
  3039. goto TransferCompletionCallbackEnd;
  3040. }
  3041. }
  3042. //
  3043. // Request the next batch of stuff (it could also be retry of the same
  3044. // batch). If this fails, complete the IRP. Do not attempt any retries, as
  3045. // failure here indicates a more serious failure (e.g. the command transfer
  3046. // failed to even be submitted).
  3047. //
  3048. Status = UsbMasspSendNextIoRequest(Disk);
  3049. if (!KSUCCESS(Status)) {
  3050. CompleteIrp = TRUE;
  3051. goto TransferCompletionCallbackEnd;
  3052. }
  3053. TransferCompletionCallbackEnd:
  3054. if (CompleteIrp != FALSE) {
  3055. ASSERT(Disk->Irp != NULL);
  3056. Irp->U.ReadWrite.IoBytesCompleted = Disk->CurrentBytesTransferred;
  3057. Irp->U.ReadWrite.NewIoOffset = Irp->U.ReadWrite.IoOffset +
  3058. Irp->U.ReadWrite.IoBytesCompleted;
  3059. IoCompleteIrp(UsbMassDriver, Irp, Status);
  3060. }
  3061. return;
  3062. }
  3063. KSTATUS
  3064. UsbMasspEvaluateCommandStatus (
  3065. PUSB_DISK Disk,
  3066. BOOL PolledIo,
  3067. BOOL DisableRecovery,
  3068. PULONG BytesTransferred
  3069. )
  3070. /*++
  3071. Routine Description:
  3072. This routine evaluates a Command Status Wrapper. This follows the USB Mass
  3073. Storage Class Bulk-Only Transport specification sections 6.5, 6.6, and 6.7.
  3074. Arguments:
  3075. Disk - Supplies a pointer to the disk that just completed a command.
  3076. PolledIo - Supplies a boolean indicating if the polled I/O transfers should
  3077. be evaluated (TRUE) or the default transfers (FALSE).
  3078. DisableRecovery - Supplies a boolean indicating if reset recovery is
  3079. disabled (TRUE) or enabled (FALSE).
  3080. BytesTransferred - Supplies a pointer where the number of completed bytes
  3081. will be returned.
  3082. Return Value:
  3083. STATUS_SUCCESS on success.
  3084. STATUS_DEVICE_IO_ERROR if the SCSI status was unsuccessful or a phase error.
  3085. STATUS_CHECKSUM_MISMATCH if the signature or tag values don't match.
  3086. Other errors if the USB transfers themselves failed.
  3087. --*/
  3088. {
  3089. PSCSI_COMMAND_BLOCK CommandBlock;
  3090. PSCSI_COMMAND_STATUS CommandStatus;
  3091. KSTATUS Status;
  3092. PUSB_TRANSFER StatusTransfer;
  3093. PUSB_MASS_STORAGE_TRANSFERS Transfers;
  3094. *BytesTransferred = 0;
  3095. if (PolledIo != FALSE) {
  3096. ASSERT(Disk->Device->PolledIoState != NULL);
  3097. Transfers = &(Disk->Device->PolledIoState->IoTransfers);
  3098. } else {
  3099. Transfers = &(Disk->Transfers);
  3100. }
  3101. //
  3102. // If the command transfer failed, there is no guarantee about any of the
  3103. // subsequent transfers. Just reset the device and exit.
  3104. //
  3105. if (!KSUCCESS(Transfers->CommandTransfer->Status)) {
  3106. Status = Transfers->CommandTransfer->Status;
  3107. goto EvaluateCommandStatusEnd;
  3108. }
  3109. ASSERT(Transfers->CommandTransfer->LengthTransferred ==
  3110. Transfers->CommandTransfer->Length);
  3111. if ((Transfers->DataInTransfer->Error != UsbErrorNone) ||
  3112. (Transfers->DataOutTransfer->Error != UsbErrorNone)) {
  3113. Status = STATUS_DEVICE_IO_ERROR;
  3114. goto EvaluateCommandStatusEnd;
  3115. }
  3116. //
  3117. // First check to see if the command status transfer itself was successful.
  3118. // If not, reset the device and return. The device will not receive another
  3119. // command transfer until it sends a CSW or a reset occurred. Without a
  3120. // successful status transfer, there is no guarantee the CSW was sent.
  3121. //
  3122. if (!KSUCCESS(Transfers->StatusTransfer->Status)) {
  3123. Status = Transfers->StatusTransfer->Status;
  3124. goto EvaluateCommandStatusEnd;
  3125. }
  3126. //
  3127. // Check to see if the command status transfer is valid. The length
  3128. // transferred has to match the length, the signature needs to match and
  3129. // the tag needs to match that of the command block transfer.
  3130. //
  3131. StatusTransfer = Transfers->StatusTransfer;
  3132. CommandBlock = (PSCSI_COMMAND_BLOCK)Transfers->CommandTransfer->Buffer;
  3133. CommandStatus = (PSCSI_COMMAND_STATUS)StatusTransfer->Buffer;
  3134. if ((StatusTransfer->LengthTransferred != StatusTransfer->Length) ||
  3135. (CommandStatus->Signature != SCSI_COMMAND_STATUS_SIGNATURE) ||
  3136. (CommandStatus->Tag != CommandBlock->Tag)) {
  3137. RtlDebugPrint("USBMASS: CSW Signature and tag were 0x%x 0x%x. "
  3138. "Possible USB or cache coherency issues.\n",
  3139. CommandStatus->Signature,
  3140. CommandStatus->Tag);
  3141. Status = STATUS_DEVICE_IO_ERROR;
  3142. goto EvaluateCommandStatusEnd;
  3143. }
  3144. //
  3145. // Check to see if the status is meaningful. A meaningful status is
  3146. // indicated in two ways. The first is when the status is either success or
  3147. // failure and the residue is less than or equal the transfer length.
  3148. //
  3149. if (((CommandStatus->Status == SCSI_STATUS_SUCCESS) ||
  3150. (CommandStatus->Status == SCSI_STATUS_FAILED)) &&
  3151. (CommandStatus->DataResidue <= CommandBlock->DataTransferLength)) {
  3152. *BytesTransferred = CommandBlock->DataTransferLength -
  3153. CommandStatus->DataResidue;
  3154. Status = STATUS_SUCCESS;
  3155. goto EvaluateCommandStatusEnd;
  3156. }
  3157. //
  3158. // The second is when the status indicates a phase error. A reset recovery
  3159. // is required and the residue data is ignored.
  3160. //
  3161. if (CommandStatus->Status == SCSI_STATUS_PHASE_ERROR) {
  3162. Status = STATUS_DEVICE_IO_ERROR;
  3163. goto EvaluateCommandStatusEnd;
  3164. }
  3165. //
  3166. // The status is valid, but not meaningful. Section 6.5 of the USB mass
  3167. // storage specification (bulk-only) indicates that a host "may" perform
  3168. // a reset recovery in this case, but is not required. Well, why not? All
  3169. // the other failures in this routine are doing it.
  3170. //
  3171. Status = STATUS_DEVICE_IO_ERROR;
  3172. EvaluateCommandStatusEnd:
  3173. if (!KSUCCESS(Status)) {
  3174. if (DisableRecovery == FALSE) {
  3175. UsbMasspResetRecovery(Disk->Device, PolledIo);
  3176. }
  3177. }
  3178. return Status;
  3179. }
  3180. KSTATUS
  3181. UsbMasspSendNextIoRequest (
  3182. PUSB_DISK Disk
  3183. )
  3184. /*++
  3185. Routine Description:
  3186. This routine starts transmission of the next chunk of I/O in a data
  3187. transfer request.
  3188. Arguments:
  3189. Disk - Supplies a pointer to the disk to transfer to or from.
  3190. Return Value:
  3191. Status code.
  3192. --*/
  3193. {
  3194. ULONGLONG Block;
  3195. UINTN BlockCount;
  3196. UINTN BytesToTransfer;
  3197. UCHAR Command;
  3198. PUCHAR CommandBuffer;
  3199. BOOL CommandIn;
  3200. UCHAR CommandLength;
  3201. PIO_BUFFER IoBuffer;
  3202. PIRP Irp;
  3203. PHYSICAL_ADDRESS PhysicalAddress;
  3204. UINTN RequestSize;
  3205. KSTATUS Status;
  3206. PUSB_TRANSFER UsbDataTransfer;
  3207. PVOID VirtualAddress;
  3208. Irp = Disk->Irp;
  3209. IoBuffer = Irp->U.ReadWrite.IoBuffer;
  3210. ASSERT(Irp != NULL);
  3211. ASSERT(IoBuffer != NULL);
  3212. ASSERT(Disk->CurrentBytesTransferred < Irp->U.ReadWrite.IoSizeInBytes);
  3213. ASSERT(Disk->CurrentFragment < IoBuffer->FragmentCount);
  3214. ASSERT(Disk->CurrentFragmentOffset <=
  3215. IoBuffer->Fragment[Disk->CurrentFragment].Size);
  3216. //
  3217. // Advance to the next fragment if the end of the previous one was reached.
  3218. //
  3219. if (Disk->CurrentFragmentOffset ==
  3220. IoBuffer->Fragment[Disk->CurrentFragment].Size) {
  3221. Disk->CurrentFragment += 1;
  3222. Disk->CurrentFragmentOffset = 0;
  3223. //
  3224. // End if this was the last fragment.
  3225. //
  3226. if (Disk->CurrentFragment == IoBuffer->FragmentCount) {
  3227. ASSERT(Disk->CurrentBytesTransferred ==
  3228. Irp->U.ReadWrite.IoSizeInBytes);
  3229. Status = STATUS_SUCCESS;
  3230. goto SendNextIoRequestEnd;
  3231. }
  3232. }
  3233. //
  3234. // Transfer the rest of the fragment, but cap it to the max of what the
  3235. // allocated USB transfer can do and on how many bytes have already been
  3236. // transferred and/or need to be transferred.
  3237. //
  3238. RequestSize = IoBuffer->Fragment[Disk->CurrentFragment].Size -
  3239. Disk->CurrentFragmentOffset;
  3240. BytesToTransfer = Irp->U.ReadWrite.IoSizeInBytes -
  3241. Disk->CurrentBytesTransferred;
  3242. if (BytesToTransfer < RequestSize) {
  3243. RequestSize = BytesToTransfer;
  3244. }
  3245. if (RequestSize > USB_MASS_MAX_DATA_TRANSFER) {
  3246. RequestSize = USB_MASS_MAX_DATA_TRANSFER;
  3247. }
  3248. ASSERT(RequestSize != 0);
  3249. ASSERT(IS_ALIGNED(RequestSize, MmGetIoBufferAlignment()) != FALSE);
  3250. PhysicalAddress =
  3251. IoBuffer->Fragment[Disk->CurrentFragment].PhysicalAddress +
  3252. Disk->CurrentFragmentOffset;
  3253. VirtualAddress = IoBuffer->Fragment[Disk->CurrentFragment].VirtualAddress +
  3254. Disk->CurrentFragmentOffset;
  3255. //
  3256. // Compute the block offset and size.
  3257. //
  3258. Block = Irp->U.ReadWrite.IoOffset + Disk->CurrentBytesTransferred;
  3259. ASSERT(IS_ALIGNED(Block, (1 << Disk->BlockShift)) != FALSE);
  3260. Block >>= Disk->BlockShift;
  3261. ASSERT(IS_ALIGNED(RequestSize, (1 << Disk->BlockShift)) != FALSE);
  3262. ASSERT(Block == (ULONG)Block);
  3263. BlockCount = RequestSize >> Disk->BlockShift;
  3264. ASSERT(BlockCount == (USHORT)BlockCount);
  3265. ASSERT(RequestSize == (ULONG)RequestSize);
  3266. //
  3267. // Watch for doing I/O off the end of the device.
  3268. //
  3269. if ((Block >= Disk->BlockCount) ||
  3270. (Block + BlockCount > Disk->BlockCount)) {
  3271. Status = STATUS_OUT_OF_BOUNDS;
  3272. goto SendNextIoRequestEnd;
  3273. }
  3274. //
  3275. // Set up the transfer.
  3276. //
  3277. if (Irp->MinorCode == IrpMinorIoRead) {
  3278. Command = SCSI_COMMAND_READ_10;
  3279. CommandLength = SCSI_COMMAND_READ_10_SIZE;
  3280. CommandIn = TRUE;
  3281. UsbDataTransfer = Disk->Transfers.DataInTransfer;
  3282. } else {
  3283. ASSERT(Irp->MinorCode == IrpMinorIoWrite);
  3284. Command = SCSI_COMMAND_WRITE_10;
  3285. CommandLength = SCSI_COMMAND_WRITE_10_SIZE;
  3286. CommandIn = FALSE;
  3287. UsbDataTransfer = Disk->Transfers.DataOutTransfer;
  3288. }
  3289. CommandBuffer = UsbMasspSetupCommand(Disk,
  3290. Command,
  3291. (ULONG)RequestSize,
  3292. CommandLength,
  3293. CommandIn,
  3294. FALSE,
  3295. VirtualAddress,
  3296. PhysicalAddress);
  3297. *CommandBuffer = Command;
  3298. *(CommandBuffer + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  3299. *(CommandBuffer + 2) = (UCHAR)(Block >> 24);
  3300. *(CommandBuffer + 3) = (UCHAR)(Block >> 16);
  3301. *(CommandBuffer + 4) = (UCHAR)(Block >> 8);
  3302. *(CommandBuffer + 5) = (UCHAR)Block;
  3303. *(CommandBuffer + 7) = (UCHAR)(BlockCount >> 8);
  3304. *(CommandBuffer + 8) = (UCHAR)BlockCount;
  3305. UsbDataTransfer->Length = (ULONG)RequestSize;
  3306. Status = UsbMasspSendCommand(Disk);
  3307. if (!KSUCCESS(Status)) {
  3308. goto SendNextIoRequestEnd;
  3309. }
  3310. Status = STATUS_SUCCESS;
  3311. SendNextIoRequestEnd:
  3312. return Status;
  3313. }
  3314. KSTATUS
  3315. UsbMasspResetRecovery (
  3316. PUSB_MASS_STORAGE_DEVICE Device,
  3317. BOOL PolledIo
  3318. )
  3319. /*++
  3320. Routine Description:
  3321. This routine issues a reset recovery to the mass storage bulk-only device.
  3322. Reset recovery consists of a bulk-only mass storage reset, clearing the
  3323. HALT feature in the IN endpoint, and then clearing the HALT feature in the
  3324. OUT endpoint.
  3325. Arguments:
  3326. Device - Supplies a pointer to the USB mass storage device that needs to
  3327. be reset.
  3328. PolledIo - Supplies a boolean indicating if polled I/O should be used to
  3329. perform the reset recovery (TRUE) or not (FALSE). The default is FALSE.
  3330. Return Value:
  3331. Status code.
  3332. --*/
  3333. {
  3334. KSTATUS Status;
  3335. //
  3336. // Proceed according to Section 5.3.4 of the USB Mass Storage
  3337. // Specification. First, reset the mass storage device and then clear the
  3338. // halts on both the IN and OUT endpoints.
  3339. //
  3340. Status = UsbMasspReset(Device, PolledIo);
  3341. if (!KSUCCESS(Status)) {
  3342. goto ResetRecoveryEnd;
  3343. }
  3344. Status = UsbMasspClearHalts(Device, PolledIo);
  3345. if (!KSUCCESS(Status)) {
  3346. goto ResetRecoveryEnd;
  3347. }
  3348. ResetRecoveryEnd:
  3349. //
  3350. // If reset recovery fails, notify the system so that action can be taken.
  3351. //
  3352. if (!KSUCCESS(Status)) {
  3353. RtlDebugPrint("USB MASS: Failed reset recovery on device 0x%08x!\n",
  3354. Device);
  3355. if (PolledIo == FALSE) {
  3356. IoSetDeviceDriverError(UsbGetDeviceToken(Device->UsbCoreHandle),
  3357. UsbMassDriver,
  3358. Status,
  3359. USB_MASS_ERROR_FAILED_RESET_RECOVERY);
  3360. }
  3361. }
  3362. return Status;
  3363. }
  3364. KSTATUS
  3365. UsbMasspReset (
  3366. PUSB_MASS_STORAGE_DEVICE Device,
  3367. BOOL PolledIo
  3368. )
  3369. /*++
  3370. Routine Description:
  3371. This routine resets the given mass storage device. It assumes that the
  3372. device lock is held or polled I/O mode is requested.
  3373. Arguments:
  3374. Device - Supplies a pointer to this mass storage device.
  3375. PolledIo - Supplies a boolean indicating if the reset should be performed
  3376. using polled I/O.
  3377. Return Value:
  3378. Status code.
  3379. --*/
  3380. {
  3381. USB_SETUP_PACKET SetupPacket;
  3382. KSTATUS Status;
  3383. ASSERT((PolledIo != FALSE) || (KeIsQueuedLockHeld(Device->Lock) != FALSE));
  3384. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  3385. SetupPacket.RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  3386. USB_SETUP_REQUEST_CLASS |
  3387. USB_SETUP_REQUEST_INTERFACE_RECIPIENT;
  3388. SetupPacket.Request = USB_MASS_REQUEST_RESET_DEVICE;
  3389. SetupPacket.Value = 0;
  3390. SetupPacket.Index = Device->InterfaceNumber;
  3391. SetupPacket.Length = 0;
  3392. //
  3393. // If polled I/O is requested, then use a USB mass specific send command.
  3394. //
  3395. if (PolledIo != FALSE) {
  3396. Status = UsbMasspSendPolledIoControlTransfer(Device,
  3397. UsbTransferDirectionOut,
  3398. &SetupPacket);
  3399. if (!KSUCCESS(Status)) {
  3400. goto ResetEnd;
  3401. }
  3402. //
  3403. // Otherwise, submit the transfer with the default command and wait for it
  3404. // to complete.
  3405. //
  3406. } else {
  3407. Status = UsbSendControlTransfer(Device->UsbCoreHandle,
  3408. UsbTransferDirectionOut,
  3409. &SetupPacket,
  3410. NULL,
  3411. 0,
  3412. NULL);
  3413. if (!KSUCCESS(Status)) {
  3414. goto ResetEnd;
  3415. }
  3416. }
  3417. ResetEnd:
  3418. return Status;
  3419. }
  3420. KSTATUS
  3421. UsbMasspClearHalts (
  3422. PUSB_MASS_STORAGE_DEVICE Device,
  3423. BOOL PolledIo
  3424. )
  3425. /*++
  3426. Routine Description:
  3427. This routine clears the HALT feature on the bulk in and out endpoints. This
  3428. routine assumes the device lock is held or polled I/O mode is requested.
  3429. Arguments:
  3430. Device - Supplies a pointer to the USB mass storage device.
  3431. PolledIo - Supplies a boolean indicating if the halt bits should be cleared
  3432. using polled I/O.
  3433. Return Value:
  3434. Status code.
  3435. --*/
  3436. {
  3437. KSTATUS Status;
  3438. Status = UsbMasspClearEndpoint(Device, Device->InEndpoint, PolledIo);
  3439. if (!KSUCCESS(Status)) {
  3440. goto ClearHaltsEnd;
  3441. }
  3442. Status = UsbMasspClearEndpoint(Device, Device->OutEndpoint, PolledIo);
  3443. if (!KSUCCESS(Status)) {
  3444. goto ClearHaltsEnd;
  3445. }
  3446. ClearHaltsEnd:
  3447. return Status;
  3448. }
  3449. KSTATUS
  3450. UsbMasspClearEndpoint (
  3451. PUSB_MASS_STORAGE_DEVICE Device,
  3452. UCHAR Endpoint,
  3453. BOOL PolledIo
  3454. )
  3455. /*++
  3456. Routine Description:
  3457. This routine clears the HALT feature on an endpoint. It assumes that the
  3458. device lock is held or polled I/O mode is requested.
  3459. Arguments:
  3460. Device - Supplies a pointer to the device whose IN endpoint needs to be
  3461. cleared.
  3462. Endpoint - Supplies the endpoint that needs to be cleared of the HALT
  3463. feature. It should either be IN or OUT.
  3464. PolledIo - Supplies a boolean indicating if the endpoint should be cleared
  3465. using polled I/O.
  3466. Return Value:
  3467. Status code.
  3468. --*/
  3469. {
  3470. USB_SETUP_PACKET SetupPacket;
  3471. KSTATUS Status;
  3472. ASSERT((PolledIo != FALSE) || (KeIsQueuedLockHeld(Device->Lock) != FALSE) ||
  3473. (Device->LunCount == 0));
  3474. if (PolledIo != FALSE) {
  3475. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  3476. SetupPacket.RequestType = USB_SETUP_REQUEST_ENDPOINT_RECIPIENT |
  3477. USB_SETUP_REQUEST_TO_DEVICE;
  3478. SetupPacket.Request = USB_REQUEST_CLEAR_FEATURE;
  3479. SetupPacket.Value = USB_FEATURE_ENDPOINT_HALT;
  3480. SetupPacket.Index = Endpoint;
  3481. SetupPacket.Length = 0;
  3482. Status = UsbMasspSendPolledIoControlTransfer(Device,
  3483. UsbTransferDirectionOut,
  3484. &SetupPacket);
  3485. if (!KSUCCESS(Status)) {
  3486. goto ClearEndpointEnd;
  3487. }
  3488. //
  3489. // The endpoint needs to be reset. The USB core conveniently does this
  3490. // automatically in the clear feature routine. But do it manually here.
  3491. //
  3492. Status = UsbResetEndpoint(Device->UsbCoreHandle, Endpoint);
  3493. if (!KSUCCESS(Status)) {
  3494. goto ClearEndpointEnd;
  3495. }
  3496. //
  3497. // Otherwise, attempt to clear the HALT feature from the endpoint using the
  3498. // built-in clear feature routine.
  3499. //
  3500. } else {
  3501. Status = UsbClearFeature(Device->UsbCoreHandle,
  3502. USB_SETUP_REQUEST_ENDPOINT_RECIPIENT,
  3503. USB_FEATURE_ENDPOINT_HALT,
  3504. Endpoint);
  3505. if (!KSUCCESS(Status)) {
  3506. goto ClearEndpointEnd;
  3507. }
  3508. }
  3509. ClearEndpointEnd:
  3510. return Status;
  3511. }
  3512. KSTATUS
  3513. UsbMasspBlockIoInitialize (
  3514. PVOID DiskToken
  3515. )
  3516. /*++
  3517. Routine Description:
  3518. This routine must be called before using the block read and write routines
  3519. in order to allow the disk to prepare for block I/O. This must be called at
  3520. low level.
  3521. Arguments:
  3522. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  3523. retrieved by querying the disk device information.
  3524. Return Value:
  3525. Status code.
  3526. --*/
  3527. {
  3528. PUSB_MASS_STORAGE_DEVICE Device;
  3529. PUSB_DISK Disk;
  3530. PVOID OriginalState;
  3531. PUSB_MASS_STORAGE_POLLED_IO_STATE PolledIoState;
  3532. KSTATUS Status;
  3533. ASSERT(KeGetRunLevel() == RunLevelLow);
  3534. Disk = (PUSB_DISK)DiskToken;
  3535. Device = Disk->Device;
  3536. //
  3537. // If the device's polled I/O state is already present, then block I/O is
  3538. // ready to go.
  3539. //
  3540. if (Device->PolledIoState != NULL) {
  3541. return STATUS_SUCCESS;
  3542. }
  3543. PolledIoState = UsbMasspCreatePolledIoState(Device);
  3544. if (PolledIoState == NULL) {
  3545. Status = STATUS_INSUFFICIENT_RESOURCES;
  3546. goto BlockIoInitializeEnd;
  3547. }
  3548. //
  3549. // Try to put this new polled I/O state into the device structure.
  3550. //
  3551. OriginalState= (PVOID)RtlAtomicCompareExchange(
  3552. (PUINTN)&(Device->PolledIoState),
  3553. (UINTN)PolledIoState,
  3554. (UINTN)NULL);
  3555. if (OriginalState == NULL) {
  3556. PolledIoState = NULL;
  3557. }
  3558. Status = STATUS_SUCCESS;
  3559. BlockIoInitializeEnd:
  3560. if (PolledIoState != NULL) {
  3561. UsbMasspDestroyPolledIoState(PolledIoState);
  3562. }
  3563. return Status;
  3564. }
  3565. KSTATUS
  3566. UsbMasspBlockIoRead (
  3567. PVOID DiskToken,
  3568. PIO_BUFFER IoBuffer,
  3569. ULONGLONG BlockAddress,
  3570. UINTN BlockCount,
  3571. PUINTN BlocksCompleted
  3572. )
  3573. /*++
  3574. Routine Description:
  3575. This routine reads the block contents from the disk into the given I/O
  3576. buffer using polled I/O. It does so without acquiring any locks or
  3577. allocating any resources, as this routine is used for crash dump support
  3578. when the system is in a very fragile state. This routine must be called at
  3579. high level.
  3580. Arguments:
  3581. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  3582. retrieved by querying the disk device information.
  3583. IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
  3584. BlockAddress - Supplies the block index to read (for physical disk, this is
  3585. the LBA).
  3586. BlockCount - Supplies the number of blocks to read.
  3587. BlocksCompleted - Supplies a pointer that receives the total number of
  3588. blocks read.
  3589. Return Value:
  3590. Status code.
  3591. --*/
  3592. {
  3593. PUSB_DISK Disk;
  3594. IRP_READ_WRITE IrpReadWrite;
  3595. KSTATUS Status;
  3596. ASSERT(KeGetRunLevel() == RunLevelHigh);
  3597. Disk = (PUSB_DISK)DiskToken;
  3598. IrpReadWrite.IoBuffer = IoBuffer;
  3599. IrpReadWrite.IoOffset = BlockAddress << Disk->BlockShift;
  3600. IrpReadWrite.IoSizeInBytes = BlockCount << Disk->BlockShift;
  3601. Status = UsbMasspPerformPolledIo(&IrpReadWrite, Disk, FALSE);
  3602. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Disk->BlockShift;
  3603. return Status;
  3604. }
  3605. KSTATUS
  3606. UsbMasspBlockIoWrite (
  3607. PVOID DiskToken,
  3608. PIO_BUFFER IoBuffer,
  3609. ULONGLONG BlockAddress,
  3610. UINTN BlockCount,
  3611. PUINTN BlocksCompleted
  3612. )
  3613. /*++
  3614. Routine Description:
  3615. This routine writes the contents of the given I/O buffer to the disk using
  3616. polled I/O. It does so without acquiring any locks or allocating any
  3617. resources, as this routine is used for crash dump support when the system
  3618. is in a very fragile state. This routine must be called at high level.
  3619. Arguments:
  3620. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  3621. retrieved by querying the disk device information.
  3622. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  3623. write.
  3624. BlockAddress - Supplies the block index to write to (for physical disk,
  3625. this is the LBA).
  3626. BlockCount - Supplies the number of blocks to write.
  3627. BlocksCompleted - Supplies a pointer that receives the total number of
  3628. blocks written.
  3629. Return Value:
  3630. Status code.
  3631. --*/
  3632. {
  3633. PUSB_DISK Disk;
  3634. IRP_READ_WRITE IrpReadWrite;
  3635. KSTATUS Status;
  3636. ASSERT(KeGetRunLevel() == RunLevelHigh);
  3637. Disk = (PUSB_DISK)DiskToken;
  3638. IrpReadWrite.IoBuffer = IoBuffer;
  3639. IrpReadWrite.IoOffset = BlockAddress << Disk->BlockShift;
  3640. IrpReadWrite.IoSizeInBytes = BlockCount << Disk->BlockShift;
  3641. Status = UsbMasspPerformPolledIo(&IrpReadWrite, Disk, TRUE);
  3642. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Disk->BlockShift;
  3643. return Status;
  3644. }
  3645. KSTATUS
  3646. UsbMasspPerformPolledIo (
  3647. PIRP_READ_WRITE IrpReadWrite,
  3648. PUSB_DISK Disk,
  3649. BOOL Write
  3650. )
  3651. /*++
  3652. Routine Description:
  3653. This routine performs polled I/O data transfers to the given USB disk.
  3654. Arguments:
  3655. IrpReadWrite - Supplies a pointer to the IRP's read/write context.
  3656. Disk - Supplies a pointer to a USB disk.
  3657. Write - Supplies a boolean indicating if this is a read (FALSE) or write
  3658. (TRUE) operation.
  3659. Return Value:
  3660. Status code.
  3661. --*/
  3662. {
  3663. UINTN BlockCount;
  3664. ULONGLONG BlockOffset;
  3665. ULONG BytesCompleted;
  3666. UINTN BytesRemaining;
  3667. UINTN BytesThisRound;
  3668. UCHAR Command;
  3669. PUCHAR CommandBuffer;
  3670. BOOL CommandIn;
  3671. UCHAR CommandLength;
  3672. KSTATUS CompletionStatus;
  3673. PUSB_MASS_STORAGE_DEVICE Device;
  3674. PIO_BUFFER_FRAGMENT Fragment;
  3675. UINTN FragmentIndex;
  3676. UINTN FragmentOffset;
  3677. PIO_BUFFER IoBuffer;
  3678. UINTN IoBufferOffset;
  3679. ULONG IrpReadWriteFlags;
  3680. PHYSICAL_ADDRESS PhysicalAddress;
  3681. BOOL ReadWriteIrpPrepared;
  3682. KSTATUS Status;
  3683. PUSB_TRANSFER UsbDataTransfer;
  3684. PVOID VirtualAddress;
  3685. ASSERT(KeGetRunLevel() == RunLevelHigh);
  3686. ASSERT(IrpReadWrite->IoBuffer != NULL);
  3687. IrpReadWrite->IoBytesCompleted = 0;
  3688. Device = Disk->Device;
  3689. ReadWriteIrpPrepared = FALSE;
  3690. //
  3691. // The polled I/O transfers better be initialized.
  3692. //
  3693. if (Device->PolledIoState == NULL) {
  3694. ASSERT(Device->PolledIoState != NULL);
  3695. Status = STATUS_NOT_INITIALIZED;
  3696. goto PerformPolledIoEnd;
  3697. }
  3698. //
  3699. // Perform a one-time reset of the I/O endpoints to prepare for the polled
  3700. // I/O. This is necessary because there may be a CBW in flight and the
  3701. // device won't like it if another CBW is sent before it has a chance to
  3702. // finish with the CSW.
  3703. //
  3704. if (Device->PolledIoState->ResetRequired != FALSE) {
  3705. Status = UsbMasspResetForPolledIo(Device);
  3706. if (!KSUCCESS(Status)) {
  3707. goto PerformPolledIoEnd;
  3708. }
  3709. Device->PolledIoState->ResetRequired = FALSE;
  3710. }
  3711. //
  3712. // Prepare for the I/O. This is not polled I/O in the normal sense, as
  3713. // USB transfers are still handling the work. So do not note it as polled.
  3714. //
  3715. IrpReadWriteFlags = 0;
  3716. if (Write != FALSE) {
  3717. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  3718. }
  3719. Status = IoPrepareReadWriteIrp(IrpReadWrite,
  3720. 1 << Disk->BlockShift,
  3721. 0,
  3722. MAX_ULONG,
  3723. IrpReadWriteFlags);
  3724. ASSERT(KSUCCESS(Status));
  3725. ReadWriteIrpPrepared = TRUE;
  3726. IoBuffer = IrpReadWrite->IoBuffer;
  3727. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
  3728. ASSERT(KSUCCESS(Status));
  3729. //
  3730. // Find the starting fragment based on the current offset.
  3731. //
  3732. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  3733. FragmentIndex = 0;
  3734. FragmentOffset = 0;
  3735. while (IoBufferOffset != 0) {
  3736. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  3737. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  3738. if (IoBufferOffset < Fragment->Size) {
  3739. FragmentOffset = IoBufferOffset;
  3740. break;
  3741. }
  3742. IoBufferOffset -= Fragment->Size;
  3743. FragmentIndex += 1;
  3744. }
  3745. //
  3746. // Set up the transfer command.
  3747. //
  3748. if (Write == FALSE) {
  3749. Command = SCSI_COMMAND_READ_10;
  3750. CommandLength = SCSI_COMMAND_READ_10_SIZE;
  3751. CommandIn = TRUE;
  3752. UsbDataTransfer = Device->PolledIoState->IoTransfers.DataInTransfer;
  3753. } else {
  3754. Command = SCSI_COMMAND_WRITE_10;
  3755. CommandLength = SCSI_COMMAND_WRITE_10_SIZE;
  3756. CommandIn = FALSE;
  3757. UsbDataTransfer = Device->PolledIoState->IoTransfers.DataOutTransfer;
  3758. }
  3759. //
  3760. // Loop reading in or writing out each fragment in the I/O buffer.
  3761. //
  3762. BytesRemaining = IrpReadWrite->IoSizeInBytes;
  3763. ASSERT(IS_ALIGNED(BytesRemaining, 1 << Disk->BlockShift) != FALSE);
  3764. ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, 1 << Disk->BlockShift) != FALSE);
  3765. BlockOffset = IrpReadWrite->IoOffset >> Disk->BlockShift;
  3766. while (BytesRemaining != 0) {
  3767. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  3768. Fragment = (PIO_BUFFER_FRAGMENT)&(IoBuffer->Fragment[FragmentIndex]);
  3769. VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
  3770. PhysicalAddress = Fragment->PhysicalAddress + FragmentOffset;
  3771. BytesThisRound = Fragment->Size - FragmentOffset;
  3772. if (BytesRemaining < BytesThisRound) {
  3773. BytesThisRound = BytesRemaining;
  3774. }
  3775. //
  3776. // Transfer the rest of the fragment, but cap it to the max of what the
  3777. // allocated USB transfer can do and on how many bytes have already been
  3778. // transferred and/or need to be transferred.
  3779. //
  3780. if (BytesThisRound > USB_MASS_MAX_DATA_TRANSFER) {
  3781. BytesThisRound = USB_MASS_MAX_DATA_TRANSFER;
  3782. }
  3783. ASSERT(BytesThisRound != 0);
  3784. ASSERT(IS_ALIGNED(BytesThisRound, 1 << Disk->BlockShift) != FALSE);
  3785. BlockCount = BytesThisRound >> Disk->BlockShift;
  3786. ASSERT(BlockCount == (USHORT)BlockCount);
  3787. ASSERT(BytesThisRound == (ULONG)BytesThisRound);
  3788. //
  3789. // Watch for doing I/O off the end of the device.
  3790. //
  3791. if ((BlockOffset >= Disk->BlockCount) ||
  3792. ((BlockOffset + BlockCount) > Disk->BlockCount)) {
  3793. Status = STATUS_OUT_OF_BOUNDS;
  3794. goto PerformPolledIoEnd;
  3795. }
  3796. CommandBuffer = UsbMasspSetupCommand(Disk,
  3797. Command,
  3798. (ULONG)BytesThisRound,
  3799. CommandLength,
  3800. CommandIn,
  3801. TRUE,
  3802. VirtualAddress,
  3803. PhysicalAddress);
  3804. *CommandBuffer = Command;
  3805. *(CommandBuffer + 1) = Disk->LunNumber << SCSI_COMMAND_LUN_SHIFT;
  3806. *(CommandBuffer + 2) = (UCHAR)(BlockOffset >> 24);
  3807. *(CommandBuffer + 3) = (UCHAR)(BlockOffset >> 16);
  3808. *(CommandBuffer + 4) = (UCHAR)(BlockOffset >> 8);
  3809. *(CommandBuffer + 5) = (UCHAR)BlockOffset;
  3810. *(CommandBuffer + 7) = (UCHAR)(BlockCount >> 8);
  3811. *(CommandBuffer + 8) = (UCHAR)BlockCount;
  3812. UsbDataTransfer->Length = (ULONG)BytesThisRound;
  3813. //
  3814. // Send the command using polled I/O.
  3815. //
  3816. Status = UsbMasspSendPolledIoCommand(Disk, &BytesCompleted);
  3817. if (!KSUCCESS(Status)) {
  3818. goto PerformPolledIoEnd;
  3819. }
  3820. if ((BytesCompleted >> Disk->BlockShift) != BlockCount) {
  3821. Status = STATUS_DATA_LENGTH_MISMATCH;
  3822. goto PerformPolledIoEnd;
  3823. }
  3824. FragmentOffset += BytesCompleted;
  3825. if (FragmentOffset == Fragment->Size) {
  3826. FragmentIndex += 1;
  3827. FragmentOffset = 0;
  3828. }
  3829. BlockOffset += BlockCount;
  3830. BytesRemaining -= BytesCompleted;
  3831. IrpReadWrite->IoBytesCompleted += BytesCompleted;
  3832. }
  3833. Status = STATUS_SUCCESS;
  3834. PerformPolledIoEnd:
  3835. if (ReadWriteIrpPrepared != FALSE) {
  3836. CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
  3837. IrpReadWriteFlags);
  3838. if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
  3839. Status = CompletionStatus;
  3840. }
  3841. }
  3842. IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
  3843. IrpReadWrite->IoBytesCompleted;
  3844. return Status;
  3845. }
  3846. KSTATUS
  3847. UsbMasspSendPolledIoCommand (
  3848. PUSB_DISK Disk,
  3849. PULONG BytesCompleted
  3850. )
  3851. /*++
  3852. Routine Description:
  3853. This routine sends the current polled I/O command to the USB mass storage
  3854. device.
  3855. Arguments:
  3856. Disk - Supplies a pointer to a USB disk.
  3857. BytesCompleted - Supplies a pointer where the number of completed bytes
  3858. will be returned.
  3859. Return Value:
  3860. Status code.
  3861. --*/
  3862. {
  3863. PUSB_TRANSFER DataTransfer;
  3864. KSTATUS Status;
  3865. PUSB_MASS_STORAGE_TRANSFERS Transfers;
  3866. ASSERT(Disk->Device->PolledIoState != NULL);
  3867. Transfers = &(Disk->Device->PolledIoState->IoTransfers);
  3868. //
  3869. // Submit the command transfer.
  3870. //
  3871. Status = UsbSubmitPolledTransfer(Transfers->CommandTransfer);
  3872. if (!KSUCCESS(Status)) {
  3873. goto PerformPolledIoEnd;
  3874. }
  3875. //
  3876. // Submit the data transfer if there is any data. Ignore failures here as
  3877. // the command status transfer is expected given that command block
  3878. // transfer succeeded.
  3879. //
  3880. DataTransfer = NULL;
  3881. if (Transfers->DataInTransfer->Length != 0) {
  3882. ASSERT(Transfers->DataOutTransfer->Length == 0);
  3883. DataTransfer = Transfers->DataInTransfer;
  3884. } else if (Transfers->DataOutTransfer->Length != 0) {
  3885. DataTransfer = Transfers->DataOutTransfer;
  3886. }
  3887. if (DataTransfer != NULL) {
  3888. UsbSubmitPolledTransfer(DataTransfer);
  3889. }
  3890. //
  3891. // Always submit the command status transfer. Ignore status here too.
  3892. //
  3893. UsbSubmitPolledTransfer(Transfers->StatusTransfer);
  3894. PerformPolledIoEnd:
  3895. //
  3896. // Now analyze the status from the transfer to see if it worked.
  3897. //
  3898. Status = UsbMasspEvaluateCommandStatus(Disk, TRUE, TRUE, BytesCompleted);
  3899. if (!KSUCCESS(Status)) {
  3900. RtlDebugPrint("USBMASS: Polled I/O failed %d.\n", Status);
  3901. }
  3902. return Status;
  3903. }
  3904. KSTATUS
  3905. UsbMasspResetForPolledIo (
  3906. PUSB_MASS_STORAGE_DEVICE Device
  3907. )
  3908. /*++
  3909. Routine Description:
  3910. This routine resets the USB Mass storage device to which the given disk is
  3911. attached in preparation for polled I/O operations. This includes halting
  3912. any in-flight transfers and performing reset recovery.
  3913. Arguments:
  3914. Device - Supplies a pointer to the USB device to be reset.
  3915. Return Value:
  3916. Status code.
  3917. --*/
  3918. {
  3919. ULONG ControlTransfers;
  3920. ULONG DataInTransfers;
  3921. ULONG DataOutTransfers;
  3922. KSTATUS Status;
  3923. Status = UsbFlushEndpoint(Device->UsbCoreHandle, 0, &ControlTransfers);
  3924. if (!KSUCCESS(Status)) {
  3925. goto ResetForPolledIoEnd;
  3926. }
  3927. Status = UsbFlushEndpoint(Device->UsbCoreHandle,
  3928. Device->InEndpoint,
  3929. &DataInTransfers);
  3930. if (!KSUCCESS(Status)) {
  3931. goto ResetForPolledIoEnd;
  3932. }
  3933. Status = UsbFlushEndpoint(Device->UsbCoreHandle,
  3934. Device->OutEndpoint,
  3935. &DataOutTransfers);
  3936. if (!KSUCCESS(Status)) {
  3937. goto ResetForPolledIoEnd;
  3938. }
  3939. Status = UsbMasspResetRecovery(Device, TRUE);
  3940. if (!KSUCCESS(Status)) {
  3941. goto ResetForPolledIoEnd;
  3942. }
  3943. ResetForPolledIoEnd:
  3944. return Status;
  3945. }
  3946. KSTATUS
  3947. UsbMasspSendPolledIoControlTransfer (
  3948. PUSB_MASS_STORAGE_DEVICE Device,
  3949. USB_TRANSFER_DIRECTION TransferDirection,
  3950. PUSB_SETUP_PACKET SetupPacket
  3951. )
  3952. /*++
  3953. Routine Description:
  3954. This routine sends a control transfer to the given USB mass storage device
  3955. using polled I/O.
  3956. Arguments:
  3957. Device - Supplies a pointer to the USB mass storage device to talk to.
  3958. TransferDirection - Supplies whether or not the transfer is to the device
  3959. or to the host.
  3960. SetupPacket - Supplies a pointer to the setup packet.
  3961. Return Value:
  3962. Stats code.
  3963. --*/
  3964. {
  3965. PIO_BUFFER IoBuffer;
  3966. KSTATUS Status;
  3967. PUSB_TRANSFER Transfer;
  3968. PVOID TransferBuffer;
  3969. //
  3970. // This routine is only meant to be used at high run level.
  3971. //
  3972. ASSERT(KeGetRunLevel() == RunLevelHigh);
  3973. //
  3974. // The polled I/O device state must be present.
  3975. //
  3976. if (Device->PolledIoState == NULL) {
  3977. ASSERT(Device->PolledIoState != NULL);
  3978. return STATUS_NOT_INITIALIZED;
  3979. }
  3980. Transfer = Device->PolledIoState->ControlTransfer;
  3981. ASSERT(Transfer != NULL);
  3982. ASSERT(TransferDirection != UsbTransferDirectionInvalid);
  3983. //
  3984. // Borrow the polled I/O state's command I/O buffer. It should not be in
  3985. // use right now.
  3986. //
  3987. IoBuffer = Device->PolledIoState->IoTransfers.CommandBuffer;
  3988. ASSERT(IoBuffer->FragmentCount == 1);
  3989. TransferBuffer = IoBuffer->Fragment[0].VirtualAddress;
  3990. RtlCopyMemory(TransferBuffer, SetupPacket, sizeof(USB_SETUP_PACKET));
  3991. //
  3992. // Initialize the USB transfer.
  3993. //
  3994. Transfer->Direction = TransferDirection;
  3995. Transfer->Length = sizeof(USB_SETUP_PACKET);
  3996. Transfer->Buffer = TransferBuffer;
  3997. Transfer->BufferPhysicalAddress = IoBuffer->Fragment[0].PhysicalAddress;
  3998. Transfer->BufferActualLength = IoBuffer->Fragment[0].Size;
  3999. //
  4000. // Submit the transfer via polled I/O and wait for it to complete.
  4001. //
  4002. Status = UsbSubmitPolledTransfer(Transfer);
  4003. if (!KSUCCESS(Status)) {
  4004. goto SendPolledIoControlTransferEnd;
  4005. }
  4006. ASSERT(KSUCCESS(Transfer->Status));
  4007. //
  4008. // Copy the results into the caller's buffer.
  4009. //
  4010. ASSERT(Transfer->LengthTransferred >= sizeof(USB_SETUP_PACKET));
  4011. Status = STATUS_SUCCESS;
  4012. SendPolledIoControlTransferEnd:
  4013. return Status;
  4014. }