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