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