2 The helper functions for BlockIo and BlockIo2 protocol.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Nonblocking I/O callback funtion when the event is signaled.
20 @param[in] Event The Event this notify function registered to.
21 @param[in] Context Pointer to the context data registered to the
34 gBS
->CloseEvent (Event
);
36 Request
= (SD_REQUEST
*) Context
;
39 DEBUG ((EFI_D_INFO
, "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",
40 Request
->SdMmcCmdBlk
.CommandIndex
, Request
->SdMmcCmdBlk
.CommandArgument
,
41 Request
->Packet
.TransactionStatus
));
44 if (EFI_ERROR (Request
->Packet
.TransactionStatus
)) {
45 Request
->Token
->TransactionStatus
= Request
->Packet
.TransactionStatus
;
48 RemoveEntryList (&Request
->Link
);
51 gBS
->SignalEvent (Request
->Token
->Event
);
58 Send command SET_RELATIVE_ADDRESS to the device to set the device address.
60 @param[in] Device A pointer to the SD_DEVICE instance.
61 @param[out] Rca The relative device address to assign.
63 @retval EFI_SUCCESS The request is executed successfully.
64 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
65 @retval Others The request could not be executed successfully.
75 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
76 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
77 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
78 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
80 PassThru
= Device
->Private
->PassThru
;
82 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
83 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
84 ZeroMem (&Packet
, sizeof (Packet
));
85 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
86 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
87 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
89 SdMmcCmdBlk
.CommandIndex
= SD_SET_RELATIVE_ADDR
;
90 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
91 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR6
;
93 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
94 if (!EFI_ERROR (Status
)) {
95 DEBUG ((EFI_D_INFO
, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk
.Resp0
));
96 *Rca
= (UINT16
)(SdMmcStatusBlk
.Resp0
>> 16);
103 Send command SELECT to the device to select/deselect the device.
105 @param[in] Device A pointer to the SD_DEVICE instance.
106 @param[in] Rca The relative device address to use.
108 @retval EFI_SUCCESS The request is executed successfully.
109 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
110 @retval Others The request could not be executed successfully.
115 IN SD_DEVICE
*Device
,
120 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
121 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
122 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
123 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
125 PassThru
= Device
->Private
->PassThru
;
127 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
128 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
129 ZeroMem (&Packet
, sizeof (Packet
));
130 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
131 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
132 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
134 SdMmcCmdBlk
.CommandIndex
= SD_SELECT_DESELECT_CARD
;
135 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
136 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
137 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
139 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
145 Send command SEND_STATUS to the device to get device status.
147 @param[in] Device A pointer to the SD_DEVICE instance.
148 @param[in] Rca The relative device address to use.
149 @param[out] DevStatus The buffer to store the device status.
151 @retval EFI_SUCCESS The request is executed successfully.
152 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
153 @retval Others The request could not be executed successfully.
158 IN SD_DEVICE
*Device
,
160 OUT UINT32
*DevStatus
164 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
165 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
166 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
167 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
169 PassThru
= Device
->Private
->PassThru
;
171 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
172 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
173 ZeroMem (&Packet
, sizeof (Packet
));
174 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
175 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
176 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
178 SdMmcCmdBlk
.CommandIndex
= SD_SEND_STATUS
;
179 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
180 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
181 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
183 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
184 if (!EFI_ERROR (Status
)) {
185 CopyMem (DevStatus
, &SdMmcStatusBlk
.Resp0
, sizeof (UINT32
));
191 Send command SEND_CSD to the device to get the CSD register data.
193 @param[in] Device A pointer to the SD_DEVICE instance.
194 @param[in] Rca The relative device address to use.
195 @param[out] Csd The buffer to store the SD_CSD register data.
197 @retval EFI_SUCCESS The request is executed successfully.
198 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
199 @retval Others The request could not be executed successfully.
204 IN SD_DEVICE
*Device
,
210 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
211 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
212 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
213 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
215 PassThru
= Device
->Private
->PassThru
;
217 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
218 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
219 ZeroMem (&Packet
, sizeof (Packet
));
220 ZeroMem (Csd
, sizeof (SD_CSD
));
222 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
223 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
224 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
226 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CSD
;
227 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
228 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
229 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
231 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
233 if (!EFI_ERROR (Status
)) {
235 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
237 CopyMem (((UINT8
*)Csd
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CSD
) - 1);
244 Send command SEND_CID to the device to get the CID register data.
246 @param[in] Device A pointer to the SD_DEVICE instance.
247 @param[in] Rca The relative device address to use.
248 @param[out] Cid The buffer to store the SD_CID register data.
250 @retval EFI_SUCCESS The request is executed successfully.
251 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
252 @retval Others The request could not be executed successfully.
257 IN SD_DEVICE
*Device
,
263 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
264 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
265 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
266 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
268 PassThru
= Device
->Private
->PassThru
;
270 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
271 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
272 ZeroMem (&Packet
, sizeof (Packet
));
273 ZeroMem (Cid
, sizeof (SD_CID
));
275 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
276 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
277 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
279 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CID
;
280 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
281 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
282 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
284 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
286 if (!EFI_ERROR (Status
)) {
288 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
290 CopyMem (((UINT8
*)Cid
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CID
) - 1);
297 Read/write single block through sync or async I/O request.
299 @param[in] Device A pointer to the SD_DEVICE instance.
300 @param[in] Lba The starting logical block address to be read/written.
301 The caller is responsible for reading/writing to only
302 legitimate locations.
303 @param[in] Buffer A pointer to the destination/source buffer for the data.
304 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
305 @param[in] IsRead Indicates it is a read or write operation.
306 @param[in] Token A pointer to the token associated with the transaction.
307 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
308 This parameter is only meaningful in async I/O request.
310 @retval EFI_SUCCESS The request is executed successfully.
311 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
312 @retval Others The request could not be executed successfully.
317 IN SD_DEVICE
*Device
,
322 IN EFI_BLOCK_IO2_TOKEN
*Token
,
327 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
328 SD_REQUEST
*RwSingleBlkReq
;
331 RwSingleBlkReq
= NULL
;
332 PassThru
= Device
->Private
->PassThru
;
334 RwSingleBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
335 if (RwSingleBlkReq
== NULL
) {
336 Status
= EFI_OUT_OF_RESOURCES
;
340 RwSingleBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
341 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
342 InsertTailList (&Device
->Queue
, &RwSingleBlkReq
->Link
);
343 gBS
->RestoreTPL (OldTpl
);
344 RwSingleBlkReq
->Packet
.SdMmcCmdBlk
= &RwSingleBlkReq
->SdMmcCmdBlk
;
345 RwSingleBlkReq
->Packet
.SdMmcStatusBlk
= &RwSingleBlkReq
->SdMmcStatusBlk
;
347 // Calculate timeout value through the below formula.
348 // Timeout = (transfer size) / (2MB/s).
349 // Taking 2MB/s as divisor as it's the lowest transfer speed
351 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
353 RwSingleBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
356 RwSingleBlkReq
->Packet
.InDataBuffer
= Buffer
;
357 RwSingleBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
359 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_SINGLE_BLOCK
;
360 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
361 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
363 RwSingleBlkReq
->Packet
.OutDataBuffer
= Buffer
;
364 RwSingleBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
366 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_SINGLE_BLOCK
;
367 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
368 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
371 if (Device
->SectorAddressing
) {
372 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
374 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
377 RwSingleBlkReq
->IsEnd
= IsEnd
;
378 RwSingleBlkReq
->Token
= Token
;
380 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
381 Status
= gBS
->CreateEvent (
386 &RwSingleBlkReq
->Event
388 if (EFI_ERROR (Status
)) {
392 RwSingleBlkReq
->Event
= NULL
;
395 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwSingleBlkReq
->Packet
, RwSingleBlkReq
->Event
);
398 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
400 // For asynchronous operation, only free request and event in error case.
401 // The request and event will be freed in asynchronous callback for success case.
403 if (EFI_ERROR (Status
) && (RwSingleBlkReq
!= NULL
)) {
404 RemoveEntryList (&RwSingleBlkReq
->Link
);
405 if (RwSingleBlkReq
->Event
!= NULL
) {
406 gBS
->CloseEvent (RwSingleBlkReq
->Event
);
408 FreePool (RwSingleBlkReq
);
412 // For synchronous operation, free request whatever the execution result is.
414 if (RwSingleBlkReq
!= NULL
) {
415 RemoveEntryList (&RwSingleBlkReq
->Link
);
416 FreePool (RwSingleBlkReq
);
424 Read/write multiple blocks through sync or async I/O request.
426 @param[in] Device A pointer to the SD_DEVICE instance.
427 @param[in] Lba The starting logical block address to be read/written.
428 The caller is responsible for reading/writing to only
429 legitimate locations.
430 @param[in] Buffer A pointer to the destination/source buffer for the data.
431 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
432 @param[in] IsRead Indicates it is a read or write operation.
433 @param[in] Token A pointer to the token associated with the transaction.
434 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
435 This parameter is only meaningful in async I/O request.
437 @retval EFI_SUCCESS The request is executed successfully.
438 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
439 @retval Others The request could not be executed successfully.
444 IN SD_DEVICE
*Device
,
449 IN EFI_BLOCK_IO2_TOKEN
*Token
,
454 SD_REQUEST
*RwMultiBlkReq
;
455 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
458 RwMultiBlkReq
= NULL
;
460 PassThru
= Device
->Private
->PassThru
;
462 RwMultiBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
463 if (RwMultiBlkReq
== NULL
) {
464 Status
= EFI_OUT_OF_RESOURCES
;
468 RwMultiBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
469 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
470 InsertTailList (&Device
->Queue
, &RwMultiBlkReq
->Link
);
471 gBS
->RestoreTPL (OldTpl
);
472 RwMultiBlkReq
->Packet
.SdMmcCmdBlk
= &RwMultiBlkReq
->SdMmcCmdBlk
;
473 RwMultiBlkReq
->Packet
.SdMmcStatusBlk
= &RwMultiBlkReq
->SdMmcStatusBlk
;
475 // Calculate timeout value through the below formula.
476 // Timeout = (transfer size) / (2MB/s).
477 // Taking 2MB/s as divisor as it's the lowest transfer speed
479 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
481 RwMultiBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
484 RwMultiBlkReq
->Packet
.InDataBuffer
= Buffer
;
485 RwMultiBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
487 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_MULTIPLE_BLOCK
;
488 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
489 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
491 RwMultiBlkReq
->Packet
.OutDataBuffer
= Buffer
;
492 RwMultiBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
494 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_MULTIPLE_BLOCK
;
495 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
496 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
499 if (Device
->SectorAddressing
) {
500 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
502 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
505 RwMultiBlkReq
->IsEnd
= IsEnd
;
506 RwMultiBlkReq
->Token
= Token
;
508 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
509 Status
= gBS
->CreateEvent (
514 &RwMultiBlkReq
->Event
516 if (EFI_ERROR (Status
)) {
520 RwMultiBlkReq
->Event
= NULL
;
523 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwMultiBlkReq
->Packet
, RwMultiBlkReq
->Event
);
526 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
528 // For asynchronous operation, only free request and event in error case.
529 // The request and event will be freed in asynchronous callback for success case.
531 if (EFI_ERROR (Status
) && (RwMultiBlkReq
!= NULL
)) {
532 RemoveEntryList (&RwMultiBlkReq
->Link
);
533 if (RwMultiBlkReq
->Event
!= NULL
) {
534 gBS
->CloseEvent (RwMultiBlkReq
->Event
);
536 FreePool (RwMultiBlkReq
);
540 // For synchronous operation, free request whatever the execution result is.
542 if (RwMultiBlkReq
!= NULL
) {
543 RemoveEntryList (&RwMultiBlkReq
->Link
);
544 FreePool (RwMultiBlkReq
);
552 This function transfers data from/to the sd memory card device.
554 @param[in] Device A pointer to the SD_DEVICE instance.
555 @param[in] MediaId The media ID that the read/write request is for.
556 @param[in] Lba The starting logical block address to be read/written.
557 The caller is responsible for reading/writing to only
558 legitimate locations.
559 @param[in, out] Buffer A pointer to the destination/source buffer for the data.
560 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
561 @param[in] IsRead Indicates it is a read or write operation.
562 @param[in, out] Token A pointer to the token associated with the transaction.
564 @retval EFI_SUCCESS The data was read/written correctly to the device.
565 @retval EFI_WRITE_PROTECTED The device can not be read/written to.
566 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.
567 @retval EFI_NO_MEDIA There is no media in the device.
568 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
569 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
570 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,
571 or the buffer is not on proper alignment.
576 IN SD_DEVICE
*Device
,
582 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
586 EFI_BLOCK_IO_MEDIA
*Media
;
594 Status
= EFI_SUCCESS
;
595 Media
= &Device
->BlockMedia
;
598 if (MediaId
!= Media
->MediaId
) {
599 return EFI_MEDIA_CHANGED
;
602 if (!IsRead
&& Media
->ReadOnly
) {
603 return EFI_WRITE_PROTECTED
;
609 if (Buffer
== NULL
) {
610 return EFI_INVALID_PARAMETER
;
613 if (BufferSize
== 0) {
614 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
615 Token
->TransactionStatus
= EFI_SUCCESS
;
616 gBS
->SignalEvent (Token
->Event
);
621 BlockSize
= Media
->BlockSize
;
622 if ((BufferSize
% BlockSize
) != 0) {
623 return EFI_BAD_BUFFER_SIZE
;
626 BlockNum
= BufferSize
/ BlockSize
;
627 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
628 return EFI_INVALID_PARAMETER
;
631 IoAlign
= Media
->IoAlign
;
632 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
633 return EFI_INVALID_PARAMETER
;
636 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
637 Token
->TransactionStatus
= EFI_SUCCESS
;
641 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
643 Remaining
= BlockNum
;
646 while (Remaining
> 0) {
647 if (Remaining
<= MaxBlock
) {
648 BlockNum
= Remaining
;
654 BufferSize
= BlockNum
* BlockSize
;
656 Status
= SdRwSingleBlock (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
658 Status
= SdRwMultiBlocks (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
660 if (EFI_ERROR (Status
)) {
663 DEBUG ((EFI_D_INFO
, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead
? "Read" : "Write", Lba
, BlockNum
, Token
->Event
, Status
));
666 Buffer
= (UINT8
*)Buffer
+ BufferSize
;
667 Remaining
-= BlockNum
;
674 Reset the Block Device.
676 @param This Indicates a pointer to the calling context.
677 @param ExtendedVerification Driver may perform diagnostics on reset.
679 @retval EFI_SUCCESS The device was reset.
680 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
687 IN EFI_BLOCK_IO_PROTOCOL
*This
,
688 IN BOOLEAN ExtendedVerification
693 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
695 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
697 PassThru
= Device
->Private
->PassThru
;
698 Status
= PassThru
->ResetDevice (PassThru
, Device
->Slot
);
699 if (EFI_ERROR (Status
)) {
700 Status
= EFI_DEVICE_ERROR
;
707 Read BufferSize bytes from Lba into Buffer.
709 @param This Indicates a pointer to the calling context.
710 @param MediaId Id of the media, changes every time the media is replaced.
711 @param Lba The starting Logical Block Address to read from
712 @param BufferSize Size of Buffer, must be a multiple of device block size.
713 @param Buffer A pointer to the destination buffer for the data. The caller is
714 responsible for either having implicit or explicit ownership of the buffer.
716 @retval EFI_SUCCESS The data was read correctly from the device.
717 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
718 @retval EFI_NO_MEDIA There is no media in the device.
719 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
720 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
721 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
722 or the buffer is not on proper alignment.
728 IN EFI_BLOCK_IO_PROTOCOL
*This
,
738 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
740 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, NULL
);
745 Write BufferSize bytes from Lba into Buffer.
747 @param This Indicates a pointer to the calling context.
748 @param MediaId The media ID that the write request is for.
749 @param Lba The starting logical block address to be written. The caller is
750 responsible for writing to only legitimate locations.
751 @param BufferSize Size of Buffer, must be a multiple of device block size.
752 @param Buffer A pointer to the source buffer for the data.
754 @retval EFI_SUCCESS The data was written correctly to the device.
755 @retval EFI_WRITE_PROTECTED The device can not be written to.
756 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
757 @retval EFI_NO_MEDIA There is no media in the device.
758 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
759 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
760 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
761 or the buffer is not on proper alignment.
767 IN EFI_BLOCK_IO_PROTOCOL
*This
,
777 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
779 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, NULL
);
784 Flush the Block Device.
786 @param This Indicates a pointer to the calling context.
788 @retval EFI_SUCCESS All outstanding data was written to the device
789 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
790 @retval EFI_NO_MEDIA There is no media in the device.
796 IN EFI_BLOCK_IO_PROTOCOL
*This
806 Reset the Block Device.
808 @param[in] This Indicates a pointer to the calling context.
809 @param[in] ExtendedVerification Driver may perform diagnostics on reset.
811 @retval EFI_SUCCESS The device was reset.
812 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
819 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
820 IN BOOLEAN ExtendedVerification
825 LIST_ENTRY
*NextLink
;
829 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
831 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
832 for (Link
= GetFirstNode (&Device
->Queue
);
833 !IsNull (&Device
->Queue
, Link
);
835 NextLink
= GetNextNode (&Device
->Queue
, Link
);
836 RemoveEntryList (Link
);
838 Request
= SD_REQUEST_FROM_LINK (Link
);
840 gBS
->CloseEvent (Request
->Event
);
841 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
843 if (Request
->IsEnd
) {
844 gBS
->SignalEvent (Request
->Token
->Event
);
849 gBS
->RestoreTPL (OldTpl
);
855 Read BufferSize bytes from Lba into Buffer.
857 @param[in] This Indicates a pointer to the calling context.
858 @param[in] MediaId Id of the media, changes every time the media is replaced.
859 @param[in] Lba The starting Logical Block Address to read from.
860 @param[in, out] Token A pointer to the token associated with the transaction.
861 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
862 @param[out] Buffer A pointer to the destination buffer for the data. The caller is
863 responsible for either having implicit or explicit ownership of the buffer.
865 @retval EFI_SUCCESS The read request was queued if Event is not NULL.
866 The data was read correctly from the device if
868 @retval EFI_DEVICE_ERROR The device reported an error while performing
870 @retval EFI_NO_MEDIA There is no media in the device.
871 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
872 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
873 intrinsic block size of the device.
874 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
875 or the buffer is not on proper alignment.
876 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
883 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
886 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
894 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
896 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, Token
);
901 Write BufferSize bytes from Lba into Buffer.
903 @param[in] This Indicates a pointer to the calling context.
904 @param[in] MediaId The media ID that the write request is for.
905 @param[in] Lba The starting logical block address to be written. The
906 caller is responsible for writing to only legitimate
908 @param[in, out] Token A pointer to the token associated with the transaction.
909 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
910 @param[in] Buffer A pointer to the source buffer for the data.
912 @retval EFI_SUCCESS The data was written correctly to the device.
913 @retval EFI_WRITE_PROTECTED The device can not be written to.
914 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
915 @retval EFI_NO_MEDIA There is no media in the device.
916 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
917 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
918 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
919 or the buffer is not on proper alignment.
925 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
928 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
936 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
938 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, Token
);
943 Flush the Block Device.
945 @param[in] This Indicates a pointer to the calling context.
946 @param[in, out] Token A pointer to the token associated with the transaction.
948 @retval EFI_SUCCESS All outstanding data was written to the device
949 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
950 @retval EFI_NO_MEDIA There is no media in the device.
956 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
957 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
961 // Signal event and return directly.
963 if (Token
!= NULL
&& Token
->Event
!= NULL
) {
964 Token
->TransactionStatus
= EFI_SUCCESS
;
965 gBS
->SignalEvent (Token
->Event
);