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