3 Block I/O protocol for MMC/SD device
5 Copyright (c) 2013-2015 Intel Corporation.
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "SDMediaDevice.h"
20 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
22 @param This The EFI_BLOCK_IO_PROTOCOL instance.
23 @param ExtendedVerification Indicates that the driver may perform a more exhaustive.
24 verification operation of the device during reset.
25 (This parameter is ingored in this driver.)
27 @retval EFI_SUCCESS Success
32 IN EFI_BLOCK_IO_PROTOCOL
*This
,
33 IN BOOLEAN ExtendedVerification
37 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
39 CardData
= CARD_DATA_FROM_THIS(This
);
40 SDHostIo
= CardData
->SDHostIo
;
42 return SDHostIo
->ResetSDHost (SDHostIo
, Reset_DAT_CMD
);
46 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
48 @param This The EFI_BLOCK_IO_PROTOCOL instance.
49 @param MediaId The media id that the write request is for.
50 @param LBA The starting logical block address to read from on the device.
51 The caller is responsible for writing to only legitimate locations.
52 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
53 intrinsic block size of the device.
54 @param Buffer A pointer to the destination buffer for the data. The caller
55 is responsible for either having implicit or explicit ownership
58 @retval EFI_SUCCESS Success
59 @retval EFI_DEVICE_ERROR Hardware Error
60 @retval EFI_INVALID_PARAMETER Parameter is error
61 @retval EFI_NO_MEDIA No media
62 @retval EFI_MEDIA_CHANGED Media Change
63 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
67 MMCSDBlockReadBlocks (
68 IN EFI_BLOCK_IO_PROTOCOL
*This
,
78 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
79 UINT32 RemainingLength
;
80 UINT32 TransferLength
;
82 BOOLEAN SectorAddressing
;
85 DEBUG((EFI_D_INFO
, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA
, Buffer
, BufferSize
));
87 CardData
= CARD_DATA_FROM_THIS(This
);
88 SDHostIo
= CardData
->SDHostIo
;
89 if (MediaId
!= CardData
->BlockIoMedia
.MediaId
) {
90 return EFI_MEDIA_CHANGED
;
93 if (ModU64x32 (BufferSize
,CardData
->BlockIoMedia
.BlockSize
) != 0) {
94 return EFI_BAD_BUFFER_SIZE
;
96 if ((CardData
->CardType
== SDMemoryCard2High
) || (CardData
->CardType
== MMCCardHighCap
)) {
97 SectorAddressing
= TRUE
;
99 SectorAddressing
= FALSE
;
101 if (SectorAddressing
) {
105 Address
= (UINT32
)DivU64x32 (MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
), 512);
110 Address
= (UINT32
)MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
);
112 TotalBlock
= (UINTN
) DivU64x32 (BufferSize
, CardData
->BlockIoMedia
.BlockSize
);
113 if (LBA
+ TotalBlock
> CardData
->BlockIoMedia
.LastBlock
+ 1) {
114 return EFI_INVALID_PARAMETER
;
119 Status
= EFI_INVALID_PARAMETER
;
120 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));
124 if ((BufferSize
% CardData
->BlockIoMedia
.BlockSize
) != 0) {
125 Status
= EFI_BAD_BUFFER_SIZE
;
126 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));
130 if (BufferSize
== 0) {
131 Status
= EFI_SUCCESS
;
138 BufferPointer
= Buffer
;
139 RemainingLength
= (UINT32
)BufferSize
;
141 while (RemainingLength
> 0) {
142 if ((BufferSize
> CardData
->BlockIoMedia
.BlockSize
)) {
143 if (RemainingLength
> SDHostIo
->HostCapability
.BoundarySize
) {
144 TransferLength
= SDHostIo
->HostCapability
.BoundarySize
;
146 TransferLength
= RemainingLength
;
149 if (CardData
->CardType
== MMCCard
|| CardData
->CardType
== MMCCardHighCap
) {
150 if (!(CardData
->ExtCSDRegister
.CARD_TYPE
& (BIT2
| BIT3
))) {
151 Status
= SendCommand (
154 CardData
->BlockIoMedia
.BlockSize
,
160 (UINT32
*)&(CardData
->CardStatus
)
162 if (EFI_ERROR (Status
)) {
166 Status
= SendCommand (
169 TransferLength
/ CardData
->BlockIoMedia
.BlockSize
,
175 (UINT32
*)&(CardData
->CardStatus
)
177 if (EFI_ERROR (Status
)) {
181 Status
= SendCommand (
186 CardData
->AlignedBuffer
,
190 (UINT32
*)&(CardData
->CardStatus
)
193 if (EFI_ERROR (Status
)) {
194 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));
198 if (RemainingLength
> CardData
->BlockIoMedia
.BlockSize
) {
199 TransferLength
= CardData
->BlockIoMedia
.BlockSize
;
201 TransferLength
= RemainingLength
;
204 Status
= SendCommand (
209 CardData
->AlignedBuffer
,
210 (UINT32
)TransferLength
,
213 (UINT32
*)&(CardData
->CardStatus
)
215 if (EFI_ERROR (Status
)) {
216 DEBUG ((EFI_D_ERROR
, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));
220 CopyMem (BufferPointer
, CardData
->AlignedBuffer
, TransferLength
);
222 if (SectorAddressing
) {
226 Address
+= TransferLength
/ 512;
231 Address
+= TransferLength
;
233 BufferPointer
+= TransferLength
;
234 RemainingLength
-= TransferLength
;
238 if (EFI_ERROR (Status
)) {
239 if ((CardData
->CardType
== SDMemoryCard
) ||
240 (CardData
->CardType
== SDMemoryCard2
)||
241 (CardData
->CardType
== SDMemoryCard2High
)) {
251 (UINT32
*)&(CardData
->CardStatus
)
263 (UINT32
*)&(CardData
->CardStatus
)
271 DEBUG((EFI_D_INFO
, "MMCSDBlockReadBlocks: Status = %r\n", Status
));
276 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
278 @param This The EFI_BLOCK_IO_PROTOCOL instance.
279 @param MediaId The media id that the write request is for.
280 @param LBA The starting logical block address to read from on the device.
281 The caller is responsible for writing to only legitimate locations.
282 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
283 intrinsic block size of the device.
284 @param Buffer A pointer to the destination buffer for the data. The caller
285 is responsible for either having implicit or explicit ownership
288 @retval EFI_SUCCESS Success
289 @retval EFI_DEVICE_ERROR Hardware Error
290 @retval EFI_INVALID_PARAMETER Parameter is error
291 @retval EFI_NO_MEDIA No media
292 @retval EFI_MEDIA_CHANGED Media Change
293 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
297 MMCSDBlockWriteBlocks (
298 IN EFI_BLOCK_IO_PROTOCOL
*This
,
308 EFI_SD_HOST_IO_PROTOCOL
*SDHostIo
;
309 UINT32 RemainingLength
;
310 UINT32 TransferLength
;
311 UINT8
*BufferPointer
;
312 BOOLEAN SectorAddressing
;
314 DEBUG((EFI_D_INFO
, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA
, Buffer
, BufferSize
));
315 Status
= EFI_SUCCESS
;
316 CardData
= CARD_DATA_FROM_THIS(This
);
317 SDHostIo
= CardData
->SDHostIo
;
318 if ((CardData
->CardType
== SDMemoryCard2High
) || (CardData
->CardType
== MMCCardHighCap
)) {
319 SectorAddressing
= TRUE
;
321 SectorAddressing
= FALSE
;
323 if (SectorAddressing
) {
327 Address
= (UINT32
)DivU64x32 (MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
), 512);
332 Address
= (UINT32
)MultU64x32 (LBA
, CardData
->BlockIoMedia
.BlockSize
);
336 Status
= EFI_INVALID_PARAMETER
;
337 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));
341 if ((BufferSize
% CardData
->BlockIoMedia
.BlockSize
) != 0) {
342 Status
= EFI_BAD_BUFFER_SIZE
;
343 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));
347 if (BufferSize
== 0) {
348 Status
= EFI_SUCCESS
;
352 if (This
->Media
->ReadOnly
== TRUE
) {
353 Status
= EFI_WRITE_PROTECTED
;
354 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: Write protected \r\n"));
360 BufferPointer
= Buffer
;
361 RemainingLength
= (UINT32
)BufferSize
;
363 while (RemainingLength
> 0) {
364 if ((BufferSize
> CardData
->BlockIoMedia
.BlockSize
) ) {
365 if (RemainingLength
> SDHostIo
->HostCapability
.BoundarySize
) {
366 TransferLength
= SDHostIo
->HostCapability
.BoundarySize
;
368 TransferLength
= RemainingLength
;
371 if (CardData
->CardType
== MMCCard
|| CardData
->CardType
== MMCCardHighCap
) {
373 if (!(CardData
->ExtCSDRegister
.CARD_TYPE
& (BIT2
| BIT3
))) {
374 Status
= SendCommand (
377 CardData
->BlockIoMedia
.BlockSize
,
383 (UINT32
*)&(CardData
->CardStatus
)
385 if (EFI_ERROR (Status
)) {
389 Status
= SendCommand (
392 TransferLength
/ CardData
->BlockIoMedia
.BlockSize
,
398 (UINT32
*)&(CardData
->CardStatus
)
400 if (EFI_ERROR (Status
)) {
405 CopyMem (CardData
->AlignedBuffer
, BufferPointer
, TransferLength
);
407 Status
= SendCommand (
409 WRITE_MULTIPLE_BLOCK
,
412 CardData
->AlignedBuffer
,
413 (UINT32
)TransferLength
,
416 (UINT32
*)&(CardData
->CardStatus
)
418 if (EFI_ERROR (Status
)) {
419 DEBUG ((EFI_D_ERROR
, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));
423 if (RemainingLength
> CardData
->BlockIoMedia
.BlockSize
) {
424 TransferLength
= CardData
->BlockIoMedia
.BlockSize
;
426 TransferLength
= RemainingLength
;
429 CopyMem (CardData
->AlignedBuffer
, BufferPointer
, TransferLength
);
431 Status
= SendCommand (
436 CardData
->AlignedBuffer
,
437 (UINT32
)TransferLength
,
440 (UINT32
*)&(CardData
->CardStatus
)
443 if (SectorAddressing
) {
447 Address
+= TransferLength
/ 512;
452 Address
+= TransferLength
;
454 BufferPointer
+= TransferLength
;
455 RemainingLength
-= TransferLength
;
459 if (EFI_ERROR (Status
)) {
469 (UINT32
*)&(CardData
->CardStatus
)
480 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
481 (In this driver, this function just returns EFI_SUCCESS.)
483 @param This The EFI_BLOCK_IO_PROTOCOL instance.
490 MMCSDBlockFlushBlocks (
491 IN EFI_BLOCK_IO_PROTOCOL
*This
499 MMC/SD card BlockIo init function.
501 @param CardData Pointer to CARD_DATA.
508 IN CARD_DATA
*CardData
514 CardData
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION
;
515 CardData
->BlockIo
.Media
= &(CardData
->BlockIoMedia
);
516 CardData
->BlockIo
.Reset
= MMCSDBlockReset
;
517 CardData
->BlockIo
.ReadBlocks
= MMCSDBlockReadBlocks
;
518 CardData
->BlockIo
.WriteBlocks
= MMCSDBlockWriteBlocks
;
519 CardData
->BlockIo
.FlushBlocks
= MMCSDBlockFlushBlocks
;
521 CardData
->BlockIoMedia
.MediaId
= 0;
522 CardData
->BlockIoMedia
.RemovableMedia
= FALSE
;
523 CardData
->BlockIoMedia
.MediaPresent
= TRUE
;
524 CardData
->BlockIoMedia
.LogicalPartition
= FALSE
;
526 if (CardData
->CSDRegister
.PERM_WRITE_PROTECT
|| CardData
->CSDRegister
.TMP_WRITE_PROTECT
) {
527 CardData
->BlockIoMedia
.ReadOnly
= TRUE
;
529 CardData
->BlockIoMedia
.ReadOnly
= FALSE
;
533 CardData
->BlockIoMedia
.WriteCaching
= FALSE
;
534 CardData
->BlockIoMedia
.BlockSize
= CardData
->BlockLen
;
535 CardData
->BlockIoMedia
.IoAlign
= 1;
536 CardData
->BlockIoMedia
.LastBlock
= (EFI_LBA
)(CardData
->BlockNumber
- 1);