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