Mmc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /** @file
  2. Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.
  3. Copyright (c) 2011, ARM Limited. All rights reserved.
  4. This program and the accompanying materials
  5. are licensed and made available under the terms and conditions of the BSD License
  6. which accompanies this distribution. The full text of the license may be found at
  7. http://opensource.org/licenses/bsd-license.php
  8. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #include <Protocol/DevicePath.h>
  12. #include <Protocol/MmcHost.h>
  13. #include <Library/BaseLib.h>
  14. #include <Library/BaseMemoryLib.h>
  15. #include <Library/MemoryAllocationLib.h>
  16. #include <Library/UefiBootServicesTableLib.h>
  17. #include <Library/DevicePathLib.h>
  18. #include <Library/DebugLib.h>
  19. #include "Mmc.h"
  20. EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {
  21. SIGNATURE_32('m','m','c','o'), // MediaId
  22. TRUE, // RemovableMedia
  23. FALSE, // MediaPresent
  24. FALSE, // LogicalPartition
  25. FALSE, // ReadOnly
  26. FALSE, // WriteCaching
  27. 512, // BlockSize
  28. 4, // IoAlign
  29. 0, // Pad
  30. 0 // LastBlock
  31. };
  32. //
  33. // This device structure is serviced as a header.
  34. // Its next field points to the first root bridge device node.
  35. //
  36. LIST_ENTRY mMmcHostPool;
  37. /**
  38. Event triggered by the timer to check if any cards have been removed
  39. or if new ones have been plugged in
  40. **/
  41. EFI_EVENT gCheckCardsEvent;
  42. /**
  43. Initialize the MMC Host Pool to support multiple MMC devices
  44. **/
  45. VOID
  46. InitializeMmcHostPool (
  47. VOID
  48. )
  49. {
  50. InitializeListHead (&mMmcHostPool);
  51. }
  52. /**
  53. Insert a new Mmc Host controller to the pool
  54. **/
  55. VOID
  56. InsertMmcHost (
  57. IN MMC_HOST_INSTANCE *MmcHostInstance
  58. )
  59. {
  60. InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));
  61. }
  62. /*
  63. Remove a new Mmc Host controller to the pool
  64. */
  65. VOID
  66. RemoveMmcHost (
  67. IN MMC_HOST_INSTANCE *MmcHostInstance
  68. )
  69. {
  70. RemoveEntryList (&(MmcHostInstance->Link));
  71. }
  72. MMC_HOST_INSTANCE* CreateMmcHostInstance (
  73. IN EFI_MMC_HOST_PROTOCOL* MmcHost
  74. )
  75. {
  76. EFI_STATUS Status;
  77. MMC_HOST_INSTANCE* MmcHostInstance;
  78. EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
  79. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  80. MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));
  81. if (MmcHostInstance == NULL) {
  82. return NULL;
  83. }
  84. MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;
  85. MmcHostInstance->State = MmcHwInitializationState;
  86. MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);
  87. if (MmcHostInstance->BlockIo.Media == NULL) {
  88. goto FREE_INSTANCE;
  89. }
  90. MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;
  91. MmcHostInstance->BlockIo.Reset = MmcReset;
  92. MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;
  93. MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;
  94. MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;
  95. MmcHostInstance->MmcHost = MmcHost;
  96. // Create DevicePath for the new MMC Host
  97. Status = MmcHost->BuildDevicePath(&NewDevicePathNode);
  98. if (EFI_ERROR (Status)) {
  99. goto FREE_MEDIA;
  100. }
  101. DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
  102. if (DevicePath == NULL) {
  103. goto FREE_MEDIA;
  104. }
  105. SetDevicePathEndNode (DevicePath);
  106. MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);
  107. // Publish BlockIO protocol interface
  108. Status = gBS->InstallMultipleProtocolInterfaces (
  109. &MmcHostInstance->MmcHandle,
  110. &gEfiBlockIoProtocolGuid,&MmcHostInstance->BlockIo,
  111. &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,
  112. NULL
  113. );
  114. if (EFI_ERROR(Status)) {
  115. goto FREE_DEVICE_PATH;
  116. }
  117. return MmcHostInstance;
  118. FREE_DEVICE_PATH:
  119. FreePool(DevicePath);
  120. FREE_MEDIA:
  121. FreePool(MmcHostInstance->BlockIo.Media);
  122. FREE_INSTANCE:
  123. FreePool(MmcHostInstance);
  124. return NULL;
  125. }
  126. EFI_STATUS DestroyMmcHostInstance (
  127. IN MMC_HOST_INSTANCE* MmcHostInstance
  128. )
  129. {
  130. EFI_STATUS Status;
  131. // Uninstall Protocol Interfaces
  132. Status = gBS->UninstallMultipleProtocolInterfaces (
  133. MmcHostInstance->MmcHandle,
  134. &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),
  135. &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,
  136. NULL
  137. );
  138. ASSERT_EFI_ERROR (Status);
  139. // Free Memory allocated for the instance
  140. if (MmcHostInstance->BlockIo.Media) {
  141. FreePool(MmcHostInstance->BlockIo.Media);
  142. }
  143. FreePool (MmcHostInstance);
  144. return Status;
  145. }
  146. /**
  147. This function checks if the controller implement the Mmc Host and the Device Path Protocols
  148. **/
  149. EFI_STATUS
  150. EFIAPI
  151. MmcDriverBindingSupported (
  152. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  153. IN EFI_HANDLE Controller,
  154. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  155. )
  156. {
  157. EFI_STATUS Status;
  158. //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  159. EFI_MMC_HOST_PROTOCOL *MmcHost;
  160. EFI_DEV_PATH_PTR Node;
  161. //
  162. // Check RemainingDevicePath validation
  163. //
  164. if (RemainingDevicePath != NULL) {
  165. //
  166. // Check if RemainingDevicePath is the End of Device Path Node,
  167. // if yes, go on checking other conditions
  168. //
  169. if (!IsDevicePathEnd (RemainingDevicePath)) {
  170. //
  171. // If RemainingDevicePath isn't the End of Device Path Node,
  172. // check its validation
  173. //
  174. Node.DevPath = RemainingDevicePath;
  175. if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
  176. Node.DevPath->SubType != HW_VENDOR_DP ||
  177. DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {
  178. return EFI_UNSUPPORTED;
  179. }
  180. }
  181. }
  182. //
  183. // Check if Mmc Host protocol is installed by platform
  184. //
  185. Status = gBS->OpenProtocol (
  186. Controller,
  187. &gEfiMmcHostProtocolGuid,
  188. (VOID **) &MmcHost,
  189. This->DriverBindingHandle,
  190. Controller,
  191. EFI_OPEN_PROTOCOL_BY_DRIVER
  192. );
  193. if (Status == EFI_ALREADY_STARTED) {
  194. return EFI_SUCCESS;
  195. }
  196. if (EFI_ERROR (Status)) {
  197. return Status;
  198. }
  199. //
  200. // Close the Mmc Host used to perform the supported test
  201. //
  202. gBS->CloseProtocol (
  203. Controller,
  204. &gEfiMmcHostProtocolGuid,
  205. This->DriverBindingHandle,
  206. Controller
  207. );
  208. return EFI_SUCCESS;
  209. }
  210. /**
  211. **/
  212. EFI_STATUS
  213. EFIAPI
  214. MmcDriverBindingStart (
  215. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  216. IN EFI_HANDLE Controller,
  217. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  218. )
  219. {
  220. EFI_STATUS Status;
  221. MMC_HOST_INSTANCE *MmcHostInstance;
  222. EFI_MMC_HOST_PROTOCOL *MmcHost;
  223. //
  224. // Check RemainingDevicePath validation
  225. //
  226. if (RemainingDevicePath != NULL) {
  227. //
  228. // Check if RemainingDevicePath is the End of Device Path Node,
  229. // if yes, return EFI_SUCCESS
  230. //
  231. if (IsDevicePathEnd (RemainingDevicePath)) {
  232. return EFI_SUCCESS;
  233. }
  234. }
  235. //
  236. // Get the Mmc Host protocol
  237. //
  238. Status = gBS->OpenProtocol (
  239. Controller,
  240. &gEfiMmcHostProtocolGuid,
  241. (VOID **) &MmcHost,
  242. This->DriverBindingHandle,
  243. Controller,
  244. EFI_OPEN_PROTOCOL_BY_DRIVER
  245. );
  246. if (EFI_ERROR (Status)) {
  247. if (Status == EFI_ALREADY_STARTED) {
  248. return EFI_SUCCESS;
  249. }
  250. return Status;
  251. }
  252. MmcHostInstance = CreateMmcHostInstance(MmcHost);
  253. if (MmcHostInstance != NULL) {
  254. // Add the handle to the pool
  255. InsertMmcHost (MmcHostInstance);
  256. MmcHostInstance->Initialized = FALSE;
  257. // Detect card presence now
  258. CheckCardsCallback (NULL, NULL);
  259. }
  260. return EFI_SUCCESS;
  261. }
  262. /**
  263. **/
  264. EFI_STATUS
  265. EFIAPI
  266. MmcDriverBindingStop (
  267. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  268. IN EFI_HANDLE Controller,
  269. IN UINTN NumberOfChildren,
  270. IN EFI_HANDLE *ChildHandleBuffer
  271. )
  272. {
  273. EFI_STATUS Status = EFI_SUCCESS;
  274. LIST_ENTRY *CurrentLink;
  275. MMC_HOST_INSTANCE *MmcHostInstance;
  276. MMC_TRACE("MmcDriverBindingStop()");
  277. // For each MMC instance
  278. CurrentLink = mMmcHostPool.ForwardLink;
  279. while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {
  280. MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);
  281. ASSERT(MmcHostInstance != NULL);
  282. // Close gEfiMmcHostProtocolGuid
  283. Status = gBS->CloseProtocol (
  284. Controller,
  285. &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,
  286. This->DriverBindingHandle
  287. );
  288. // Remove MMC Host Instance from the pool
  289. RemoveMmcHost (MmcHostInstance);
  290. // Destroy MmcHostInstance
  291. DestroyMmcHostInstance (MmcHostInstance);
  292. }
  293. return Status;
  294. }
  295. VOID
  296. EFIAPI
  297. CheckCardsCallback (
  298. IN EFI_EVENT Event,
  299. IN VOID *Context
  300. )
  301. {
  302. LIST_ENTRY *CurrentLink;
  303. MMC_HOST_INSTANCE *MmcHostInstance;
  304. EFI_STATUS Status;
  305. CurrentLink = mMmcHostPool.ForwardLink;
  306. while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) {
  307. MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);
  308. ASSERT(MmcHostInstance != NULL);
  309. if (MmcHostInstance->MmcHost->IsCardPresent() == !MmcHostInstance->Initialized) {
  310. MmcHostInstance->State = MmcHwInitializationState;
  311. MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;
  312. MmcHostInstance->Initialized = !MmcHostInstance->Initialized;
  313. if(MmcHostInstance->BlockIo.Media->MediaPresent) {
  314. InitializeMmcDevice(MmcHostInstance);
  315. }
  316. Status = gBS->ReinstallProtocolInterface (
  317. (MmcHostInstance->MmcHandle),
  318. &gEfiBlockIoProtocolGuid,
  319. &(MmcHostInstance->BlockIo),
  320. &(MmcHostInstance->BlockIo)
  321. );
  322. if (EFI_ERROR(Status)) {
  323. Print(L"MMC Card: Error reinstalling BlockIo interface\n");
  324. }
  325. }
  326. CurrentLink = CurrentLink->ForwardLink;
  327. }
  328. }
  329. EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {
  330. MmcDriverBindingSupported,
  331. MmcDriverBindingStart,
  332. MmcDriverBindingStop,
  333. 0xa,
  334. NULL,
  335. NULL
  336. };
  337. /**
  338. **/
  339. EFI_STATUS
  340. EFIAPI
  341. MmcDxeInitialize (
  342. IN EFI_HANDLE ImageHandle,
  343. IN EFI_SYSTEM_TABLE *SystemTable
  344. )
  345. {
  346. EFI_STATUS Status;
  347. //
  348. // Initializes MMC Host pool
  349. //
  350. InitializeMmcHostPool ();
  351. //
  352. // Install driver model protocol(s).
  353. //
  354. Status = EfiLibInstallDriverBindingComponentName2 (
  355. ImageHandle,
  356. SystemTable,
  357. &gMmcDriverBinding,
  358. ImageHandle,
  359. &gMmcComponentName,
  360. &gMmcComponentName2
  361. );
  362. ASSERT_EFI_ERROR (Status);
  363. // Install driver diagnostics
  364. Status = gBS->InstallMultipleProtocolInterfaces (
  365. &ImageHandle,
  366. &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,
  367. NULL
  368. );
  369. ASSERT_EFI_ERROR (Status);
  370. // Use a timer to detect if a card has been plugged in or removed
  371. Status = gBS->CreateEvent (
  372. EVT_NOTIFY_SIGNAL | EVT_TIMER,
  373. TPL_CALLBACK,
  374. CheckCardsCallback,
  375. NULL,
  376. &gCheckCardsEvent);
  377. ASSERT_EFI_ERROR (Status);
  378. Status = gBS->SetTimer(
  379. gCheckCardsEvent,
  380. TimerPeriodic,
  381. (UINT64)(10*1000*200)); // 200 ms
  382. ASSERT_EFI_ERROR (Status);
  383. return Status;
  384. }