sdomap4.c 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. sdomap4.c
  9. Abstract:
  10. This module implements the SD/MMC driver for TI OMAP4 SoCs.
  11. Author:
  12. Evan Green 16-Mar-2014
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include "sdomap4.h"
  21. //
  22. // --------------------------------------------------------------------- Macros
  23. //
  24. //
  25. // These macros read and write SD controller registers.
  26. //
  27. #define SD_OMAP4_READ_REGISTER(_Device, _Register) \
  28. HlReadRegister32((_Device)->ControllerBase + (_Register))
  29. #define SD_OMAP4_WRITE_REGISTER(_Device, _Register, _Value) \
  30. HlWriteRegister32((_Device)->ControllerBase + (_Register), (_Value))
  31. //
  32. // ---------------------------------------------------------------- Definitions
  33. //
  34. //
  35. // ------------------------------------------------------ Data Type Definitions
  36. //
  37. //
  38. // ----------------------------------------------- Internal Function Prototypes
  39. //
  40. KSTATUS
  41. SdOmap4AddDevice (
  42. PVOID Driver,
  43. PCSTR DeviceId,
  44. PCSTR ClassId,
  45. PCSTR CompatibleIds,
  46. PVOID DeviceToken
  47. );
  48. VOID
  49. SdOmap4DispatchStateChange (
  50. PIRP Irp,
  51. PVOID DeviceContext,
  52. PVOID IrpContext
  53. );
  54. VOID
  55. SdOmap4DispatchOpen (
  56. PIRP Irp,
  57. PVOID DeviceContext,
  58. PVOID IrpContext
  59. );
  60. VOID
  61. SdOmap4DispatchClose (
  62. PIRP Irp,
  63. PVOID DeviceContext,
  64. PVOID IrpContext
  65. );
  66. VOID
  67. SdOmap4DispatchIo (
  68. PIRP Irp,
  69. PVOID DeviceContext,
  70. PVOID IrpContext
  71. );
  72. VOID
  73. SdOmap4DispatchSystemControl (
  74. PIRP Irp,
  75. PVOID DeviceContext,
  76. PVOID IrpContext
  77. );
  78. VOID
  79. SdOmap4ParentDispatchStateChange (
  80. PIRP Irp,
  81. PSD_OMAP4_CONTEXT Context,
  82. PVOID IrpContext
  83. );
  84. VOID
  85. SdOmap4ChildDispatchStateChange (
  86. PIRP Irp,
  87. PSD_OMAP4_CHILD Child,
  88. PVOID IrpContext
  89. );
  90. KSTATUS
  91. SdOmap4ParentProcessResourceRequirements (
  92. PIRP Irp,
  93. PSD_OMAP4_CONTEXT Device
  94. );
  95. KSTATUS
  96. SdOmap4ParentStartDevice (
  97. PIRP Irp,
  98. PSD_OMAP4_CONTEXT Device
  99. );
  100. KSTATUS
  101. SdOmap4ParentQueryChildren (
  102. PIRP Irp,
  103. PSD_OMAP4_CONTEXT Device
  104. );
  105. KSTATUS
  106. SdOmap4ResetController (
  107. PSD_OMAP4_CONTEXT Device
  108. );
  109. INTERRUPT_STATUS
  110. SdOmap4InterruptService (
  111. PVOID Context
  112. );
  113. INTERRUPT_STATUS
  114. SdOmap4InterruptServiceDispatch (
  115. PVOID Context
  116. );
  117. VOID
  118. SdOmap4SdDmaCompletion (
  119. PSD_CONTROLLER Controller,
  120. PVOID Context,
  121. UINTN BytesTransferred,
  122. KSTATUS Status
  123. );
  124. PSD_OMAP4_CHILD
  125. SdOmap4pCreateChild (
  126. PSD_OMAP4_CONTEXT Device
  127. );
  128. VOID
  129. SdOmap4pDestroyChild (
  130. PSD_OMAP4_CHILD Child
  131. );
  132. VOID
  133. SdOmap4pChildAddReference (
  134. PSD_OMAP4_CHILD Child
  135. );
  136. VOID
  137. SdOmap4pChildReleaseReference (
  138. PSD_OMAP4_CHILD Child
  139. );
  140. KSTATUS
  141. SdOmap4ChildBlockIoReset (
  142. PVOID DiskToken
  143. );
  144. KSTATUS
  145. SdOmap4ChildBlockIoRead (
  146. PVOID DiskToken,
  147. PIO_BUFFER IoBuffer,
  148. ULONGLONG BlockAddress,
  149. UINTN BlockCount,
  150. PUINTN BlocksCompleted
  151. );
  152. KSTATUS
  153. SdOmap4ChildBlockIoWrite (
  154. PVOID DiskToken,
  155. PIO_BUFFER IoBuffer,
  156. ULONGLONG BlockAddress,
  157. UINTN BlockCount,
  158. PUINTN BlocksCompleted
  159. );
  160. KSTATUS
  161. SdOmap4PerformIoPolled (
  162. PIRP_READ_WRITE IrpReadWrite,
  163. PSD_OMAP4_CHILD Child,
  164. BOOL Write,
  165. BOOL LockRequired
  166. );
  167. KSTATUS
  168. SdOmap4GetSetBusWidth (
  169. PSD_CONTROLLER Controller,
  170. PVOID Context,
  171. BOOL Set
  172. );
  173. KSTATUS
  174. SdOmap4InitializeDma (
  175. PSD_OMAP4_CONTEXT Device
  176. );
  177. VOID
  178. SdOmap4DmaInterfaceCallback (
  179. PVOID Context,
  180. PDEVICE Device,
  181. PVOID InterfaceBuffer,
  182. ULONG InterfaceBufferSize,
  183. BOOL Arrival
  184. );
  185. VOID
  186. SdOmap4PerformDmaIo (
  187. PSD_OMAP4_CHILD Child,
  188. PIRP Irp
  189. );
  190. KSTATUS
  191. SdOmap4SetupEdma (
  192. PSD_OMAP4_CHILD Child,
  193. PULONGLONG Size
  194. );
  195. VOID
  196. SdOmap4EdmaCompletion (
  197. PDMA_TRANSFER Transfer
  198. );
  199. VOID
  200. SdOmap4DmaCompletion (
  201. PSD_CONTROLLER Controller,
  202. PVOID Context,
  203. UINTN BytesTransferred,
  204. KSTATUS Status
  205. );
  206. //
  207. // -------------------------------------------------------------------- Globals
  208. //
  209. PDRIVER SdOmap4Driver = NULL;
  210. UUID SdOmap4DiskInterfaceUuid = UUID_DISK_INTERFACE;
  211. UUID SdOmap4DmaUuid = UUID_DMA_INTERFACE;
  212. UUID SdOmap4Edma3Uuid = UUID_EDMA_CONTROLLER;
  213. DISK_INTERFACE SdOmap4DiskInterfaceTemplate = {
  214. DISK_INTERFACE_VERSION,
  215. NULL,
  216. 0,
  217. 0,
  218. NULL,
  219. SdOmap4ChildBlockIoReset,
  220. SdOmap4ChildBlockIoRead,
  221. SdOmap4ChildBlockIoWrite
  222. };
  223. //
  224. // ------------------------------------------------------------------ Functions
  225. //
  226. KSTATUS
  227. DriverEntry (
  228. PDRIVER Driver
  229. )
  230. /*++
  231. Routine Description:
  232. This routine is the entry point for the SD/MMC driver. It registers its
  233. other dispatch functions, and performs driver-wide initialization.
  234. Arguments:
  235. Driver - Supplies a pointer to the driver object.
  236. Return Value:
  237. STATUS_SUCCESS on success.
  238. Failure code on error.
  239. --*/
  240. {
  241. DRIVER_FUNCTION_TABLE FunctionTable;
  242. KSTATUS Status;
  243. SdOmap4Driver = Driver;
  244. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  245. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  246. FunctionTable.AddDevice = SdOmap4AddDevice;
  247. FunctionTable.DispatchStateChange = SdOmap4DispatchStateChange;
  248. FunctionTable.DispatchOpen = SdOmap4DispatchOpen;
  249. FunctionTable.DispatchClose = SdOmap4DispatchClose;
  250. FunctionTable.DispatchIo = SdOmap4DispatchIo;
  251. FunctionTable.DispatchSystemControl = SdOmap4DispatchSystemControl;
  252. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  253. return Status;
  254. }
  255. KSTATUS
  256. SdOmap4AddDevice (
  257. PVOID Driver,
  258. PCSTR DeviceId,
  259. PCSTR ClassId,
  260. PCSTR CompatibleIds,
  261. PVOID DeviceToken
  262. )
  263. /*++
  264. Routine Description:
  265. This routine is called when a device is detected for which the SD/MMC driver
  266. acts as the function driver. The driver will attach itself to the stack.
  267. Arguments:
  268. Driver - Supplies a pointer to the driver being called.
  269. DeviceId - Supplies a pointer to a string with the device ID.
  270. ClassId - Supplies a pointer to a string containing the device's class ID.
  271. CompatibleIds - Supplies a pointer to a string containing device IDs
  272. that would be compatible with this device.
  273. DeviceToken - Supplies an opaque token that the driver can use to identify
  274. the device in the system. This token should be used when attaching to
  275. the stack.
  276. Return Value:
  277. STATUS_SUCCESS on success.
  278. Failure code if the driver was unsuccessful in attaching itself.
  279. --*/
  280. {
  281. PSD_OMAP4_CONTEXT Context;
  282. KSTATUS Status;
  283. //
  284. // Allocate non-paged pool because this device could be the paging device.
  285. //
  286. Context = MmAllocateNonPagedPool(sizeof(SD_OMAP4_CONTEXT),
  287. SD_ALLOCATION_TAG);
  288. if (Context == NULL) {
  289. Status = STATUS_INSUFFICIENT_RESOURCES;
  290. goto AddDeviceEnd;
  291. }
  292. RtlZeroMemory(Context, sizeof(SD_OMAP4_CONTEXT));
  293. Context->Type = SdOmap4Parent;
  294. Context->InterruptHandle = INVALID_HANDLE;
  295. Context->Lock = KeCreateQueuedLock();
  296. if (Context->Lock == NULL) {
  297. Status = STATUS_INSUFFICIENT_RESOURCES;
  298. goto AddDeviceEnd;
  299. }
  300. if (IoAreDeviceIdsEqual(DeviceId, SD_OMAP4_DEVICE_ID) != 0) {
  301. Context->Soc = SdTiSocOmap4;
  302. } else if (IoAreDeviceIdsEqual(DeviceId, SD_AM335_DEVICE_ID) != 0) {
  303. Context->Soc = SdTiSocAm335;
  304. } else {
  305. ASSERT(FALSE);
  306. Status = STATUS_NO_ELIGIBLE_DEVICES;
  307. goto AddDeviceEnd;
  308. }
  309. Status = IoAttachDriverToDevice(Driver, DeviceToken, Context);
  310. if (!KSUCCESS(Status)) {
  311. goto AddDeviceEnd;
  312. }
  313. AddDeviceEnd:
  314. if (!KSUCCESS(Status)) {
  315. if (Context != NULL) {
  316. MmFreeNonPagedPool(Context);
  317. }
  318. }
  319. return Status;
  320. }
  321. VOID
  322. SdOmap4DispatchStateChange (
  323. PIRP Irp,
  324. PVOID DeviceContext,
  325. PVOID IrpContext
  326. )
  327. /*++
  328. Routine Description:
  329. This routine handles State Change IRPs.
  330. Arguments:
  331. Irp - Supplies a pointer to the I/O request packet.
  332. DeviceContext - Supplies the context pointer supplied by the driver when it
  333. attached itself to the driver stack. Presumably this pointer contains
  334. driver-specific device context.
  335. IrpContext - Supplies the context pointer supplied by the driver when
  336. the IRP was created.
  337. Return Value:
  338. None.
  339. --*/
  340. {
  341. PSD_OMAP4_CONTEXT Context;
  342. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  343. Context = DeviceContext;
  344. switch (Context->Type) {
  345. case SdOmap4Parent:
  346. SdOmap4ParentDispatchStateChange(Irp, Context, IrpContext);
  347. break;
  348. case SdOmap4Child:
  349. SdOmap4ChildDispatchStateChange(Irp,
  350. (PSD_OMAP4_CHILD)Context,
  351. IrpContext);
  352. break;
  353. default:
  354. ASSERT(FALSE);
  355. break;
  356. }
  357. return;
  358. }
  359. VOID
  360. SdOmap4DispatchOpen (
  361. PIRP Irp,
  362. PVOID DeviceContext,
  363. PVOID IrpContext
  364. )
  365. /*++
  366. Routine Description:
  367. This routine handles Open IRPs.
  368. Arguments:
  369. Irp - Supplies a pointer to the I/O request packet.
  370. DeviceContext - Supplies the context pointer supplied by the driver when it
  371. attached itself to the driver stack. Presumably this pointer contains
  372. driver-specific device context.
  373. IrpContext - Supplies the context pointer supplied by the driver when
  374. the IRP was created.
  375. Return Value:
  376. None.
  377. --*/
  378. {
  379. PSD_OMAP4_CHILD Child;
  380. Child = DeviceContext;
  381. //
  382. // Only the child can be opened or closed.
  383. //
  384. if (Child->Type != SdOmap4Child) {
  385. return;
  386. }
  387. SdOmap4pChildAddReference(Child);
  388. IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
  389. return;
  390. }
  391. VOID
  392. SdOmap4DispatchClose (
  393. PIRP Irp,
  394. PVOID DeviceContext,
  395. PVOID IrpContext
  396. )
  397. /*++
  398. Routine Description:
  399. This routine handles Close IRPs.
  400. Arguments:
  401. Irp - Supplies a pointer to the I/O request packet.
  402. DeviceContext - Supplies the context pointer supplied by the driver when it
  403. attached itself to the driver stack. Presumably this pointer contains
  404. driver-specific device context.
  405. IrpContext - Supplies the context pointer supplied by the driver when
  406. the IRP was created.
  407. Return Value:
  408. None.
  409. --*/
  410. {
  411. PSD_OMAP4_CHILD Child;
  412. Child = DeviceContext;
  413. if (Child->Type != SdOmap4Child) {
  414. return;
  415. }
  416. SdOmap4pChildReleaseReference(Child);
  417. IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
  418. return;
  419. }
  420. VOID
  421. SdOmap4DispatchIo (
  422. PIRP Irp,
  423. PVOID DeviceContext,
  424. PVOID IrpContext
  425. )
  426. /*++
  427. Routine Description:
  428. This routine handles I/O IRPs.
  429. Arguments:
  430. Irp - Supplies a pointer to the I/O request packet.
  431. DeviceContext - Supplies the context pointer supplied by the driver when it
  432. attached itself to the driver stack. Presumably this pointer contains
  433. driver-specific device context.
  434. IrpContext - Supplies the context pointer supplied by the driver when
  435. the IRP was created.
  436. Return Value:
  437. None.
  438. --*/
  439. {
  440. PSD_OMAP4_CHILD Child;
  441. BOOL CompleteIrp;
  442. PSD_CONTROLLER Controller;
  443. ULONG IrpReadWriteFlags;
  444. KSTATUS IrpStatus;
  445. KSTATUS Status;
  446. BOOL Write;
  447. ASSERT(KeGetRunLevel() == RunLevelLow);
  448. Child = DeviceContext;
  449. if (Child->Type != SdOmap4Child) {
  450. ASSERT(FALSE);
  451. return;
  452. }
  453. CompleteIrp = TRUE;
  454. Controller = Child->Controller;
  455. Write = FALSE;
  456. if (Irp->MinorCode == IrpMinorIoWrite) {
  457. Write = TRUE;
  458. }
  459. //
  460. // Polled I/O is shared by a few code paths and prepares the IRP for I/O
  461. // further down the stack. It should also only be hit in the down direction
  462. // path as it always completes the IRP.
  463. //
  464. if ((Child->Flags & SD_OMAP4_CHILD_FLAG_DMA_SUPPORTED) == 0) {
  465. ASSERT(Irp->Direction == IrpDown);
  466. Status = SdOmap4PerformIoPolled(&(Irp->U.ReadWrite),
  467. Child,
  468. Write,
  469. TRUE);
  470. goto DispatchIoEnd;
  471. }
  472. //
  473. // Set the IRP read/write flags for the preparation and completion steps.
  474. //
  475. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_DMA;
  476. if (Write != FALSE) {
  477. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  478. }
  479. if (Irp->Direction == IrpDown) {
  480. Controller->Try = 0;
  481. }
  482. //
  483. // If the IRP is on the way up, then clean up after the DMA as this IRP is
  484. // still sitting in the channel. An IRP going up is already complete.
  485. //
  486. if (Irp->Direction == IrpUp) {
  487. ASSERT(Irp == Child->Irp);
  488. Child->Irp = NULL;
  489. //
  490. // Try to recover on failure.
  491. //
  492. IrpStatus = IoGetIrpStatus(Irp);
  493. if (!KSUCCESS(IrpStatus)) {
  494. Status = SdErrorRecovery(Controller);
  495. if (!KSUCCESS(Status)) {
  496. IrpStatus = Status;
  497. IoUpdateIrpStatus(Irp, IrpStatus);
  498. }
  499. //
  500. // Do not make further attempts if the media is gone or enough
  501. // attempts have been made.
  502. //
  503. if (((Controller->Flags &
  504. SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) ||
  505. ((Controller->Flags &
  506. SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
  507. (Controller->Try >= SD_MAX_IO_RETRIES)) {
  508. IrpStatus = STATUS_SUCCESS;
  509. } else {
  510. Controller->Try += 1;
  511. }
  512. }
  513. KeReleaseQueuedLock(Child->ControllerLock);
  514. Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite),
  515. IrpReadWriteFlags);
  516. if (!KSUCCESS(Status)) {
  517. IoUpdateIrpStatus(Irp, Status);
  518. }
  519. //
  520. // Potentially return the completed IRP.
  521. //
  522. if (KSUCCESS(IrpStatus)) {
  523. CompleteIrp = FALSE;
  524. goto DispatchIoEnd;
  525. }
  526. }
  527. //
  528. // Start the DMA on the way down.
  529. //
  530. Irp->U.ReadWrite.IoBytesCompleted = 0;
  531. Irp->U.ReadWrite.NewIoOffset = Irp->U.ReadWrite.IoOffset;
  532. ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
  533. ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
  534. ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoOffset,
  535. 1 << Child->BlockShift) != FALSE);
  536. ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoSizeInBytes,
  537. 1 << Child->BlockShift) != FALSE);
  538. //
  539. // Before acquiring the controller's lock and starting the DMA, prepare
  540. // the I/O context for SD (i.e. it must use physical addresses that
  541. // are less than 4GB and be sector size aligned).
  542. //
  543. Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
  544. 1 << Child->BlockShift,
  545. 0,
  546. MAX_ULONG,
  547. IrpReadWriteFlags);
  548. if (!KSUCCESS(Status)) {
  549. goto DispatchIoEnd;
  550. }
  551. //
  552. // Lock the controller to serialize access to the hardware.
  553. //
  554. KeAcquireQueuedLock(Child->ControllerLock);
  555. if (((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
  556. ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0)) {
  557. Status = STATUS_NO_MEDIA;
  558. if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
  559. Status = STATUS_MEDIA_CHANGED;
  560. }
  561. KeReleaseQueuedLock(Child->ControllerLock);
  562. IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  563. goto DispatchIoEnd;
  564. }
  565. //
  566. // If it's DMA, just send it on through.
  567. //
  568. Child->Irp = Irp;
  569. CompleteIrp = FALSE;
  570. IoPendIrp(SdOmap4Driver, Irp);
  571. SdOmap4PerformDmaIo(Child, Irp);
  572. //
  573. // DMA transfers are self perpetuating, so after kicking off this
  574. // first transfer, return. This returns with the lock held because
  575. // I/O is still in progress.
  576. //
  577. ASSERT(KeIsQueuedLockHeld(Child->ControllerLock) != FALSE);
  578. DispatchIoEnd:
  579. if (CompleteIrp != FALSE) {
  580. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  581. }
  582. return;
  583. }
  584. VOID
  585. SdOmap4DispatchSystemControl (
  586. PIRP Irp,
  587. PVOID DeviceContext,
  588. PVOID IrpContext
  589. )
  590. /*++
  591. Routine Description:
  592. This routine handles System Control IRPs.
  593. Arguments:
  594. Irp - Supplies a pointer to the I/O request packet.
  595. DeviceContext - Supplies the context pointer supplied by the driver when it
  596. attached itself to the driver stack. Presumably this pointer contains
  597. driver-specific device context.
  598. IrpContext - Supplies the context pointer supplied by the driver when
  599. the IRP was created.
  600. Return Value:
  601. None.
  602. --*/
  603. {
  604. PSD_OMAP4_CHILD Child;
  605. PVOID Context;
  606. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  607. PSYSTEM_CONTROL_LOOKUP Lookup;
  608. PFILE_PROPERTIES Properties;
  609. ULONGLONG PropertiesFileSize;
  610. KSTATUS Status;
  611. Context = Irp->U.SystemControl.SystemContext;
  612. Child = DeviceContext;
  613. //
  614. // Only child devices are supported.
  615. //
  616. if (Child->Type != SdOmap4Child) {
  617. ASSERT(Child->Type == SdOmap4Parent);
  618. return;
  619. }
  620. switch (Irp->MinorCode) {
  621. case IrpMinorSystemControlLookup:
  622. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  623. Status = STATUS_PATH_NOT_FOUND;
  624. if (Lookup->Root != FALSE) {
  625. //
  626. // Enable opening of the root as a single file.
  627. //
  628. Properties = &(Lookup->Properties);
  629. Properties->FileId = 0;
  630. Properties->Type = IoObjectBlockDevice;
  631. Properties->HardLinkCount = 1;
  632. Properties->BlockCount = Child->BlockCount;
  633. Properties->BlockSize = 1 << Child->BlockShift;
  634. WRITE_INT64_SYNC(&(Properties->FileSize),
  635. Child->BlockCount << Child->BlockShift);
  636. Status = STATUS_SUCCESS;
  637. }
  638. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  639. break;
  640. //
  641. // Writes to the disk's properties are not allowed. Fail if the data
  642. // has changed.
  643. //
  644. case IrpMinorSystemControlWriteFileProperties:
  645. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  646. Properties = FileOperation->FileProperties;
  647. READ_INT64_SYNC(&(Properties->FileSize), &PropertiesFileSize);
  648. if ((Properties->FileId != 0) ||
  649. (Properties->Type != IoObjectBlockDevice) ||
  650. (Properties->HardLinkCount != 1) ||
  651. (Properties->BlockSize != (1 << Child->BlockShift)) ||
  652. (Properties->BlockCount != Child->BlockCount) ||
  653. (PropertiesFileSize != (Child->BlockCount << Child->BlockShift))) {
  654. Status = STATUS_NOT_SUPPORTED;
  655. } else {
  656. Status = STATUS_SUCCESS;
  657. }
  658. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  659. break;
  660. //
  661. // Do not support hard disk device truncation.
  662. //
  663. case IrpMinorSystemControlTruncate:
  664. IoCompleteIrp(SdOmap4Driver, Irp, STATUS_NOT_SUPPORTED);
  665. break;
  666. //
  667. // Gather and return device information.
  668. //
  669. case IrpMinorSystemControlDeviceInformation:
  670. break;
  671. case IrpMinorSystemControlSynchronize:
  672. IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
  673. break;
  674. //
  675. // Ignore everything unrecognized.
  676. //
  677. default:
  678. ASSERT(FALSE);
  679. break;
  680. }
  681. return;
  682. }
  683. VOID
  684. SdOmap4ParentDispatchStateChange (
  685. PIRP Irp,
  686. PSD_OMAP4_CONTEXT Context,
  687. PVOID IrpContext
  688. )
  689. /*++
  690. Routine Description:
  691. This routine handles State Change IRPs for a parent device.
  692. Arguments:
  693. Irp - Supplies a pointer to the I/O request packet.
  694. Context - Supplies a pointer to the controller information.
  695. IrpContext - Supplies the context pointer supplied by the driver when
  696. the IRP was created.
  697. Return Value:
  698. None.
  699. --*/
  700. {
  701. KSTATUS Status;
  702. if (Irp->Direction == IrpUp) {
  703. if (!KSUCCESS(IoGetIrpStatus(Irp))) {
  704. return;
  705. }
  706. switch (Irp->MinorCode) {
  707. case IrpMinorQueryResources:
  708. Status = SdOmap4ParentProcessResourceRequirements(Irp, Context);
  709. if (!KSUCCESS(Status)) {
  710. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  711. }
  712. break;
  713. case IrpMinorStartDevice:
  714. Status = SdOmap4ParentStartDevice(Irp, Context);
  715. if (!KSUCCESS(Status)) {
  716. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  717. }
  718. break;
  719. case IrpMinorQueryChildren:
  720. Status = SdOmap4ParentQueryChildren(Irp, Context);
  721. if (!KSUCCESS(Status)) {
  722. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  723. }
  724. break;
  725. default:
  726. break;
  727. }
  728. }
  729. return;
  730. }
  731. VOID
  732. SdOmap4ChildDispatchStateChange (
  733. PIRP Irp,
  734. PSD_OMAP4_CHILD Child,
  735. PVOID IrpContext
  736. )
  737. /*++
  738. Routine Description:
  739. This routine handles State Change IRPs for a parent device.
  740. Arguments:
  741. Irp - Supplies a pointer to the I/O request packet.
  742. Child - Supplies a pointer to the child device information.
  743. IrpContext - Supplies the context pointer supplied by the driver when
  744. the IRP was created.
  745. Return Value:
  746. None.
  747. --*/
  748. {
  749. BOOL CompleteIrp;
  750. KSTATUS Status;
  751. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  752. //
  753. // The IRP is on its way down the stack. Do most processing here.
  754. //
  755. if (Irp->Direction == IrpDown) {
  756. Status = STATUS_NOT_SUPPORTED;
  757. CompleteIrp = TRUE;
  758. switch (Irp->MinorCode) {
  759. case IrpMinorQueryResources:
  760. Status = STATUS_SUCCESS;
  761. break;
  762. case IrpMinorStartDevice:
  763. Status = STATUS_SUCCESS;
  764. if (Child->DiskInterface.DiskToken == NULL) {
  765. RtlCopyMemory(&(Child->DiskInterface),
  766. &SdOmap4DiskInterfaceTemplate,
  767. sizeof(DISK_INTERFACE));
  768. Child->DiskInterface.BlockSize = 1 << Child->BlockShift;
  769. Child->DiskInterface.BlockCount = Child->BlockCount;
  770. Child->DiskInterface.DiskToken = Child;
  771. Status = IoCreateInterface(&SdOmap4DiskInterfaceUuid,
  772. Child->Device,
  773. &(Child->DiskInterface),
  774. sizeof(DISK_INTERFACE));
  775. if (!KSUCCESS(Status)) {
  776. Child->DiskInterface.DiskToken = NULL;
  777. }
  778. }
  779. break;
  780. case IrpMinorQueryChildren:
  781. Irp->U.QueryChildren.Children = NULL;
  782. Irp->U.QueryChildren.ChildCount = 0;
  783. Status = STATUS_SUCCESS;
  784. break;
  785. case IrpMinorQueryInterface:
  786. break;
  787. case IrpMinorRemoveDevice:
  788. if (Child->DiskInterface.DiskToken != NULL) {
  789. Status = IoDestroyInterface(&SdOmap4DiskInterfaceUuid,
  790. Child->Device,
  791. &(Child->DiskInterface));
  792. ASSERT(KSUCCESS(Status));
  793. Child->DiskInterface.DiskToken = NULL;
  794. }
  795. SdOmap4pChildReleaseReference(Child);
  796. Status = STATUS_SUCCESS;
  797. break;
  798. //
  799. // Pass all other IRPs down.
  800. //
  801. default:
  802. CompleteIrp = FALSE;
  803. break;
  804. }
  805. //
  806. // Complete the IRP unless there's a reason not to.
  807. //
  808. if (CompleteIrp != FALSE) {
  809. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  810. }
  811. //
  812. // The IRP is completed and is on its way back up.
  813. //
  814. } else {
  815. ASSERT(Irp->Direction == IrpUp);
  816. }
  817. return;
  818. }
  819. KSTATUS
  820. SdOmap4ParentProcessResourceRequirements (
  821. PIRP Irp,
  822. PSD_OMAP4_CONTEXT Device
  823. )
  824. /*++
  825. Routine Description:
  826. This routine filters through the resource requirements presented by the
  827. bus for a SD OMAP4 Host controller. It adds an interrupt vector requirement
  828. for any interrupt line requested.
  829. Arguments:
  830. Irp - Supplies a pointer to the I/O request packet.
  831. Device - Supplies a pointer to this device.
  832. Return Value:
  833. Status code.
  834. --*/
  835. {
  836. PRESOURCE_CONFIGURATION_LIST Requirements;
  837. KSTATUS Status;
  838. RESOURCE_REQUIREMENT VectorRequirement;
  839. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  840. (Irp->MinorCode == IrpMinorQueryResources));
  841. //
  842. // Initialize a nice interrupt vector requirement in preparation.
  843. //
  844. RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
  845. VectorRequirement.Type = ResourceTypeInterruptVector;
  846. VectorRequirement.Minimum = 0;
  847. VectorRequirement.Maximum = -1;
  848. VectorRequirement.Length = 1;
  849. //
  850. // Loop through all configuration lists, creating a vector for each line.
  851. //
  852. Requirements = Irp->U.QueryResources.ResourceRequirements;
  853. Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
  854. &VectorRequirement);
  855. if (!KSUCCESS(Status)) {
  856. goto ProcessResourceRequirementsEnd;
  857. }
  858. ProcessResourceRequirementsEnd:
  859. return Status;
  860. }
  861. KSTATUS
  862. SdOmap4ParentStartDevice (
  863. PIRP Irp,
  864. PSD_OMAP4_CONTEXT Device
  865. )
  866. /*++
  867. Routine Description:
  868. This routine starts up the OMAP4 SD controller.
  869. Arguments:
  870. Irp - Supplies a pointer to the I/O request packet.
  871. Device - Supplies a pointer to this SD OMAP4 device.
  872. Return Value:
  873. Status code.
  874. --*/
  875. {
  876. PRESOURCE_ALLOCATION Allocation;
  877. PRESOURCE_ALLOCATION_LIST AllocationList;
  878. IO_CONNECT_INTERRUPT_PARAMETERS Connect;
  879. PRESOURCE_ALLOCATION ControllerBase;
  880. PRESOURCE_ALLOCATION DmaRx;
  881. PRESOURCE_ALLOCATION DmaTx;
  882. PRESOURCE_ALLOCATION LineAllocation;
  883. SD_INITIALIZATION_BLOCK Parameters;
  884. KSTATUS Status;
  885. ControllerBase = NULL;
  886. DmaRx = NULL;
  887. DmaTx = NULL;
  888. //
  889. // Loop through the allocated resources to get the controller base and the
  890. // interrupt.
  891. //
  892. AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
  893. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  894. while (Allocation != NULL) {
  895. //
  896. // If the resource is an interrupt vector, then it should have an
  897. // owning interrupt line allocation.
  898. //
  899. if (Allocation->Type == ResourceTypeInterruptVector) {
  900. //
  901. // Currently only one interrupt resource is expected.
  902. //
  903. ASSERT((Device->Flags &
  904. SD_OMAP4_DEVICE_FLAG_INTERRUPT_RESOURCES_FOUND) == 0);
  905. ASSERT(Allocation->OwningAllocation != NULL);
  906. //
  907. // Save the line and vector number.
  908. //
  909. LineAllocation = Allocation->OwningAllocation;
  910. Device->InterruptLine = LineAllocation->Allocation;
  911. Device->InterruptVector = Allocation->Allocation;
  912. RtlAtomicOr32(&(Device->Flags),
  913. SD_OMAP4_DEVICE_FLAG_INTERRUPT_RESOURCES_FOUND);
  914. } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
  915. ASSERT(ControllerBase == NULL);
  916. ControllerBase = Allocation;
  917. } else if (Allocation->Type == ResourceTypeDmaChannel) {
  918. if (DmaTx == NULL) {
  919. DmaTx = Allocation;
  920. } else if (DmaRx == NULL) {
  921. DmaRx = Allocation;
  922. }
  923. }
  924. //
  925. // Get the next allocation in the list.
  926. //
  927. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  928. }
  929. //
  930. // Fail to start if the controller base was not found.
  931. //
  932. if ((ControllerBase == NULL) ||
  933. (ControllerBase->Length < SD_OMAP4_CONTROLLER_LENGTH)) {
  934. Status = STATUS_INVALID_CONFIGURATION;
  935. goto StartDeviceEnd;
  936. }
  937. //
  938. // Initialize OMAP4 specific stuff.
  939. //
  940. Device->ControllerPhysical = ControllerBase->Allocation;
  941. if (Device->ControllerBase == NULL) {
  942. Device->ControllerBase = MmMapPhysicalAddress(
  943. ControllerBase->Allocation,
  944. ControllerBase->Length,
  945. TRUE,
  946. FALSE,
  947. TRUE);
  948. if (Device->ControllerBase == NULL) {
  949. Status = STATUS_INSUFFICIENT_RESOURCES;
  950. goto StartDeviceEnd;
  951. }
  952. }
  953. if (Device->Soc == SdTiSocOmap4) {
  954. OmapI2cInitialize();
  955. Status = Omap4Twl6030InitializeMmcPower();
  956. if (!KSUCCESS(Status)) {
  957. ASSERT(FALSE);
  958. goto StartDeviceEnd;
  959. }
  960. } else if (Device->Soc == SdTiSocAm335) {
  961. //
  962. // Try to fire up system DMA.
  963. //
  964. Device->TxDmaResource = DmaTx;
  965. Device->RxDmaResource = DmaRx;
  966. if ((DmaTx != NULL) && (DmaRx != NULL)) {
  967. Status = SdOmap4InitializeDma(Device);
  968. if (!KSUCCESS(Status)) {
  969. Device->TxDmaResource = NULL;
  970. Device->RxDmaResource = NULL;
  971. }
  972. }
  973. }
  974. Status = SdOmap4ResetController(Device);
  975. if (Status == STATUS_NO_MEDIA) {
  976. Status = STATUS_SUCCESS;
  977. goto StartDeviceEnd;
  978. } else if (!KSUCCESS(Status)) {
  979. RtlDebugPrint("SdOmap4ResetController Failed: %d\n", Status);
  980. goto StartDeviceEnd;
  981. }
  982. //
  983. // Initialize the standard SD controller.
  984. //
  985. if (Device->Controller == NULL) {
  986. RtlZeroMemory(&Parameters, sizeof(SD_INITIALIZATION_BLOCK));
  987. Parameters.StandardControllerBase =
  988. Device->ControllerBase + SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET;
  989. Parameters.Voltages = SD_VOLTAGE_29_30 | SD_VOLTAGE_30_31;
  990. Parameters.HostCapabilities = SD_MODE_4BIT |
  991. SD_MODE_8BIT |
  992. SD_MODE_HIGH_SPEED |
  993. SD_MODE_AUTO_CMD12 |
  994. SD_MODE_CMD23;
  995. if (Device->Dma != NULL) {
  996. Parameters.HostCapabilities |= SD_MODE_SYSTEM_DMA;
  997. }
  998. Parameters.FundamentalClock = SD_OMAP4_FUNDAMENTAL_CLOCK_SPEED;
  999. Parameters.FunctionTable.GetSetBusWidth = SdOmap4GetSetBusWidth;
  1000. Parameters.ConsumerContext = Device;
  1001. Parameters.OsDevice = Irp->Device;
  1002. Device->Controller = SdCreateController(&Parameters);
  1003. if (Device->Controller == NULL) {
  1004. Status = STATUS_INSUFFICIENT_RESOURCES;
  1005. goto StartDeviceEnd;
  1006. }
  1007. }
  1008. //
  1009. // Attempt to connect the interrupt before initializing the controller. The
  1010. // initialization process may trigger some interrupts.
  1011. //
  1012. if (Device->InterruptHandle == INVALID_HANDLE) {
  1013. RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
  1014. Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
  1015. Connect.Device = Irp->Device;
  1016. Connect.LineNumber = Device->InterruptLine;
  1017. Connect.Vector = Device->InterruptVector;
  1018. Connect.InterruptServiceRoutine = SdOmap4InterruptService;
  1019. Connect.DispatchServiceRoutine = SdOmap4InterruptServiceDispatch;
  1020. Connect.Context = Device;
  1021. Connect.Interrupt = &(Device->InterruptHandle);
  1022. Status = IoConnectInterrupt(&Connect);
  1023. if (!KSUCCESS(Status)) {
  1024. goto StartDeviceEnd;
  1025. }
  1026. Device->Controller->InterruptHandle = Device->InterruptHandle;
  1027. }
  1028. Status = STATUS_SUCCESS;
  1029. StartDeviceEnd:
  1030. if (!KSUCCESS(Status)) {
  1031. if (Device->InterruptHandle != INVALID_HANDLE) {
  1032. IoDisconnectInterrupt(Device->InterruptHandle);
  1033. Device->InterruptHandle = INVALID_HANDLE;
  1034. }
  1035. if (Device->Controller != NULL) {
  1036. SdDestroyController(Device->Controller);
  1037. Device->Controller = NULL;
  1038. }
  1039. }
  1040. return Status;
  1041. }
  1042. KSTATUS
  1043. SdOmap4ParentQueryChildren (
  1044. PIRP Irp,
  1045. PSD_OMAP4_CONTEXT Device
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. This routine potentially enumerates the disk device for the SD OMAP4
  1050. controller.
  1051. Arguments:
  1052. Irp - Supplies a pointer to the I/O request packet.
  1053. Device - Supplies a pointer to this device.
  1054. Return Value:
  1055. Status code.
  1056. --*/
  1057. {
  1058. ULONG BlockSize;
  1059. PSTR DeviceId;
  1060. ULONG FlagsMask;
  1061. PSD_OMAP4_CHILD NewChild;
  1062. ULONG OldFlags;
  1063. KSTATUS Status;
  1064. NewChild = NULL;
  1065. //
  1066. // Check to see if any changes to the children are pending.
  1067. //
  1068. FlagsMask = ~(SD_CONTROLLER_FLAG_INSERTION_PENDING |
  1069. SD_CONTROLLER_FLAG_REMOVAL_PENDING);
  1070. OldFlags = RtlAtomicAnd32(&(Device->Controller->Flags), FlagsMask);
  1071. //
  1072. // If either a removal or insertion is pending, clean out the old child.
  1073. // In practice, not all removals interrupt, meaning that two insertions can
  1074. // arrive in a row.
  1075. //
  1076. FlagsMask = SD_CONTROLLER_FLAG_INSERTION_PENDING |
  1077. SD_CONTROLLER_FLAG_REMOVAL_PENDING;
  1078. if ((OldFlags & FlagsMask) != 0) {
  1079. if (Device->Child != NULL) {
  1080. KeAcquireQueuedLock(Device->Lock);
  1081. RtlAtomicAnd32(&(Device->Controller->Flags),
  1082. ~SD_CONTROLLER_FLAG_MEDIA_PRESENT);
  1083. KeReleaseQueuedLock(Device->Lock);
  1084. Device->Child = NULL;
  1085. }
  1086. }
  1087. //
  1088. // If an insertion is pending, try to enumerate the child.
  1089. //
  1090. if ((OldFlags & SD_CONTROLLER_FLAG_INSERTION_PENDING) != 0) {
  1091. ASSERT(Device->Child == NULL);
  1092. RtlAtomicAnd32(&(Device->Controller->Flags),
  1093. ~SD_CONTROLLER_FLAG_MEDIA_CHANGED);
  1094. Status = SdInitializeController(Device->Controller, FALSE);
  1095. if (!KSUCCESS(Status)) {
  1096. if (Status == STATUS_TIMEOUT) {
  1097. Status = STATUS_SUCCESS;
  1098. } else {
  1099. RtlDebugPrint("SdInitializeController failed: %d\n", Status);
  1100. }
  1101. goto ParentQueryChildrenEnd;
  1102. }
  1103. NewChild = SdOmap4pCreateChild(Device);
  1104. if (NewChild == NULL) {
  1105. Status = STATUS_INSUFFICIENT_RESOURCES;
  1106. goto ParentQueryChildrenEnd;
  1107. }
  1108. BlockSize = 0;
  1109. Status = SdGetMediaParameters(NewChild->Controller,
  1110. &(NewChild->BlockCount),
  1111. &BlockSize);
  1112. if (!KSUCCESS(Status)) {
  1113. if (Status == STATUS_NO_MEDIA) {
  1114. Status = STATUS_SUCCESS;
  1115. }
  1116. goto ParentQueryChildrenEnd;
  1117. }
  1118. ASSERT(POWER_OF_2(BlockSize) != FALSE);
  1119. NewChild->BlockShift = RtlCountTrailingZeros32(BlockSize);
  1120. //
  1121. // Try to enable DMA, but it's okay if it doesn't succeed. DMA is
  1122. // currently disabled on the TI AM33xx until EDMA is implemented.
  1123. //
  1124. if ((Device->Dma != NULL) || (Device->Soc != SdTiSocAm335)) {
  1125. Status = SdStandardInitializeDma(Device->Controller);
  1126. if (KSUCCESS(Status)) {
  1127. NewChild->Flags |= SD_OMAP4_CHILD_FLAG_DMA_SUPPORTED;
  1128. } else if (Status == STATUS_NO_MEDIA) {
  1129. Status = STATUS_SUCCESS;
  1130. goto ParentQueryChildrenEnd;
  1131. }
  1132. }
  1133. DeviceId = SD_MMC_DEVICE_ID;
  1134. if (SD_IS_CARD_SD(Device->Controller)) {
  1135. DeviceId = SD_CARD_DEVICE_ID;
  1136. }
  1137. Status = IoCreateDevice(SdOmap4Driver,
  1138. NewChild,
  1139. Irp->Device,
  1140. DeviceId,
  1141. DISK_CLASS_ID,
  1142. NULL,
  1143. &(NewChild->Device));
  1144. if (!KSUCCESS(Status)) {
  1145. return Status;
  1146. }
  1147. Device->Child = NewChild;
  1148. NewChild = NULL;
  1149. }
  1150. //
  1151. // If there's no child present, don't enumerate it.
  1152. //
  1153. if (Device->Child == NULL) {
  1154. return STATUS_SUCCESS;
  1155. }
  1156. ASSERT((Device->Child != NULL) && (Device->Child->Device != NULL));
  1157. //
  1158. // Enumerate the one child.
  1159. //
  1160. Status = IoMergeChildArrays(Irp,
  1161. &(Device->Child->Device),
  1162. 1,
  1163. SD_ALLOCATION_TAG);
  1164. ParentQueryChildrenEnd:
  1165. if (NewChild != NULL) {
  1166. ASSERT(NewChild->Device == NULL);
  1167. SdOmap4pChildReleaseReference(NewChild);
  1168. }
  1169. return Status;
  1170. }
  1171. KSTATUS
  1172. SdOmap4ResetController (
  1173. PSD_OMAP4_CONTEXT Device
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. This routine resets the OMAP4 SD controller and card.
  1178. Arguments:
  1179. Device - Supplies a pointer to this SD OMAP4 device.
  1180. Return Value:
  1181. Status code.
  1182. --*/
  1183. {
  1184. ULONG ClockControl;
  1185. ULONG Divisor;
  1186. ULONGLONG Frequency;
  1187. ULONG Register;
  1188. KSTATUS Status;
  1189. ULONGLONG Timeout;
  1190. ULONG Value;
  1191. Frequency = HlQueryTimeCounterFrequency();
  1192. //
  1193. // Perform a soft reset on the HSMMC part.
  1194. //
  1195. SD_OMAP4_WRITE_REGISTER(Device,
  1196. SD_OMAP4_SYSCONFIG_REGISTER,
  1197. SD_OMAP4_SYSCONFIG_SOFT_RESET);
  1198. Status = STATUS_TIMEOUT;
  1199. Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
  1200. do {
  1201. if ((SD_OMAP4_READ_REGISTER(Device, SD_OMAP4_SYSSTATUS_REGISTER) &
  1202. SD_OMAP4_SYSSTATUS_RESET_DONE) != 0) {
  1203. Status = STATUS_SUCCESS;
  1204. break;
  1205. }
  1206. } while (KeGetRecentTimeCounter() <= Timeout);
  1207. if (!KSUCCESS(Status)) {
  1208. return Status;
  1209. }
  1210. //
  1211. // Perform a reset on the SD controller.
  1212. //
  1213. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterClockControl;
  1214. Value = SD_OMAP4_READ_REGISTER(Device, Register);
  1215. Value |= SD_CLOCK_CONTROL_RESET_ALL;
  1216. Status = STATUS_TIMEOUT;
  1217. Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
  1218. do {
  1219. if ((SD_OMAP4_READ_REGISTER(Device, Register) &
  1220. SD_CLOCK_CONTROL_RESET_ALL) == 0) {
  1221. Status = STATUS_SUCCESS;
  1222. break;
  1223. }
  1224. } while (KeGetRecentTimeCounter() <= Timeout);
  1225. if (!KSUCCESS(Status)) {
  1226. return Status;
  1227. }
  1228. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
  1229. SdRegisterInterruptStatus;
  1230. SD_OMAP4_WRITE_REGISTER(Device, Register, 0xFFFFFFFF);
  1231. //
  1232. // Set up the host control register for 3 Volts.
  1233. //
  1234. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterHostControl;
  1235. Value = SD_HOST_CONTROL_POWER_3V0;
  1236. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1237. //
  1238. // Add the 3.0V and 1.8V capabilities to the capability register.
  1239. //
  1240. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterCapabilities;
  1241. Value = SD_OMAP4_READ_REGISTER(Device, Register);
  1242. Value |= SD_CAPABILITY_VOLTAGE_3V0 | SD_CAPABILITY_VOLTAGE_1V8;
  1243. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1244. //
  1245. // Initialize the HSMMC control register.
  1246. //
  1247. Register = SD_OMAP4_CON_REGISTER;
  1248. Value = SD_OMAP4_READ_REGISTER(Device, Register) &
  1249. SD_OMAP4_CON_DEBOUNCE_MASK;
  1250. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1251. //
  1252. // Set up the clock control register for 400kHz in preparation for sending
  1253. // CMD0 with INIT held.
  1254. //
  1255. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterClockControl;
  1256. ClockControl = SD_CLOCK_CONTROL_DEFAULT_TIMEOUT <<
  1257. SD_CLOCK_CONTROL_TIMEOUT_SHIFT;
  1258. SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
  1259. Divisor = SD_OMAP4_INITIAL_DIVISOR;
  1260. ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_MASK) <<
  1261. SD_CLOCK_CONTROL_DIVISOR_SHIFT;
  1262. ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_HIGH_MASK) >>
  1263. SD_CLOCK_CONTROL_DIVISOR_HIGH_SHIFT;
  1264. ClockControl |= SD_CLOCK_CONTROL_INTERNAL_CLOCK_ENABLE;
  1265. SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
  1266. SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
  1267. Status = STATUS_TIMEOUT;
  1268. Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
  1269. do {
  1270. Value = SD_OMAP4_READ_REGISTER(Device, Register);
  1271. if ((Value & SD_CLOCK_CONTROL_CLOCK_STABLE) != 0) {
  1272. Status = STATUS_SUCCESS;
  1273. break;
  1274. }
  1275. } while (KeGetRecentTimeCounter() <= Timeout);
  1276. if (!KSUCCESS(Status)) {
  1277. return Status;
  1278. }
  1279. ClockControl |= SD_CLOCK_CONTROL_SD_CLOCK_ENABLE;
  1280. SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
  1281. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterHostControl;
  1282. Value = SD_OMAP4_READ_REGISTER(Device, Register);
  1283. Value |= SD_HOST_CONTROL_POWER_ENABLE;
  1284. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1285. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
  1286. SdRegisterInterruptStatusEnable;
  1287. Value = SD_INTERRUPT_STATUS_ENABLE_DEFAULT_MASK;
  1288. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1289. //
  1290. // Reset the card by setting the init flag and issuing the card reset (go
  1291. // idle, command 0) command.
  1292. //
  1293. Register = SD_OMAP4_CON_REGISTER;
  1294. Value = SD_OMAP4_READ_REGISTER(Device, Register) | SD_OMAP4_CON_INIT |
  1295. SD_OMAP4_CON_DMA_MASTER;
  1296. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1297. //
  1298. // Write a 0 to the command register to issue the command.
  1299. //
  1300. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterCommand;
  1301. SD_OMAP4_WRITE_REGISTER(Device, Register, 0);
  1302. //
  1303. // Wait for the command to complete.
  1304. //
  1305. Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
  1306. SdRegisterInterruptStatus;
  1307. Status = STATUS_TIMEOUT;
  1308. Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
  1309. do {
  1310. Value = SD_OMAP4_READ_REGISTER(Device, Register);
  1311. if (Value != 0) {
  1312. if ((Value & SD_INTERRUPT_STATUS_COMMAND_COMPLETE) != 0) {
  1313. Status = STATUS_SUCCESS;
  1314. } else if ((Value &
  1315. SD_INTERRUPT_STATUS_COMMAND_TIMEOUT_ERROR) != 0) {
  1316. Status = STATUS_NO_MEDIA;
  1317. } else {
  1318. Status = STATUS_DEVICE_IO_ERROR;
  1319. }
  1320. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1321. break;
  1322. }
  1323. } while (KeGetRecentTimeCounter() <= Timeout);
  1324. //
  1325. // Disable the INIT line.
  1326. //
  1327. Register = SD_OMAP4_CON_REGISTER;
  1328. Value = SD_OMAP4_READ_REGISTER(Device, Register) & (~SD_OMAP4_CON_INIT);
  1329. SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
  1330. if (!KSUCCESS(Status)) {
  1331. return Status;
  1332. }
  1333. return STATUS_SUCCESS;
  1334. }
  1335. INTERRUPT_STATUS
  1336. SdOmap4InterruptService (
  1337. PVOID Context
  1338. )
  1339. /*++
  1340. Routine Description:
  1341. This routine implements the OMAP4 SD interrupt service routine.
  1342. Arguments:
  1343. Context - Supplies the context pointer given to the system when the
  1344. interrupt was connected. In this case, this points to the OMAP4 SD
  1345. controller.
  1346. Return Value:
  1347. Interrupt status.
  1348. --*/
  1349. {
  1350. PSD_OMAP4_CONTEXT Device;
  1351. Device = Context;
  1352. return SdStandardInterruptService(Device->Controller);
  1353. }
  1354. INTERRUPT_STATUS
  1355. SdOmap4InterruptServiceDispatch (
  1356. PVOID Context
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. This routine implements the dispatch level OMAP4 SD interrupt service
  1361. routine.
  1362. Arguments:
  1363. Context - Supplies the context pointer given to the system when the
  1364. interrupt was connected. In this case, this points to the OMAP4 SD
  1365. controller.
  1366. Return Value:
  1367. Interrupt status.
  1368. --*/
  1369. {
  1370. PSD_OMAP4_CONTEXT Device;
  1371. Device = Context;
  1372. return SdStandardInterruptServiceDispatch(Device->Controller);
  1373. }
  1374. VOID
  1375. SdOmap4SdDmaCompletion (
  1376. PSD_CONTROLLER Controller,
  1377. PVOID Context,
  1378. UINTN BytesTransferred,
  1379. KSTATUS Status
  1380. )
  1381. /*++
  1382. Routine Description:
  1383. This routine is called by the SD library when a DMA transfer completes.
  1384. This routine is called from a DPC and, as a result, can get called back
  1385. at dispatch level.
  1386. Arguments:
  1387. Controller - Supplies a pointer to the controller.
  1388. Context - Supplies a context pointer passed to the library when the DMA
  1389. request was issued.
  1390. BytesTransferred - Supplies the number of bytes transferred in the request.
  1391. Status - Supplies the status code representing the completion of the I/O.
  1392. Return Value:
  1393. None.
  1394. --*/
  1395. {
  1396. PSD_OMAP4_CHILD Child;
  1397. Child = Context;
  1398. if ((!KSUCCESS(Status)) || (Child->Parent->Dma == NULL)) {
  1399. if (Child->Parent->Dma != NULL) {
  1400. Child->Parent->Dma->Cancel(Child->Parent->Dma,
  1401. Child->Parent->DmaTransfer);
  1402. }
  1403. if (!KSUCCESS(Status)) {
  1404. RtlDebugPrint("OMAP4 SD Completion %d Bytes %ld\n",
  1405. Status,
  1406. BytesTransferred);
  1407. }
  1408. SdOmap4DmaCompletion(Controller, Context, BytesTransferred, Status);
  1409. //
  1410. // If this is an SD interrupt coming in and system DMA is enabled, only
  1411. // complete the transfer if SD came in last.
  1412. //
  1413. } else if (RtlAtomicAdd32(&(Child->RemainingInterrupts), -1) == 1) {
  1414. SdOmap4DmaCompletion(Controller, Context, 0, Status);
  1415. }
  1416. return;
  1417. }
  1418. PSD_OMAP4_CHILD
  1419. SdOmap4pCreateChild (
  1420. PSD_OMAP4_CONTEXT Device
  1421. )
  1422. /*++
  1423. Routine Description:
  1424. This routine creates an SD child context.
  1425. Arguments:
  1426. Device - Supplies a pointer to the parent device to which the child belongs.
  1427. Return Value:
  1428. Returns a pointer to the new child on success or NULL on failure.
  1429. --*/
  1430. {
  1431. PSD_OMAP4_CHILD Child;
  1432. Child = MmAllocateNonPagedPool(sizeof(SD_OMAP4_CHILD), SD_ALLOCATION_TAG);
  1433. if (Child == NULL) {
  1434. return NULL;
  1435. }
  1436. RtlZeroMemory(Child, sizeof(SD_OMAP4_CHILD));
  1437. Child->Type = SdOmap4Child;
  1438. Child->Parent = Device;
  1439. Child->Controller = Device->Controller;
  1440. Child->ControllerLock = Device->Lock;
  1441. Child->ReferenceCount = 1;
  1442. return Child;
  1443. }
  1444. VOID
  1445. SdOmap4pDestroyChild (
  1446. PSD_OMAP4_CHILD Child
  1447. )
  1448. /*++
  1449. Routine Description:
  1450. This routine destroys the given SD child device.
  1451. Arguments:
  1452. Child - Supplies a pointer to the SD child device to destroy.
  1453. Return Value:
  1454. None.
  1455. --*/
  1456. {
  1457. ASSERT(Child->DiskInterface.DiskToken == NULL);
  1458. ASSERT(Child->Irp == NULL);
  1459. MmFreeNonPagedPool(Child);
  1460. return;
  1461. }
  1462. VOID
  1463. SdOmap4pChildAddReference (
  1464. PSD_OMAP4_CHILD Child
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. This routine adds a reference to SD child device.
  1469. Arguments:
  1470. Child - Supplies a pointer to the SD child device.
  1471. Return Value:
  1472. None.
  1473. --*/
  1474. {
  1475. ULONG OldReferenceCount;
  1476. OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), 1);
  1477. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1478. return;
  1479. }
  1480. VOID
  1481. SdOmap4pChildReleaseReference (
  1482. PSD_OMAP4_CHILD Child
  1483. )
  1484. /*++
  1485. Routine Description:
  1486. This routine releases a reference from the SD child.
  1487. Arguments:
  1488. Child - Supplies a pointer to the SD child.
  1489. Return Value:
  1490. None.
  1491. --*/
  1492. {
  1493. ULONG OldReferenceCount;
  1494. OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), (ULONG)-1);
  1495. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1496. if (OldReferenceCount == 1) {
  1497. SdOmap4pDestroyChild(Child);
  1498. }
  1499. return;
  1500. }
  1501. KSTATUS
  1502. SdOmap4ChildBlockIoReset (
  1503. PVOID DiskToken
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. This routine must be called immediately before using the block read and
  1508. write routines in order to allow the disk to reset any I/O channels in
  1509. preparation for imminent block I/O. This routine is called at high run
  1510. level.
  1511. Arguments:
  1512. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1513. retrieved by querying the disk device information.
  1514. Return Value:
  1515. Status code.
  1516. --*/
  1517. {
  1518. PSD_OMAP4_CHILD Child;
  1519. KSTATUS Status;
  1520. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1521. Child = (PSD_OMAP4_CHILD)DiskToken;
  1522. //
  1523. // Put the SD controller into critical execution mode.
  1524. //
  1525. SdSetCriticalMode(Child->Controller, TRUE);
  1526. //
  1527. // Abort any current transaction that might have been left incomplete
  1528. // when the crash occurred.
  1529. //
  1530. Status = SdAbortTransaction(Child->Controller, FALSE);
  1531. return Status;
  1532. }
  1533. KSTATUS
  1534. SdOmap4ChildBlockIoRead (
  1535. PVOID DiskToken,
  1536. PIO_BUFFER IoBuffer,
  1537. ULONGLONG BlockAddress,
  1538. UINTN BlockCount,
  1539. PUINTN BlocksCompleted
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. This routine reads the block contents from the disk into the given I/O
  1544. buffer using polled I/O. It does so without acquiring any locks or
  1545. allocating any resources, as this routine is used for crash dump support
  1546. when the system is in a very fragile state. This routine must be called at
  1547. high level.
  1548. Arguments:
  1549. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1550. retrieved by querying the disk device information.
  1551. IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
  1552. BlockAddress - Supplies the block index to read (for physical disk, this is
  1553. the LBA).
  1554. BlockCount - Supplies the number of blocks to read.
  1555. BlocksCompleted - Supplies a pointer that receives the total number of
  1556. blocks read.
  1557. Return Value:
  1558. Status code.
  1559. --*/
  1560. {
  1561. PSD_OMAP4_CHILD Child;
  1562. IRP_READ_WRITE IrpReadWrite;
  1563. KSTATUS Status;
  1564. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1565. Child = (PSD_OMAP4_CHILD)DiskToken;
  1566. IrpReadWrite.IoBuffer = IoBuffer;
  1567. IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
  1568. IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
  1569. //
  1570. // As this read routine is meant for critical code paths (crash dump),
  1571. // indicate that the channel should not be locked when performing the I/O.
  1572. // It may be that some other thread holds the lock, which would cause a
  1573. // dead lock as all other processors and threads are likely frozen.
  1574. //
  1575. Status = SdOmap4PerformIoPolled(&IrpReadWrite, Child, FALSE, FALSE);
  1576. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
  1577. return Status;
  1578. }
  1579. KSTATUS
  1580. SdOmap4ChildBlockIoWrite (
  1581. PVOID DiskToken,
  1582. PIO_BUFFER IoBuffer,
  1583. ULONGLONG BlockAddress,
  1584. UINTN BlockCount,
  1585. PUINTN BlocksCompleted
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. This routine writes the contents of the given I/O buffer to the disk using
  1590. polled I/O. It does so without acquiring any locks or allocating any
  1591. resources, as this routine is used for crash dump support when the system
  1592. is in a very fragile state. This routine must be called at high level.
  1593. Arguments:
  1594. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1595. retrieved by querying the disk device information.
  1596. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  1597. write.
  1598. BlockAddress - Supplies the block index to write to (for physical disk,
  1599. this is the LBA).
  1600. BlockCount - Supplies the number of blocks to write.
  1601. BlocksCompleted - Supplies a pointer that receives the total number of
  1602. blocks written.
  1603. Return Value:
  1604. Status code.
  1605. --*/
  1606. {
  1607. PSD_OMAP4_CHILD Child;
  1608. IRP_READ_WRITE IrpReadWrite;
  1609. KSTATUS Status;
  1610. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1611. Child = (PSD_OMAP4_CHILD)DiskToken;
  1612. IrpReadWrite.IoBuffer = IoBuffer;
  1613. IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
  1614. IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
  1615. //
  1616. // As this write routine is meant for critical code paths (crash dump),
  1617. // indicate that the channel should not be locked when performing the I/O.
  1618. // It may be that some other thread holds the lock, which would cause a
  1619. // dead lock as all other processors and threads are likely frozen.
  1620. //
  1621. Status = SdOmap4PerformIoPolled(&IrpReadWrite, Child, TRUE, FALSE);
  1622. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
  1623. return Status;
  1624. }
  1625. KSTATUS
  1626. SdOmap4PerformIoPolled (
  1627. PIRP_READ_WRITE IrpReadWrite,
  1628. PSD_OMAP4_CHILD Child,
  1629. BOOL Write,
  1630. BOOL LockRequired
  1631. )
  1632. /*++
  1633. Routine Description:
  1634. This routine performs polled I/O data transfers.
  1635. Arguments:
  1636. IrpReadWrite - Supplies a pointer to the IRP's read/write context.
  1637. Child - Supplies a pointer to the SD child device.
  1638. Write - Supplies a boolean indicating if this is a read operation (TRUE) or
  1639. a write operation (FALSE).
  1640. LockRequired - Supplies a boolean indicating if this operation requires the
  1641. child's controller lock to be acquired (TRUE) or not (FALSE).
  1642. Return Value:
  1643. None.
  1644. --*/
  1645. {
  1646. UINTN BlockCount;
  1647. ULONGLONG BlockOffset;
  1648. UINTN BytesRemaining;
  1649. UINTN BytesThisRound;
  1650. KSTATUS CompletionStatus;
  1651. PSD_CONTROLLER Controller;
  1652. PIO_BUFFER_FRAGMENT Fragment;
  1653. UINTN FragmentIndex;
  1654. UINTN FragmentOffset;
  1655. PIO_BUFFER IoBuffer;
  1656. UINTN IoBufferOffset;
  1657. ULONG IrpReadWriteFlags;
  1658. BOOL LockHeld;
  1659. BOOL ReadWriteIrpPrepared;
  1660. KSTATUS Status;
  1661. PVOID VirtualAddress;
  1662. Controller = Child->Controller;
  1663. IrpReadWrite->IoBytesCompleted = 0;
  1664. LockHeld = FALSE;
  1665. ReadWriteIrpPrepared = FALSE;
  1666. ASSERT(IrpReadWrite->IoBuffer != NULL);
  1667. ASSERT(Child->Type == SdOmap4Child);
  1668. ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
  1669. //
  1670. // Validate the supplied I/O buffer is aligned and big enough.
  1671. //
  1672. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_POLLED;
  1673. if (Write != FALSE) {
  1674. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  1675. }
  1676. Status = IoPrepareReadWriteIrp(IrpReadWrite,
  1677. 1 << Child->BlockShift,
  1678. 0,
  1679. MAX_ULONGLONG,
  1680. IrpReadWriteFlags);
  1681. if (!KSUCCESS(Status)) {
  1682. goto PerformIoPolledEnd;
  1683. }
  1684. ReadWriteIrpPrepared = TRUE;
  1685. //
  1686. // Make sure the I/O buffer is mapped before use. SD depends on the buffer
  1687. // being mapped.
  1688. //
  1689. IoBuffer = IrpReadWrite->IoBuffer;
  1690. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
  1691. if (!KSUCCESS(Status)) {
  1692. goto PerformIoPolledEnd;
  1693. }
  1694. //
  1695. // Find the starting fragment based on the current offset.
  1696. //
  1697. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  1698. FragmentIndex = 0;
  1699. FragmentOffset = 0;
  1700. while (IoBufferOffset != 0) {
  1701. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1702. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1703. if (IoBufferOffset < Fragment->Size) {
  1704. FragmentOffset = IoBufferOffset;
  1705. break;
  1706. }
  1707. IoBufferOffset -= Fragment->Size;
  1708. FragmentIndex += 1;
  1709. }
  1710. if (LockRequired != FALSE) {
  1711. KeAcquireQueuedLock(Child->ControllerLock);
  1712. LockHeld = TRUE;
  1713. }
  1714. if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
  1715. Status = STATUS_MEDIA_CHANGED;
  1716. goto PerformIoPolledEnd;
  1717. } else if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
  1718. Status = STATUS_NO_MEDIA;
  1719. goto PerformIoPolledEnd;
  1720. }
  1721. //
  1722. // Loop reading in or writing out each fragment in the I/O buffer.
  1723. //
  1724. BytesRemaining = IrpReadWrite->IoSizeInBytes;
  1725. ASSERT(IS_ALIGNED(BytesRemaining, 1 << Child->BlockShift) != FALSE);
  1726. ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, 1 << Child->BlockShift) != FALSE);
  1727. BlockOffset = IrpReadWrite->IoOffset >> Child->BlockShift;
  1728. while (BytesRemaining != 0) {
  1729. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1730. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1731. VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
  1732. BytesThisRound = Fragment->Size - FragmentOffset;
  1733. if (BytesRemaining < BytesThisRound) {
  1734. BytesThisRound = BytesRemaining;
  1735. }
  1736. ASSERT(IS_ALIGNED(BytesThisRound, (1 << Child->BlockShift)) != FALSE);
  1737. BlockCount = BytesThisRound >> Child->BlockShift;
  1738. //
  1739. // Make sure the system isn't trying to do I/O off the end of the disk.
  1740. //
  1741. ASSERT(BlockOffset < Child->BlockCount);
  1742. ASSERT(BlockCount >= 1);
  1743. Status = SdBlockIoPolled(Controller,
  1744. BlockOffset,
  1745. BlockCount,
  1746. VirtualAddress,
  1747. Write);
  1748. if (!KSUCCESS(Status)) {
  1749. goto PerformIoPolledEnd;
  1750. }
  1751. BlockOffset += BlockCount;
  1752. BytesRemaining -= BytesThisRound;
  1753. IrpReadWrite->IoBytesCompleted += BytesThisRound;
  1754. FragmentOffset += BytesThisRound;
  1755. if (FragmentOffset >= Fragment->Size) {
  1756. FragmentIndex += 1;
  1757. FragmentOffset = 0;
  1758. }
  1759. }
  1760. Status = STATUS_SUCCESS;
  1761. PerformIoPolledEnd:
  1762. if (LockHeld != FALSE) {
  1763. KeReleaseQueuedLock(Child->ControllerLock);
  1764. }
  1765. if (ReadWriteIrpPrepared != FALSE) {
  1766. CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
  1767. IrpReadWriteFlags);
  1768. if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
  1769. Status = CompletionStatus;
  1770. }
  1771. }
  1772. IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
  1773. IrpReadWrite->IoBytesCompleted;
  1774. return Status;
  1775. }
  1776. KSTATUS
  1777. SdOmap4GetSetBusWidth (
  1778. PSD_CONTROLLER Controller,
  1779. PVOID Context,
  1780. BOOL Set
  1781. )
  1782. /*++
  1783. Routine Description:
  1784. This routine gets or sets the controller's bus width. The bus width is
  1785. stored in the controller structure.
  1786. Arguments:
  1787. Controller - Supplies a pointer to the controller.
  1788. Context - Supplies a context pointer passed to the SD/MMC library upon
  1789. creation of the controller.
  1790. Set - Supplies a boolean indicating whether the bus width should be queried
  1791. or set.
  1792. Return Value:
  1793. Status code.
  1794. --*/
  1795. {
  1796. PSD_OMAP4_CONTEXT Device;
  1797. KSTATUS Status;
  1798. ULONG Value;
  1799. Device = Context;
  1800. Status = SdStandardGetSetBusWidth(Controller, Context, Set);
  1801. if (!KSUCCESS(Status)) {
  1802. return Status;
  1803. }
  1804. Value = SD_OMAP4_READ_REGISTER(Device, SD_OMAP4_CON_REGISTER);
  1805. switch (Controller->BusWidth) {
  1806. case 1:
  1807. case 4:
  1808. Value &= ~SD_OMAP4_CON_8BIT;
  1809. break;
  1810. case 8:
  1811. Value |= SD_OMAP4_CON_8BIT;
  1812. break;
  1813. default:
  1814. ASSERT(FALSE);
  1815. return STATUS_INVALID_PARAMETER;
  1816. }
  1817. SD_OMAP4_WRITE_REGISTER(Device, SD_OMAP4_CON_REGISTER, Value);
  1818. return STATUS_SUCCESS;
  1819. }
  1820. KSTATUS
  1821. SdOmap4InitializeDma (
  1822. PSD_OMAP4_CONTEXT Device
  1823. )
  1824. /*++
  1825. Routine Description:
  1826. This routine attempts to wire up EDMA on the SD controller.
  1827. Arguments:
  1828. Device - Supplies a pointer to this SD OMAP4 device.
  1829. Return Value:
  1830. Status code.
  1831. --*/
  1832. {
  1833. UINTN AllocationSize;
  1834. PEDMA_CONFIGURATION Configuration;
  1835. DMA_INFORMATION Information;
  1836. PRESOURCE_ALLOCATION Resource;
  1837. KSTATUS Status;
  1838. PDMA_TRANSFER Transfer;
  1839. Resource = Device->TxDmaResource;
  1840. ASSERT((Resource != NULL) &&
  1841. (Device->RxDmaResource != NULL) &&
  1842. (Resource->Provider == Device->RxDmaResource->Provider));
  1843. Status = IoRegisterForInterfaceNotifications(&SdOmap4DmaUuid,
  1844. SdOmap4DmaInterfaceCallback,
  1845. Resource->Provider,
  1846. Device,
  1847. TRUE);
  1848. if (!KSUCCESS(Status)) {
  1849. goto InitializeDmaEnd;
  1850. }
  1851. if (Device->Dma == NULL) {
  1852. Status = STATUS_NOT_SUPPORTED;
  1853. goto InitializeDmaEnd;
  1854. }
  1855. RtlZeroMemory(&Information, sizeof(DMA_INFORMATION));
  1856. Information.Version = DMA_INFORMATION_VERSION;
  1857. Status = Device->Dma->GetInformation(Device->Dma, &Information);
  1858. if (!KSUCCESS(Status)) {
  1859. goto InitializeDmaEnd;
  1860. }
  1861. if (RtlAreUuidsEqual(&(Information.ControllerUuid), &SdOmap4Edma3Uuid) ==
  1862. FALSE) {
  1863. Status = STATUS_NOT_SUPPORTED;
  1864. goto InitializeDmaEnd;
  1865. }
  1866. if (Device->DmaTransfer == NULL) {
  1867. Status = Device->Dma->AllocateTransfer(Device->Dma, &Transfer);
  1868. if (!KSUCCESS(Status)) {
  1869. goto InitializeDmaEnd;
  1870. }
  1871. Device->DmaTransfer = Transfer;
  1872. AllocationSize = sizeof(EDMA_CONFIGURATION);
  1873. Configuration = MmAllocateNonPagedPool(AllocationSize,
  1874. SD_ALLOCATION_TAG);
  1875. if (Configuration == NULL) {
  1876. Status = STATUS_INSUFFICIENT_RESOURCES;
  1877. goto InitializeDmaEnd;
  1878. }
  1879. RtlZeroMemory(Configuration, AllocationSize);
  1880. Device->EdmaConfiguration = Configuration;
  1881. //
  1882. // Fill in some of the fields that will never change transfer to
  1883. // transfer.
  1884. //
  1885. Transfer->Configuration = Configuration;
  1886. Transfer->ConfigurationSize = sizeof(EDMA_CONFIGURATION);
  1887. Transfer->CompletionCallback = SdOmap4EdmaCompletion;
  1888. Transfer->Width = 32;
  1889. Transfer->Device.Address = Device->ControllerPhysical +
  1890. SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
  1891. SdRegisterBufferDataPort;
  1892. Configuration->Mode = EdmaTriggerModeEvent;
  1893. Configuration->Param.ACount = 4;
  1894. }
  1895. InitializeDmaEnd:
  1896. if (!KSUCCESS(Status)) {
  1897. if (Device->DmaTransfer != NULL) {
  1898. Device->Dma->FreeTransfer(Device->Dma, Device->DmaTransfer);
  1899. Device->DmaTransfer = NULL;
  1900. }
  1901. if (Device->EdmaConfiguration != NULL) {
  1902. MmFreeNonPagedPool(Device->EdmaConfiguration);
  1903. Device->EdmaConfiguration = NULL;
  1904. }
  1905. IoUnregisterForInterfaceNotifications(&SdOmap4DmaUuid,
  1906. SdOmap4DmaInterfaceCallback,
  1907. Resource->Provider,
  1908. Device);
  1909. }
  1910. return Status;
  1911. }
  1912. VOID
  1913. SdOmap4DmaInterfaceCallback (
  1914. PVOID Context,
  1915. PDEVICE Device,
  1916. PVOID InterfaceBuffer,
  1917. ULONG InterfaceBufferSize,
  1918. BOOL Arrival
  1919. )
  1920. /*++
  1921. Routine Description:
  1922. This routine is called to notify listeners that an interface has arrived
  1923. or departed.
  1924. Arguments:
  1925. Context - Supplies the caller's context pointer, supplied when the caller
  1926. requested interface notifications.
  1927. Device - Supplies a pointer to the device exposing or deleting the
  1928. interface.
  1929. InterfaceBuffer - Supplies a pointer to the interface buffer of the
  1930. interface.
  1931. InterfaceBufferSize - Supplies the buffer size.
  1932. Arrival - Supplies TRUE if a new interface is arriving, or FALSE if an
  1933. interface is departing.
  1934. Return Value:
  1935. None.
  1936. --*/
  1937. {
  1938. PSD_OMAP4_CONTEXT Sd;
  1939. Sd = Context;
  1940. ASSERT(InterfaceBufferSize >= sizeof(DMA_INTERFACE));
  1941. ASSERT((Sd->Dma == NULL) || (Sd->Dma == InterfaceBuffer));
  1942. if (Arrival != FALSE) {
  1943. Sd->Dma = InterfaceBuffer;
  1944. } else {
  1945. Sd->Dma = NULL;
  1946. }
  1947. return;
  1948. }
  1949. VOID
  1950. SdOmap4PerformDmaIo (
  1951. PSD_OMAP4_CHILD Child,
  1952. PIRP Irp
  1953. )
  1954. /*++
  1955. Routine Description:
  1956. This routine performs DMA-based I/O for the OMAP SD controller.
  1957. Arguments:
  1958. Child - Supplies a pointer to the child device.
  1959. Irp - Supplies a pointer to the partially completed IRP.
  1960. Return Value:
  1961. None.
  1962. --*/
  1963. {
  1964. UINTN BlockCount;
  1965. ULONGLONG BlockOffset;
  1966. IO_OFFSET IoOffset;
  1967. ULONGLONG IoSize;
  1968. KSTATUS Status;
  1969. BOOL Write;
  1970. IoOffset = Irp->U.ReadWrite.IoOffset + Irp->U.ReadWrite.IoBytesCompleted;
  1971. BlockOffset = IoOffset >> Child->BlockShift;
  1972. IoSize = Irp->U.ReadWrite.IoSizeInBytes - Irp->U.ReadWrite.IoBytesCompleted;
  1973. Write = FALSE;
  1974. if (Irp->MinorCode == IrpMinorIoWrite) {
  1975. Write = TRUE;
  1976. }
  1977. ASSERT(BlockOffset < Child->BlockCount);
  1978. //
  1979. // Set up the DMA transfer if the controller uses system DMA.
  1980. //
  1981. if (Child->Parent->Dma != NULL) {
  1982. ASSERT(Child->Parent->Soc == SdTiSocAm335);
  1983. Status = SdOmap4SetupEdma(Child, &IoSize);
  1984. if (!KSUCCESS(Status)) {
  1985. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  1986. return;
  1987. }
  1988. } else {
  1989. Child->RemainingInterrupts = 1;
  1990. }
  1991. BlockCount = IoSize >> Child->BlockShift;
  1992. ASSERT((BlockCount >= 1) && ((BlockCount << Child->BlockShift) == IoSize));
  1993. SdStandardBlockIoDma(Child->Controller,
  1994. BlockOffset,
  1995. BlockCount,
  1996. Irp->U.ReadWrite.IoBuffer,
  1997. Irp->U.ReadWrite.IoBytesCompleted,
  1998. Write,
  1999. SdOmap4SdDmaCompletion,
  2000. Child);
  2001. return;
  2002. }
  2003. KSTATUS
  2004. SdOmap4SetupEdma (
  2005. PSD_OMAP4_CHILD Child,
  2006. PULONGLONG Size
  2007. )
  2008. /*++
  2009. Routine Description:
  2010. This routine submits a system DMA request on behalf of the SD controller.
  2011. Arguments:
  2012. Child - Supplies a pointer to the child device.
  2013. Size - Supplies a pointer where the actual size of the DMA transfer will
  2014. be returned on success.
  2015. Return Value:
  2016. Status code.
  2017. --*/
  2018. {
  2019. ULONG BlockLength;
  2020. ULONG Channel;
  2021. PEDMA_CONFIGURATION Configuration;
  2022. PDMA_INTERFACE Dma;
  2023. PDMA_TRANSFER DmaTransfer;
  2024. PIRP Irp;
  2025. KSTATUS Status;
  2026. Dma = Child->Parent->Dma;
  2027. DmaTransfer = Child->Parent->DmaTransfer;
  2028. Configuration = DmaTransfer->Configuration;
  2029. Irp = Child->Irp;
  2030. DmaTransfer->Memory = Irp->U.ReadWrite.IoBuffer;
  2031. DmaTransfer->Completed = Irp->U.ReadWrite.IoBytesCompleted;
  2032. DmaTransfer->Size = Irp->U.ReadWrite.IoSizeInBytes;
  2033. DmaTransfer->UserContext = Child;
  2034. Configuration->Param.Options = EDMA_TRANSFER_AB_SYNCHRONIZED |
  2035. EDMA_TRANSFER_FIFO_WIDTH_32;
  2036. if (Irp->MinorCode == IrpMinorIoWrite) {
  2037. DmaTransfer->Allocation = Child->Parent->TxDmaResource;
  2038. Channel = DmaTransfer->Allocation->Allocation;
  2039. DmaTransfer->Direction = DmaTransferToDevice;
  2040. BlockLength = Child->Controller->WriteBlockLength;
  2041. Configuration->Param.BCount = BlockLength / Configuration->Param.ACount;
  2042. Configuration->Param.SourceBIndex = Configuration->Param.ACount;
  2043. Configuration->Param.SourceCIndex = BlockLength;
  2044. Configuration->Param.DestinationBIndex = 0;
  2045. Configuration->Param.DestinationCIndex = 0;
  2046. Configuration->Param.Options |= EDMA_TRANSFER_DESTINATION_FIFO |
  2047. ((Channel <<
  2048. EDMA_TRANSFER_COMPLETION_CODE_SHIFT) &
  2049. EDMA_TRANSFER_COMPLETION_CODE_MASK);
  2050. } else {
  2051. DmaTransfer->Allocation = Child->Parent->RxDmaResource;
  2052. Channel = DmaTransfer->Allocation->Allocation;
  2053. DmaTransfer->Direction = DmaTransferFromDevice;
  2054. BlockLength = Child->Controller->ReadBlockLength;
  2055. Configuration->Param.BCount = BlockLength / Configuration->Param.ACount;
  2056. Configuration->Param.DestinationBIndex = Configuration->Param.ACount;
  2057. Configuration->Param.DestinationCIndex = BlockLength;
  2058. Configuration->Param.SourceBIndex = 0;
  2059. Configuration->Param.SourceCIndex = 0;
  2060. Configuration->Param.Options |= EDMA_TRANSFER_SOURCE_FIFO |
  2061. ((Channel <<
  2062. EDMA_TRANSFER_COMPLETION_CODE_SHIFT) &
  2063. EDMA_TRANSFER_COMPLETION_CODE_MASK);
  2064. }
  2065. ASSERT(Child->RemainingInterrupts == 0);
  2066. Child->RemainingInterrupts = 2;
  2067. Status = Dma->Submit(Dma, DmaTransfer);
  2068. *Size = DmaTransfer->Size - DmaTransfer->Completed;
  2069. return Status;
  2070. }
  2071. VOID
  2072. SdOmap4EdmaCompletion (
  2073. PDMA_TRANSFER Transfer
  2074. )
  2075. /*++
  2076. Routine Description:
  2077. This routine is called when a transfer set has completed or errored out.
  2078. Arguments:
  2079. Transfer - Supplies a pointer to the transfer that completed.
  2080. Return Value:
  2081. None.
  2082. --*/
  2083. {
  2084. PSD_OMAP4_CHILD Child;
  2085. UINTN CompletedThisRound;
  2086. KSTATUS Status;
  2087. Child = Transfer->UserContext;
  2088. Status = Transfer->Status;
  2089. CompletedThisRound = Transfer->Completed -
  2090. Child->Irp->U.ReadWrite.IoBytesCompleted;
  2091. if (!KSUCCESS(Status)) {
  2092. RtlDebugPrint("OMAP4 EDMA SD Completion %d Bytes %ld\n",
  2093. Status,
  2094. CompletedThisRound);
  2095. }
  2096. SdOmap4DmaCompletion(Child->Controller, Child, CompletedThisRound, Status);
  2097. return;
  2098. }
  2099. VOID
  2100. SdOmap4DmaCompletion (
  2101. PSD_CONTROLLER Controller,
  2102. PVOID Context,
  2103. UINTN BytesTransferred,
  2104. KSTATUS Status
  2105. )
  2106. /*++
  2107. Routine Description:
  2108. This routine is called indirectly by either the EDMA code or the SD library
  2109. code once the transfer has actually completed. It either completes the IRP
  2110. or fires up a new transfer.
  2111. Arguments:
  2112. Controller - Supplies a pointer to the controller.
  2113. Context - Supplies a context pointer passed to the library when the DMA
  2114. request was issued.
  2115. BytesTransferred - Supplies the number of bytes transferred in the request
  2116. this round.
  2117. Status - Supplies the status code representing the completion of the I/O.
  2118. Return Value:
  2119. None.
  2120. --*/
  2121. {
  2122. PSD_OMAP4_CHILD Child;
  2123. PIRP Irp;
  2124. Child = Context;
  2125. Irp = Child->Irp;
  2126. ASSERT(Irp != NULL);
  2127. if (!KSUCCESS(Status)) {
  2128. RtlAtomicAdd32(&(Child->RemainingInterrupts), -1);
  2129. RtlDebugPrint("SD OMAP4 Failed 0x%x 0x%I64x 0x%x: %d\n",
  2130. Irp->MinorCode,
  2131. Irp->U.ReadWrite.IoOffset,
  2132. Irp->U.ReadWrite.IoSizeInBytes,
  2133. Status);
  2134. SdAbortTransaction(Controller, FALSE);
  2135. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  2136. return;
  2137. }
  2138. if (BytesTransferred != 0) {
  2139. Irp->U.ReadWrite.IoBytesCompleted += BytesTransferred;
  2140. Irp->U.ReadWrite.NewIoOffset += BytesTransferred;
  2141. //
  2142. // If more interrupts are expected, don't complete just yet.
  2143. //
  2144. if (RtlAtomicAdd32(&(Child->RemainingInterrupts), -1) != 1) {
  2145. return;
  2146. }
  2147. //
  2148. // Otherwise if this is SD and it was the last remaining interrupt, the
  2149. // DMA portion better be complete already.
  2150. //
  2151. } else {
  2152. ASSERT(Child->RemainingInterrupts == 0);
  2153. }
  2154. //
  2155. // If this transfer's over, complete the IRP.
  2156. //
  2157. if (Irp->U.ReadWrite.IoBytesCompleted ==
  2158. Irp->U.ReadWrite.IoSizeInBytes) {
  2159. IoCompleteIrp(SdOmap4Driver, Irp, Status);
  2160. return;
  2161. }
  2162. SdOmap4PerformDmaIo(Child, Irp);
  2163. return;
  2164. }