]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / SdDxe / SdBlockIo.c
CommitLineData
48555339
FT
1/** @file\r
2 The helper functions for BlockIo and BlockIo2 protocol.\r
3\r
0f4387e5 4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
48555339
FT
6\r
7**/\r
8\r
9#include "SdDxe.h"\r
10\r
11/**\r
b854b075 12 Nonblocking I/O callback function when the event is signaled.\r
48555339
FT
13\r
14 @param[in] Event The Event this notify function registered to.\r
15 @param[in] Context Pointer to the context data registered to the\r
16 Event.\r
17\r
18**/\r
19VOID\r
20EFIAPI\r
21AsyncIoCallback (\r
1436aea4
MK
22 IN EFI_EVENT Event,\r
23 IN VOID *Context\r
48555339
FT
24 )\r
25{\r
1436aea4 26 SD_REQUEST *Request;\r
48555339
FT
27\r
28 gBS->CloseEvent (Event);\r
29\r
1436aea4 30 Request = (SD_REQUEST *)Context;\r
48555339
FT
31\r
32 DEBUG_CODE_BEGIN ();\r
1436aea4
MK
33 DEBUG ((\r
34 DEBUG_INFO,\r
35 "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",\r
36 Request->SdMmcCmdBlk.CommandIndex,\r
37 Request->SdMmcCmdBlk.CommandArgument,\r
38 Request->Packet.TransactionStatus\r
39 ));\r
48555339
FT
40 DEBUG_CODE_END ();\r
41\r
42 if (EFI_ERROR (Request->Packet.TransactionStatus)) {\r
43 Request->Token->TransactionStatus = Request->Packet.TransactionStatus;\r
44 }\r
45\r
46 RemoveEntryList (&Request->Link);\r
47\r
48 if (Request->IsEnd) {\r
49 gBS->SignalEvent (Request->Token->Event);\r
50 }\r
51\r
52 FreePool (Request);\r
53}\r
54\r
55/**\r
56 Send command SET_RELATIVE_ADDRESS to the device to set the device address.\r
57\r
58 @param[in] Device A pointer to the SD_DEVICE instance.\r
59 @param[out] Rca The relative device address to assign.\r
60\r
61 @retval EFI_SUCCESS The request is executed successfully.\r
62 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
63 @retval Others The request could not be executed successfully.\r
64\r
65**/\r
66EFI_STATUS\r
67SdSetRca (\r
1436aea4
MK
68 IN SD_DEVICE *Device,\r
69 OUT UINT16 *Rca\r
48555339
FT
70 )\r
71{\r
72 EFI_STATUS Status;\r
73 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
74 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
75 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
76 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
77\r
78 PassThru = Device->Private->PassThru;\r
79\r
80 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
81 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
82 ZeroMem (&Packet, sizeof (Packet));\r
83 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
84 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
85 Packet.Timeout = SD_GENERIC_TIMEOUT;\r
86\r
87 SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;\r
88 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
89 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;\r
90\r
91 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);\r
92 if (!EFI_ERROR (Status)) {\r
87000d77 93 DEBUG ((DEBUG_INFO, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk.Resp0));\r
48555339
FT
94 *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);\r
95 }\r
96\r
97 return Status;\r
98}\r
99\r
100/**\r
101 Send command SELECT to the device to select/deselect the device.\r
102\r
103 @param[in] Device A pointer to the SD_DEVICE instance.\r
104 @param[in] Rca The relative device address to use.\r
105\r
106 @retval EFI_SUCCESS The request is executed successfully.\r
107 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
108 @retval Others The request could not be executed successfully.\r
109\r
110**/\r
111EFI_STATUS\r
112SdSelect (\r
1436aea4
MK
113 IN SD_DEVICE *Device,\r
114 IN UINT16 Rca\r
48555339
FT
115 )\r
116{\r
117 EFI_STATUS Status;\r
118 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
119 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
120 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
121 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
122\r
123 PassThru = Device->Private->PassThru;\r
124\r
125 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
126 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
127 ZeroMem (&Packet, sizeof (Packet));\r
128 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
129 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
130 Packet.Timeout = SD_GENERIC_TIMEOUT;\r
131\r
132 SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;\r
133 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
ac30e4c1
FT
134 if (Rca != 0) {\r
135 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;\r
136 }\r
1436aea4 137\r
48555339
FT
138 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
139\r
140 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);\r
141\r
142 return Status;\r
143}\r
144\r
145/**\r
146 Send command SEND_STATUS to the device to get device status.\r
147\r
148 @param[in] Device A pointer to the SD_DEVICE instance.\r
149 @param[in] Rca The relative device address to use.\r
150 @param[out] DevStatus The buffer to store the device status.\r
151\r
152 @retval EFI_SUCCESS The request is executed successfully.\r
153 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
154 @retval Others The request could not be executed successfully.\r
155\r
156**/\r
157EFI_STATUS\r
158SdSendStatus (\r
1436aea4
MK
159 IN SD_DEVICE *Device,\r
160 IN UINT16 Rca,\r
161 OUT UINT32 *DevStatus\r
48555339
FT
162 )\r
163{\r
164 EFI_STATUS Status;\r
165 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
166 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
167 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
168 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
169\r
170 PassThru = Device->Private->PassThru;\r
171\r
172 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
173 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
174 ZeroMem (&Packet, sizeof (Packet));\r
175 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
176 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
177 Packet.Timeout = SD_GENERIC_TIMEOUT;\r
178\r
1436aea4
MK
179 SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;\r
180 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
181 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
48555339
FT
182 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
183\r
184 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);\r
185 if (!EFI_ERROR (Status)) {\r
186 CopyMem (DevStatus, &SdMmcStatusBlk.Resp0, sizeof (UINT32));\r
187 }\r
1436aea4 188\r
48555339
FT
189 return Status;\r
190}\r
191\r
192/**\r
193 Send command SEND_CSD to the device to get the CSD register data.\r
194\r
195 @param[in] Device A pointer to the SD_DEVICE instance.\r
196 @param[in] Rca The relative device address to use.\r
197 @param[out] Csd The buffer to store the SD_CSD register data.\r
198\r
199 @retval EFI_SUCCESS The request is executed successfully.\r
200 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
201 @retval Others The request could not be executed successfully.\r
202\r
203**/\r
204EFI_STATUS\r
205SdGetCsd (\r
1436aea4
MK
206 IN SD_DEVICE *Device,\r
207 IN UINT16 Rca,\r
208 OUT SD_CSD *Csd\r
48555339
FT
209 )\r
210{\r
211 EFI_STATUS Status;\r
212 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
213 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
214 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
215 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
216\r
217 PassThru = Device->Private->PassThru;\r
218\r
219 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
220 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
221 ZeroMem (&Packet, sizeof (Packet));\r
222 ZeroMem (Csd, sizeof (SD_CSD));\r
223\r
224 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
225 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
226 Packet.Timeout = SD_GENERIC_TIMEOUT;\r
227\r
1436aea4
MK
228 SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;\r
229 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
230 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;\r
48555339
FT
231 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
232\r
233 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);\r
234\r
235 if (!EFI_ERROR (Status)) {\r
236 //\r
237 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
238 //\r
1436aea4 239 CopyMem (((UINT8 *)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);\r
48555339
FT
240 }\r
241\r
242 return Status;\r
243}\r
244\r
245/**\r
246 Send command SEND_CID to the device to get the CID register data.\r
247\r
248 @param[in] Device A pointer to the SD_DEVICE instance.\r
249 @param[in] Rca The relative device address to use.\r
250 @param[out] Cid The buffer to store the SD_CID register data.\r
251\r
252 @retval EFI_SUCCESS The request is executed successfully.\r
253 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
254 @retval Others The request could not be executed successfully.\r
255\r
256**/\r
257EFI_STATUS\r
258SdGetCid (\r
1436aea4
MK
259 IN SD_DEVICE *Device,\r
260 IN UINT16 Rca,\r
261 OUT SD_CID *Cid\r
48555339
FT
262 )\r
263{\r
264 EFI_STATUS Status;\r
265 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
266 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
267 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
268 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
269\r
270 PassThru = Device->Private->PassThru;\r
271\r
272 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
273 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
274 ZeroMem (&Packet, sizeof (Packet));\r
275 ZeroMem (Cid, sizeof (SD_CID));\r
276\r
277 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
278 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
279 Packet.Timeout = SD_GENERIC_TIMEOUT;\r
280\r
1436aea4
MK
281 SdMmcCmdBlk.CommandIndex = SD_SEND_CID;\r
282 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
283 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;\r
48555339
FT
284 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
285\r
286 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);\r
287\r
288 if (!EFI_ERROR (Status)) {\r
289 //\r
290 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
291 //\r
1436aea4 292 CopyMem (((UINT8 *)Cid) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CID) - 1);\r
48555339
FT
293 }\r
294\r
295 return Status;\r
296}\r
297\r
298/**\r
299 Read/write single block through sync or async I/O request.\r
300\r
301 @param[in] Device A pointer to the SD_DEVICE instance.\r
302 @param[in] Lba The starting logical block address to be read/written.\r
303 The caller is responsible for reading/writing to only\r
304 legitimate locations.\r
305 @param[in] Buffer A pointer to the destination/source buffer for the data.\r
306 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
307 @param[in] IsRead Indicates it is a read or write operation.\r
308 @param[in] Token A pointer to the token associated with the transaction.\r
309 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.\r
310 This parameter is only meaningful in async I/O request.\r
311\r
312 @retval EFI_SUCCESS The request is executed successfully.\r
313 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
314 @retval Others The request could not be executed successfully.\r
315\r
316**/\r
317EFI_STATUS\r
318SdRwSingleBlock (\r
1436aea4
MK
319 IN SD_DEVICE *Device,\r
320 IN EFI_LBA Lba,\r
321 IN VOID *Buffer,\r
322 IN UINTN BufferSize,\r
323 IN BOOLEAN IsRead,\r
324 IN EFI_BLOCK_IO2_TOKEN *Token,\r
325 IN BOOLEAN IsEnd\r
48555339
FT
326 )\r
327{\r
1436aea4
MK
328 EFI_STATUS Status;\r
329 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
330 SD_REQUEST *RwSingleBlkReq;\r
331 EFI_TPL OldTpl;\r
48555339
FT
332\r
333 RwSingleBlkReq = NULL;\r
334 PassThru = Device->Private->PassThru;\r
335\r
336 RwSingleBlkReq = AllocateZeroPool (sizeof (SD_REQUEST));\r
337 if (RwSingleBlkReq == NULL) {\r
338 Status = EFI_OUT_OF_RESOURCES;\r
339 goto Error;\r
340 }\r
341\r
342 RwSingleBlkReq->Signature = SD_REQUEST_SIGNATURE;\r
1436aea4 343 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339
FT
344 InsertTailList (&Device->Queue, &RwSingleBlkReq->Link);\r
345 gBS->RestoreTPL (OldTpl);\r
346 RwSingleBlkReq->Packet.SdMmcCmdBlk = &RwSingleBlkReq->SdMmcCmdBlk;\r
347 RwSingleBlkReq->Packet.SdMmcStatusBlk = &RwSingleBlkReq->SdMmcStatusBlk;\r
348 //\r
349 // Calculate timeout value through the below formula.\r
350 // Timeout = (transfer size) / (2MB/s).\r
351 // Taking 2MB/s as divisor as it's the lowest transfer speed\r
352 // above class 2.\r
353 // Refer to SD Physical Layer Simplified spec section 3.4 for details.\r
354 //\r
355 RwSingleBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;\r
356\r
357 if (IsRead) {\r
358 RwSingleBlkReq->Packet.InDataBuffer = Buffer;\r
359 RwSingleBlkReq->Packet.InTransferLength = (UINT32)BufferSize;\r
360\r
361 RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_SINGLE_BLOCK;\r
362 RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
363 RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
364 } else {\r
365 RwSingleBlkReq->Packet.OutDataBuffer = Buffer;\r
366 RwSingleBlkReq->Packet.OutTransferLength = (UINT32)BufferSize;\r
367\r
368 RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_SINGLE_BLOCK;\r
369 RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
370 RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
371 }\r
372\r
373 if (Device->SectorAddressing) {\r
374 RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba;\r
375 } else {\r
376 RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize);\r
377 }\r
378\r
379 RwSingleBlkReq->IsEnd = IsEnd;\r
380 RwSingleBlkReq->Token = Token;\r
381\r
382 if ((Token != NULL) && (Token->Event != NULL)) {\r
383 Status = gBS->CreateEvent (\r
384 EVT_NOTIFY_SIGNAL,\r
3b1d8241 385 TPL_NOTIFY,\r
48555339
FT
386 AsyncIoCallback,\r
387 RwSingleBlkReq,\r
388 &RwSingleBlkReq->Event\r
389 );\r
390 if (EFI_ERROR (Status)) {\r
391 goto Error;\r
392 }\r
393 } else {\r
394 RwSingleBlkReq->Event = NULL;\r
395 }\r
396\r
397 Status = PassThru->PassThru (PassThru, Device->Slot, &RwSingleBlkReq->Packet, RwSingleBlkReq->Event);\r
398\r
399Error:\r
400 if ((Token != NULL) && (Token->Event != NULL)) {\r
401 //\r
402 // For asynchronous operation, only free request and event in error case.\r
403 // The request and event will be freed in asynchronous callback for success case.\r
404 //\r
405 if (EFI_ERROR (Status) && (RwSingleBlkReq != NULL)) {\r
3b1d8241 406 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339 407 RemoveEntryList (&RwSingleBlkReq->Link);\r
3b1d8241 408 gBS->RestoreTPL (OldTpl);\r
48555339
FT
409 if (RwSingleBlkReq->Event != NULL) {\r
410 gBS->CloseEvent (RwSingleBlkReq->Event);\r
411 }\r
1436aea4 412\r
48555339
FT
413 FreePool (RwSingleBlkReq);\r
414 }\r
415 } else {\r
416 //\r
417 // For synchronous operation, free request whatever the execution result is.\r
418 //\r
419 if (RwSingleBlkReq != NULL) {\r
3b1d8241 420 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339 421 RemoveEntryList (&RwSingleBlkReq->Link);\r
3b1d8241 422 gBS->RestoreTPL (OldTpl);\r
48555339
FT
423 FreePool (RwSingleBlkReq);\r
424 }\r
425 }\r
426\r
427 return Status;\r
428}\r
429\r
430/**\r
431 Read/write multiple blocks through sync or async I/O request.\r
432\r
433 @param[in] Device A pointer to the SD_DEVICE instance.\r
434 @param[in] Lba The starting logical block address to be read/written.\r
435 The caller is responsible for reading/writing to only\r
436 legitimate locations.\r
437 @param[in] Buffer A pointer to the destination/source buffer for the data.\r
438 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
439 @param[in] IsRead Indicates it is a read or write operation.\r
440 @param[in] Token A pointer to the token associated with the transaction.\r
441 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.\r
442 This parameter is only meaningful in async I/O request.\r
443\r
444 @retval EFI_SUCCESS The request is executed successfully.\r
445 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
446 @retval Others The request could not be executed successfully.\r
447\r
448**/\r
449EFI_STATUS\r
450SdRwMultiBlocks (\r
1436aea4
MK
451 IN SD_DEVICE *Device,\r
452 IN EFI_LBA Lba,\r
453 IN VOID *Buffer,\r
454 IN UINTN BufferSize,\r
455 IN BOOLEAN IsRead,\r
456 IN EFI_BLOCK_IO2_TOKEN *Token,\r
457 IN BOOLEAN IsEnd\r
48555339
FT
458 )\r
459{\r
1436aea4
MK
460 EFI_STATUS Status;\r
461 SD_REQUEST *RwMultiBlkReq;\r
462 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
463 EFI_TPL OldTpl;\r
48555339
FT
464\r
465 RwMultiBlkReq = NULL;\r
466\r
467 PassThru = Device->Private->PassThru;\r
468\r
469 RwMultiBlkReq = AllocateZeroPool (sizeof (SD_REQUEST));\r
470 if (RwMultiBlkReq == NULL) {\r
471 Status = EFI_OUT_OF_RESOURCES;\r
472 goto Error;\r
473 }\r
474\r
475 RwMultiBlkReq->Signature = SD_REQUEST_SIGNATURE;\r
1436aea4 476 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339
FT
477 InsertTailList (&Device->Queue, &RwMultiBlkReq->Link);\r
478 gBS->RestoreTPL (OldTpl);\r
479 RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk;\r
480 RwMultiBlkReq->Packet.SdMmcStatusBlk = &RwMultiBlkReq->SdMmcStatusBlk;\r
481 //\r
482 // Calculate timeout value through the below formula.\r
483 // Timeout = (transfer size) / (2MB/s).\r
484 // Taking 2MB/s as divisor as it's the lowest transfer speed\r
485 // above class 2.\r
486 // Refer to SD Physical Layer Simplified spec section 3.4 for details.\r
487 //\r
488 RwMultiBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;\r
489\r
490 if (IsRead) {\r
491 RwMultiBlkReq->Packet.InDataBuffer = Buffer;\r
492 RwMultiBlkReq->Packet.InTransferLength = (UINT32)BufferSize;\r
493\r
494 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_MULTIPLE_BLOCK;\r
495 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
496 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
497 } else {\r
498 RwMultiBlkReq->Packet.OutDataBuffer = Buffer;\r
499 RwMultiBlkReq->Packet.OutTransferLength = (UINT32)BufferSize;\r
500\r
501 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_MULTIPLE_BLOCK;\r
502 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
503 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
504 }\r
505\r
506 if (Device->SectorAddressing) {\r
507 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba;\r
508 } else {\r
509 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize);\r
510 }\r
511\r
512 RwMultiBlkReq->IsEnd = IsEnd;\r
513 RwMultiBlkReq->Token = Token;\r
514\r
515 if ((Token != NULL) && (Token->Event != NULL)) {\r
516 Status = gBS->CreateEvent (\r
517 EVT_NOTIFY_SIGNAL,\r
3b1d8241 518 TPL_NOTIFY,\r
48555339
FT
519 AsyncIoCallback,\r
520 RwMultiBlkReq,\r
521 &RwMultiBlkReq->Event\r
522 );\r
523 if (EFI_ERROR (Status)) {\r
524 goto Error;\r
525 }\r
526 } else {\r
527 RwMultiBlkReq->Event = NULL;\r
528 }\r
529\r
530 Status = PassThru->PassThru (PassThru, Device->Slot, &RwMultiBlkReq->Packet, RwMultiBlkReq->Event);\r
531\r
532Error:\r
533 if ((Token != NULL) && (Token->Event != NULL)) {\r
534 //\r
535 // For asynchronous operation, only free request and event in error case.\r
536 // The request and event will be freed in asynchronous callback for success case.\r
537 //\r
538 if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) {\r
3b1d8241 539 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339 540 RemoveEntryList (&RwMultiBlkReq->Link);\r
3b1d8241 541 gBS->RestoreTPL (OldTpl);\r
48555339
FT
542 if (RwMultiBlkReq->Event != NULL) {\r
543 gBS->CloseEvent (RwMultiBlkReq->Event);\r
544 }\r
1436aea4 545\r
48555339
FT
546 FreePool (RwMultiBlkReq);\r
547 }\r
548 } else {\r
549 //\r
550 // For synchronous operation, free request whatever the execution result is.\r
551 //\r
552 if (RwMultiBlkReq != NULL) {\r
3b1d8241 553 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339 554 RemoveEntryList (&RwMultiBlkReq->Link);\r
3b1d8241 555 gBS->RestoreTPL (OldTpl);\r
48555339
FT
556 FreePool (RwMultiBlkReq);\r
557 }\r
558 }\r
559\r
560 return Status;\r
561}\r
562\r
563/**\r
564 This function transfers data from/to the sd memory card device.\r
565\r
566 @param[in] Device A pointer to the SD_DEVICE instance.\r
567 @param[in] MediaId The media ID that the read/write request is for.\r
568 @param[in] Lba The starting logical block address to be read/written.\r
569 The caller is responsible for reading/writing to only\r
570 legitimate locations.\r
571 @param[in, out] Buffer A pointer to the destination/source buffer for the data.\r
572 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
573 @param[in] IsRead Indicates it is a read or write operation.\r
574 @param[in, out] Token A pointer to the token associated with the transaction.\r
575\r
576 @retval EFI_SUCCESS The data was read/written correctly to the device.\r
577 @retval EFI_WRITE_PROTECTED The device can not be read/written to.\r
578 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.\r
579 @retval EFI_NO_MEDIA There is no media in the device.\r
b854b075 580 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
48555339
FT
581 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
582 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,\r
583 or the buffer is not on proper alignment.\r
584\r
585**/\r
586EFI_STATUS\r
587SdReadWrite (\r
1436aea4
MK
588 IN SD_DEVICE *Device,\r
589 IN UINT32 MediaId,\r
590 IN EFI_LBA Lba,\r
591 IN OUT VOID *Buffer,\r
592 IN UINTN BufferSize,\r
593 IN BOOLEAN IsRead,\r
594 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
48555339
FT
595 )\r
596{\r
1436aea4
MK
597 EFI_STATUS Status;\r
598 EFI_BLOCK_IO_MEDIA *Media;\r
599 UINTN BlockSize;\r
600 UINTN BlockNum;\r
601 UINTN IoAlign;\r
602 UINTN Remaining;\r
603 UINT32 MaxBlock;\r
604 BOOLEAN LastRw;\r
48555339
FT
605\r
606 Status = EFI_SUCCESS;\r
607 Media = &Device->BlockMedia;\r
608 LastRw = FALSE;\r
609\r
610 if (MediaId != Media->MediaId) {\r
611 return EFI_MEDIA_CHANGED;\r
612 }\r
613\r
614 if (!IsRead && Media->ReadOnly) {\r
615 return EFI_WRITE_PROTECTED;\r
616 }\r
617\r
618 //\r
619 // Check parameters.\r
620 //\r
621 if (Buffer == NULL) {\r
622 return EFI_INVALID_PARAMETER;\r
623 }\r
624\r
625 if (BufferSize == 0) {\r
626 if ((Token != NULL) && (Token->Event != NULL)) {\r
627 Token->TransactionStatus = EFI_SUCCESS;\r
628 gBS->SignalEvent (Token->Event);\r
629 }\r
1436aea4 630\r
48555339
FT
631 return EFI_SUCCESS;\r
632 }\r
633\r
634 BlockSize = Media->BlockSize;\r
635 if ((BufferSize % BlockSize) != 0) {\r
636 return EFI_BAD_BUFFER_SIZE;\r
637 }\r
638\r
1436aea4 639 BlockNum = BufferSize / BlockSize;\r
48555339
FT
640 if ((Lba + BlockNum - 1) > Media->LastBlock) {\r
641 return EFI_INVALID_PARAMETER;\r
642 }\r
643\r
644 IoAlign = Media->IoAlign;\r
1436aea4 645 if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {\r
48555339
FT
646 return EFI_INVALID_PARAMETER;\r
647 }\r
648\r
649 if ((Token != NULL) && (Token->Event != NULL)) {\r
650 Token->TransactionStatus = EFI_SUCCESS;\r
651 }\r
652\r
653 //\r
654 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.\r
655 //\r
656 Remaining = BlockNum;\r
657 MaxBlock = 0xFFFF;\r
658\r
659 while (Remaining > 0) {\r
660 if (Remaining <= MaxBlock) {\r
661 BlockNum = Remaining;\r
662 LastRw = TRUE;\r
663 } else {\r
664 BlockNum = MaxBlock;\r
665 }\r
666\r
667 BufferSize = BlockNum * BlockSize;\r
668 if (BlockNum == 1) {\r
669 Status = SdRwSingleBlock (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw);\r
670 } else {\r
671 Status = SdRwMultiBlocks (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw);\r
672 }\r
1436aea4 673\r
48555339
FT
674 if (EFI_ERROR (Status)) {\r
675 return Status;\r
676 }\r
1436aea4
MK
677\r
678 DEBUG ((\r
679 DEBUG_BLKIO,\r
680 "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",\r
681 IsRead ? "Read" : "Write",\r
682 Lba,\r
683 BlockNum,\r
684 (Token != NULL) ? Token->Event : NULL,\r
685 Status\r
686 ));\r
687 Lba += BlockNum;\r
688 Buffer = (UINT8 *)Buffer + BufferSize;\r
48555339
FT
689 Remaining -= BlockNum;\r
690 }\r
691\r
692 return Status;\r
693}\r
694\r
695/**\r
696 Reset the Block Device.\r
697\r
698 @param This Indicates a pointer to the calling context.\r
699 @param ExtendedVerification Driver may perform diagnostics on reset.\r
700\r
701 @retval EFI_SUCCESS The device was reset.\r
702 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
703 not be reset.\r
704\r
705**/\r
706EFI_STATUS\r
707EFIAPI\r
708SdReset (\r
1436aea4
MK
709 IN EFI_BLOCK_IO_PROTOCOL *This,\r
710 IN BOOLEAN ExtendedVerification\r
48555339
FT
711 )\r
712{\r
1436aea4
MK
713 EFI_STATUS Status;\r
714 SD_DEVICE *Device;\r
715 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
48555339
FT
716\r
717 Device = SD_DEVICE_DATA_FROM_BLKIO (This);\r
718\r
719 PassThru = Device->Private->PassThru;\r
720 Status = PassThru->ResetDevice (PassThru, Device->Slot);\r
721 if (EFI_ERROR (Status)) {\r
722 Status = EFI_DEVICE_ERROR;\r
723 }\r
724\r
725 return Status;\r
726}\r
727\r
728/**\r
729 Read BufferSize bytes from Lba into Buffer.\r
730\r
731 @param This Indicates a pointer to the calling context.\r
732 @param MediaId Id of the media, changes every time the media is replaced.\r
733 @param Lba The starting Logical Block Address to read from\r
734 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
735 @param Buffer A pointer to the destination buffer for the data. The caller is\r
736 responsible for either having implicit or explicit ownership of the buffer.\r
737\r
738 @retval EFI_SUCCESS The data was read correctly from the device.\r
739 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
740 @retval EFI_NO_MEDIA There is no media in the device.\r
b854b075 741 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
48555339
FT
742 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
743 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
744 or the buffer is not on proper alignment.\r
745\r
746**/\r
747EFI_STATUS\r
748EFIAPI\r
749SdReadBlocks (\r
750 IN EFI_BLOCK_IO_PROTOCOL *This,\r
751 IN UINT32 MediaId,\r
752 IN EFI_LBA Lba,\r
753 IN UINTN BufferSize,\r
1436aea4 754 OUT VOID *Buffer\r
48555339
FT
755 )\r
756{\r
1436aea4
MK
757 EFI_STATUS Status;\r
758 SD_DEVICE *Device;\r
48555339
FT
759\r
760 Device = SD_DEVICE_DATA_FROM_BLKIO (This);\r
761\r
762 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, NULL);\r
763 return Status;\r
764}\r
765\r
766/**\r
767 Write BufferSize bytes from Lba into Buffer.\r
768\r
769 @param This Indicates a pointer to the calling context.\r
770 @param MediaId The media ID that the write request is for.\r
771 @param Lba The starting logical block address to be written. The caller is\r
772 responsible for writing to only legitimate locations.\r
773 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
774 @param Buffer A pointer to the source buffer for the data.\r
775\r
776 @retval EFI_SUCCESS The data was written correctly to the device.\r
777 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
778 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
779 @retval EFI_NO_MEDIA There is no media in the device.\r
b854b075 780 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
48555339
FT
781 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
782 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
783 or the buffer is not on proper alignment.\r
784\r
785**/\r
786EFI_STATUS\r
787EFIAPI\r
788SdWriteBlocks (\r
1436aea4
MK
789 IN EFI_BLOCK_IO_PROTOCOL *This,\r
790 IN UINT32 MediaId,\r
791 IN EFI_LBA Lba,\r
792 IN UINTN BufferSize,\r
793 IN VOID *Buffer\r
48555339
FT
794 )\r
795{\r
1436aea4
MK
796 EFI_STATUS Status;\r
797 SD_DEVICE *Device;\r
48555339
FT
798\r
799 Device = SD_DEVICE_DATA_FROM_BLKIO (This);\r
800\r
801 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, NULL);\r
802 return Status;\r
803}\r
804\r
805/**\r
806 Flush the Block Device.\r
807\r
808 @param This Indicates a pointer to the calling context.\r
809\r
810 @retval EFI_SUCCESS All outstanding data was written to the device\r
811 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
812 @retval EFI_NO_MEDIA There is no media in the device.\r
813\r
814**/\r
815EFI_STATUS\r
816EFIAPI\r
817SdFlushBlocks (\r
1436aea4 818 IN EFI_BLOCK_IO_PROTOCOL *This\r
48555339
FT
819 )\r
820{\r
821 //\r
822 // return directly\r
823 //\r
824 return EFI_SUCCESS;\r
825}\r
826\r
827/**\r
828 Reset the Block Device.\r
829\r
830 @param[in] This Indicates a pointer to the calling context.\r
831 @param[in] ExtendedVerification Driver may perform diagnostics on reset.\r
832\r
833 @retval EFI_SUCCESS The device was reset.\r
834 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
835 not be reset.\r
836\r
837**/\r
838EFI_STATUS\r
839EFIAPI\r
840SdResetEx (\r
841 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
842 IN BOOLEAN ExtendedVerification\r
843 )\r
844{\r
1436aea4
MK
845 SD_DEVICE *Device;\r
846 LIST_ENTRY *Link;\r
847 LIST_ENTRY *NextLink;\r
848 SD_REQUEST *Request;\r
849 EFI_TPL OldTpl;\r
48555339
FT
850\r
851 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);\r
852\r
3b1d8241 853 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339
FT
854 for (Link = GetFirstNode (&Device->Queue);\r
855 !IsNull (&Device->Queue, Link);\r
1436aea4
MK
856 Link = NextLink)\r
857 {\r
48555339
FT
858 NextLink = GetNextNode (&Device->Queue, Link);\r
859 RemoveEntryList (Link);\r
860\r
861 Request = SD_REQUEST_FROM_LINK (Link);\r
862\r
863 gBS->CloseEvent (Request->Event);\r
864 Request->Token->TransactionStatus = EFI_ABORTED;\r
865\r
866 if (Request->IsEnd) {\r
867 gBS->SignalEvent (Request->Token->Event);\r
868 }\r
869\r
870 FreePool (Request);\r
871 }\r
1436aea4 872\r
48555339
FT
873 gBS->RestoreTPL (OldTpl);\r
874\r
875 return EFI_SUCCESS;\r
876}\r
877\r
878/**\r
879 Read BufferSize bytes from Lba into Buffer.\r
880\r
881 @param[in] This Indicates a pointer to the calling context.\r
882 @param[in] MediaId Id of the media, changes every time the media is replaced.\r
883 @param[in] Lba The starting Logical Block Address to read from.\r
884 @param[in, out] Token A pointer to the token associated with the transaction.\r
885 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
886 @param[out] Buffer A pointer to the destination buffer for the data. The caller is\r
887 responsible for either having implicit or explicit ownership of the buffer.\r
888\r
889 @retval EFI_SUCCESS The read request was queued if Event is not NULL.\r
890 The data was read correctly from the device if\r
891 the Event is NULL.\r
892 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
893 the read.\r
894 @retval EFI_NO_MEDIA There is no media in the device.\r
895 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
896 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
897 intrinsic block size of the device.\r
898 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
899 or the buffer is not on proper alignment.\r
900 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
901 of resources.\r
902\r
903**/\r
904EFI_STATUS\r
905EFIAPI\r
906SdReadBlocksEx (\r
1436aea4
MK
907 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
908 IN UINT32 MediaId,\r
909 IN EFI_LBA Lba,\r
910 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
911 IN UINTN BufferSize,\r
912 OUT VOID *Buffer\r
48555339
FT
913 )\r
914{\r
1436aea4
MK
915 EFI_STATUS Status;\r
916 SD_DEVICE *Device;\r
48555339
FT
917\r
918 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);\r
919\r
920 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, Token);\r
921 return Status;\r
922}\r
923\r
924/**\r
925 Write BufferSize bytes from Lba into Buffer.\r
926\r
927 @param[in] This Indicates a pointer to the calling context.\r
928 @param[in] MediaId The media ID that the write request is for.\r
929 @param[in] Lba The starting logical block address to be written. The\r
930 caller is responsible for writing to only legitimate\r
931 locations.\r
932 @param[in, out] Token A pointer to the token associated with the transaction.\r
933 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
934 @param[in] Buffer A pointer to the source buffer for the data.\r
935\r
936 @retval EFI_SUCCESS The data was written correctly to the device.\r
937 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
938 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
939 @retval EFI_NO_MEDIA There is no media in the device.\r
b854b075 940 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
48555339
FT
941 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
942 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
943 or the buffer is not on proper alignment.\r
944\r
945**/\r
946EFI_STATUS\r
947EFIAPI\r
948SdWriteBlocksEx (\r
1436aea4
MK
949 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
950 IN UINT32 MediaId,\r
951 IN EFI_LBA Lba,\r
952 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
953 IN UINTN BufferSize,\r
954 IN VOID *Buffer\r
48555339
FT
955 )\r
956{\r
1436aea4
MK
957 EFI_STATUS Status;\r
958 SD_DEVICE *Device;\r
48555339
FT
959\r
960 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);\r
961\r
962 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, Token);\r
963 return Status;\r
964}\r
965\r
966/**\r
967 Flush the Block Device.\r
968\r
969 @param[in] This Indicates a pointer to the calling context.\r
970 @param[in, out] Token A pointer to the token associated with the transaction.\r
971\r
972 @retval EFI_SUCCESS All outstanding data was written to the device\r
973 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
974 @retval EFI_NO_MEDIA There is no media in the device.\r
975\r
976**/\r
977EFI_STATUS\r
978EFIAPI\r
979SdFlushBlocksEx (\r
980 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
981 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
982 )\r
983{\r
984 //\r
985 // Signal event and return directly.\r
986 //\r
1436aea4 987 if ((Token != NULL) && (Token->Event != NULL)) {\r
48555339
FT
988 Token->TransactionStatus = EFI_SUCCESS;\r
989 gBS->SignalEvent (Token->Event);\r
990 }\r
991\r
992 return EFI_SUCCESS;\r
993}\r
994\r
275d5136
FT
995/**\r
996 Set the erase start address through sync or async I/O request.\r
997\r
998 @param[in] Device A pointer to the SD_DEVICE instance.\r
999 @param[in] StartLba The starting logical block address to be erased.\r
1000 @param[in] Token A pointer to the token associated with the transaction.\r
1001 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.\r
1002 This parameter is only meaningful in async I/O request.\r
1003\r
1004 @retval EFI_SUCCESS The request is executed successfully.\r
1005 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
1006 @retval Others The request could not be executed successfully.\r
1007\r
1008**/\r
1009EFI_STATUS\r
1010SdEraseBlockStart (\r
1436aea4
MK
1011 IN SD_DEVICE *Device,\r
1012 IN EFI_LBA StartLba,\r
1013 IN EFI_BLOCK_IO2_TOKEN *Token,\r
1014 IN BOOLEAN IsEnd\r
275d5136
FT
1015 )\r
1016{\r
1436aea4
MK
1017 EFI_STATUS Status;\r
1018 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
1019 SD_REQUEST *EraseBlockStart;\r
1020 EFI_TPL OldTpl;\r
275d5136
FT
1021\r
1022 EraseBlockStart = NULL;\r
1023 PassThru = Device->Private->PassThru;\r
1024\r
1025 EraseBlockStart = AllocateZeroPool (sizeof (SD_REQUEST));\r
1026 if (EraseBlockStart == NULL) {\r
1027 Status = EFI_OUT_OF_RESOURCES;\r
1028 goto Error;\r
1029 }\r
1030\r
1031 EraseBlockStart->Signature = SD_REQUEST_SIGNATURE;\r
1436aea4 1032 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136
FT
1033 InsertTailList (&Device->Queue, &EraseBlockStart->Link);\r
1034 gBS->RestoreTPL (OldTpl);\r
1035 EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk;\r
1036 EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;\r
1037 EraseBlockStart->Packet.Timeout = SD_GENERIC_TIMEOUT;\r
1038\r
1039 EraseBlockStart->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_START;\r
1040 EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
1041 EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
1042\r
1043 if (Device->SectorAddressing) {\r
1044 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;\r
1045 } else {\r
1046 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Device->BlockMedia.BlockSize);\r
1047 }\r
1048\r
1049 EraseBlockStart->IsEnd = IsEnd;\r
1050 EraseBlockStart->Token = Token;\r
1051\r
1052 if ((Token != NULL) && (Token->Event != NULL)) {\r
1053 Status = gBS->CreateEvent (\r
1054 EVT_NOTIFY_SIGNAL,\r
3b1d8241 1055 TPL_NOTIFY,\r
275d5136
FT
1056 AsyncIoCallback,\r
1057 EraseBlockStart,\r
1058 &EraseBlockStart->Event\r
1059 );\r
1060 if (EFI_ERROR (Status)) {\r
1061 goto Error;\r
1062 }\r
1063 } else {\r
1064 EraseBlockStart->Event = NULL;\r
1065 }\r
1066\r
1067 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event);\r
1068\r
1069Error:\r
1070 if ((Token != NULL) && (Token->Event != NULL)) {\r
1071 //\r
1072 // For asynchronous operation, only free request and event in error case.\r
1073 // The request and event will be freed in asynchronous callback for success case.\r
1074 //\r
1075 if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) {\r
3b1d8241 1076 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1077 RemoveEntryList (&EraseBlockStart->Link);\r
3b1d8241 1078 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1079 if (EraseBlockStart->Event != NULL) {\r
1080 gBS->CloseEvent (EraseBlockStart->Event);\r
1081 }\r
1436aea4 1082\r
275d5136
FT
1083 FreePool (EraseBlockStart);\r
1084 }\r
1085 } else {\r
1086 //\r
1087 // For synchronous operation, free request whatever the execution result is.\r
1088 //\r
1089 if (EraseBlockStart != NULL) {\r
3b1d8241 1090 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1091 RemoveEntryList (&EraseBlockStart->Link);\r
3b1d8241 1092 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1093 FreePool (EraseBlockStart);\r
1094 }\r
1095 }\r
1096\r
1097 return Status;\r
1098}\r
1099\r
1100/**\r
1101 Set the erase end address through sync or async I/O request.\r
1102\r
1103 @param[in] Device A pointer to the SD_DEVICE instance.\r
1104 @param[in] EndLba The ending logical block address to be erased.\r
1105 @param[in] Token A pointer to the token associated with the transaction.\r
1106 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.\r
1107 This parameter is only meaningful in async I/O request.\r
1108\r
1109 @retval EFI_SUCCESS The request is executed successfully.\r
1110 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
1111 @retval Others The request could not be executed successfully.\r
1112\r
1113**/\r
1114EFI_STATUS\r
1115SdEraseBlockEnd (\r
1436aea4
MK
1116 IN SD_DEVICE *Device,\r
1117 IN EFI_LBA EndLba,\r
1118 IN EFI_BLOCK_IO2_TOKEN *Token,\r
1119 IN BOOLEAN IsEnd\r
275d5136
FT
1120 )\r
1121{\r
1436aea4
MK
1122 EFI_STATUS Status;\r
1123 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
1124 SD_REQUEST *EraseBlockEnd;\r
1125 EFI_TPL OldTpl;\r
275d5136
FT
1126\r
1127 EraseBlockEnd = NULL;\r
1128 PassThru = Device->Private->PassThru;\r
1129\r
1130 EraseBlockEnd = AllocateZeroPool (sizeof (SD_REQUEST));\r
1131 if (EraseBlockEnd == NULL) {\r
1132 Status = EFI_OUT_OF_RESOURCES;\r
1133 goto Error;\r
1134 }\r
1135\r
1136 EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE;\r
1436aea4 1137 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136
FT
1138 InsertTailList (&Device->Queue, &EraseBlockEnd->Link);\r
1139 gBS->RestoreTPL (OldTpl);\r
1140 EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk;\r
1141 EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;\r
1142 EraseBlockEnd->Packet.Timeout = SD_GENERIC_TIMEOUT;\r
1143\r
1144 EraseBlockEnd->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_END;\r
1145 EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
1146 EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
1147\r
1148 if (Device->SectorAddressing) {\r
1149 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;\r
1150 } else {\r
1151 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Device->BlockMedia.BlockSize);\r
1152 }\r
1153\r
1154 EraseBlockEnd->IsEnd = IsEnd;\r
1155 EraseBlockEnd->Token = Token;\r
1156\r
1157 if ((Token != NULL) && (Token->Event != NULL)) {\r
1158 Status = gBS->CreateEvent (\r
1159 EVT_NOTIFY_SIGNAL,\r
3b1d8241 1160 TPL_NOTIFY,\r
275d5136
FT
1161 AsyncIoCallback,\r
1162 EraseBlockEnd,\r
1163 &EraseBlockEnd->Event\r
1164 );\r
1165 if (EFI_ERROR (Status)) {\r
1166 goto Error;\r
1167 }\r
1168 } else {\r
1169 EraseBlockEnd->Event = NULL;\r
1170 }\r
1171\r
1172 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event);\r
1173\r
1174Error:\r
1175 if ((Token != NULL) && (Token->Event != NULL)) {\r
1176 //\r
1177 // For asynchronous operation, only free request and event in error case.\r
1178 // The request and event will be freed in asynchronous callback for success case.\r
1179 //\r
1180 if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) {\r
3b1d8241 1181 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1182 RemoveEntryList (&EraseBlockEnd->Link);\r
3b1d8241 1183 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1184 if (EraseBlockEnd->Event != NULL) {\r
1185 gBS->CloseEvent (EraseBlockEnd->Event);\r
1186 }\r
1436aea4 1187\r
275d5136
FT
1188 FreePool (EraseBlockEnd);\r
1189 }\r
1190 } else {\r
1191 //\r
1192 // For synchronous operation, free request whatever the execution result is.\r
1193 //\r
1194 if (EraseBlockEnd != NULL) {\r
3b1d8241 1195 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1196 RemoveEntryList (&EraseBlockEnd->Link);\r
3b1d8241 1197 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1198 FreePool (EraseBlockEnd);\r
1199 }\r
1200 }\r
1201\r
1202 return Status;\r
1203}\r
1204\r
1205/**\r
1206 Erase specified blocks through sync or async I/O request.\r
1207\r
1208 @param[in] Device A pointer to the SD_DEVICE instance.\r
1209 @param[in] Token A pointer to the token associated with the transaction.\r
1210 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.\r
1211 This parameter is only meaningful in async I/O request.\r
1212\r
1213 @retval EFI_SUCCESS The request is executed successfully.\r
1214 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.\r
1215 @retval Others The request could not be executed successfully.\r
1216\r
1217**/\r
1218EFI_STATUS\r
1219SdEraseBlock (\r
1436aea4
MK
1220 IN SD_DEVICE *Device,\r
1221 IN EFI_BLOCK_IO2_TOKEN *Token,\r
1222 IN BOOLEAN IsEnd\r
275d5136
FT
1223 )\r
1224{\r
1436aea4
MK
1225 EFI_STATUS Status;\r
1226 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
1227 SD_REQUEST *EraseBlock;\r
1228 EFI_TPL OldTpl;\r
275d5136
FT
1229\r
1230 EraseBlock = NULL;\r
1231 PassThru = Device->Private->PassThru;\r
1232\r
1233 EraseBlock = AllocateZeroPool (sizeof (SD_REQUEST));\r
1234 if (EraseBlock == NULL) {\r
1235 Status = EFI_OUT_OF_RESOURCES;\r
1236 goto Error;\r
1237 }\r
1238\r
1239 EraseBlock->Signature = SD_REQUEST_SIGNATURE;\r
1436aea4 1240 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136
FT
1241 InsertTailList (&Device->Queue, &EraseBlock->Link);\r
1242 gBS->RestoreTPL (OldTpl);\r
1243 EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk;\r
1244 EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;\r
1245 EraseBlock->Packet.Timeout = SD_GENERIC_TIMEOUT;\r
1246\r
1247 EraseBlock->SdMmcCmdBlk.CommandIndex = SD_ERASE;\r
1248 EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
1249 EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;\r
1250\r
1251 EraseBlock->IsEnd = IsEnd;\r
1252 EraseBlock->Token = Token;\r
1253\r
1254 if ((Token != NULL) && (Token->Event != NULL)) {\r
1255 Status = gBS->CreateEvent (\r
1256 EVT_NOTIFY_SIGNAL,\r
3b1d8241 1257 TPL_NOTIFY,\r
275d5136
FT
1258 AsyncIoCallback,\r
1259 EraseBlock,\r
1260 &EraseBlock->Event\r
1261 );\r
1262 if (EFI_ERROR (Status)) {\r
1263 goto Error;\r
1264 }\r
1265 } else {\r
1266 EraseBlock->Event = NULL;\r
1267 }\r
1268\r
1269 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event);\r
1270\r
1271Error:\r
1272 if ((Token != NULL) && (Token->Event != NULL)) {\r
1273 //\r
1274 // For asynchronous operation, only free request and event in error case.\r
1275 // The request and event will be freed in asynchronous callback for success case.\r
1276 //\r
1277 if (EFI_ERROR (Status) && (EraseBlock != NULL)) {\r
3b1d8241 1278 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1279 RemoveEntryList (&EraseBlock->Link);\r
3b1d8241 1280 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1281 if (EraseBlock->Event != NULL) {\r
1282 gBS->CloseEvent (EraseBlock->Event);\r
1283 }\r
1436aea4 1284\r
275d5136
FT
1285 FreePool (EraseBlock);\r
1286 }\r
1287 } else {\r
1288 //\r
1289 // For synchronous operation, free request whatever the execution result is.\r
1290 //\r
1291 if (EraseBlock != NULL) {\r
3b1d8241 1292 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
275d5136 1293 RemoveEntryList (&EraseBlock->Link);\r
3b1d8241 1294 gBS->RestoreTPL (OldTpl);\r
275d5136
FT
1295 FreePool (EraseBlock);\r
1296 }\r
1297 }\r
1298\r
1299 return Status;\r
1300}\r
1301\r
1302/**\r
1303 Erase a specified number of device blocks.\r
1304\r
1305 @param[in] This Indicates a pointer to the calling context.\r
1306 @param[in] MediaId The media ID that the erase request is for.\r
1307 @param[in] Lba The starting logical block address to be\r
1308 erased. The caller is responsible for erasing\r
1309 only legitimate locations.\r
1310 @param[in, out] Token A pointer to the token associated with the\r
1311 transaction.\r
1312 @param[in] Size The size in bytes to be erased. This must be\r
1313 a multiple of the physical block size of the\r
1314 device.\r
1315\r
1316 @retval EFI_SUCCESS The erase request was queued if Event is not\r
1317 NULL. The data was erased correctly to the\r
1318 device if the Event is NULL.to the device.\r
1319 @retval EFI_WRITE_PROTECTED The device cannot be erased due to write\r
1320 protection.\r
1321 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
1322 to perform the erase operation.\r
1323 @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not\r
1324 valid.\r
1325 @retval EFI_NO_MEDIA There is no media in the device.\r
1326 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1327\r
1328**/\r
1329EFI_STATUS\r
1330EFIAPI\r
1331SdEraseBlocks (\r
1436aea4
MK
1332 IN EFI_ERASE_BLOCK_PROTOCOL *This,\r
1333 IN UINT32 MediaId,\r
1334 IN EFI_LBA Lba,\r
1335 IN OUT EFI_ERASE_BLOCK_TOKEN *Token,\r
1336 IN UINTN Size\r
275d5136
FT
1337 )\r
1338{\r
1436aea4
MK
1339 EFI_STATUS Status;\r
1340 EFI_BLOCK_IO_MEDIA *Media;\r
1341 UINTN BlockSize;\r
1342 UINTN BlockNum;\r
1343 EFI_LBA LastLba;\r
1344 SD_DEVICE *Device;\r
275d5136
FT
1345\r
1346 Status = EFI_SUCCESS;\r
1347 Device = SD_DEVICE_DATA_FROM_ERASEBLK (This);\r
1348 Media = &Device->BlockMedia;\r
1349\r
1350 if (MediaId != Media->MediaId) {\r
1351 return EFI_MEDIA_CHANGED;\r
1352 }\r
1353\r
1354 if (Media->ReadOnly) {\r
1355 return EFI_WRITE_PROTECTED;\r
1356 }\r
1357\r
1358 //\r
1359 // Check parameters.\r
1360 //\r
1361 BlockSize = Media->BlockSize;\r
1362 if ((Size % BlockSize) != 0) {\r
1363 return EFI_INVALID_PARAMETER;\r
1364 }\r
1365\r
1436aea4 1366 BlockNum = Size / BlockSize;\r
275d5136
FT
1367 if ((Lba + BlockNum - 1) > Media->LastBlock) {\r
1368 return EFI_INVALID_PARAMETER;\r
1369 }\r
1370\r
1371 if ((Token != NULL) && (Token->Event != NULL)) {\r
1372 Token->TransactionStatus = EFI_SUCCESS;\r
1373 }\r
1374\r
1375 LastLba = Lba + BlockNum - 1;\r
1376\r
1436aea4 1377 Status = SdEraseBlockStart (Device, Lba, (EFI_BLOCK_IO2_TOKEN *)Token, FALSE);\r
275d5136
FT
1378 if (EFI_ERROR (Status)) {\r
1379 return Status;\r
1380 }\r
1381\r
1436aea4 1382 Status = SdEraseBlockEnd (Device, LastLba, (EFI_BLOCK_IO2_TOKEN *)Token, FALSE);\r
275d5136
FT
1383 if (EFI_ERROR (Status)) {\r
1384 return Status;\r
1385 }\r
1386\r
1436aea4 1387 Status = SdEraseBlock (Device, (EFI_BLOCK_IO2_TOKEN *)Token, TRUE);\r
275d5136
FT
1388 if (EFI_ERROR (Status)) {\r
1389 return Status;\r
1390 }\r
1391\r
695d90b9
GJ
1392 DEBUG ((\r
1393 DEBUG_INFO,\r
1394 "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",\r
1395 Lba,\r
1396 BlockNum,\r
1397 (Token != NULL) ? Token->Event : NULL,\r
1398 Status\r
1399 ));\r
275d5136
FT
1400\r
1401 return Status;\r
1402}\r