TianoCore EDK2 master
Loading...
Searching...
No Matches
MmcBlockIo.c
Go to the documentation of this file.
1
10
11#include "Mmc.h"
12
14MmcNotifyState (
15 IN MMC_HOST_INSTANCE *MmcHostInstance,
16 IN MMC_STATE State
17 )
18{
19 MmcHostInstance->State = State;
20 return MmcHostInstance->MmcHost->NotifyState (MmcHostInstance->MmcHost, State);
21}
22
24EFIAPI
25MmcGetCardStatus (
26 IN MMC_HOST_INSTANCE *MmcHostInstance
27 )
28{
29 EFI_STATUS Status;
30 UINT32 Response[4];
31 UINTN CmdArg;
32 EFI_MMC_HOST_PROTOCOL *MmcHost;
33
34 Status = EFI_SUCCESS;
35 MmcHost = MmcHostInstance->MmcHost;
36 CmdArg = 0;
37
38 if (MmcHost == NULL) {
39 return EFI_INVALID_PARAMETER;
40 }
41
42 if (MmcHostInstance->State != MmcHwInitializationState) {
43 // Get the Status of the card.
44 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
45 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
46 if (EFI_ERROR (Status)) {
47 DEBUG ((DEBUG_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));
48 return Status;
49 }
50
51 // Read Response
52 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
53 PrintResponseR1 (Response[0]);
54 }
55
56 return Status;
57}
58
60EFIAPI
63 IN BOOLEAN ExtendedVerification
64 )
65{
66 MMC_HOST_INSTANCE *MmcHostInstance;
67
68 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
69
70 if (MmcHostInstance->MmcHost == NULL) {
71 // Nothing to do
72 return EFI_SUCCESS;
73 }
74
75 // If a card is not present then clear all media settings
76 if (!MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost)) {
77 MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
78 MmcHostInstance->BlockIo.Media->LastBlock = 0;
79 MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo
80 MmcHostInstance->BlockIo.Media->ReadOnly = FALSE;
81
82 // Indicate that the driver requires initialization
83 MmcHostInstance->State = MmcHwInitializationState;
84
85 return EFI_SUCCESS;
86 }
87
88 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
89 // on power and restart Identification mode
90 return EFI_SUCCESS;
91}
92
94MmcDetectCard (
96 )
97{
98 if (!MmcHost->IsCardPresent (MmcHost)) {
99 return EFI_NO_MEDIA;
100 } else {
101 return EFI_SUCCESS;
102 }
103}
104
106MmcStopTransmission (
107 EFI_MMC_HOST_PROTOCOL *MmcHost
108 )
109{
110 EFI_STATUS Status;
111 UINT32 Response[4];
112
113 // Command 12 - Stop transmission (ends read or write)
114 // Normally only needed for streaming transfers or after error.
115 Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
116 if (!EFI_ERROR (Status)) {
117 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1b, Response);
118 }
119
120 return Status;
121}
122
123#define MMCI0_BLOCKLEN 512
124#define MMCI0_TIMEOUT 10000
125
126STATIC
128MmcTransferBlock (
130 IN UINTN Cmd,
131 IN UINTN Transfer,
132 IN UINT32 MediaId,
133 IN EFI_LBA Lba,
134 IN UINTN BufferSize,
135 OUT VOID *Buffer
136 )
137{
138 EFI_STATUS Status;
139 UINTN CmdArg;
140 INTN Timeout;
141 UINT32 Response[4];
142 MMC_HOST_INSTANCE *MmcHostInstance;
143 EFI_MMC_HOST_PROTOCOL *MmcHost;
144
145 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
146 MmcHost = MmcHostInstance->MmcHost;
147
148 if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
149 // Set command argument based on the card capacity
150 // if 0 : SDSC card
151 // if 1 : SDXC/SDHC
152 if (MmcHostInstance->CardInfo.OCRData.AccessMode & SD_CARD_CAPACITY) {
153 CmdArg = Lba;
154 } else {
155 CmdArg = MultU64x32 (Lba, This->Media->BlockSize);
156 }
157 } else {
158 // Set command argument based on the card access mode (Byte mode or Block mode)
159 if ((MmcHostInstance->CardInfo.OCRData.AccessMode & MMC_OCR_ACCESS_MASK) ==
160 MMC_OCR_ACCESS_SECTOR)
161 {
162 CmdArg = Lba;
163 } else {
164 CmdArg = MultU64x32 (Lba, This->Media->BlockSize);
165 }
166 }
167
168 Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
169 if (EFI_ERROR (Status)) {
170 DEBUG ((DEBUG_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
171 return Status;
172 }
173
174 if (Transfer == MMC_IOBLOCKS_READ) {
175 // Read Data
176 Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
177 if (EFI_ERROR (Status)) {
178 DEBUG ((DEBUG_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
179 MmcStopTransmission (MmcHost);
180 return Status;
181 }
182
183 Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
184 if (EFI_ERROR (Status)) {
185 DEBUG ((DEBUG_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
186 return Status;
187 }
188 } else {
189 // Write Data
190 Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
191 if (EFI_ERROR (Status)) {
192 DEBUG ((DEBUG_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
193 MmcStopTransmission (MmcHost);
194 return Status;
195 }
196 }
197
198 // Command 13 - Read status and wait for programming to complete (return to tran)
199 Timeout = MMCI0_TIMEOUT;
200 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
201 Response[0] = 0;
202 while ( !(Response[0] & MMC_R0_READY_FOR_DATA)
203 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
204 && Timeout--)
205 {
206 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
207 if (!EFI_ERROR (Status)) {
208 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
209 if (Response[0] & MMC_R0_READY_FOR_DATA) {
210 break; // Prevents delay once finished
211 }
212 }
213 }
214
215 if (BufferSize > This->Media->BlockSize) {
216 Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
217 if (EFI_ERROR (Status)) {
218 DEBUG ((DEBUG_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
219 }
220
221 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1b, Response);
222 }
223
224 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
225 if (EFI_ERROR (Status)) {
226 DEBUG ((DEBUG_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
227 return Status;
228 }
229
230 return Status;
231}
232
234MmcIoBlocks (
236 IN UINTN Transfer,
237 IN UINT32 MediaId,
238 IN EFI_LBA Lba,
239 IN UINTN BufferSize,
240 OUT VOID *Buffer
241 )
242{
243 UINT32 Response[4];
244 EFI_STATUS Status;
245 UINTN CmdArg;
246 INTN Timeout;
247 UINTN Cmd;
248 MMC_HOST_INSTANCE *MmcHostInstance;
249 EFI_MMC_HOST_PROTOCOL *MmcHost;
250 UINTN BytesRemainingToBeTransfered;
251 UINTN BlockCount;
252 UINTN ConsumeSize;
253 UINT32 MaxBlock;
254 UINTN RemainingBlock;
255
256 BlockCount = 1;
257 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
258 ASSERT (MmcHostInstance != NULL);
259 MmcHost = MmcHostInstance->MmcHost;
260 ASSERT (MmcHost);
261
262 if (This->Media->MediaId != MediaId) {
263 return EFI_MEDIA_CHANGED;
264 }
265
266 if ((MmcHost == NULL) || (Buffer == NULL)) {
267 return EFI_INVALID_PARAMETER;
268 }
269
270 // Check if a Card is Present
271 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
272 return EFI_NO_MEDIA;
273 }
274
275 // Reading 0 Byte is valid
276 if (BufferSize == 0) {
277 return EFI_SUCCESS;
278 }
279
280 // The buffer size must be an exact multiple of the block size
281 if ((BufferSize % This->Media->BlockSize) != 0) {
282 return EFI_BAD_BUFFER_SIZE;
283 }
284
285 if (MMC_HOST_HAS_ISMULTIBLOCK (MmcHost) && MmcHost->IsMultiBlock (MmcHost)) {
286 BlockCount = BufferSize / This->Media->BlockSize;
287 }
288
289 // All blocks must be within the device
290 if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
291 return EFI_INVALID_PARAMETER;
292 }
293
294 if ((Transfer == MMC_IOBLOCKS_WRITE) && (This->Media->ReadOnly == TRUE)) {
295 return EFI_WRITE_PROTECTED;
296 }
297
298 // Check the alignment
299 if ((This->Media->IoAlign > 2) && (((UINTN)Buffer & (This->Media->IoAlign - 1)) != 0)) {
300 return EFI_INVALID_PARAMETER;
301 }
302
303 // Max block number in single cmd is 65535 blocks.
304 MaxBlock = 0xFFFF;
305 RemainingBlock = BlockCount;
306 BytesRemainingToBeTransfered = BufferSize;
307 while (BytesRemainingToBeTransfered > 0) {
308 if (RemainingBlock <= MaxBlock) {
309 BlockCount = RemainingBlock;
310 } else {
311 BlockCount = MaxBlock;
312 }
313
314 // Check if the Card is in Ready status
315 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
316 Response[0] = 0;
317 Timeout = 20;
318 while ( (!(Response[0] & MMC_R0_READY_FOR_DATA))
319 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
320 && Timeout--)
321 {
322 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
323 if (!EFI_ERROR (Status)) {
324 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
325 }
326 }
327
328 if (0 == Timeout) {
329 DEBUG ((DEBUG_ERROR, "The Card is busy\n"));
330 return EFI_NOT_READY;
331 }
332
333 if (Transfer == MMC_IOBLOCKS_READ) {
334 if (BlockCount == 1) {
335 // Read a single block
336 Cmd = MMC_CMD17;
337 } else {
338 // Read multiple blocks
339 Cmd = MMC_CMD18;
340 }
341 } else {
342 if (BlockCount == 1) {
343 // Write a single block
344 Cmd = MMC_CMD24;
345 } else {
346 // Write multiple blocks
347 Cmd = MMC_CMD25;
348 }
349 }
350
351 ConsumeSize = BlockCount * This->Media->BlockSize;
352 if (BytesRemainingToBeTransfered < ConsumeSize) {
353 ConsumeSize = BytesRemainingToBeTransfered;
354 }
355
356 Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
357 if (EFI_ERROR (Status)) {
358 DEBUG ((DEBUG_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
359 }
360
361 RemainingBlock -= BlockCount;
362 BytesRemainingToBeTransfered -= ConsumeSize;
363 if (BytesRemainingToBeTransfered > 0) {
364 Lba += BlockCount;
365 Buffer = (UINT8 *)Buffer + ConsumeSize;
366 }
367 }
368
369 return EFI_SUCCESS;
370}
371
373EFIAPI
376 IN UINT32 MediaId,
377 IN EFI_LBA Lba,
378 IN UINTN BufferSize,
379 OUT VOID *Buffer
380 )
381{
382 return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);
383}
384
386EFIAPI
389 IN UINT32 MediaId,
390 IN EFI_LBA Lba,
391 IN UINTN BufferSize,
392 IN VOID *Buffer
393 )
394{
395 return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);
396}
397
399EFIAPI
402 )
403{
404 return EFI_SUCCESS;
405}
UINT64 UINTN
INT64 INTN
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_STATUS EFIAPI MmcFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL *This)
Definition: MmcBlockIo.c:400
EFI_STATUS EFIAPI MmcReadBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: MmcBlockIo.c:374
EFI_STATUS EFIAPI MmcWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer)
Definition: MmcBlockIo.c:387
EFI_STATUS EFIAPI MmcReset(IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: MmcBlockIo.c:61
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:224
UINT32 BlockSize
Definition: BlockIo.h:167
EFI_LBA LastBlock
Definition: BlockIo.h:178
BOOLEAN MediaPresent
Definition: BlockIo.h:144
BOOLEAN ReadOnly
Definition: BlockIo.h:156