]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
da6202983b3cf9f03135d176ba1e3520f999458e
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / MMCSDBlockIo.c
1 /** @file
2
3 Block I/O protocol for MMC/SD device
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "SDMediaDevice.h"
12
13 /**
14 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
15
16 @param This The EFI_BLOCK_IO_PROTOCOL instance.
17 @param ExtendedVerification Indicates that the driver may perform a more exhaustive.
18 verification operation of the device during reset.
19 (This parameter is ingored in this driver.)
20
21 @retval EFI_SUCCESS Success
22 **/
23 EFI_STATUS
24 EFIAPI
25 MMCSDBlockReset (
26 IN EFI_BLOCK_IO_PROTOCOL *This,
27 IN BOOLEAN ExtendedVerification
28 )
29 {
30 CARD_DATA *CardData;
31 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
32
33 CardData = CARD_DATA_FROM_THIS(This);
34 SDHostIo = CardData->SDHostIo;
35
36 return SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);
37 }
38
39 /**
40 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
41
42 @param This The EFI_BLOCK_IO_PROTOCOL instance.
43 @param MediaId The media id that the write request is for.
44 @param LBA The starting logical block address to read from on the device.
45 The caller is responsible for writing to only legitimate locations.
46 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
47 intrinsic block size of the device.
48 @param Buffer A pointer to the destination buffer for the data. The caller
49 is responsible for either having implicit or explicit ownership
50 of the buffer.
51
52 @retval EFI_SUCCESS Success
53 @retval EFI_DEVICE_ERROR Hardware Error
54 @retval EFI_INVALID_PARAMETER Parameter is error
55 @retval EFI_NO_MEDIA No media
56 @retval EFI_MEDIA_CHANGED Media Change
57 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
58 **/
59 EFI_STATUS
60 EFIAPI
61 MMCSDBlockReadBlocks (
62 IN EFI_BLOCK_IO_PROTOCOL *This,
63 IN UINT32 MediaId,
64 IN EFI_LBA LBA,
65 IN UINTN BufferSize,
66 OUT VOID *Buffer
67 )
68 {
69 EFI_STATUS Status;
70 UINT32 Address;
71 CARD_DATA *CardData;
72 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
73 UINT32 RemainingLength;
74 UINT32 TransferLength;
75 UINT8 *BufferPointer;
76 BOOLEAN SectorAddressing;
77 UINTN TotalBlock;
78
79 DEBUG((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
80 Status = EFI_SUCCESS;
81 CardData = CARD_DATA_FROM_THIS(This);
82 SDHostIo = CardData->SDHostIo;
83 if (MediaId != CardData->BlockIoMedia.MediaId) {
84 return EFI_MEDIA_CHANGED;
85 }
86
87 if (ModU64x32 (BufferSize,CardData->BlockIoMedia.BlockSize) != 0) {
88 return EFI_BAD_BUFFER_SIZE;
89 }
90 if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {
91 SectorAddressing = TRUE;
92 } else {
93 SectorAddressing = FALSE;
94 }
95 if (SectorAddressing) {
96 //
97 //Block Address
98 //
99 Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
100 } else {
101 //
102 //Byte Address
103 //
104 Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
105 }
106 TotalBlock = (UINTN) DivU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize);
107 if (LBA + TotalBlock > CardData->BlockIoMedia.LastBlock + 1) {
108 return EFI_INVALID_PARAMETER;
109 }
110
111
112 if (!Buffer) {
113 Status = EFI_INVALID_PARAMETER;
114 DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));
115 goto Done;
116 }
117
118 if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
119 Status = EFI_BAD_BUFFER_SIZE;
120 DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));
121 goto Done;
122 }
123
124 if (BufferSize == 0) {
125 Status = EFI_SUCCESS;
126 goto Done;
127 }
128
129
130
131
132 BufferPointer = Buffer;
133 RemainingLength = (UINT32)BufferSize;
134
135 while (RemainingLength > 0) {
136 if ((BufferSize > CardData->BlockIoMedia.BlockSize)) {
137 if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {
138 TransferLength = SDHostIo->HostCapability.BoundarySize;
139 } else {
140 TransferLength = RemainingLength;
141 }
142
143 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
144 if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
145 Status = SendCommand (
146 CardData,
147 SET_BLOCKLEN,
148 CardData->BlockIoMedia.BlockSize,
149 NoData,
150 NULL,
151 0,
152 ResponseR1,
153 TIMEOUT_COMMAND,
154 (UINT32*)&(CardData->CardStatus)
155 );
156 if (EFI_ERROR (Status)) {
157 break;
158 }
159 }
160 Status = SendCommand (
161 CardData,
162 SET_BLOCK_COUNT,
163 TransferLength / CardData->BlockIoMedia.BlockSize,
164 NoData,
165 NULL,
166 0,
167 ResponseR1,
168 TIMEOUT_COMMAND,
169 (UINT32*)&(CardData->CardStatus)
170 );
171 if (EFI_ERROR (Status)) {
172 break;
173 }
174 }
175 Status = SendCommand (
176 CardData,
177 READ_MULTIPLE_BLOCK,
178 Address,
179 InData,
180 CardData->AlignedBuffer,
181 TransferLength,
182 ResponseR1,
183 TIMEOUT_DATA,
184 (UINT32*)&(CardData->CardStatus)
185 );
186
187 if (EFI_ERROR (Status)) {
188 DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));
189 break;
190 }
191 } else {
192 if (RemainingLength > CardData->BlockIoMedia.BlockSize) {
193 TransferLength = CardData->BlockIoMedia.BlockSize;
194 } else {
195 TransferLength = RemainingLength;
196 }
197
198 Status = SendCommand (
199 CardData,
200 READ_SINGLE_BLOCK,
201 Address,
202 InData,
203 CardData->AlignedBuffer,
204 (UINT32)TransferLength,
205 ResponseR1,
206 TIMEOUT_DATA,
207 (UINT32*)&(CardData->CardStatus)
208 );
209 if (EFI_ERROR (Status)) {
210 DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));
211 break;
212 }
213 }
214 CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);
215
216 if (SectorAddressing) {
217 //
218 //Block Address
219 //
220 Address += TransferLength / 512;
221 } else {
222 //
223 //Byte Address
224 //
225 Address += TransferLength;
226 }
227 BufferPointer += TransferLength;
228 RemainingLength -= TransferLength;
229 }
230
231
232 if (EFI_ERROR (Status)) {
233 if ((CardData->CardType == SDMemoryCard) ||
234 (CardData->CardType == SDMemoryCard2)||
235 (CardData->CardType == SDMemoryCard2High)) {
236 SendCommand (
237 CardData,
238 STOP_TRANSMISSION,
239 0,
240 NoData,
241 NULL,
242 0,
243 ResponseR1b,
244 TIMEOUT_COMMAND,
245 (UINT32*)&(CardData->CardStatus)
246 );
247 } else {
248 SendCommand (
249 CardData,
250 STOP_TRANSMISSION,
251 0,
252 NoData,
253 NULL,
254 0,
255 ResponseR1,
256 TIMEOUT_COMMAND,
257 (UINT32*)&(CardData->CardStatus)
258 );
259 }
260
261 }
262
263
264 Done:
265 DEBUG((EFI_D_INFO, "MMCSDBlockReadBlocks: Status = %r\n", Status));
266 return Status;
267 }
268
269 /**
270 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
271
272 @param This The EFI_BLOCK_IO_PROTOCOL instance.
273 @param MediaId The media id that the write request is for.
274 @param LBA The starting logical block address to read from on the device.
275 The caller is responsible for writing to only legitimate locations.
276 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
277 intrinsic block size of the device.
278 @param Buffer A pointer to the destination buffer for the data. The caller
279 is responsible for either having implicit or explicit ownership
280 of the buffer.
281
282 @retval EFI_SUCCESS Success
283 @retval EFI_DEVICE_ERROR Hardware Error
284 @retval EFI_INVALID_PARAMETER Parameter is error
285 @retval EFI_NO_MEDIA No media
286 @retval EFI_MEDIA_CHANGED Media Change
287 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
288 **/
289 EFI_STATUS
290 EFIAPI
291 MMCSDBlockWriteBlocks (
292 IN EFI_BLOCK_IO_PROTOCOL *This,
293 IN UINT32 MediaId,
294 IN EFI_LBA LBA,
295 IN UINTN BufferSize,
296 IN VOID *Buffer
297 )
298 {
299 EFI_STATUS Status;
300 UINT32 Address;
301 CARD_DATA *CardData;
302 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
303 UINT32 RemainingLength;
304 UINT32 TransferLength;
305 UINT8 *BufferPointer;
306 BOOLEAN SectorAddressing;
307
308 DEBUG((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
309 Status = EFI_SUCCESS;
310 CardData = CARD_DATA_FROM_THIS(This);
311 SDHostIo = CardData->SDHostIo;
312 if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {
313 SectorAddressing = TRUE;
314 } else {
315 SectorAddressing = FALSE;
316 }
317 if (SectorAddressing) {
318 //
319 //Block Address
320 //
321 Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
322 } else {
323 //
324 //Byte Address
325 //
326 Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
327 }
328
329 if (!Buffer) {
330 Status = EFI_INVALID_PARAMETER;
331 DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));
332 goto Done;
333 }
334
335 if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
336 Status = EFI_BAD_BUFFER_SIZE;
337 DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));
338 goto Done;
339 }
340
341 if (BufferSize == 0) {
342 Status = EFI_SUCCESS;
343 goto Done;
344 }
345
346 if (This->Media->ReadOnly == TRUE) {
347 Status = EFI_WRITE_PROTECTED;
348 DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n"));
349 goto Done;
350 }
351
352
353
354 BufferPointer = Buffer;
355 RemainingLength = (UINT32)BufferSize;
356
357 while (RemainingLength > 0) {
358 if ((BufferSize > CardData->BlockIoMedia.BlockSize) ) {
359 if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {
360 TransferLength = SDHostIo->HostCapability.BoundarySize;
361 } else {
362 TransferLength = RemainingLength;
363 }
364
365 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {
366
367 if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {
368 Status = SendCommand (
369 CardData,
370 SET_BLOCKLEN,
371 CardData->BlockIoMedia.BlockSize,
372 NoData,
373 NULL,
374 0,
375 ResponseR1,
376 TIMEOUT_COMMAND,
377 (UINT32*)&(CardData->CardStatus)
378 );
379 if (EFI_ERROR (Status)) {
380 break;
381 }
382 }
383 Status = SendCommand (
384 CardData,
385 SET_BLOCK_COUNT,
386 TransferLength / CardData->BlockIoMedia.BlockSize,
387 NoData,
388 NULL,
389 0,
390 ResponseR1,
391 TIMEOUT_COMMAND,
392 (UINT32*)&(CardData->CardStatus)
393 );
394 if (EFI_ERROR (Status)) {
395 break;
396 }
397 }
398
399 CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
400
401 Status = SendCommand (
402 CardData,
403 WRITE_MULTIPLE_BLOCK,
404 Address,
405 OutData,
406 CardData->AlignedBuffer,
407 (UINT32)TransferLength,
408 ResponseR1,
409 TIMEOUT_DATA,
410 (UINT32*)&(CardData->CardStatus)
411 );
412 if (EFI_ERROR (Status)) {
413 DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));
414 break;
415 }
416 } else {
417 if (RemainingLength > CardData->BlockIoMedia.BlockSize) {
418 TransferLength = CardData->BlockIoMedia.BlockSize;
419 } else {
420 TransferLength = RemainingLength;
421 }
422
423 CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
424
425 Status = SendCommand (
426 CardData,
427 WRITE_BLOCK,
428 Address,
429 OutData,
430 CardData->AlignedBuffer,
431 (UINT32)TransferLength,
432 ResponseR1,
433 TIMEOUT_DATA,
434 (UINT32*)&(CardData->CardStatus)
435 );
436 }
437 if (SectorAddressing) {
438 //
439 //Block Address
440 //
441 Address += TransferLength / 512;
442 } else {
443 //
444 //Byte Address
445 //
446 Address += TransferLength;
447 }
448 BufferPointer += TransferLength;
449 RemainingLength -= TransferLength;
450
451 }
452
453 if (EFI_ERROR (Status)) {
454 SendCommand (
455 CardData,
456 STOP_TRANSMISSION,
457 0,
458 NoData,
459 NULL,
460 0,
461 ResponseR1b,
462 TIMEOUT_COMMAND,
463 (UINT32*)&(CardData->CardStatus)
464 );
465
466 }
467
468
469 Done:
470 return EFI_SUCCESS;
471 }
472
473 /**
474 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
475 (In this driver, this function just returns EFI_SUCCESS.)
476
477 @param This The EFI_BLOCK_IO_PROTOCOL instance.
478
479 @retval EFI_SUCCESS
480 @retval Others
481 **/
482 EFI_STATUS
483 EFIAPI
484 MMCSDBlockFlushBlocks (
485 IN EFI_BLOCK_IO_PROTOCOL *This
486 )
487 {
488 return EFI_SUCCESS;
489 }
490
491
492 /**
493 MMC/SD card BlockIo init function.
494
495 @param CardData Pointer to CARD_DATA.
496
497 @retval EFI_SUCCESS
498 @retval Others
499 **/
500 EFI_STATUS
501 MMCSDBlockIoInit (
502 IN CARD_DATA *CardData
503 )
504 {
505 //
506 //BlockIO protocol
507 //
508 CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
509 CardData->BlockIo.Media = &(CardData->BlockIoMedia);
510 CardData->BlockIo.Reset = MMCSDBlockReset;
511 CardData->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ;
512 CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;
513 CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;
514
515 CardData->BlockIoMedia.MediaId = 0;
516 CardData->BlockIoMedia.RemovableMedia = FALSE;
517 CardData->BlockIoMedia.MediaPresent = TRUE;
518 CardData->BlockIoMedia.LogicalPartition = FALSE;
519
520 if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) {
521 CardData->BlockIoMedia.ReadOnly = TRUE;
522 } else {
523 CardData->BlockIoMedia.ReadOnly = FALSE;
524 }
525
526
527 CardData->BlockIoMedia.WriteCaching = FALSE;
528 CardData->BlockIoMedia.BlockSize = CardData->BlockLen;
529 CardData->BlockIoMedia.IoAlign = 1;
530 CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);
531
532
533 return EFI_SUCCESS;
534
535 }
536
537
538