sd.c 55 KB

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