• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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