]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / CEATA.c
1 /** @file
2
3 CEATA specific functions implementation
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "SDMediaDevice.h"
12
13 /**
14 Send RW_MULTIPLE_REGISTER command
15
16 @param CardData Pointer to CARD_DATA.
17 @param Address Register address.
18 @param ByteCount Buffer size.
19 @param Write TRUE means write, FALSE means read.
20 @param Buffer Buffer pointer.
21
22 @retval EFI_SUCCESS Success
23 @retval EFI_DEVICE_ERROR Hardware Error
24 @retval EFI_INVALID_PARAMETER Parameter is error
25 @retval EFI_NO_MEDIA No media
26 @retval EFI_MEDIA_CHANGED Media Change
27 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
28
29 **/
30 EFI_STATUS
31 ReadWriteMultipleRegister (
32 IN CARD_DATA *CardData,
33 IN UINT16 Address,
34 IN UINT8 ByteCount,
35 IN BOOLEAN Write,
36 IN UINT8 *Buffer
37 )
38 {
39 EFI_STATUS Status;
40 UINT32 Argument;
41
42 Status = EFI_SUCCESS;
43
44 if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {
45 Status = EFI_INVALID_PARAMETER;
46 goto Exit;
47 }
48
49 Argument = (Address << 16) | ByteCount;
50 if (Write) {
51 Argument |= BIT31;
52 }
53
54
55 if (Write) {
56 CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);
57
58 Status = SendCommand (
59 CardData,
60 RW_MULTIPLE_REGISTER,
61 Argument,
62 OutData,
63 CardData->AlignedBuffer,
64 ByteCount,
65 ResponseR1b,
66 TIMEOUT_DATA,
67 (UINT32*)&(CardData->CardStatus)
68 );
69 } else {
70 Status = SendCommand (
71 CardData,
72 RW_MULTIPLE_REGISTER,
73 Argument,
74 InData,
75 CardData->AlignedBuffer,
76 ByteCount,
77 ResponseR1,
78 TIMEOUT_DATA,
79 (UINT32*)&(CardData->CardStatus)
80 );
81 if (!EFI_ERROR (Status)) {
82 CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);
83 }
84
85 }
86 Exit:
87 return Status;
88 }
89
90 /**
91 Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command
92
93 @param CardData Pointer to CARD_DATA.
94 @param DataUnitCount Buffer size in 512 bytes unit.
95 @param Write TRUE means write, FALSE means read.
96 @param Buffer Buffer pointer.
97
98 @retval EFI_SUCCESS Success
99 @retval EFI_DEVICE_ERROR Hardware Error
100 @retval EFI_INVALID_PARAMETER Parameter is error
101 @retval EFI_NO_MEDIA No media
102 @retval EFI_MEDIA_CHANGED Media Change
103 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
104
105 **/
106 EFI_STATUS
107 ReadWriteMultipleBlock (
108 IN CARD_DATA *CardData,
109 IN UINT16 DataUnitCount,
110 IN BOOLEAN Write,
111 IN UINT8 *Buffer
112 )
113 {
114 EFI_STATUS Status;
115 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
116 UINT32 TransferLength;
117
118 Status = EFI_SUCCESS;
119 SDHostIo = CardData->SDHostIo;
120
121 TransferLength = DataUnitCount * DATA_UNIT_SIZE;
122 if (TransferLength > SDHostIo->HostCapability.BoundarySize) {
123 return EFI_INVALID_PARAMETER;
124 }
125
126 if (Write) {
127 CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);
128
129 Status = SendCommand (
130 CardData,
131 RW_MULTIPLE_BLOCK,
132 (DataUnitCount | BIT31),
133 OutData,
134 CardData->AlignedBuffer,
135 TransferLength,
136 ResponseR1b,
137 TIMEOUT_DATA,
138 (UINT32*)&(CardData->CardStatus)
139 );
140 } else {
141 Status = SendCommand (
142 CardData,
143 RW_MULTIPLE_BLOCK,
144 DataUnitCount,
145 InData,
146 CardData->AlignedBuffer,
147 TransferLength,
148 ResponseR1,
149 TIMEOUT_DATA,
150 (UINT32*)&(CardData->CardStatus)
151 );
152 if (!EFI_ERROR (Status)) {
153 CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);
154 }
155 }
156
157 return Status;
158 }
159
160 /**
161 Send software reset
162
163 @param CardData Pointer to CARD_DATA.
164
165 @retval EFI_SUCCESS Success
166 @retval EFI_DEVICE_ERROR Hardware Error
167 @retval EFI_INVALID_PARAMETER Parameter is error
168 @retval EFI_NO_MEDIA No media
169 @retval EFI_MEDIA_CHANGED Media Change
170 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
171
172 **/
173 EFI_STATUS
174 SoftwareReset (
175 IN CARD_DATA *CardData
176 )
177 {
178 EFI_STATUS Status;
179 UINT8 Data;
180 UINT32 TimeOut;
181
182 Data = BIT2;
183
184 Status = FastIO (CardData, Reg_Control, &Data, TRUE);
185 if (EFI_ERROR (Status)) {
186 goto Exit;
187 }
188
189 TimeOut = 5 * 1000;
190
191 do {
192 gBS->Stall (1 * 1000);
193 Status = FastIO (CardData, Reg_Control, &Data, FALSE);
194 if (EFI_ERROR (Status)) {
195 goto Exit;
196 }
197 if ((Data & BIT2) == BIT2) {
198 break;
199 }
200
201 TimeOut--;
202 } while (TimeOut > 0);
203
204 if (TimeOut == 0) {
205 Status = EFI_TIMEOUT;
206 goto Exit;
207 }
208
209 Data &= ~BIT2;
210 Status = FastIO (CardData, Reg_Control, &Data, TRUE);
211
212 TimeOut = 5 * 1000;
213
214 do {
215 gBS->Stall (1 * 1000);
216 Status = FastIO (CardData, Reg_Control, &Data, FALSE);
217 if (EFI_ERROR (Status)) {
218 goto Exit;
219 }
220 if ((Data & BIT2) != BIT2) {
221 break;
222 }
223
224 TimeOut--;
225 } while (TimeOut > 0);
226
227
228 if (TimeOut == 0) {
229 Status = EFI_TIMEOUT;
230 goto Exit;
231 }
232
233
234 Exit:
235 return Status;
236 }
237
238
239 /**
240 SendATACommand specificed in Taskfile
241
242 @param CardData Pointer to CARD_DATA.
243 @param TaskFile Pointer to TASK_FILE.
244 @param Write TRUE means write, FALSE means read.
245 @param Buffer If NULL, means no data transfer, neither read nor write.
246 @param SectorCount Buffer size in 512 bytes unit.
247
248 @retval EFI_SUCCESS Success
249 @retval EFI_DEVICE_ERROR Hardware Error
250 @retval EFI_INVALID_PARAMETER Parameter is error
251 @retval EFI_NO_MEDIA No media
252 @retval EFI_MEDIA_CHANGED Media Change
253 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
254
255 **/
256 EFI_STATUS
257 SendATACommand (
258 IN CARD_DATA *CardData,
259 IN TASK_FILE *TaskFile,
260 IN BOOLEAN Write,
261 IN UINT8 *Buffer,
262 IN UINT16 SectorCount
263 )
264 {
265 EFI_STATUS Status;
266 UINT8 Data;
267 UINT32 TimeOut;
268
269 //
270 //Write register
271 //
272 Status = ReadWriteMultipleRegister (
273 CardData,
274 0,
275 sizeof (TASK_FILE),
276 TRUE,
277 (UINT8*)TaskFile
278 );
279 if (EFI_ERROR (Status)) {
280 DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));
281 goto Exit;
282 }
283
284 TimeOut = 5000;
285 do {
286 gBS->Stall (1 * 1000);
287 Data = 0;
288 Status = FastIO (
289 CardData,
290 Reg_Command_Status,
291 &Data,
292 FALSE
293 );
294 if (EFI_ERROR (Status)) {
295 return Status;
296 }
297
298 if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {
299 break;
300 }
301
302 TimeOut --;
303 } while (TimeOut > 0);
304
305 if (TimeOut == 0) {
306 DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));
307 Status = EFI_TIMEOUT;
308 goto Exit;
309 }
310
311
312 if (Buffer != NULL) {
313 Status = ReadWriteMultipleBlock (
314 CardData,
315 SectorCount,
316 Write,
317 (UINT8*)Buffer
318 );
319 if (EFI_ERROR (Status)) {
320 DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));
321 goto Exit;
322 }
323
324 TimeOut = 5 * 1000;
325 do {
326 gBS->Stall (1 * 1000);
327
328 Data = 0;
329 Status = FastIO (
330 CardData,
331 Reg_Command_Status,
332 &Data,
333 FALSE
334 );
335 if (EFI_ERROR (Status)) {
336 return Status;
337 }
338
339 if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {
340 break;
341 }
342
343 TimeOut --;
344 } while (TimeOut > 0);
345 if (TimeOut == 0) {
346 DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));
347 Status = EFI_TIMEOUT;
348 goto Exit;
349 }
350
351
352 if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {
353 Status = EFI_SUCCESS;
354 } else {
355 Status = EFI_DEVICE_ERROR;
356 }
357 }
358
359 Exit:
360 if (EFI_ERROR (Status)) {
361 SoftwareReset (CardData);
362 }
363
364 return Status;
365 }
366
367 /**
368 IDENTIFY_DEVICE command
369
370 @param CardData Pointer to CARD_DATA.
371
372 @retval EFI_SUCCESS Success
373 @retval EFI_DEVICE_ERROR Hardware Error
374 @retval EFI_INVALID_PARAMETER Parameter is error
375 @retval EFI_NO_MEDIA No media
376 @retval EFI_MEDIA_CHANGED Media Change
377 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
378
379 **/
380 EFI_STATUS
381 IndentifyDevice (
382 IN CARD_DATA *CardData
383 )
384 {
385 EFI_STATUS Status;
386
387 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
388
389 //
390 //The host only supports nIEN = 0
391 //
392 CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;
393
394
395 Status = SendATACommand (
396 CardData,
397 &CardData->TaskFile,
398 FALSE,
399 (UINT8*)&(CardData->IndentifyDeviceData),
400 1
401 );
402
403
404 return Status;
405 }
406
407 /**
408 FLUSH_CACHE_EXT command
409
410 @param CardData Pointer to CARD_DATA.
411
412 @retval EFI_SUCCESS Success
413 @retval EFI_DEVICE_ERROR Hardware Error
414 @retval EFI_INVALID_PARAMETER Parameter is error
415 @retval EFI_NO_MEDIA No media
416 @retval EFI_MEDIA_CHANGED Media Change
417 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
418
419 **/
420 EFI_STATUS
421 FlushCache (
422 IN CARD_DATA *CardData
423 )
424 {
425
426 //
427 //Hitachi CE-ATA will always make the busy high after
428 //receving this command
429 //
430 /*
431 EFI_STATUS Status;
432 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
433 //
434 //The host only supports nIEN = 0
435 //
436 CardData->TaskFile.Command_Status = FLUSH_CACHE_EXT;
437
438 Status = SendATACommand (
439 CardData,
440 &CardData->TaskFile,
441 FALSE,
442 NULL,
443 0
444 );
445 */
446 return EFI_SUCCESS;
447 }
448
449 /**
450 STANDBY_IMMEDIATE command
451
452 @param CardData Pointer to CARD_DATA.
453
454 @retval EFI_SUCCESS Success
455 @retval EFI_DEVICE_ERROR Hardware Error
456 @retval EFI_INVALID_PARAMETER Parameter is error
457 @retval EFI_NO_MEDIA No media
458 @retval EFI_MEDIA_CHANGED Media Change
459 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
460
461 **/
462 EFI_STATUS
463 StandByImmediate (
464 IN CARD_DATA *CardData
465 )
466 {
467 EFI_STATUS Status;
468
469 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
470 //
471 //The host only supports nIEN = 0
472 //
473 CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;
474
475
476 Status = SendATACommand (
477 CardData,
478 &CardData->TaskFile,
479 FALSE,
480 NULL,
481 0
482 );
483 return Status;
484 }
485
486 /**
487 READ_DMA_EXT command
488
489 @param CardData Pointer to CARD_DATA.
490 @param LBA The starting logical block address to read from on the device.
491 @param Buffer A pointer to the destination buffer for the data. The caller
492 is responsible for either having implicit or explicit ownership
493 of the buffer.
494 @param SectorCount Size in 512 bytes unit.
495
496 @retval EFI_SUCCESS Success
497 @retval EFI_DEVICE_ERROR Hardware Error
498 @retval EFI_INVALID_PARAMETER Parameter is error
499 @retval EFI_NO_MEDIA No media
500 @retval EFI_MEDIA_CHANGED Media Change
501 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
502
503 **/
504 EFI_STATUS
505 ReadDMAExt (
506 IN CARD_DATA *CardData,
507 IN EFI_LBA LBA,
508 IN UINT8 *Buffer,
509 IN UINT16 SectorCount
510 )
511 {
512
513 EFI_STATUS Status;
514
515 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
516 //
517 //The host only supports nIEN = 0
518 //
519 CardData->TaskFile.Command_Status = READ_DMA_EXT;
520
521 CardData->TaskFile.SectorCount = (UINT8)SectorCount;
522 CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
523
524 CardData->TaskFile.LBALow = (UINT8)LBA;
525 CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
526 CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
527
528 CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
529 CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
530 CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
531
532 Status = SendATACommand (
533 CardData,
534 &CardData->TaskFile,
535 FALSE,
536 Buffer,
537 SectorCount
538 );
539 return Status;
540
541 }
542
543 /**
544 WRITE_DMA_EXT command
545
546 @param CardData Pointer to CARD_DATA.
547 @param LBA The starting logical block address to read from on the device.
548 @param Buffer A pointer to the destination buffer for the data. The caller
549 is responsible for either having implicit or explicit ownership
550 of the buffer.
551 @param SectorCount Size in 512 bytes unit.
552
553 @retval EFI_SUCCESS Success
554 @retval EFI_DEVICE_ERROR Hardware Error
555 @retval EFI_INVALID_PARAMETER Parameter is error
556 @retval EFI_NO_MEDIA No media
557 @retval EFI_MEDIA_CHANGED Media Change
558 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
559
560 **/
561 EFI_STATUS
562 WriteDMAExt (
563 IN CARD_DATA *CardData,
564 IN EFI_LBA LBA,
565 IN UINT8 *Buffer,
566 IN UINT16 SectorCount
567 )
568 {
569
570 EFI_STATUS Status;
571
572 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
573 //
574 //The host only supports nIEN = 0
575 //
576 CardData->TaskFile.Command_Status = WRITE_DMA_EXT;
577
578 CardData->TaskFile.SectorCount = (UINT8)SectorCount;
579 CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
580
581 CardData->TaskFile.LBALow = (UINT8)LBA;
582 CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
583 CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
584
585 CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
586 CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
587 CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
588
589 Status = SendATACommand (
590 CardData,
591 &CardData->TaskFile,
592 TRUE,
593 Buffer,
594 SectorCount
595 );
596 return Status;
597
598 }
599
600
601 /**
602 Judge whether it is CE-ATA device or not.
603
604 @param CardData Pointer to CARD_DATA.
605
606 @retval TRUE
607 @retval FALSE
608
609 **/
610 BOOLEAN
611 IsCEATADevice (
612 IN CARD_DATA *CardData
613 )
614 {
615 EFI_STATUS Status;
616
617 Status = ReadWriteMultipleRegister (
618 CardData,
619 0,
620 sizeof (TASK_FILE),
621 FALSE,
622 (UINT8*)&CardData->TaskFile
623 );
624 if (EFI_ERROR (Status)) {
625 //
626 //To bring back the normal MMC card to work
627 //
628 CardData->SDHostIo->ResetSDHost (CardData->SDHostIo, Reset_DAT_CMD);
629 return FALSE;
630 }
631
632 if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&
633 CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA
634 ) {
635 //
636 //Disable Auto CMD for CE-ATA
637 //
638 CardData->SDHostIo->EnableAutoStopCmd (CardData->SDHostIo, FALSE);
639
640 return TRUE;
641 }
642
643 return FALSE;
644 }
645
646
647