sd.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532
  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. sd.c
  9. Abstract:
  10. This module implements the SD/MMC driver.
  11. Author:
  12. Evan Green 27-Feb-2014
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. //
  20. // Define away the API decorator.
  21. //
  22. #define SD_API
  23. #include <minoca/kernel/driver.h>
  24. #include <minoca/intrface/disk.h>
  25. #include <minoca/sd/sd.h>
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // Define the maximum number of slots that can be on one device. On current
  31. // implementations this is limited by the number of PCI BARs, where each
  32. // slot gets a BAR.
  33. //
  34. #define MAX_SD_SLOTS 6
  35. //
  36. // Define the amount of time in microseconds to wait after an insertion event
  37. // to allow the card to simmer down in the slot.
  38. //
  39. #define SD_INSERTION_SETTLE_DELAY 50000
  40. //
  41. // Define the set of flags for an SD disk.
  42. //
  43. #define SD_DISK_FLAG_DMA_SUPPORTED 0x00000001
  44. //
  45. // ------------------------------------------------------ Data Type Definitions
  46. //
  47. typedef enum _SD_DEVICE_TYPE {
  48. SdDeviceInvalid,
  49. SdDeviceBus,
  50. SdDeviceSlot,
  51. SdDeviceDisk
  52. } SD_DEVICE_TYPE, *PSD_DEVICE_TYPE;
  53. typedef struct _SD_BUS SD_BUS, *PSD_BUS;
  54. typedef struct _SD_SLOT SD_SLOT, *PSD_SLOT;
  55. /*++
  56. Structure Description:
  57. This structure describes an SD/MMC disk context (the context used by the
  58. bus driver for the disk device).
  59. Members:
  60. Type - Stores the type identifying this as an SD disk structure.
  61. ReferenceCount - Stores a reference count for the disk.
  62. Device - Stores a pointer to the OS device for the disk.
  63. Parent - Stores a pointer to the parent slot.
  64. Controller - Stores a pointer to the SD controller structure.
  65. ControllerLock - Stores a pointer to the lock used to serialize access to
  66. the controller. This is owned by the parent slot.
  67. Irp - Stores a pointer to the current IRP running on this disk.
  68. Flags - Stores a bitmask of flags describing the disk state. See
  69. SD_DISK_FLAG_* for definitions;
  70. BlockShift - Stores the block size shift of the disk.
  71. BlockCount - Stores the number of blocks on the disk.
  72. DiskInterface - Stores the disk interface presented to the system.
  73. --*/
  74. typedef struct _SD_DISK {
  75. SD_DEVICE_TYPE Type;
  76. volatile ULONG ReferenceCount;
  77. PDEVICE Device;
  78. PSD_SLOT Parent;
  79. PSD_CONTROLLER Controller;
  80. PQUEUED_LOCK ControllerLock;
  81. PIRP Irp;
  82. ULONG Flags;
  83. ULONG BlockShift;
  84. ULONGLONG BlockCount;
  85. DISK_INTERFACE DiskInterface;
  86. } SD_DISK, *PSD_DISK;
  87. /*++
  88. Structure Description:
  89. This structure describes an SD/MMC slot (the context used by the bus driver
  90. for the individual SD slot).
  91. Members:
  92. Type - Stores the type identifying this as an SD slot.
  93. Device - Stores a pointer to the OS device for the slot.
  94. Controller - Stores a pointer to the SD controller structure.
  95. ControllerBase - Stores the virtual address of the base of the controller
  96. registers.
  97. Resource - Stores a pointer to the resource describing the location of the
  98. controller.
  99. ChildIndex - Stores the child index of this device.
  100. Parent - Stores a pointer back to the parent.
  101. Disk - Stores a pointer to the child disk context.
  102. Lock - Stores a pointer to a lock used to serialize access to the
  103. controller.
  104. --*/
  105. struct _SD_SLOT {
  106. SD_DEVICE_TYPE Type;
  107. PDEVICE Device;
  108. PSD_CONTROLLER Controller;
  109. PVOID ControllerBase;
  110. PRESOURCE_ALLOCATION Resource;
  111. UINTN ChildIndex;
  112. PSD_BUS Parent;
  113. PSD_DISK Disk;
  114. PQUEUED_LOCK Lock;
  115. };
  116. /*++
  117. Structure Description:
  118. This structure describes an SD/MMC driver context (the function driver
  119. context for the SD bus controller).
  120. Members:
  121. Type - Stores the type identifying this as an SD controller.
  122. Slots - Stores the array of SD slots.
  123. Handle - Stores the connected interrupt handle.
  124. InterruptLine - Stores ths interrupt line of the controller.
  125. InterruptVector - Stores the interrupt vector of the controller.
  126. InterruptResourcesFound - Stores a boolean indicating whether or not
  127. interrupt resources were located for this device.
  128. --*/
  129. struct _SD_BUS {
  130. SD_DEVICE_TYPE Type;
  131. SD_SLOT Slots[MAX_SD_SLOTS];
  132. HANDLE InterruptHandle;
  133. ULONGLONG InterruptLine;
  134. ULONGLONG InterruptVector;
  135. BOOL InterruptResourcesFound;
  136. };
  137. //
  138. // ----------------------------------------------- Internal Function Prototypes
  139. //
  140. KSTATUS
  141. SdAddDevice (
  142. PVOID Driver,
  143. PCSTR DeviceId,
  144. PCSTR ClassId,
  145. PCSTR CompatibleIds,
  146. PVOID DeviceToken
  147. );
  148. VOID
  149. SdDispatchStateChange (
  150. PIRP Irp,
  151. PVOID DeviceContext,
  152. PVOID IrpContext
  153. );
  154. VOID
  155. SdDispatchOpen (
  156. PIRP Irp,
  157. PVOID DeviceContext,
  158. PVOID IrpContext
  159. );
  160. VOID
  161. SdDispatchClose (
  162. PIRP Irp,
  163. PVOID DeviceContext,
  164. PVOID IrpContext
  165. );
  166. VOID
  167. SdDispatchIo (
  168. PIRP Irp,
  169. PVOID DeviceContext,
  170. PVOID IrpContext
  171. );
  172. VOID
  173. SdDispatchSystemControl (
  174. PIRP Irp,
  175. PVOID DeviceContext,
  176. PVOID IrpContext
  177. );
  178. INTERRUPT_STATUS
  179. SdBusInterruptService (
  180. PVOID Context
  181. );
  182. INTERRUPT_STATUS
  183. SdBusInterruptServiceDispatch (
  184. PVOID Context
  185. );
  186. VOID
  187. SdpBusDispatchStateChange (
  188. PIRP Irp,
  189. PSD_BUS Bus
  190. );
  191. VOID
  192. SdpSlotDispatchStateChange (
  193. PIRP Irp,
  194. PSD_SLOT Slot
  195. );
  196. VOID
  197. SdpDiskDispatchStateChange (
  198. PIRP Irp,
  199. PSD_DISK Disk
  200. );
  201. KSTATUS
  202. SdpBusProcessResourceRequirements (
  203. PIRP Irp,
  204. PSD_BUS Bus
  205. );
  206. KSTATUS
  207. SdpBusStartDevice (
  208. PIRP Irp,
  209. PSD_BUS Bus
  210. );
  211. KSTATUS
  212. SdpBusQueryChildren (
  213. PIRP Irp,
  214. PSD_BUS Context
  215. );
  216. KSTATUS
  217. SdpSlotStartDevice (
  218. PIRP Irp,
  219. PSD_SLOT Slot
  220. );
  221. KSTATUS
  222. SdpSlotQueryChildren (
  223. PIRP Irp,
  224. PSD_SLOT Slot
  225. );
  226. PSD_DISK
  227. SdpCreateDisk (
  228. PSD_SLOT Slot
  229. );
  230. VOID
  231. SdpDestroyDisk (
  232. PSD_DISK Disk
  233. );
  234. VOID
  235. SdpDiskAddReference (
  236. PSD_DISK Disk
  237. );
  238. VOID
  239. SdpDiskReleaseReference (
  240. PSD_DISK Disk
  241. );
  242. VOID
  243. SdpDmaCompletion (
  244. PSD_CONTROLLER Controller,
  245. PVOID Context,
  246. UINTN BytesTransferred,
  247. KSTATUS Status
  248. );
  249. KSTATUS
  250. SdpDiskBlockIoReset (
  251. PVOID DiskToken
  252. );
  253. KSTATUS
  254. SdpDiskBlockIoRead (
  255. PVOID DiskToken,
  256. PIO_BUFFER IoBuffer,
  257. ULONGLONG BlockAddress,
  258. UINTN BlockCount,
  259. PUINTN BlocksCompleted
  260. );
  261. KSTATUS
  262. SdpDiskBlockIoWrite (
  263. PVOID DiskToken,
  264. PIO_BUFFER IoBuffer,
  265. ULONGLONG BlockAddress,
  266. UINTN BlockCount,
  267. PUINTN BlocksCompleted
  268. );
  269. KSTATUS
  270. SdpPerformIoPolled (
  271. PIRP_READ_WRITE IrpReadWrite,
  272. PSD_DISK Disk,
  273. BOOL Write,
  274. BOOL LockRequired
  275. );
  276. //
  277. // -------------------------------------------------------------------- Globals
  278. //
  279. PDRIVER SdDriver = NULL;
  280. UUID SdDiskInterfaceUuid = UUID_DISK_INTERFACE;
  281. DISK_INTERFACE SdDiskInterfaceTemplate = {
  282. DISK_INTERFACE_VERSION,
  283. NULL,
  284. 0,
  285. 0,
  286. NULL,
  287. SdpDiskBlockIoReset,
  288. SdpDiskBlockIoRead,
  289. SdpDiskBlockIoWrite
  290. };
  291. //
  292. // ------------------------------------------------------------------ Functions
  293. //
  294. __USED
  295. KSTATUS
  296. DriverEntry (
  297. PDRIVER Driver
  298. )
  299. /*++
  300. Routine Description:
  301. This routine is the entry point for the SD/MMC driver. It registers its
  302. other dispatch functions, and performs driver-wide initialization.
  303. Arguments:
  304. Driver - Supplies a pointer to the driver object.
  305. Return Value:
  306. STATUS_SUCCESS on success.
  307. Failure code on error.
  308. --*/
  309. {
  310. DRIVER_FUNCTION_TABLE FunctionTable;
  311. KSTATUS Status;
  312. SdDriver = Driver;
  313. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  314. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  315. FunctionTable.AddDevice = SdAddDevice;
  316. FunctionTable.DispatchStateChange = SdDispatchStateChange;
  317. FunctionTable.DispatchOpen = SdDispatchOpen;
  318. FunctionTable.DispatchClose = SdDispatchClose;
  319. FunctionTable.DispatchIo = SdDispatchIo;
  320. FunctionTable.DispatchSystemControl = SdDispatchSystemControl;
  321. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  322. return Status;
  323. }
  324. KSTATUS
  325. SdAddDevice (
  326. PVOID Driver,
  327. PCSTR DeviceId,
  328. PCSTR ClassId,
  329. PCSTR CompatibleIds,
  330. PVOID DeviceToken
  331. )
  332. /*++
  333. Routine Description:
  334. This routine is called when a device is detected for which the SD/MMC driver
  335. acts as the function driver. The driver will attach itself to the stack.
  336. Arguments:
  337. Driver - Supplies a pointer to the driver being called.
  338. DeviceId - Supplies a pointer to a string with the device ID.
  339. ClassId - Supplies a pointer to a string containing the device's class ID.
  340. CompatibleIds - Supplies a pointer to a string containing device IDs
  341. that would be compatible with this device.
  342. DeviceToken - Supplies an opaque token that the driver can use to identify
  343. the device in the system. This token should be used when attaching to
  344. the stack.
  345. Return Value:
  346. STATUS_SUCCESS on success.
  347. Failure code if the driver was unsuccessful in attaching itself.
  348. --*/
  349. {
  350. PSD_BUS Context;
  351. PSD_SLOT Slot;
  352. UINTN SlotIndex;
  353. KSTATUS Status;
  354. Context = MmAllocateNonPagedPool(sizeof(SD_BUS), SD_ALLOCATION_TAG);
  355. if (Context == NULL) {
  356. return STATUS_INSUFFICIENT_RESOURCES;
  357. }
  358. RtlZeroMemory(Context, sizeof(SD_BUS));
  359. Context->Type = SdDeviceBus;
  360. Context->InterruptHandle = INVALID_HANDLE;
  361. for (SlotIndex = 0; SlotIndex < MAX_SD_SLOTS; SlotIndex += 1) {
  362. Slot = &(Context->Slots[SlotIndex]);
  363. Slot->Type = SdDeviceSlot;
  364. Slot->ChildIndex = SlotIndex;
  365. Slot->Parent = Context;
  366. }
  367. Status = IoAttachDriverToDevice(Driver, DeviceToken, Context);
  368. if (!KSUCCESS(Status)) {
  369. MmFreeNonPagedPool(Context);
  370. }
  371. return Status;
  372. }
  373. VOID
  374. SdDispatchStateChange (
  375. PIRP Irp,
  376. PVOID DeviceContext,
  377. PVOID IrpContext
  378. )
  379. /*++
  380. Routine Description:
  381. This routine handles State Change IRPs.
  382. Arguments:
  383. Irp - Supplies a pointer to the I/O request packet.
  384. DeviceContext - Supplies the context pointer supplied by the driver when it
  385. attached itself to the driver stack. Presumably this pointer contains
  386. driver-specific device context.
  387. IrpContext - Supplies the context pointer supplied by the driver when
  388. the IRP was created.
  389. Return Value:
  390. None.
  391. --*/
  392. {
  393. PSD_BUS Context;
  394. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  395. Context = (PSD_BUS)DeviceContext;
  396. switch (Context->Type) {
  397. case SdDeviceBus:
  398. SdpBusDispatchStateChange(Irp, Context);
  399. break;
  400. case SdDeviceSlot:
  401. SdpSlotDispatchStateChange(Irp, (PSD_SLOT)Context);
  402. break;
  403. case SdDeviceDisk:
  404. SdpDiskDispatchStateChange(Irp, (PSD_DISK)Context);
  405. break;
  406. default:
  407. ASSERT(FALSE);
  408. break;
  409. }
  410. return;
  411. }
  412. VOID
  413. SdDispatchOpen (
  414. PIRP Irp,
  415. PVOID DeviceContext,
  416. PVOID IrpContext
  417. )
  418. /*++
  419. Routine Description:
  420. This routine handles Open IRPs.
  421. Arguments:
  422. Irp - Supplies a pointer to the I/O request packet.
  423. DeviceContext - Supplies the context pointer supplied by the driver when it
  424. attached itself to the driver stack. Presumably this pointer contains
  425. driver-specific device context.
  426. IrpContext - Supplies the context pointer supplied by the driver when
  427. the IRP was created.
  428. Return Value:
  429. None.
  430. --*/
  431. {
  432. PSD_DISK Disk;
  433. Disk = DeviceContext;
  434. if (Disk->Type != SdDeviceDisk) {
  435. return;
  436. }
  437. SdpDiskAddReference(Disk);
  438. IoCompleteIrp(SdDriver, Irp, STATUS_SUCCESS);
  439. return;
  440. }
  441. VOID
  442. SdDispatchClose (
  443. PIRP Irp,
  444. PVOID DeviceContext,
  445. PVOID IrpContext
  446. )
  447. /*++
  448. Routine Description:
  449. This routine handles Close IRPs.
  450. Arguments:
  451. Irp - Supplies a pointer to the I/O request packet.
  452. DeviceContext - Supplies the context pointer supplied by the driver when it
  453. attached itself to the driver stack. Presumably this pointer contains
  454. driver-specific device context.
  455. IrpContext - Supplies the context pointer supplied by the driver when
  456. the IRP was created.
  457. Return Value:
  458. None.
  459. --*/
  460. {
  461. PSD_DISK Disk;
  462. Disk = DeviceContext;
  463. if (Disk->Type != SdDeviceDisk) {
  464. return;
  465. }
  466. SdpDiskReleaseReference(Disk);
  467. IoCompleteIrp(SdDriver, Irp, STATUS_SUCCESS);
  468. return;
  469. }
  470. VOID
  471. SdDispatchIo (
  472. PIRP Irp,
  473. PVOID DeviceContext,
  474. PVOID IrpContext
  475. )
  476. /*++
  477. Routine Description:
  478. This routine handles I/O IRPs.
  479. Arguments:
  480. Irp - Supplies a pointer to the I/O request packet.
  481. DeviceContext - Supplies the context pointer supplied by the driver when it
  482. attached itself to the driver stack. Presumably this pointer contains
  483. driver-specific device context.
  484. IrpContext - Supplies the context pointer supplied by the driver when
  485. the IRP was created.
  486. Return Value:
  487. None.
  488. --*/
  489. {
  490. UINTN BlockCount;
  491. ULONGLONG BlockOffset;
  492. UINTN BytesToComplete;
  493. BOOL CompleteIrp;
  494. PSD_CONTROLLER Controller;
  495. PSD_DISK Disk;
  496. IO_OFFSET IoOffset;
  497. ULONG IrpReadWriteFlags;
  498. KSTATUS IrpStatus;
  499. KSTATUS Status;
  500. BOOL Write;
  501. ASSERT(KeGetRunLevel() == RunLevelLow);
  502. Disk = DeviceContext;
  503. if (Disk->Type != SdDeviceDisk) {
  504. ASSERT(FALSE);
  505. return;
  506. }
  507. CompleteIrp = TRUE;
  508. Write = FALSE;
  509. if (Irp->MinorCode == IrpMinorIoWrite) {
  510. Write = TRUE;
  511. }
  512. //
  513. // Polled I/O is shared by a few code paths and prepares the IRP for I/O
  514. // further down the stack. It should also only be hit in the down direction
  515. // path as it always completes the IRP.
  516. //
  517. if ((Disk->Flags & SD_DISK_FLAG_DMA_SUPPORTED) == 0) {
  518. ASSERT(Irp->Direction == IrpDown);
  519. Status = SdpPerformIoPolled(&(Irp->U.ReadWrite), Disk, Write, TRUE);
  520. goto DispatchIoEnd;
  521. }
  522. //
  523. // Set the IRP read/write flags for the preparation and completion steps.
  524. //
  525. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_DMA;
  526. if (Write != FALSE) {
  527. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  528. }
  529. Controller = Disk->Controller;
  530. if (Irp->Direction == IrpDown) {
  531. Controller->Try = 0;
  532. }
  533. //
  534. // If the IRP is on the way up, then clean up after the DMA as this IRP is
  535. // still sitting in the channel. An IRP going up is already complete.
  536. //
  537. if (Irp->Direction == IrpUp) {
  538. ASSERT (Irp == Disk->Irp);
  539. Disk->Irp = NULL;
  540. //
  541. // Try to recover on failure.
  542. //
  543. IrpStatus = IoGetIrpStatus(Irp);
  544. if (!KSUCCESS(IrpStatus)) {
  545. Status = SdErrorRecovery(Controller);
  546. if (!KSUCCESS(Status)) {
  547. IrpStatus = Status;
  548. IoUpdateIrpStatus(Irp, IrpStatus);
  549. }
  550. //
  551. // Do not make further attempts if the media is gone or enough
  552. // attempts have been made.
  553. //
  554. if (((Controller->Flags &
  555. SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) ||
  556. ((Controller->Flags &
  557. SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
  558. (Controller->Try >= SD_MAX_IO_RETRIES)) {
  559. IrpStatus = STATUS_SUCCESS;
  560. } else {
  561. Controller->Try += 1;
  562. }
  563. }
  564. KeReleaseQueuedLock(Disk->ControllerLock);
  565. Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite),
  566. IrpReadWriteFlags);
  567. if (!KSUCCESS(Status)) {
  568. IoUpdateIrpStatus(Irp, Status);
  569. }
  570. //
  571. // Potentially return the completed IRP.
  572. //
  573. if (KSUCCESS(IrpStatus)) {
  574. CompleteIrp = FALSE;
  575. goto DispatchIoEnd;
  576. }
  577. }
  578. //
  579. // Start the DMA on the way down.
  580. //
  581. BytesToComplete = Irp->U.ReadWrite.IoSizeInBytes;
  582. IoOffset = Irp->U.ReadWrite.IoOffset;
  583. Irp->U.ReadWrite.IoBytesCompleted = 0;
  584. ASSERT((Disk->BlockCount != 0) && (Disk->BlockShift != 0));
  585. ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
  586. ASSERT(IS_ALIGNED(IoOffset, 1ULL << Disk->BlockShift) != FALSE);
  587. ASSERT(IS_ALIGNED(BytesToComplete, 1ULL << Disk->BlockShift) != FALSE);
  588. //
  589. // Before acquiring the controller's lock and starting the DMA, prepare
  590. // the I/O context for SD (i.e. it must use physical addresses that
  591. // are less than 4GB and be sector size aligned).
  592. //
  593. Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
  594. 1ULL << Disk->BlockShift,
  595. 0,
  596. MAX_ULONG,
  597. IrpReadWriteFlags);
  598. if (!KSUCCESS(Status)) {
  599. goto DispatchIoEnd;
  600. }
  601. //
  602. // Lock the controller to serialize access to the hardware.
  603. //
  604. KeAcquireQueuedLock(Disk->ControllerLock);
  605. if (((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
  606. ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0)) {
  607. Status = STATUS_NO_MEDIA;
  608. if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
  609. Status = STATUS_MEDIA_CHANGED;
  610. }
  611. KeReleaseQueuedLock(Disk->ControllerLock);
  612. IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  613. goto DispatchIoEnd;
  614. }
  615. //
  616. // Pend the IRP and fire up the DMA.
  617. //
  618. Irp->U.ReadWrite.NewIoOffset = Irp->U.ReadWrite.IoOffset;
  619. Disk->Irp = Irp;
  620. BlockOffset = IoOffset >> Disk->BlockShift;
  621. BlockCount = BytesToComplete >> Disk->BlockShift;
  622. CompleteIrp = FALSE;
  623. IoPendIrp(SdDriver, Irp);
  624. //
  625. // Make sure the system isn't trying to do I/O off the end of the disk.
  626. //
  627. ASSERT(BlockOffset < Disk->BlockCount);
  628. ASSERT(BlockCount >= 1);
  629. SdStandardBlockIoDma(Controller,
  630. BlockOffset,
  631. BlockCount,
  632. Irp->U.ReadWrite.IoBuffer,
  633. 0,
  634. Write,
  635. SdpDmaCompletion,
  636. Disk);
  637. //
  638. // DMA transfers are self perpetuating, so after kicking off this first
  639. // transfer, return. This returns with the lock held because I/O is
  640. // still in progress.
  641. //
  642. ASSERT(KeIsQueuedLockHeld(Disk->ControllerLock) != FALSE);
  643. ASSERT(CompleteIrp == FALSE);
  644. DispatchIoEnd:
  645. if (CompleteIrp != FALSE) {
  646. IoCompleteIrp(SdDriver, Irp, Status);
  647. }
  648. return;
  649. }
  650. VOID
  651. SdDispatchSystemControl (
  652. PIRP Irp,
  653. PVOID DeviceContext,
  654. PVOID IrpContext
  655. )
  656. /*++
  657. Routine Description:
  658. This routine handles System Control IRPs.
  659. Arguments:
  660. Irp - Supplies a pointer to the I/O request packet.
  661. DeviceContext - Supplies the context pointer supplied by the driver when it
  662. attached itself to the driver stack. Presumably this pointer contains
  663. driver-specific device context.
  664. IrpContext - Supplies the context pointer supplied by the driver when
  665. the IRP was created.
  666. Return Value:
  667. None.
  668. --*/
  669. {
  670. PVOID Context;
  671. PSD_DISK Disk;
  672. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  673. PSYSTEM_CONTROL_LOOKUP Lookup;
  674. PFILE_PROPERTIES Properties;
  675. ULONGLONG PropertiesFileSize;
  676. KSTATUS Status;
  677. Context = Irp->U.SystemControl.SystemContext;
  678. Disk = DeviceContext;
  679. //
  680. // Only disk devices are supported.
  681. //
  682. if (Disk->Type != SdDeviceDisk) {
  683. return;
  684. }
  685. switch (Irp->MinorCode) {
  686. case IrpMinorSystemControlLookup:
  687. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  688. Status = STATUS_PATH_NOT_FOUND;
  689. if (Lookup->Root != FALSE) {
  690. //
  691. // Enable opening of the root as a single file.
  692. //
  693. Properties = Lookup->Properties;
  694. Properties->FileId = 0;
  695. Properties->Type = IoObjectBlockDevice;
  696. Properties->HardLinkCount = 1;
  697. Properties->BlockCount = Disk->BlockCount;
  698. Properties->BlockSize = 1ULL << Disk->BlockShift;
  699. Properties->Size = Disk->BlockCount << Disk->BlockShift;
  700. Status = STATUS_SUCCESS;
  701. }
  702. IoCompleteIrp(SdDriver, Irp, Status);
  703. break;
  704. //
  705. // Writes to the disk's properties are not allowed. Fail if the data
  706. // has changed.
  707. //
  708. case IrpMinorSystemControlWriteFileProperties:
  709. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  710. Properties = FileOperation->FileProperties;
  711. PropertiesFileSize = Properties->Size;
  712. if ((Properties->FileId != 0) ||
  713. (Properties->Type != IoObjectBlockDevice) ||
  714. (Properties->HardLinkCount != 1) ||
  715. (Properties->BlockSize != (1ULL << Disk->BlockShift)) ||
  716. (Properties->BlockCount != Disk->BlockCount) ||
  717. (PropertiesFileSize != (Disk->BlockCount << Disk->BlockShift))) {
  718. Status = STATUS_NOT_SUPPORTED;
  719. } else {
  720. Status = STATUS_SUCCESS;
  721. }
  722. IoCompleteIrp(SdDriver, Irp, Status);
  723. break;
  724. //
  725. // Do not support hard disk device truncation.
  726. //
  727. case IrpMinorSystemControlTruncate:
  728. IoCompleteIrp(SdDriver, Irp, STATUS_NOT_SUPPORTED);
  729. break;
  730. //
  731. // Gather and return device information.
  732. //
  733. case IrpMinorSystemControlDeviceInformation:
  734. break;
  735. case IrpMinorSystemControlSynchronize:
  736. IoCompleteIrp(SdDriver, Irp, STATUS_SUCCESS);
  737. break;
  738. //
  739. // Ignore everything unrecognized.
  740. //
  741. default:
  742. ASSERT(FALSE);
  743. break;
  744. }
  745. return;
  746. }
  747. INTERRUPT_STATUS
  748. SdBusInterruptService (
  749. PVOID Context
  750. )
  751. /*++
  752. Routine Description:
  753. This routine implements the interrupt service routine for an SD bus.
  754. Arguments:
  755. Context - Supplies a pointer to the device context.
  756. Return Value:
  757. Returns whether or not the SD controller caused the interrupt.
  758. --*/
  759. {
  760. PSD_BUS Bus;
  761. PSD_SLOT Slot;
  762. UINTN SlotIndex;
  763. INTERRUPT_STATUS Status;
  764. INTERRUPT_STATUS TotalStatus;
  765. Bus = Context;
  766. TotalStatus = InterruptStatusNotClaimed;
  767. for (SlotIndex = 0; SlotIndex < MAX_SD_SLOTS; SlotIndex += 1) {
  768. Slot = &(Bus->Slots[SlotIndex]);
  769. if (Slot->Controller == NULL) {
  770. break;
  771. }
  772. Status = SdStandardInterruptService(Slot->Controller);
  773. if (Status != InterruptStatusNotClaimed) {
  774. TotalStatus = Status;
  775. }
  776. }
  777. return TotalStatus;
  778. }
  779. INTERRUPT_STATUS
  780. SdBusInterruptServiceDispatch (
  781. PVOID Context
  782. )
  783. /*++
  784. Routine Description:
  785. This routine implements the dispatch level interrupt service routine for an
  786. SD bus.
  787. Arguments:
  788. Context - Supplies a pointer to the device context.
  789. Return Value:
  790. Returns whether or not the SD controller caused the interrupt.
  791. --*/
  792. {
  793. PSD_BUS Bus;
  794. PSD_SLOT Slot;
  795. UINTN SlotIndex;
  796. INTERRUPT_STATUS Status;
  797. INTERRUPT_STATUS TotalStatus;
  798. Bus = Context;
  799. TotalStatus = InterruptStatusNotClaimed;
  800. for (SlotIndex = 0; SlotIndex < MAX_SD_SLOTS; SlotIndex += 1) {
  801. Slot = &(Bus->Slots[SlotIndex]);
  802. if (Slot->Controller == NULL) {
  803. break;
  804. }
  805. Status = SdStandardInterruptServiceDispatch(Slot->Controller);
  806. if (Status != InterruptStatusNotClaimed) {
  807. TotalStatus = Status;
  808. }
  809. }
  810. return TotalStatus;
  811. }
  812. VOID
  813. SdpBusDispatchStateChange (
  814. PIRP Irp,
  815. PSD_BUS Bus
  816. )
  817. /*++
  818. Routine Description:
  819. This routine handles State Change IRPs for the SD bus device.
  820. Arguments:
  821. Irp - Supplies a pointer to the I/O request packet.
  822. Bus - Supplies a pointer to the SD bus.
  823. Return Value:
  824. None.
  825. --*/
  826. {
  827. KSTATUS Status;
  828. if (Irp->Direction == IrpUp) {
  829. if (!KSUCCESS(IoGetIrpStatus(Irp))) {
  830. return;
  831. }
  832. switch (Irp->MinorCode) {
  833. case IrpMinorQueryResources:
  834. Status = SdpBusProcessResourceRequirements(Irp, Bus);
  835. if (!KSUCCESS(Status)) {
  836. IoCompleteIrp(SdDriver, Irp, Status);
  837. }
  838. break;
  839. case IrpMinorStartDevice:
  840. Status = SdpBusStartDevice(Irp, Bus);
  841. if (!KSUCCESS(Status)) {
  842. IoCompleteIrp(SdDriver, Irp, Status);
  843. }
  844. break;
  845. case IrpMinorQueryChildren:
  846. Status = SdpBusQueryChildren(Irp, Bus);
  847. if (!KSUCCESS(Status)) {
  848. IoCompleteIrp(SdDriver, Irp, Status);
  849. }
  850. break;
  851. default:
  852. break;
  853. }
  854. }
  855. return;
  856. }
  857. VOID
  858. SdpSlotDispatchStateChange (
  859. PIRP Irp,
  860. PSD_SLOT Slot
  861. )
  862. /*++
  863. Routine Description:
  864. This routine handles State Change IRPs for the SD bus device.
  865. Arguments:
  866. Irp - Supplies a pointer to the I/O request packet.
  867. Slot - Supplies a pointer to the SD slot.
  868. Return Value:
  869. None.
  870. --*/
  871. {
  872. KSTATUS Status;
  873. //
  874. // Actively handle IRPs as the bus driver for the slot.
  875. //
  876. if (Irp->Direction == IrpDown) {
  877. switch (Irp->MinorCode) {
  878. case IrpMinorStartDevice:
  879. Status = SdpSlotStartDevice(Irp, Slot);
  880. IoCompleteIrp(SdDriver, Irp, Status);
  881. break;
  882. case IrpMinorQueryResources:
  883. IoCompleteIrp(SdDriver, Irp, STATUS_SUCCESS);
  884. break;
  885. case IrpMinorQueryChildren:
  886. Status = SdpSlotQueryChildren(Irp, Slot);
  887. IoCompleteIrp(SdDriver, Irp, Status);
  888. break;
  889. default:
  890. break;
  891. }
  892. }
  893. return;
  894. }
  895. VOID
  896. SdpDiskDispatchStateChange (
  897. PIRP Irp,
  898. PSD_DISK Disk
  899. )
  900. /*++
  901. Routine Description:
  902. This routine handles State Change IRPs for a parent device.
  903. Arguments:
  904. Irp - Supplies a pointer to the I/O request packet.
  905. Disk - Supplies a pointer to the SD disk.
  906. Return Value:
  907. None.
  908. --*/
  909. {
  910. BOOL CompleteIrp;
  911. KSTATUS Status;
  912. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  913. //
  914. // The IRP is on its way down the stack. Do most processing here.
  915. //
  916. if (Irp->Direction == IrpDown) {
  917. Status = STATUS_NOT_SUPPORTED;
  918. CompleteIrp = TRUE;
  919. switch (Irp->MinorCode) {
  920. case IrpMinorQueryResources:
  921. Status = STATUS_SUCCESS;
  922. break;
  923. case IrpMinorStartDevice:
  924. //
  925. // Publish the disk interface.
  926. //
  927. Status = STATUS_SUCCESS;
  928. if (Disk->DiskInterface.DiskToken == NULL) {
  929. RtlCopyMemory(&(Disk->DiskInterface),
  930. &SdDiskInterfaceTemplate,
  931. sizeof(DISK_INTERFACE));
  932. Disk->DiskInterface.DiskToken = Disk;
  933. Disk->DiskInterface.BlockSize = 1ULL << Disk->BlockShift;
  934. ASSERT(Disk->DiskInterface.BlockSize ==
  935. (1ULL << Disk->BlockShift));
  936. Disk->DiskInterface.BlockCount = Disk->BlockCount;
  937. Status = IoCreateInterface(&SdDiskInterfaceUuid,
  938. Disk->Device,
  939. &(Disk->DiskInterface),
  940. sizeof(DISK_INTERFACE));
  941. if (!KSUCCESS(Status)) {
  942. Disk->DiskInterface.DiskToken = NULL;
  943. }
  944. }
  945. break;
  946. case IrpMinorQueryChildren:
  947. Irp->U.QueryChildren.Children = NULL;
  948. Irp->U.QueryChildren.ChildCount = 0;
  949. Status = STATUS_SUCCESS;
  950. break;
  951. case IrpMinorQueryInterface:
  952. break;
  953. case IrpMinorRemoveDevice:
  954. if (Disk->DiskInterface.DiskToken != NULL) {
  955. Status = IoDestroyInterface(&SdDiskInterfaceUuid,
  956. Disk->Device,
  957. &(Disk->DiskInterface));
  958. ASSERT(KSUCCESS(Status));
  959. Disk->DiskInterface.DiskToken = NULL;
  960. }
  961. SdpDiskReleaseReference(Disk);
  962. Status = STATUS_SUCCESS;
  963. break;
  964. //
  965. // Pass all other IRPs down.
  966. //
  967. default:
  968. CompleteIrp = FALSE;
  969. break;
  970. }
  971. //
  972. // Complete the IRP unless there's a reason not to.
  973. //
  974. if (CompleteIrp != FALSE) {
  975. IoCompleteIrp(SdDriver, Irp, Status);
  976. }
  977. //
  978. // The IRP is completed and is on its way back up.
  979. //
  980. } else {
  981. ASSERT(Irp->Direction == IrpUp);
  982. }
  983. return;
  984. }
  985. KSTATUS
  986. SdpBusProcessResourceRequirements (
  987. PIRP Irp,
  988. PSD_BUS Bus
  989. )
  990. /*++
  991. Routine Description:
  992. This routine filters through the resource requirements presented by the
  993. bus for a SD Bus controller. It adds an interrupt vector requirement
  994. for any interrupt line requested.
  995. Arguments:
  996. Irp - Supplies a pointer to the I/O request packet.
  997. Bus - Supplies a pointer to the bus context.
  998. Return Value:
  999. Status code.
  1000. --*/
  1001. {
  1002. PRESOURCE_CONFIGURATION_LIST Requirements;
  1003. KSTATUS Status;
  1004. RESOURCE_REQUIREMENT VectorRequirement;
  1005. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  1006. (Irp->MinorCode == IrpMinorQueryResources));
  1007. //
  1008. // Initialize a nice interrupt vector requirement in preparation.
  1009. //
  1010. RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
  1011. VectorRequirement.Type = ResourceTypeInterruptVector;
  1012. VectorRequirement.Minimum = 0;
  1013. VectorRequirement.Maximum = -1;
  1014. VectorRequirement.Length = 1;
  1015. //
  1016. // Loop through all configuration lists, creating a vector for each line.
  1017. //
  1018. Requirements = Irp->U.QueryResources.ResourceRequirements;
  1019. Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
  1020. &VectorRequirement);
  1021. if (!KSUCCESS(Status)) {
  1022. goto BusProcessResourceRequirementsEnd;
  1023. }
  1024. BusProcessResourceRequirementsEnd:
  1025. return Status;
  1026. }
  1027. KSTATUS
  1028. SdpBusStartDevice (
  1029. PIRP Irp,
  1030. PSD_BUS Bus
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. This routine starts an SD bus device.
  1035. Arguments:
  1036. Irp - Supplies a pointer to the I/O request packet.
  1037. Bus - Supplies a pointer to the bus context.
  1038. Return Value:
  1039. Status code.
  1040. --*/
  1041. {
  1042. PRESOURCE_ALLOCATION Allocation;
  1043. PRESOURCE_ALLOCATION_LIST AllocationList;
  1044. IO_CONNECT_INTERRUPT_PARAMETERS Connect;
  1045. PRESOURCE_ALLOCATION LineAllocation;
  1046. UINTN SlotIndex;
  1047. KSTATUS Status;
  1048. for (SlotIndex = 0; SlotIndex < MAX_SD_SLOTS; SlotIndex += 1) {
  1049. Bus->Slots[SlotIndex].Resource = NULL;
  1050. ASSERT(Bus->Slots[SlotIndex].Controller == NULL);
  1051. }
  1052. SlotIndex = 0;
  1053. //
  1054. // Loop through the allocated resources to get the controller base and the
  1055. // interrupt.
  1056. //
  1057. AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
  1058. ASSERT(AllocationList != NULL);
  1059. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1060. while (Allocation != NULL) {
  1061. //
  1062. // If the resource is an interrupt vector, then it should have an
  1063. // owning interrupt line allocation.
  1064. //
  1065. if (Allocation->Type == ResourceTypeInterruptVector) {
  1066. //
  1067. // Currently only one interrupt resource is expected.
  1068. //
  1069. ASSERT(Bus->InterruptResourcesFound == FALSE);
  1070. ASSERT(Allocation->OwningAllocation != NULL);
  1071. //
  1072. // Save the line and vector number.
  1073. //
  1074. LineAllocation = Allocation->OwningAllocation;
  1075. Bus->InterruptLine = LineAllocation->Allocation;
  1076. Bus->InterruptVector = Allocation->Allocation;
  1077. Bus->InterruptResourcesFound = TRUE;
  1078. } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
  1079. if ((SlotIndex < MAX_SD_SLOTS) && (Allocation->Length > 0)) {
  1080. Bus->Slots[SlotIndex].Resource = Allocation;
  1081. SlotIndex += 1;
  1082. }
  1083. }
  1084. //
  1085. // Get the next allocation in the list.
  1086. //
  1087. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1088. }
  1089. //
  1090. // Attempt to connect the interrupt.
  1091. //
  1092. if (Bus->InterruptHandle == INVALID_HANDLE) {
  1093. RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
  1094. Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
  1095. Connect.Device = Irp->Device;
  1096. Connect.LineNumber = Bus->InterruptLine;
  1097. Connect.Vector = Bus->InterruptVector;
  1098. Connect.InterruptServiceRoutine = SdBusInterruptService;
  1099. Connect.DispatchServiceRoutine = SdBusInterruptServiceDispatch;
  1100. Connect.Context = Bus;
  1101. Connect.Interrupt = &(Bus->InterruptHandle);
  1102. Status = IoConnectInterrupt(&Connect);
  1103. if (!KSUCCESS(Status)) {
  1104. goto StartDeviceEnd;
  1105. }
  1106. }
  1107. Status = STATUS_SUCCESS;
  1108. StartDeviceEnd:
  1109. if (!KSUCCESS(Status)) {
  1110. if (Bus->InterruptHandle != INVALID_HANDLE) {
  1111. IoDisconnectInterrupt(Bus->InterruptHandle);
  1112. Bus->InterruptHandle = INVALID_HANDLE;
  1113. }
  1114. }
  1115. return Status;
  1116. }
  1117. KSTATUS
  1118. SdpBusQueryChildren (
  1119. PIRP Irp,
  1120. PSD_BUS Context
  1121. )
  1122. /*++
  1123. Routine Description:
  1124. This routine handles State Change IRPs for the SD bus device.
  1125. Arguments:
  1126. Irp - Supplies a pointer to the I/O request packet.
  1127. Context - Supplies a pointer to the bus context.
  1128. Return Value:
  1129. Status code.
  1130. --*/
  1131. {
  1132. UINTN ChildCount;
  1133. UINTN ChildIndex;
  1134. PDEVICE Children[MAX_SD_SLOTS];
  1135. PSD_SLOT Slot;
  1136. KSTATUS Status;
  1137. ChildCount = 0;
  1138. for (ChildIndex = 0; ChildIndex < MAX_SD_SLOTS; ChildIndex += 1) {
  1139. Slot = &(Context->Slots[ChildIndex]);
  1140. if (Slot->Resource != NULL) {
  1141. if (Slot->Device == NULL) {
  1142. Status = IoCreateDevice(SdDriver,
  1143. Slot,
  1144. Irp->Device,
  1145. SD_SLOT_DEVICE_ID,
  1146. NULL,
  1147. NULL,
  1148. &(Slot->Device));
  1149. if (!KSUCCESS(Status)) {
  1150. goto BusQueryChildrenEnd;
  1151. }
  1152. }
  1153. Children[ChildCount] = Slot->Device;
  1154. ChildCount += 1;
  1155. }
  1156. }
  1157. if (ChildCount != 0) {
  1158. Status = IoMergeChildArrays(Irp,
  1159. Children,
  1160. ChildCount,
  1161. SD_ALLOCATION_TAG);
  1162. if (!KSUCCESS(Status)) {
  1163. goto BusQueryChildrenEnd;
  1164. }
  1165. }
  1166. Status = STATUS_SUCCESS;
  1167. BusQueryChildrenEnd:
  1168. return Status;
  1169. }
  1170. KSTATUS
  1171. SdpSlotStartDevice (
  1172. PIRP Irp,
  1173. PSD_SLOT Slot
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. This routine starts an SD slot device.
  1178. Arguments:
  1179. Irp - Supplies a pointer to the I/O request packet.
  1180. Slot - Supplies a pointer to the slot context.
  1181. Return Value:
  1182. Status code.
  1183. --*/
  1184. {
  1185. SD_INITIALIZATION_BLOCK Parameters;
  1186. KSTATUS Status;
  1187. ASSERT(Slot->Resource != NULL);
  1188. //
  1189. // Initialize the controller base.
  1190. //
  1191. if (Slot->ControllerBase == NULL) {
  1192. Slot->ControllerBase = MmMapPhysicalAddress(Slot->Resource->Allocation,
  1193. Slot->Resource->Length,
  1194. TRUE,
  1195. FALSE,
  1196. TRUE);
  1197. if (Slot->ControllerBase == NULL) {
  1198. Status = STATUS_INSUFFICIENT_RESOURCES;
  1199. goto StartDeviceEnd;
  1200. }
  1201. }
  1202. if (Slot->Lock == NULL) {
  1203. Slot->Lock = KeCreateQueuedLock();
  1204. if (Slot->Lock == NULL) {
  1205. Status = STATUS_INSUFFICIENT_RESOURCES;
  1206. goto StartDeviceEnd;
  1207. }
  1208. }
  1209. //
  1210. // Initialize the standard SD controller.
  1211. //
  1212. if (Slot->Controller == NULL) {
  1213. RtlZeroMemory(&Parameters, sizeof(SD_INITIALIZATION_BLOCK));
  1214. Parameters.ConsumerContext = Slot;
  1215. Parameters.StandardControllerBase = Slot->ControllerBase;
  1216. Parameters.HostCapabilities = SD_MODE_AUTO_CMD12 |
  1217. SD_MODE_4BIT |
  1218. SD_MODE_RESPONSE136_SHIFTED |
  1219. SD_MODE_CMD23;
  1220. Parameters.OsDevice = Slot->Device;
  1221. Slot->Controller = SdCreateController(&Parameters);
  1222. if (Slot->Controller == NULL) {
  1223. Status = STATUS_INSUFFICIENT_RESOURCES;
  1224. goto StartDeviceEnd;
  1225. }
  1226. Slot->Controller->InterruptHandle = Slot->Parent->InterruptHandle;
  1227. }
  1228. Status = STATUS_SUCCESS;
  1229. StartDeviceEnd:
  1230. if (!KSUCCESS(Status)) {
  1231. if (Slot->Lock != NULL) {
  1232. KeDestroyQueuedLock(Slot->Lock);
  1233. }
  1234. if (Slot->Controller != NULL) {
  1235. SdDestroyController(Slot->Controller);
  1236. Slot->Controller = NULL;
  1237. }
  1238. }
  1239. return Status;
  1240. }
  1241. KSTATUS
  1242. SdpSlotQueryChildren (
  1243. PIRP Irp,
  1244. PSD_SLOT Slot
  1245. )
  1246. /*++
  1247. Routine Description:
  1248. This routine potentially enumerates an SD card in a given slot.
  1249. Arguments:
  1250. Irp - Supplies a pointer to the I/O request packet.
  1251. Slot - Supplies a pointer to the SD slot that may contain the card.
  1252. Return Value:
  1253. Status code.
  1254. --*/
  1255. {
  1256. ULONG BlockSize;
  1257. PSTR DeviceId;
  1258. ULONG FlagsMask;
  1259. PSD_DISK NewDisk;
  1260. ULONG OldFlags;
  1261. KSTATUS Status;
  1262. NewDisk = NULL;
  1263. //
  1264. // Collect the current pending status.
  1265. //
  1266. FlagsMask = ~(SD_CONTROLLER_FLAG_INSERTION_PENDING |
  1267. SD_CONTROLLER_FLAG_REMOVAL_PENDING);
  1268. OldFlags = RtlAtomicAnd32(&(Slot->Controller->Flags), FlagsMask);
  1269. //
  1270. // If either removal or insertion is pending, remove the existing disk. In
  1271. // theory, an insertion should always follow a removal, but this does not
  1272. // appear to be the case in practice when cards are quickly removed and
  1273. // inserted.
  1274. //
  1275. FlagsMask = SD_CONTROLLER_FLAG_INSERTION_PENDING |
  1276. SD_CONTROLLER_FLAG_REMOVAL_PENDING;
  1277. if ((OldFlags & FlagsMask) != 0) {
  1278. if (Slot->Disk != NULL) {
  1279. KeAcquireQueuedLock(Slot->Lock);
  1280. RtlAtomicAnd32(&(Slot->Disk->Controller->Flags),
  1281. ~SD_CONTROLLER_FLAG_MEDIA_PRESENT);
  1282. KeReleaseQueuedLock(Slot->Lock);
  1283. Slot->Disk = NULL;
  1284. }
  1285. }
  1286. //
  1287. // Check to see if there's an insertion pending, re-initialize the
  1288. // controller and create a new disk if there is one present.
  1289. //
  1290. if ((OldFlags & SD_CONTROLLER_FLAG_INSERTION_PENDING) != 0) {
  1291. ASSERT(Slot->Disk == NULL);
  1292. KeDelayExecution(FALSE, FALSE, SD_INSERTION_SETTLE_DELAY);
  1293. RtlAtomicAnd32(&(Slot->Controller->Flags),
  1294. ~SD_CONTROLLER_FLAG_MEDIA_CHANGED);
  1295. Status = SdInitializeController(Slot->Controller, TRUE);
  1296. if (!KSUCCESS(Status)) {
  1297. if (Status == STATUS_TIMEOUT) {
  1298. Status = STATUS_SUCCESS;
  1299. }
  1300. goto SlotQueryChildrenEnd;
  1301. }
  1302. //
  1303. // Allocate a new disk context for the slot. The disk was at least
  1304. // present long enough to be enumerated.
  1305. //
  1306. NewDisk = SdpCreateDisk(Slot);
  1307. if (NewDisk == NULL) {
  1308. Status = STATUS_INSUFFICIENT_RESOURCES;
  1309. goto SlotQueryChildrenEnd;
  1310. }
  1311. //
  1312. // The slot just got a new disk, set the block size and count. Ignore
  1313. // cases where the card immediately got removed. Act like it was never
  1314. // seen.
  1315. //
  1316. BlockSize = 0;
  1317. Status = SdGetMediaParameters(NewDisk->Controller,
  1318. &(NewDisk->BlockCount),
  1319. &BlockSize);
  1320. if (!KSUCCESS(Status)) {
  1321. if (Status == STATUS_NO_MEDIA) {
  1322. Status = STATUS_SUCCESS;
  1323. }
  1324. goto SlotQueryChildrenEnd;
  1325. }
  1326. ASSERT(POWER_OF_2(BlockSize) != FALSE);
  1327. NewDisk->BlockShift = RtlCountTrailingZeros32(BlockSize);
  1328. //
  1329. // Initialize DMA support, but it's okay if it doesn't succeed. Again,
  1330. // don't bother reporting the disk if it got removed.
  1331. //
  1332. Status = SdStandardInitializeDma(NewDisk->Controller);
  1333. if (KSUCCESS(Status)) {
  1334. NewDisk->Flags |= SD_DISK_FLAG_DMA_SUPPORTED;
  1335. } else if (Status == STATUS_NO_MEDIA) {
  1336. Status = STATUS_SUCCESS;
  1337. goto SlotQueryChildrenEnd;
  1338. }
  1339. //
  1340. // Create the OS device for the disk.
  1341. //
  1342. DeviceId = SD_MMC_DEVICE_ID;
  1343. if (SD_IS_CARD_SD(NewDisk->Controller)) {
  1344. DeviceId = SD_CARD_DEVICE_ID;
  1345. }
  1346. Status = IoCreateDevice(SdDriver,
  1347. NewDisk,
  1348. Irp->Device,
  1349. DeviceId,
  1350. DISK_CLASS_ID,
  1351. NULL,
  1352. &(NewDisk->Device));
  1353. if (!KSUCCESS(Status)) {
  1354. goto SlotQueryChildrenEnd;
  1355. }
  1356. //
  1357. // The disk for the slot is all set to go.
  1358. //
  1359. Slot->Disk = NewDisk;
  1360. NewDisk = NULL;
  1361. }
  1362. //
  1363. // If there's no disk, don't enumerate it.
  1364. //
  1365. if (Slot->Disk == NULL) {
  1366. Status = STATUS_SUCCESS;
  1367. goto SlotQueryChildrenEnd;
  1368. }
  1369. ASSERT((Slot->Disk != NULL) && (Slot->Disk->Device != NULL));
  1370. //
  1371. // Enumerate the one child.
  1372. //
  1373. Status = IoMergeChildArrays(Irp,
  1374. &(Slot->Disk->Device),
  1375. 1,
  1376. SD_ALLOCATION_TAG);
  1377. if (!KSUCCESS(Status)) {
  1378. goto SlotQueryChildrenEnd;
  1379. }
  1380. SlotQueryChildrenEnd:
  1381. if (NewDisk != NULL) {
  1382. ASSERT(NewDisk->Device == NULL);
  1383. SdpDiskReleaseReference(NewDisk);
  1384. }
  1385. return Status;
  1386. }
  1387. PSD_DISK
  1388. SdpCreateDisk (
  1389. PSD_SLOT Slot
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This routine creates an SD disk context.
  1394. Arguments:
  1395. Slot - Supplies a pointer to the SD slot to which the disk belongs.
  1396. Return Value:
  1397. Returns a pointer to the new SD disk on success or NULL on failure.
  1398. --*/
  1399. {
  1400. PSD_DISK Disk;
  1401. Disk = MmAllocateNonPagedPool(sizeof(SD_DISK), SD_ALLOCATION_TAG);
  1402. if (Disk == NULL) {
  1403. return NULL;
  1404. }
  1405. RtlZeroMemory(Disk, sizeof(SD_DISK));
  1406. Disk->Type = SdDeviceDisk;
  1407. Disk->Parent = Slot;
  1408. Disk->Controller = Slot->Controller;
  1409. Disk->ControllerLock = Slot->Lock;
  1410. Disk->ReferenceCount = 1;
  1411. return Disk;
  1412. }
  1413. VOID
  1414. SdpDestroyDisk (
  1415. PSD_DISK Disk
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. This routine destroys the given SD disk.
  1420. Arguments:
  1421. Disk - Supplies a pointer to the SD disk to destroy.
  1422. Return Value:
  1423. None.
  1424. --*/
  1425. {
  1426. ASSERT(Disk->DiskInterface.DiskToken == NULL);
  1427. ASSERT(Disk->Irp == NULL);
  1428. MmFreeNonPagedPool(Disk);
  1429. return;
  1430. }
  1431. VOID
  1432. SdpDiskAddReference (
  1433. PSD_DISK Disk
  1434. )
  1435. /*++
  1436. Routine Description:
  1437. This routine adds a reference to SD disk.
  1438. Arguments:
  1439. Disk - Supplies a pointer to the SD disk.
  1440. Return Value:
  1441. None.
  1442. --*/
  1443. {
  1444. ULONG OldReferenceCount;
  1445. OldReferenceCount = RtlAtomicAdd32(&(Disk->ReferenceCount), 1);
  1446. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1447. return;
  1448. }
  1449. VOID
  1450. SdpDiskReleaseReference (
  1451. PSD_DISK Disk
  1452. )
  1453. /*++
  1454. Routine Description:
  1455. This routine releases a reference from the SD disk.
  1456. Arguments:
  1457. Disk - Supplies a pointer to the SD disk.
  1458. Return Value:
  1459. None.
  1460. --*/
  1461. {
  1462. ULONG OldReferenceCount;
  1463. OldReferenceCount = RtlAtomicAdd32(&(Disk->ReferenceCount), (ULONG)-1);
  1464. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1465. if (OldReferenceCount == 1) {
  1466. SdpDestroyDisk(Disk);
  1467. }
  1468. return;
  1469. }
  1470. VOID
  1471. SdpDmaCompletion (
  1472. PSD_CONTROLLER Controller,
  1473. PVOID Context,
  1474. UINTN BytesTransferred,
  1475. KSTATUS Status
  1476. )
  1477. /*++
  1478. Routine Description:
  1479. This routine is called by the SD library when a DMA transfer completes.
  1480. This routine is called from a DPC and, as a result, can get called back
  1481. at dispatch level.
  1482. Arguments:
  1483. Controller - Supplies a pointer to the controller.
  1484. Context - Supplies a context pointer passed to the library when the DMA
  1485. request was issued.
  1486. BytesTransferred - Supplies the number of bytes transferred in the request.
  1487. Status - Supplies the status code representing the completion of the I/O.
  1488. Return Value:
  1489. None.
  1490. --*/
  1491. {
  1492. UINTN BlockCount;
  1493. ULONGLONG BlockOffset;
  1494. PSD_DISK Disk;
  1495. ULONGLONG IoOffset;
  1496. UINTN IoSize;
  1497. PIRP Irp;
  1498. BOOL Write;
  1499. Disk = Context;
  1500. Irp = Disk->Irp;
  1501. ASSERT(Irp != NULL);
  1502. if (!KSUCCESS(Status)) {
  1503. RtlDebugPrint("SD Failed: %d 0x%I64x 0x%x 0x%x\n",
  1504. Status,
  1505. Irp->U.ReadWrite.IoOffset,
  1506. Irp->U.ReadWrite.IoSizeInBytes,
  1507. Irp->MinorCode);
  1508. IoCompleteIrp(SdDriver, Irp, Status);
  1509. return;
  1510. }
  1511. Irp->U.ReadWrite.IoBytesCompleted += BytesTransferred;
  1512. Irp->U.ReadWrite.NewIoOffset += BytesTransferred;
  1513. //
  1514. // If this transfer's over, unlock and complete the IRP.
  1515. //
  1516. if (Irp->U.ReadWrite.IoBytesCompleted ==
  1517. Irp->U.ReadWrite.IoSizeInBytes) {
  1518. IoCompleteIrp(SdDriver, Irp, Status);
  1519. return;
  1520. }
  1521. IoOffset = Irp->U.ReadWrite.NewIoOffset;
  1522. ASSERT(IoOffset ==
  1523. (Irp->U.ReadWrite.IoOffset + Irp->U.ReadWrite.IoBytesCompleted));
  1524. BlockOffset = IoOffset >> Disk->BlockShift;
  1525. IoSize = Irp->U.ReadWrite.IoSizeInBytes - Irp->U.ReadWrite.IoBytesCompleted;
  1526. BlockCount = IoSize >> Disk->BlockShift;
  1527. Write = FALSE;
  1528. if (Irp->MinorCode == IrpMinorIoWrite) {
  1529. Write = TRUE;
  1530. }
  1531. SdStandardBlockIoDma(Disk->Controller,
  1532. BlockOffset,
  1533. BlockCount,
  1534. Irp->U.ReadWrite.IoBuffer,
  1535. Irp->U.ReadWrite.IoBytesCompleted,
  1536. Write,
  1537. SdpDmaCompletion,
  1538. Disk);
  1539. return;
  1540. }
  1541. KSTATUS
  1542. SdpDiskBlockIoReset (
  1543. PVOID DiskToken
  1544. )
  1545. /*++
  1546. Routine Description:
  1547. This routine must be called immediately before using the block read and
  1548. write routines in order to allow the disk to reset any I/O channels in
  1549. preparation for imminent block I/O. This routine is called at high run
  1550. level.
  1551. Arguments:
  1552. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1553. retrieved by querying the disk device information.
  1554. Return Value:
  1555. Status code.
  1556. --*/
  1557. {
  1558. PSD_DISK Disk;
  1559. KSTATUS Status;
  1560. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1561. Disk = (PSD_DISK)DiskToken;
  1562. //
  1563. // Put the SD controller into critical execution mode.
  1564. //
  1565. SdSetCriticalMode(Disk->Controller, TRUE);
  1566. //
  1567. // Abort any current transaction that might have been left incomplete
  1568. // when the crash occurred.
  1569. //
  1570. Status = SdAbortTransaction(Disk->Controller, FALSE);
  1571. return Status;
  1572. }
  1573. KSTATUS
  1574. SdpDiskBlockIoRead (
  1575. PVOID DiskToken,
  1576. PIO_BUFFER IoBuffer,
  1577. ULONGLONG BlockAddress,
  1578. UINTN BlockCount,
  1579. PUINTN BlocksCompleted
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. This routine reads the block contents from the disk into the given I/O
  1584. buffer using polled I/O. It does so without acquiring any locks or
  1585. allocating any resources, as this routine is used for crash dump support
  1586. when the system is in a very fragile state. This routine must be called at
  1587. high level.
  1588. Arguments:
  1589. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1590. retrieved by querying the disk device information.
  1591. IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
  1592. BlockAddress - Supplies the block index to read (for physical disk, this is
  1593. the LBA).
  1594. BlockCount - Supplies the number of blocks to read.
  1595. BlocksCompleted - Supplies a pointer that receives the total number of
  1596. blocks read.
  1597. Return Value:
  1598. Status code.
  1599. --*/
  1600. {
  1601. PSD_DISK Disk;
  1602. IRP_READ_WRITE IrpReadWrite;
  1603. KSTATUS Status;
  1604. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1605. Disk = (PSD_DISK)DiskToken;
  1606. IrpReadWrite.IoBuffer = IoBuffer;
  1607. IrpReadWrite.IoOffset = BlockAddress << Disk->BlockShift;
  1608. IrpReadWrite.IoSizeInBytes = BlockCount << Disk->BlockShift;
  1609. //
  1610. // As this read routine is meant for critical code paths (crash dump),
  1611. // indicate that the channel should not be locked when performing the I/O.
  1612. // It may be that some other thread holds the lock, which would cause a
  1613. // dead lock as all other processors and threads are likely frozen.
  1614. //
  1615. Status = SdpPerformIoPolled(&IrpReadWrite, Disk, FALSE, FALSE);
  1616. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Disk->BlockShift;
  1617. return Status;
  1618. }
  1619. KSTATUS
  1620. SdpDiskBlockIoWrite (
  1621. PVOID DiskToken,
  1622. PIO_BUFFER IoBuffer,
  1623. ULONGLONG BlockAddress,
  1624. UINTN BlockCount,
  1625. PUINTN BlocksCompleted
  1626. )
  1627. /*++
  1628. Routine Description:
  1629. This routine writes the contents of the given I/O buffer to the disk using
  1630. polled I/O. It does so without acquiring any locks or allocating any
  1631. resources, as this routine is used for crash dump support when the system
  1632. is in a very fragile state. This routine must be called at high level.
  1633. Arguments:
  1634. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  1635. retrieved by querying the disk device information.
  1636. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  1637. write.
  1638. BlockAddress - Supplies the block index to write to (for physical disk,
  1639. this is the LBA).
  1640. BlockCount - Supplies the number of blocks to write.
  1641. BlocksCompleted - Supplies a pointer that receives the total number of
  1642. blocks written.
  1643. Return Value:
  1644. Status code.
  1645. --*/
  1646. {
  1647. PSD_DISK Disk;
  1648. IRP_READ_WRITE IrpReadWrite;
  1649. KSTATUS Status;
  1650. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1651. Disk = (PSD_DISK)DiskToken;
  1652. IrpReadWrite.IoBuffer = IoBuffer;
  1653. IrpReadWrite.IoOffset = BlockAddress << Disk->BlockShift;
  1654. IrpReadWrite.IoSizeInBytes = BlockCount << Disk->BlockShift;
  1655. //
  1656. // As this write routine is meant for critical code paths (crash dump),
  1657. // indicate that the channel should not be locked when performing the I/O.
  1658. // It may be that some other thread holds the lock, which would cause a
  1659. // dead lock as all other processors and threads are likely frozen.
  1660. //
  1661. Status = SdpPerformIoPolled(&IrpReadWrite, Disk, TRUE, FALSE);
  1662. *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Disk->BlockShift;
  1663. return Status;
  1664. }
  1665. KSTATUS
  1666. SdpPerformIoPolled (
  1667. PIRP_READ_WRITE IrpReadWrite,
  1668. PSD_DISK Disk,
  1669. BOOL Write,
  1670. BOOL LockRequired
  1671. )
  1672. /*++
  1673. Routine Description:
  1674. This routine performs polled I/O data transfers.
  1675. Arguments:
  1676. IrpReadWrite - Supplies a pointer to an IRP read/write context.
  1677. Disk - Supplies a pointer to the SD disk device.
  1678. Write - Supplies a boolean indicating if this is a read operation (TRUE) or
  1679. a write operation (FALSE).
  1680. LockRequired - Supplies a boolean indicating if the controller lock needs
  1681. to be acquired (TRUE) or it does not (FALSE).
  1682. Return Value:
  1683. None.
  1684. --*/
  1685. {
  1686. UINTN BlockCount;
  1687. ULONGLONG BlockOffset;
  1688. UINTN BytesRemaining;
  1689. UINTN BytesThisRound;
  1690. KSTATUS CompletionStatus;
  1691. PSD_CONTROLLER Controller;
  1692. PIO_BUFFER_FRAGMENT Fragment;
  1693. UINTN FragmentIndex;
  1694. UINTN FragmentOffset;
  1695. PIO_BUFFER IoBuffer;
  1696. UINTN IoBufferOffset;
  1697. ULONG IrpReadWriteFlags;
  1698. BOOL LockHeld;
  1699. BOOL ReadWriteIrpPrepared;
  1700. KSTATUS Status;
  1701. PVOID VirtualAddress;
  1702. IrpReadWrite->IoBytesCompleted = 0;
  1703. LockHeld = FALSE;
  1704. ReadWriteIrpPrepared = FALSE;
  1705. ASSERT(IrpReadWrite->IoBuffer != NULL);
  1706. ASSERT((Disk->BlockCount != 0) && (Disk->BlockShift != 0));
  1707. //
  1708. // Validate the supplied I/O buffer is aligned and big enough.
  1709. //
  1710. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_POLLED;
  1711. if (Write != FALSE) {
  1712. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  1713. }
  1714. Status = IoPrepareReadWriteIrp(IrpReadWrite,
  1715. 1ULL << Disk->BlockShift,
  1716. 0,
  1717. MAX_ULONGLONG,
  1718. IrpReadWriteFlags);
  1719. if (!KSUCCESS(Status)) {
  1720. goto PerformIoPolledEnd;
  1721. }
  1722. ReadWriteIrpPrepared = TRUE;
  1723. //
  1724. // Make sure the I/O buffer is mapped before use. SD depends on the buffer
  1725. // being mapped.
  1726. //
  1727. IoBuffer = IrpReadWrite->IoBuffer;
  1728. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
  1729. if (!KSUCCESS(Status)) {
  1730. goto PerformIoPolledEnd;
  1731. }
  1732. //
  1733. // Find the starting fragment based on the current offset.
  1734. //
  1735. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  1736. FragmentIndex = 0;
  1737. FragmentOffset = 0;
  1738. while (IoBufferOffset != 0) {
  1739. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1740. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1741. if (IoBufferOffset < Fragment->Size) {
  1742. FragmentOffset = IoBufferOffset;
  1743. break;
  1744. }
  1745. IoBufferOffset -= Fragment->Size;
  1746. FragmentIndex += 1;
  1747. }
  1748. if (LockRequired != FALSE) {
  1749. KeAcquireQueuedLock(Disk->ControllerLock);
  1750. LockHeld = TRUE;
  1751. }
  1752. Controller = Disk->Controller;
  1753. if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
  1754. Status = STATUS_MEDIA_CHANGED;
  1755. goto PerformIoPolledEnd;
  1756. } else if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
  1757. Status = STATUS_NO_MEDIA;
  1758. goto PerformIoPolledEnd;
  1759. }
  1760. //
  1761. // Loop reading in or writing out each fragment in the I/O buffer.
  1762. //
  1763. BytesRemaining = IrpReadWrite->IoSizeInBytes;
  1764. ASSERT(IS_ALIGNED(BytesRemaining, 1ULL << Disk->BlockShift) != FALSE);
  1765. ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, 1ULL << Disk->BlockShift) !=
  1766. FALSE);
  1767. BlockOffset = IrpReadWrite->IoOffset >> Disk->BlockShift;
  1768. while (BytesRemaining != 0) {
  1769. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1770. Fragment = (PIO_BUFFER_FRAGMENT)&(IoBuffer->Fragment[FragmentIndex]);
  1771. VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
  1772. BytesThisRound = Fragment->Size - FragmentOffset;
  1773. if (BytesRemaining < BytesThisRound) {
  1774. BytesThisRound = BytesRemaining;
  1775. }
  1776. ASSERT(IS_ALIGNED(BytesThisRound, (1ULL << Disk->BlockShift)) != FALSE);
  1777. BlockCount = BytesThisRound >> Disk->BlockShift;
  1778. //
  1779. // Make sure the system isn't trying to do I/O off the end of the disk.
  1780. //
  1781. ASSERT(BlockOffset < Disk->BlockCount);
  1782. ASSERT(BlockCount >= 1);
  1783. Status = SdBlockIoPolled(Disk->Controller,
  1784. BlockOffset,
  1785. BlockCount,
  1786. VirtualAddress,
  1787. Write);
  1788. if (!KSUCCESS(Status)) {
  1789. goto PerformIoPolledEnd;
  1790. }
  1791. BlockOffset += BlockCount;
  1792. BytesRemaining -= BytesThisRound;
  1793. IrpReadWrite->IoBytesCompleted += BytesThisRound;
  1794. FragmentOffset += BytesThisRound;
  1795. if (FragmentOffset >= Fragment->Size) {
  1796. FragmentIndex += 1;
  1797. FragmentOffset = 0;
  1798. }
  1799. }
  1800. Status = STATUS_SUCCESS;
  1801. PerformIoPolledEnd:
  1802. if (LockHeld != FALSE) {
  1803. KeReleaseQueuedLock(Disk->ControllerLock);
  1804. }
  1805. if (ReadWriteIrpPrepared != FALSE) {
  1806. CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
  1807. IrpReadWriteFlags);
  1808. if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
  1809. Status = CompletionStatus;
  1810. }
  1811. }
  1812. IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
  1813. IrpReadWrite->IoBytesCompleted;
  1814. return Status;
  1815. }