]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
ArmPlatformPkg/PL180MciDxe: Clean code
[mirror_edk2.git] / ArmPlatformPkg / Drivers / PL180MciDxe / PL180Mci.c
... / ...
CommitLineData
1/** @file\r
2 This file implement the MMC Host Protocol for the ARM PrimeCell PL180.\r
3\r
4 Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
5 \r
6 This program and the accompanying materials \r
7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
9 http://opensource.org/licenses/bsd-license.php \r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include "PL180Mci.h"\r
17\r
18#include <Library/DevicePathLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20\r
21EFI_MMC_HOST_PROTOCOL *gpMmcHost;\r
22\r
23// Untested ...\r
24//#define USE_STREAM\r
25\r
26#define MMCI0_BLOCKLEN 512\r
27#define MMCI0_POW2_BLOCKLEN 9\r
28#define MMCI0_TIMEOUT 1000\r
29\r
30#define SYS_MCI_CARDIN BIT0\r
31#define SYS_MCI_WPROT BIT1\r
32\r
33BOOLEAN\r
34MciIsPowerOn (\r
35 VOID\r
36 )\r
37{\r
38 return ((MmioRead32 (MCI_POWER_CONTROL_REG) & MCI_POWER_ON) == MCI_POWER_ON);\r
39}\r
40\r
41EFI_STATUS\r
42MciInitialize (\r
43 VOID\r
44 )\r
45{\r
46 MCI_TRACE ("MciInitialize()");\r
47 return EFI_SUCCESS;\r
48}\r
49\r
50BOOLEAN\r
51MciIsCardPresent (\r
52 IN EFI_MMC_HOST_PROTOCOL *This\r
53 )\r
54{\r
55 return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_CARDIN);\r
56}\r
57\r
58BOOLEAN\r
59MciIsReadOnly (\r
60 IN EFI_MMC_HOST_PROTOCOL *This\r
61 )\r
62{\r
63 return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);\r
64}\r
65\r
66#if 0\r
67//Note: This function has been commented out because it is not used yet.\r
68// This function could be used to remove the hardcoded BlockLen used\r
69// in MciPrepareDataPath\r
70\r
71// Convert block size to 2^n\r
72STATIC\r
73UINT32\r
74GetPow2BlockLen (\r
75 IN UINT32 BlockLen\r
76 )\r
77{\r
78 UINTN Loop;\r
79 UINTN Pow2BlockLen;\r
80\r
81 Loop = 0x8000;\r
82 Pow2BlockLen = 15;\r
83 do {\r
84 Loop = (Loop >> 1) & 0xFFFF;\r
85 Pow2BlockLen--;\r
86 } while (Pow2BlockLen && (!(Loop & BlockLen)));\r
87\r
88 return Pow2BlockLen;\r
89}\r
90#endif\r
91\r
92VOID\r
93MciPrepareDataPath (\r
94 IN UINTN TransferDirection\r
95 )\r
96{\r
97 // Set Data Length & Data Timer\r
98 MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);\r
99 MmioWrite32 (MCI_DATA_LENGTH_REG, MMCI0_BLOCKLEN);\r
100\r
101#ifndef USE_STREAM\r
102 //Note: we are using a hardcoded BlockLen (==512). If we decide to use a variable size, we could\r
103 // compute the pow2 of BlockLen with the above function GetPow2BlockLen ()\r
104 MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));\r
105#else\r
106 MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);\r
107#endif\r
108}\r
109\r
110EFI_STATUS\r
111MciSendCommand (\r
112 IN EFI_MMC_HOST_PROTOCOL *This,\r
113 IN MMC_CMD MmcCmd,\r
114 IN UINT32 Argument\r
115 )\r
116{\r
117 UINT32 Status;\r
118 UINT32 Cmd;\r
119 UINTN RetVal;\r
120 UINTN CmdCtrlReg;\r
121 UINT32 DoneMask;\r
122\r
123 RetVal = EFI_SUCCESS;\r
124\r
125 if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {\r
126 MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);\r
127 } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {\r
128 MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);\r
129 }\r
130\r
131 // Create Command for PL180\r
132 Cmd = (MMC_GET_INDX (MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLE;\r
133 if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {\r
134 Cmd |= MCI_CPSM_WAIT_RESPONSE;\r
135 }\r
136\r
137 if (MmcCmd & MMC_CMD_LONG_RESPONSE) {\r
138 Cmd |= MCI_CPSM_LONG_RESPONSE;\r
139 }\r
140\r
141 // Clear Status register static flags\r
142 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
143\r
144 // Write to command argument register\r
145 MmioWrite32 (MCI_ARGUMENT_REG, Argument);\r
146\r
147 // Write to command register\r
148 MmioWrite32 (MCI_COMMAND_REG, Cmd);\r
149\r
150 DoneMask = (Cmd & MCI_CPSM_WAIT_RESPONSE)\r
151 ? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)\r
152 : (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_ERROR);\r
153 do {\r
154 Status = MmioRead32 (MCI_STATUS_REG);\r
155 } while (! (Status & DoneMask));\r
156\r
157 if ((Status & MCI_STATUS_CMD_ERROR)) {\r
158 // Clear Status register error flags\r
159 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);\r
160 \r
161 if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
162 DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
163 RetVal = EFI_NO_RESPONSE;\r
164 } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
165 //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
166 RetVal = EFI_TIMEOUT;\r
167 } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
168 // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.\r
169 RetVal = EFI_CRC_ERROR;\r
170 }\r
171 }\r
172\r
173 // Disable Command Path\r
174 CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);\r
175 MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));\r
176 return RetVal;\r
177}\r
178\r
179EFI_STATUS\r
180MciReceiveResponse (\r
181 IN EFI_MMC_HOST_PROTOCOL *This,\r
182 IN MMC_RESPONSE_TYPE Type,\r
183 IN UINT32* Buffer\r
184 )\r
185{\r
186 if (Buffer == NULL) {\r
187 return EFI_INVALID_PARAMETER;\r
188 }\r
189\r
190 if ( (Type == MMC_RESPONSE_TYPE_R1)\r
191 || (Type == MMC_RESPONSE_TYPE_R1b)\r
192 || (Type == MMC_RESPONSE_TYPE_R3)\r
193 || (Type == MMC_RESPONSE_TYPE_R6)\r
194 || (Type == MMC_RESPONSE_TYPE_R7))\r
195 {\r
196 Buffer[0] = MmioRead32 (MCI_RESPONSE3_REG);\r
197 } else if (Type == MMC_RESPONSE_TYPE_R2) {\r
198 Buffer[0] = MmioRead32 (MCI_RESPONSE0_REG);\r
199 Buffer[1] = MmioRead32 (MCI_RESPONSE1_REG);\r
200 Buffer[2] = MmioRead32 (MCI_RESPONSE2_REG);\r
201 Buffer[3] = MmioRead32 (MCI_RESPONSE3_REG);\r
202 }\r
203\r
204 return EFI_SUCCESS;\r
205}\r
206\r
207EFI_STATUS\r
208MciReadBlockData (\r
209 IN EFI_MMC_HOST_PROTOCOL *This,\r
210 IN EFI_LBA Lba,\r
211 IN UINTN Length,\r
212 IN UINT32* Buffer\r
213 )\r
214{\r
215 UINTN Loop;\r
216 UINTN Finish;\r
217 UINTN Status;\r
218 EFI_STATUS RetVal;\r
219 UINTN DataCtrlReg;\r
220\r
221 RetVal = EFI_SUCCESS;\r
222\r
223 // Read data from the RX FIFO\r
224 Loop = 0;\r
225 Finish = MMCI0_BLOCKLEN / 4;\r
226 do {\r
227 // Read the Status flags\r
228 Status = MmioRead32 (MCI_STATUS_REG);\r
229\r
230 // Do eight reads if possible else a single read\r
231 if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {\r
232 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
233 Loop++;\r
234 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
235 Loop++;\r
236 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
237 Loop++;\r
238 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
239 Loop++;\r
240 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
241 Loop++;\r
242 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
243 Loop++;\r
244 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
245 Loop++;\r
246 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
247 Loop++;\r
248 } else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {\r
249 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
250 Loop++;\r
251 } else {\r
252 //Check for error conditions and timeouts\r
253 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
254 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
255 RetVal = EFI_TIMEOUT;\r
256 break;\r
257 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
258 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
259 RetVal = EFI_CRC_ERROR;\r
260 break;\r
261 } else if (Status & MCI_STATUS_CMD_START_BIT_ERROR) {\r
262 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
263 RetVal = EFI_NO_RESPONSE;\r
264 break;\r
265 }\r
266 }\r
267 //clear RX over run flag\r
268 if(Status & MCI_STATUS_CMD_RXOVERRUN) {\r
269 MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);\r
270 }\r
271 } while ((Loop < Finish));\r
272\r
273 // Clear Status flags\r
274 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
275\r
276 //Disable Data path\r
277 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
278 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
279\r
280 return RetVal;\r
281}\r
282\r
283EFI_STATUS\r
284MciWriteBlockData (\r
285 IN EFI_MMC_HOST_PROTOCOL *This,\r
286 IN EFI_LBA Lba,\r
287 IN UINTN Length,\r
288 IN UINT32* Buffer\r
289 )\r
290{\r
291 UINTN Loop;\r
292 UINTN Finish;\r
293 UINTN Timer;\r
294 UINTN Status;\r
295 EFI_STATUS RetVal;\r
296 UINTN DataCtrlReg;\r
297\r
298 RetVal = EFI_SUCCESS;\r
299\r
300 // Write the data to the TX FIFO\r
301 Loop = 0;\r
302 Finish = MMCI0_BLOCKLEN / 4;\r
303 Timer = MMCI0_TIMEOUT * 100;\r
304 do {\r
305 // Read the Status flags\r
306 Status = MmioRead32 (MCI_STATUS_REG);\r
307\r
308 // Do eight writes if possible else a single write\r
309 if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {\r
310 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
311 Loop++;\r
312 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
313 Loop++;\r
314 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
315 Loop++;\r
316 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
317 Loop++;\r
318 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
319 Loop++;\r
320 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
321 Loop++;\r
322 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
323 Loop++;\r
324 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
325 Loop++;\r
326 } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {\r
327 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
328 Loop++;\r
329 } else {\r
330 // Check for error conditions and timeouts\r
331 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
332 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
333 RetVal = EFI_TIMEOUT;\r
334 goto Exit;\r
335 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
336 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
337 RetVal = EFI_CRC_ERROR;\r
338 goto Exit;\r
339 } else if (Status & MCI_STATUS_CMD_TX_UNDERRUN) {\r
340 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TX buffer Underrun! Response:0x%X Status:0x%x, Number of bytes written 0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status, Loop));\r
341 RetVal = EFI_BUFFER_TOO_SMALL;\r
342 ASSERT(0);\r
343 goto Exit;\r
344 }\r
345 }\r
346 } while (Loop < Finish);\r
347\r
348 // Wait for FIFO to drain\r
349 Timer = MMCI0_TIMEOUT * 60;\r
350 Status = MmioRead32 (MCI_STATUS_REG);\r
351#ifndef USE_STREAM\r
352 // Single block\r
353 while (((Status & MCI_STATUS_TXDONE) != MCI_STATUS_TXDONE) && Timer) {\r
354#else\r
355 // Stream\r
356 while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {\r
357#endif\r
358 NanoSecondDelay(10);\r
359 Status = MmioRead32 (MCI_STATUS_REG);\r
360 Timer--;\r
361 }\r
362\r
363 // Clear Status flags\r
364 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
365\r
366 if (Timer == 0) {\r
367 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));\r
368 RetVal = EFI_TIMEOUT;\r
369 }\r
370\r
371Exit:\r
372 // Disable Data path\r
373 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
374 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
375 return RetVal;\r
376}\r
377\r
378EFI_STATUS\r
379MciNotifyState (\r
380 IN EFI_MMC_HOST_PROTOCOL *This,\r
381 IN MMC_STATE State\r
382 )\r
383{\r
384 UINT32 Data32;\r
385\r
386 switch (State) {\r
387 case MmcInvalidState:\r
388 ASSERT (0);\r
389 break;\r
390 case MmcHwInitializationState:\r
391 // If device already turn on then restart it\r
392 Data32 = MmioRead32 (MCI_POWER_CONTROL_REG);\r
393 if ((Data32 & 0x2) == MCI_POWER_UP) {\r
394 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOff MCI");\r
395\r
396 // Turn off\r
397 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0);\r
398 MmioWrite32 (MCI_POWER_CONTROL_REG, 0);\r
399 MicroSecondDelay (100);\r
400 }\r
401\r
402 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOn MCI");\r
403 // Setup clock\r
404 // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz\r
405 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
406\r
407 // Set the voltage\r
408 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));\r
409 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);\r
410 MicroSecondDelay (10);\r
411 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);\r
412 MicroSecondDelay (100);\r
413\r
414 // Set Data Length & Data Timer\r
415 MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFF);\r
416 MmioWrite32 (MCI_DATA_LENGTH_REG, 8);\r
417\r
418 ASSERT ((MmioRead32 (MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);\r
419 break;\r
420 case MmcIdleState:\r
421 MCI_TRACE ("MciNotifyState(MmcIdleState)");\r
422 break;\r
423 case MmcReadyState:\r
424 MCI_TRACE ("MciNotifyState(MmcReadyState)");\r
425 break;\r
426 case MmcIdentificationState:\r
427 MCI_TRACE ("MciNotifyState (MmcIdentificationState)");\r
428 break;\r
429 case MmcStandByState:{\r
430 volatile UINT32 PwrCtrlReg;\r
431 MCI_TRACE ("MciNotifyState (MmcStandByState)");\r
432\r
433 // Enable MCICMD push-pull drive\r
434 PwrCtrlReg = MmioRead32 (MCI_POWER_CONTROL_REG);\r
435 //Disable Open Drain output\r
436 PwrCtrlReg &= ~ (MCI_POWER_OPENDRAIN);\r
437 MmioWrite32 (MCI_POWER_CONTROL_REG, PwrCtrlReg);\r
438\r
439 // Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)\r
440 //\r
441 // Note: Increasing clock speed causes TX FIFO under-run errors.\r
442 // So careful when optimising this driver for higher performance.\r
443 //\r
444 MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
445 // Set MMCI0 clock to 24MHz (by bypassing the divider)\r
446 //MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);\r
447 break;\r
448 }\r
449 case MmcTransferState:\r
450 //MCI_TRACE ("MciNotifyState(MmcTransferState)");\r
451 break;\r
452 case MmcSendingDataState:\r
453 MCI_TRACE ("MciNotifyState(MmcSendingDataState)");\r
454 break;\r
455 case MmcReceiveDataState:\r
456 MCI_TRACE ("MciNotifyState(MmcReceiveDataState)");\r
457 break;\r
458 case MmcProgrammingState:\r
459 MCI_TRACE ("MciNotifyState(MmcProgrammingState)");\r
460 break;\r
461 case MmcDisconnectState:\r
462 MCI_TRACE ("MciNotifyState(MmcDisconnectState)");\r
463 break;\r
464 default:\r
465 ASSERT (0);\r
466 }\r
467 return EFI_SUCCESS;\r
468}\r
469\r
470EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;\r
471\r
472EFI_STATUS\r
473MciBuildDevicePath (\r
474 IN EFI_MMC_HOST_PROTOCOL *This,\r
475 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
476 )\r
477{\r
478 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
479\r
480 NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));\r
481 CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mPL180MciDevicePathGuid);\r
482\r
483 *DevicePath = NewDevicePathNode;\r
484 return EFI_SUCCESS;\r
485}\r
486\r
487EFI_MMC_HOST_PROTOCOL gMciHost = {\r
488 MMC_HOST_PROTOCOL_REVISION,\r
489 MciIsCardPresent,\r
490 MciIsReadOnly,\r
491 MciBuildDevicePath,\r
492 MciNotifyState,\r
493 MciSendCommand,\r
494 MciReceiveResponse,\r
495 MciReadBlockData,\r
496 MciWriteBlockData\r
497};\r
498\r
499EFI_STATUS\r
500PL180MciDxeInitialize (\r
501 IN EFI_HANDLE ImageHandle,\r
502 IN EFI_SYSTEM_TABLE *SystemTable\r
503 )\r
504{\r
505 EFI_STATUS Status;\r
506 EFI_HANDLE Handle;\r
507\r
508 Handle = NULL;\r
509\r
510 MCI_TRACE ("PL180MciDxeInitialize()");\r
511\r
512 //Publish Component Name, BlockIO protocol interfaces\r
513 Status = gBS->InstallMultipleProtocolInterfaces (\r
514 &Handle, \r
515 &gEfiMmcHostProtocolGuid, &gMciHost,\r
516 NULL\r
517 );\r
518 ASSERT_EFI_ERROR (Status);\r
519\r
520 return EFI_SUCCESS;\r
521}\r