3 Block I/O protocol for MMC/SD device
5 Copyright (c) 2013-2015 Intel Corporation.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "SDMediaDevice.h"
14 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
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.)
21 @retval EFI_SUCCESS Success
26 IN EFI_BLOCK_IO_PROTOCOL
*This
,
27 IN BOOLEAN ExtendedVerification
31 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
33 CardData
= CARD_DATA_FROM_THIS(This
);
34 SDHostIo
= CardData
->SDHostIo
;
36 return SDHostIo
->ResetSDHost (SDHostIo
, Reset_DAT_CMD
);
40 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
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
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
61 MMCSDBlockReadBlocks (
62 IN EFI_BLOCK_IO_PROTOCOL
*This
,
72 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
73 UINT32 RemainingLength
;
74 UINT32 TransferLength
;
76 BOOLEAN SectorAddressing
;
79 DEBUG((EFI_D_INFO
, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA
, Buffer
, BufferSize
));
81 CardData
= CARD_DATA_FROM_THIS(This
);
82 SDHostIo
= CardData
->SDHostIo
;
83 if (MediaId
!= CardData
->BlockIoMedia
.MediaId
) {
84 return EFI_MEDIA_CHANGED
;
87 if (ModU64x32 (BufferSize
,CardData
->BlockIoMedia
.BlockSize
) != 0) {
88 return EFI_BAD_BUFFER_SIZE
;
90 if ((CardData
->CardType
== SDMemoryCard2High
) || (CardData
->CardType
== MMCCardHighCap
)) {
91 SectorAddressing
= TRUE
;
93 SectorAddressing
= FALSE
;
95 if (SectorAddressing
) {
99 Address
= (UINT32
)DivU64x32 (MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
), 512);
104 Address
= (UINT32
)MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
);
106 TotalBlock
= (UINTN
) DivU64x32 (BufferSize
, CardData
->BlockIoMedia
.BlockSize
);
107 if (LBA
+ TotalBlock
> CardData
->BlockIoMedia
.LastBlock
+ 1) {
108 return EFI_INVALID_PARAMETER
;
113 Status
= EFI_INVALID_PARAMETER
;
114 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));
118 if ((BufferSize
% CardData
->BlockIoMedia
.BlockSize
) != 0) {
119 Status
= EFI_BAD_BUFFER_SIZE
;
120 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));
124 if (BufferSize
== 0) {
125 Status
= EFI_SUCCESS
;
132 BufferPointer
= Buffer
;
133 RemainingLength
= (UINT32
)BufferSize
;
135 while (RemainingLength
> 0) {
136 if ((BufferSize
> CardData
->BlockIoMedia
.BlockSize
)) {
137 if (RemainingLength
> SDHostIo
->HostCapability
.BoundarySize
) {
138 TransferLength
= SDHostIo
->HostCapability
.BoundarySize
;
140 TransferLength
= RemainingLength
;
143 if (CardData
->CardType
== MMCCard
|| CardData
->CardType
== MMCCardHighCap
) {
144 if (!(CardData
->ExtCSDRegister
.CARD_TYPE
& (BIT2
| BIT3
))) {
145 Status
= SendCommand (
148 CardData
->BlockIoMedia
.BlockSize
,
154 (UINT32
*)&(CardData
->CardStatus
)
156 if (EFI_ERROR (Status
)) {
160 Status
= SendCommand (
163 TransferLength
/ CardData
->BlockIoMedia
.BlockSize
,
169 (UINT32
*)&(CardData
->CardStatus
)
171 if (EFI_ERROR (Status
)) {
175 Status
= SendCommand (
180 CardData
->AlignedBuffer
,
184 (UINT32
*)&(CardData
->CardStatus
)
187 if (EFI_ERROR (Status
)) {
188 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));
192 if (RemainingLength
> CardData
->BlockIoMedia
.BlockSize
) {
193 TransferLength
= CardData
->BlockIoMedia
.BlockSize
;
195 TransferLength
= RemainingLength
;
198 Status
= SendCommand (
203 CardData
->AlignedBuffer
,
204 (UINT32
)TransferLength
,
207 (UINT32
*)&(CardData
->CardStatus
)
209 if (EFI_ERROR (Status
)) {
210 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));
214 CopyMem (BufferPointer
, CardData
->AlignedBuffer
, TransferLength
);
216 if (SectorAddressing
) {
220 Address
+= TransferLength
/ 512;
225 Address
+= TransferLength
;
227 BufferPointer
+= TransferLength
;
228 RemainingLength
-= TransferLength
;
232 if (EFI_ERROR (Status
)) {
233 if ((CardData
->CardType
== SDMemoryCard
) ||
234 (CardData
->CardType
== SDMemoryCard2
)||
235 (CardData
->CardType
== SDMemoryCard2High
)) {
245 (UINT32
*)&(CardData
->CardStatus
)
257 (UINT32
*)&(CardData
->CardStatus
)
265 DEBUG((EFI_D_INFO
, "MMCSDBlockReadBlocks: Status = %r\n", Status
));
270 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
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
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
291 MMCSDBlockWriteBlocks (
292 IN EFI_BLOCK_IO_PROTOCOL
*This
,
302 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
303 UINT32 RemainingLength
;
304 UINT32 TransferLength
;
305 UINT8
*BufferPointer
;
306 BOOLEAN SectorAddressing
;
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
;
315 SectorAddressing
= FALSE
;
317 if (SectorAddressing
) {
321 Address
= (UINT32
)DivU64x32 (MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
), 512);
326 Address
= (UINT32
)MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
);
330 Status
= EFI_INVALID_PARAMETER
;
331 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));
335 if ((BufferSize
% CardData
->BlockIoMedia
.BlockSize
) != 0) {
336 Status
= EFI_BAD_BUFFER_SIZE
;
337 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));
341 if (BufferSize
== 0) {
342 Status
= EFI_SUCCESS
;
346 if (This
->Media
->ReadOnly
== TRUE
) {
347 Status
= EFI_WRITE_PROTECTED
;
348 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Write protected \r\n"));
354 BufferPointer
= Buffer
;
355 RemainingLength
= (UINT32
)BufferSize
;
357 while (RemainingLength
> 0) {
358 if ((BufferSize
> CardData
->BlockIoMedia
.BlockSize
) ) {
359 if (RemainingLength
> SDHostIo
->HostCapability
.BoundarySize
) {
360 TransferLength
= SDHostIo
->HostCapability
.BoundarySize
;
362 TransferLength
= RemainingLength
;
365 if (CardData
->CardType
== MMCCard
|| CardData
->CardType
== MMCCardHighCap
) {
367 if (!(CardData
->ExtCSDRegister
.CARD_TYPE
& (BIT2
| BIT3
))) {
368 Status
= SendCommand (
371 CardData
->BlockIoMedia
.BlockSize
,
377 (UINT32
*)&(CardData
->CardStatus
)
379 if (EFI_ERROR (Status
)) {
383 Status
= SendCommand (
386 TransferLength
/ CardData
->BlockIoMedia
.BlockSize
,
392 (UINT32
*)&(CardData
->CardStatus
)
394 if (EFI_ERROR (Status
)) {
399 CopyMem (CardData
->AlignedBuffer
, BufferPointer
, TransferLength
);
401 Status
= SendCommand (
403 WRITE_MULTIPLE_BLOCK
,
406 CardData
->AlignedBuffer
,
407 (UINT32
)TransferLength
,
410 (UINT32
*)&(CardData
->CardStatus
)
412 if (EFI_ERROR (Status
)) {
413 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));
417 if (RemainingLength
> CardData
->BlockIoMedia
.BlockSize
) {
418 TransferLength
= CardData
->BlockIoMedia
.BlockSize
;
420 TransferLength
= RemainingLength
;
423 CopyMem (CardData
->AlignedBuffer
, BufferPointer
, TransferLength
);
425 Status
= SendCommand (
430 CardData
->AlignedBuffer
,
431 (UINT32
)TransferLength
,
434 (UINT32
*)&(CardData
->CardStatus
)
437 if (SectorAddressing
) {
441 Address
+= TransferLength
/ 512;
446 Address
+= TransferLength
;
448 BufferPointer
+= TransferLength
;
449 RemainingLength
-= TransferLength
;
453 if (EFI_ERROR (Status
)) {
463 (UINT32
*)&(CardData
->CardStatus
)
474 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
475 (In this driver, this function just returns EFI_SUCCESS.)
477 @param This The EFI_BLOCK_IO_PROTOCOL instance.
484 MMCSDBlockFlushBlocks (
485 IN EFI_BLOCK_IO_PROTOCOL
*This
493 MMC/SD card BlockIo init function.
495 @param CardData Pointer to CARD_DATA.
502 IN CARD_DATA
*CardData
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
;
515 CardData
->BlockIoMedia
.MediaId
= 0;
516 CardData
->BlockIoMedia
.RemovableMedia
= FALSE
;
517 CardData
->BlockIoMedia
.MediaPresent
= TRUE
;
518 CardData
->BlockIoMedia
.LogicalPartition
= FALSE
;
520 if (CardData
->CSDRegister
.PERM_WRITE_PROTECT
|| CardData
->CSDRegister
.TMP_WRITE_PROTECT
) {
521 CardData
->BlockIoMedia
.ReadOnly
= TRUE
;
523 CardData
->BlockIoMedia
.ReadOnly
= FALSE
;
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);