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 UINT8 Data;
273 UINT32 TimeOut;
274
275 //
276 //Write register
277 //
278 Status = ReadWriteMultipleRegister (
279 CardData,
280 0,
281 sizeof (TASK_FILE),
282 TRUE,
283 (UINT8*)TaskFile
284 );
285 if (EFI_ERROR (Status)) {
286 DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));
287 goto Exit;
288 }
289
290 TimeOut = 5000;
291 do {
292 gBS->Stall (1 * 1000);
293 Data = 0;
294 Status = FastIO (
295 CardData,
296 Reg_Command_Status,
297 &Data,
298 FALSE
299 );
300 if (EFI_ERROR (Status)) {
301 return Status;
302 }
303
304 if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {
305 break;
306 }
307
308 TimeOut --;
309 } while (TimeOut > 0);
310
311 if (TimeOut == 0) {
312 DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));
313 Status = EFI_TIMEOUT;
314 goto Exit;
315 }
316
317
318 if (Buffer != NULL) {
319 Status = ReadWriteMultipleBlock (
320 CardData,
321 SectorCount,
322 Write,
323 (UINT8*)Buffer
324 );
325 if (EFI_ERROR (Status)) {
326 DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));
327 goto Exit;
328 }
329
330 TimeOut = 5 * 1000;
331 do {
332 gBS->Stall (1 * 1000);
333
334 Data = 0;
335 Status = FastIO (
336 CardData,
337 Reg_Command_Status,
338 &Data,
339 FALSE
340 );
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344
345 if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {
346 break;
347 }
348
349 TimeOut --;
350 } while (TimeOut > 0);
351 if (TimeOut == 0) {
352 DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));
353 Status = EFI_TIMEOUT;
354 goto Exit;
355 }
356
357
358 if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {
359 Status = EFI_SUCCESS;
360 } else {
361 Status = EFI_DEVICE_ERROR;
362 }
363 }
364
365 Exit:
366 if (EFI_ERROR (Status)) {
367 SoftwareReset (CardData);
368 }
369
370 return Status;
371 }
372
373 /**
374 IDENTIFY_DEVICE command
375
376 @param CardData Pointer to CARD_DATA.
377
378 @retval EFI_SUCCESS Success
379 @retval EFI_DEVICE_ERROR Hardware Error
380 @retval EFI_INVALID_PARAMETER Parameter is error
381 @retval EFI_NO_MEDIA No media
382 @retval EFI_MEDIA_CHANGED Media Change
383 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
384
385 **/
386 EFI_STATUS
IndentifyDevice(IN CARD_DATA * CardData)387 IndentifyDevice (
388 IN CARD_DATA *CardData
389 )
390 {
391 EFI_STATUS Status;
392
393 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
394
395 //
396 //The host only supports nIEN = 0
397 //
398 CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;
399
400
401 Status = SendATACommand (
402 CardData,
403 &CardData->TaskFile,
404 FALSE,
405 (UINT8*)&(CardData->IndentifyDeviceData),
406 1
407 );
408
409
410 return Status;
411 }
412
413 /**
414 FLUSH_CACHE_EXT command
415
416 @param CardData Pointer to CARD_DATA.
417
418 @retval EFI_SUCCESS Success
419 @retval EFI_DEVICE_ERROR Hardware Error
420 @retval EFI_INVALID_PARAMETER Parameter is error
421 @retval EFI_NO_MEDIA No media
422 @retval EFI_MEDIA_CHANGED Media Change
423 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
424
425 **/
426 EFI_STATUS
FlushCache(IN CARD_DATA * CardData)427 FlushCache (
428 IN CARD_DATA *CardData
429 )
430 {
431
432 //
433 //Hitachi CE-ATA will always make the busy high after
434 //receving this command
435 //
436 /*
437 EFI_STATUS Status;
438 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
439 //
440 //The host only supports nIEN = 0
441 //
442 CardData->TaskFile.Command_Status = FLUSH_CACHE_EXT;
443
444 Status = SendATACommand (
445 CardData,
446 &CardData->TaskFile,
447 FALSE,
448 NULL,
449 0
450 );
451 */
452 return EFI_SUCCESS;
453 }
454
455 /**
456 STANDBY_IMMEDIATE command
457
458 @param CardData Pointer to CARD_DATA.
459
460 @retval EFI_SUCCESS Success
461 @retval EFI_DEVICE_ERROR Hardware Error
462 @retval EFI_INVALID_PARAMETER Parameter is error
463 @retval EFI_NO_MEDIA No media
464 @retval EFI_MEDIA_CHANGED Media Change
465 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
466
467 **/
468 EFI_STATUS
StandByImmediate(IN CARD_DATA * CardData)469 StandByImmediate (
470 IN CARD_DATA *CardData
471 )
472 {
473 EFI_STATUS Status;
474
475 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
476 //
477 //The host only supports nIEN = 0
478 //
479 CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;
480
481
482 Status = SendATACommand (
483 CardData,
484 &CardData->TaskFile,
485 FALSE,
486 NULL,
487 0
488 );
489 return Status;
490 }
491
492 /**
493 READ_DMA_EXT command
494
495 @param CardData Pointer to CARD_DATA.
496 @param LBA The starting logical block address to read from on the device.
497 @param Buffer A pointer to the destination buffer for the data. The caller
498 is responsible for either having implicit or explicit ownership
499 of the buffer.
500 @param SectorCount Size in 512 bytes unit.
501
502 @retval EFI_SUCCESS Success
503 @retval EFI_DEVICE_ERROR Hardware Error
504 @retval EFI_INVALID_PARAMETER Parameter is error
505 @retval EFI_NO_MEDIA No media
506 @retval EFI_MEDIA_CHANGED Media Change
507 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
508
509 **/
510 EFI_STATUS
ReadDMAExt(IN CARD_DATA * CardData,IN EFI_LBA LBA,IN UINT8 * Buffer,IN UINT16 SectorCount)511 ReadDMAExt (
512 IN CARD_DATA *CardData,
513 IN EFI_LBA LBA,
514 IN UINT8 *Buffer,
515 IN UINT16 SectorCount
516 )
517 {
518
519 EFI_STATUS Status;
520
521 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
522 //
523 //The host only supports nIEN = 0
524 //
525 CardData->TaskFile.Command_Status = READ_DMA_EXT;
526
527 CardData->TaskFile.SectorCount = (UINT8)SectorCount;
528 CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
529
530 CardData->TaskFile.LBALow = (UINT8)LBA;
531 CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
532 CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
533
534 CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
535 CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
536 CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
537
538 Status = SendATACommand (
539 CardData,
540 &CardData->TaskFile,
541 FALSE,
542 Buffer,
543 SectorCount
544 );
545 return Status;
546
547 }
548
549 /**
550 WRITE_DMA_EXT command
551
552 @param CardData Pointer to CARD_DATA.
553 @param LBA The starting logical block address to read from on the device.
554 @param Buffer A pointer to the destination buffer for the data. The caller
555 is responsible for either having implicit or explicit ownership
556 of the buffer.
557 @param SectorCount Size in 512 bytes unit.
558
559 @retval EFI_SUCCESS Success
560 @retval EFI_DEVICE_ERROR Hardware Error
561 @retval EFI_INVALID_PARAMETER Parameter is error
562 @retval EFI_NO_MEDIA No media
563 @retval EFI_MEDIA_CHANGED Media Change
564 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
565
566 **/
567 EFI_STATUS
WriteDMAExt(IN CARD_DATA * CardData,IN EFI_LBA LBA,IN UINT8 * Buffer,IN UINT16 SectorCount)568 WriteDMAExt (
569 IN CARD_DATA *CardData,
570 IN EFI_LBA LBA,
571 IN UINT8 *Buffer,
572 IN UINT16 SectorCount
573 )
574 {
575
576 EFI_STATUS Status;
577
578 ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
579 //
580 //The host only supports nIEN = 0
581 //
582 CardData->TaskFile.Command_Status = WRITE_DMA_EXT;
583
584 CardData->TaskFile.SectorCount = (UINT8)SectorCount;
585 CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
586
587 CardData->TaskFile.LBALow = (UINT8)LBA;
588 CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
589 CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
590
591 CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
592 CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
593 CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
594
595 Status = SendATACommand (
596 CardData,
597 &CardData->TaskFile,
598 TRUE,
599 Buffer,
600 SectorCount
601 );
602 return Status;
603
604 }
605
606
607 /**
608 Judge whether it is CE-ATA device or not.
609
610 @param CardData Pointer to CARD_DATA.
611
612 @retval TRUE
613 @retval FALSE
614
615 **/
616 BOOLEAN
IsCEATADevice(IN CARD_DATA * CardData)617 IsCEATADevice (
618 IN CARD_DATA *CardData
619 )
620 {
621 EFI_STATUS Status;
622
623 Status = ReadWriteMultipleRegister (
624 CardData,
625 0,
626 sizeof (TASK_FILE),
627 FALSE,
628 (UINT8*)&CardData->TaskFile
629 );
630 if (EFI_ERROR (Status)) {
631 //
632 //To bring back the normal MMC card to work
633 //
634 CardData->SDHostIo->ResetSDHost (CardData->SDHostIo, Reset_DAT_CMD);
635 return FALSE;
636 }
637
638 if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&
639 CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA
640 ) {
641 //
642 //Disable Auto CMD for CE-ATA
643 //
644 CardData->SDHostIo->EnableAutoStopCmd (CardData->SDHostIo, FALSE);
645
646 return TRUE;
647 }
648
649 return FALSE;
650 }
651
652
653
654