]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Omap35xxPkg/MMCHSDxe/MMCHS.c
Omap35xxPkg/MMCHSDxe: Fixed initialization when started from gBS->ConnectController()
[mirror_edk2.git] / Omap35xxPkg / MMCHSDxe / MMCHS.c
index 61bf215f7ea4cbe685cfebab8ea623d7042bcac6..786bc882731d276656c1caf111c022f1fc954fe9 100644 (file)
@@ -21,8 +21,6 @@
 
 **/
 
-#include <Uefi.h>
-
 #include "MMCHS.h"
 
 EFI_BLOCK_IO_MEDIA gMMCHSMedia = {
@@ -223,6 +221,9 @@ CalculateCardCLKD (
 
   MaxDataTransferRate = gCardInfo.CSDData.TRAN_SPEED;
 
+  // For SD Cards  we would need to send CMD6 to set
+  // speeds abouve 25MHz. High Speed mode 50 MHz and up
+
   //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
   switch (MaxDataTransferRate & 0x7) {
     case 0:
@@ -593,9 +594,6 @@ GetCardSpecificData (
   //Calculate total number of blocks and max. data transfer rate supported by the detected card.
   GetCardConfigurationData();
 
-  //Change MMCHS clock frequency to what detected card can support.
-  UpdateMMCHSClkFrequency(gCardInfo.ClockFrequencySelect);
-
   return Status;
 }
 
@@ -616,6 +614,23 @@ PerformCardConfiguration (
     return Status;
   }
 
+  if ((gCardInfo.CardType != UNKNOWN_CARD) && (gCardInfo.CardType != MMC_CARD)) {
+    // We could read SCR register, but SD Card Phys spec stats any SD Card shall
+    // set SCR.SD_BUS_WIDTHS to support 4-bit mode, so why bother?
+    // Send ACMD6 (application specific commands must be prefixed with CMD55)
+    Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
+    if (!EFI_ERROR (Status)) {
+      // set device into 4-bit data bus mode
+      Status = SendCmd (ACMD6, ACMD6_INT_EN, 0x2);
+      if (!EFI_ERROR (Status)) {
+        // Set host controler into 4-bit mode
+        MmioOr32 (MMCHS_HCTL, DTW_4_BIT);
+        DEBUG ((EFI_D_INFO, "SD Memory Card set to 4-bit mode\n"));
+      }
+    }
+  }
+
   //Send CMD16 to set the block length
   CmdArgument = gCardInfo.BlockSize;
   Status = SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
@@ -624,6 +639,9 @@ PerformCardConfiguration (
     return Status;
   }
 
+  //Change MMCHS clock frequency to what detected card can support.
+  UpdateMMCHSClkFrequency(gCardInfo.ClockFrequencySelect);
+
   return EFI_SUCCESS;
 }
 
@@ -712,27 +730,238 @@ WriteBlockData (
   return EFI_SUCCESS;
 }
 
+EFI_STATUS
+DmaBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN  UINTN                       Lba,
+  IN OUT VOID                     *Buffer,
+  IN  UINTN                       BlockCount,
+  IN  OPERATION_TYPE              OperationType
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 DmaSize = 0;
+  UINTN                 Cmd = 0;
+  UINTN                 CmdInterruptEnable;
+  UINTN                 CmdArgument;
+  VOID                  *BufferMap;
+  EFI_PHYSICAL_ADDRESS  BufferAddress;
+  OMAP_DMA4             Dma4;
+  DMA_MAP_OPERATION     DmaOperation;
+  EFI_STATUS            MmcStatus;
+  UINTN                 RetryCount = 0;
+
+CpuDeadLoop ();
+  // Map passed in buffer for DMA xfer
+  DmaSize = BlockCount * This->Media->BlockSize;
+  Status = DmaMap (DmaOperation, Buffer, &DmaSize, &BufferAddress, &BufferMap);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (&DmaOperation, sizeof (DMA_MAP_OPERATION));
+  
+
+  Dma4.DataType = 2;                      // DMA4_CSDPi[1:0]   32-bit elements from MMCHS_DATA
+
+  Dma4.SourceEndiansim = 0;               // DMA4_CSDPi[21]    
+
+  Dma4.DestinationEndianism = 0;          // DMA4_CSDPi[19]
+
+  Dma4.SourcePacked = 0;                  // DMA4_CSDPi[6]
+
+  Dma4.DestinationPacked = 0;             // DMA4_CSDPi[13]
+
+  Dma4.NumberOfElementPerFrame = This->Media->BlockSize/4; // DMA4_CENi  (TRM 4K is optimum value)  
+
+  Dma4.NumberOfFramePerTransferBlock = BlockCount;         // DMA4_CFNi    
+
+  Dma4.ReadPriority = 0;                  // DMA4_CCRi[6]      Low priority read  
+
+  Dma4.WritePriority = 0;                 // DMA4_CCRi[23]     Prefetech disabled
+
+
+  //Populate the command information based on the operation type.
+  if (OperationType == READ) {
+    Cmd = CMD18; //Multiple block read
+    CmdInterruptEnable = CMD18_INT_EN;
+    DmaOperation = MapOperationBusMasterCommonBuffer;
+
+    Dma4.ReadPortAccessType =0 ;            // DMA4_CSDPi[8:7]   Can not burst MMCHS_DATA reg
+
+    Dma4.WritePortAccessType = 3;           // DMA4_CSDPi[15:14] Memory burst 16x32
+
+    Dma4.WriteMode = 1;                     // DMA4_CSDPi[17:16] Write posted
+
+    
+
+    Dma4.SourceStartAddress = MMCHS_DATA;                   // DMA4_CSSAi
+
+    Dma4.DestinationStartAddress = (UINT32)BufferAddress;   // DMA4_CDSAi
+
+    Dma4.SourceElementIndex = 1;                            // DMA4_CSEi
+
+    Dma4.SourceFrameIndex = 0x200;                          // DMA4_CSFi
+
+    Dma4.DestinationElementIndex = 1;                       // DMA4_CDEi
+
+    Dma4.DestinationFrameIndex = 0;                         // DMA4_CDFi
+
+
+
+    Dma4.ReadPortAccessMode = 0;            // DMA4_CCRi[13:12]  Always read MMCHS_DATA
+
+    Dma4.WritePortAccessMode = 1;           // DMA4_CCRi[15:14]  Post increment memory address
+
+    Dma4.ReadRequestNumber = 0x1e;          // DMA4_CCRi[4:0]    Syncro with MMCA_DMA_RX (61)  
+
+    Dma4.WriteRequestNumber = 1;            // DMA4_CCRi[20:19]  Syncro upper 0x3e == 62 (one based)
+
+  } else if (OperationType == WRITE) { 
+    Cmd = CMD25; //Multiple block write
+    CmdInterruptEnable = CMD25_INT_EN;
+    DmaOperation = MapOperationBusMasterRead;
+
+    Dma4.ReadPortAccessType = 3;            // DMA4_CSDPi[8:7]   Memory burst 16x32
+
+    Dma4.WritePortAccessType = 0;           // DMA4_CSDPi[15:14] Can not burst MMCHS_DATA reg
+
+    Dma4.WriteMode = 1;                     // DMA4_CSDPi[17:16] Write posted ???
+
+    
+
+    Dma4.SourceStartAddress = (UINT32)BufferAddress;        // DMA4_CSSAi
+
+    Dma4.DestinationStartAddress = MMCHS_DATA;              // DMA4_CDSAi
+
+    Dma4.SourceElementIndex = 1;                            // DMA4_CSEi
+
+    Dma4.SourceFrameIndex = 0x200;                          // DMA4_CSFi
+
+    Dma4.DestinationElementIndex = 1;                       // DMA4_CDEi
+
+    Dma4.DestinationFrameIndex = 0;                         // DMA4_CDFi
+
+
+
+    Dma4.ReadPortAccessMode = 1;            // DMA4_CCRi[13:12]  Post increment memory address
+
+    Dma4.WritePortAccessMode = 0;           // DMA4_CCRi[15:14]  Always write MMCHS_DATA
+
+    Dma4.ReadRequestNumber = 0x1d;          // DMA4_CCRi[4:0]    Syncro with MMCA_DMA_TX (60)  
+
+    Dma4.WriteRequestNumber = 1;            // DMA4_CCRi[20:19]  Syncro upper 0x3d == 61 (one based)
+
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+
+  EnableDmaChannel (2, &Dma4);
+  
+
+  //Set command argument based on the card access mode (Byte mode or Block mode)
+  if (gCardInfo.OCRData.AccessMode & BIT1) {
+    CmdArgument = Lba;
+  } else {
+    CmdArgument = Lba * This->Media->BlockSize;
+  }
+
+  //Send Command.
+  Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
+    return Status;
+  }
+
+    //Check for the Transfer completion.
+  while (RetryCount < MAX_RETRY_COUNT) {
+    //Read Status
+    do {
+      MmcStatus = MmioRead32 (MMCHS_STAT);
+    } while (MmcStatus == 0);
+
+    //Check if Transfer complete (TC) bit is set?
+    if (MmcStatus & TC) {
+      break;
+    } else {
+      DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));
+      //Check if DEB, DCRC or DTO interrupt occured.
+      if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {
+        //There was an error during the data transfer.
+
+        //Set SRD bit to 1 and wait until it return to 0x0.
+        MmioOr32 (MMCHS_SYSCTL, SRD);
+        while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);
+
+        DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);
+        DmaUnmap (BufferMap);
+        return EFI_DEVICE_ERROR;
+      }
+    }
+    RetryCount++;
+  } 
+
+  DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);
+  Status = DmaUnmap (BufferMap);
+
+  if (RetryCount == MAX_RETRY_COUNT) {
+    DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));
+    return EFI_TIMEOUT;
+  }
+
+  return Status;
+}
+
 
 EFI_STATUS
-TransferBlockData (
-  IN  EFI_BLOCK_IO_PROTOCOL       *This,
-  OUT VOID                        *Buffer,
+TransferBlock (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN  UINTN                       Lba,
+  IN OUT VOID                     *Buffer,
   IN  OPERATION_TYPE              OperationType
   )
 {
   EFI_STATUS Status;
   UINTN      MmcStatus;
   UINTN      RetryCount = 0;
+  UINTN      Cmd = 0;
+  UINTN      CmdInterruptEnable = 0;
+  UINTN      CmdArgument = 0;
+
+
+  //Populate the command information based on the operation type.
+  if (OperationType == READ) {
+    Cmd = CMD17; //Single block read
+    CmdInterruptEnable = CMD18_INT_EN;
+  } else if (OperationType == WRITE) { 
+    Cmd = CMD24; //Single block write
+    CmdInterruptEnable = CMD24_INT_EN;
+  }
+
+  //Set command argument based on the card access mode (Byte mode or Block mode)
+  if (gCardInfo.OCRData.AccessMode & BIT1) {
+    CmdArgument = Lba;
+  } else {
+    CmdArgument = Lba * This->Media->BlockSize;
+  }
+
+  //Send Command.
+  Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
+    return Status;
+  }
 
   //Read or Write data.
   if (OperationType == READ) {
-    Status = ReadBlockData(This, Buffer);
+    Status = ReadBlockData (This, Buffer);
     if (EFI_ERROR(Status)) {
       DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
       return Status;
     }
   } else if (OperationType == WRITE) {
-    Status = WriteBlockData(This, Buffer);
+    Status = WriteBlockData (This, Buffer);
     if (EFI_ERROR(Status)) {
       DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
       return Status;
@@ -874,11 +1103,13 @@ DetectCard (
   gMMCHSMedia.ReadOnly     = (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
   gMMCHSMedia.MediaPresent = TRUE; 
   gMMCHSMedia.MediaId++; 
-  gMediaChange = FALSE;
+
+  DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));
 
   return Status;
 }
 
+#define MAX_MMCHS_TRANSFER_SIZE  0x4000
 
 EFI_STATUS
 SdReadWrite (
@@ -891,26 +1122,19 @@ SdReadWrite (
 {
   EFI_STATUS Status = EFI_SUCCESS;
   UINTN      RetryCount = 0;
-  UINTN      NumBlocks;
-  UINTN      Cmd = 0;
-  UINTN      CmdInterruptEnable = 0;
-  UINTN      CmdArgument = 0;
-  EFI_TPL    OldTpl;\r
-  BOOLEAN    MediaPresentLastTime;\r
-  BOOLEAN    Update;\r
+  UINTN      BlockCount;
+  UINTN      BytesToBeTranferedThisPass = 0;
+  UINTN      BytesRemainingToBeTransfered;
+  EFI_TPL    OldTpl;
 
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  BOOLEAN    Update;
 
 
-  if (Buffer == NULL) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Done;
-  }
   
   Update               = FALSE;
-  MediaPresentLastTime = gMMCHSMedia.MediaPresent;
 
   if (gMediaChange) {
+    Update = TRUE;
     Status = DetectCard  ();
     if (EFI_ERROR (Status)) {
       // We detected a removal
@@ -918,8 +1142,6 @@ SdReadWrite (
       gMMCHSMedia.LastBlock    = 0;
       gMMCHSMedia.BlockSize    = 512;  // Should be zero but there is a bug in DiskIo
       gMMCHSMedia.ReadOnly     = FALSE; 
-    } else {
-      Update = TRUE;
     }
     gMediaChange             = FALSE;
   } else if (!gMMCHSMedia.MediaPresent) {
@@ -927,20 +1149,27 @@ SdReadWrite (
     goto Done;
   }
 
-  if ((MediaPresentLastTime != gMMCHSMedia.MediaPresent) || Update) {
-    gBS->ReinstallProtocolInterface (\r
-          gImageHandle,\r
-          &gEfiBlockIoProtocolGuid,\r
-          &gBlockIo,\r
-          &gBlockIo\r
-          );\r
+  if (Update) {
+    DEBUG ((EFI_D_INFO, "SD Card ReinstallProtocolInterface ()\n"));
+    gBS->ReinstallProtocolInterface (
+          gImageHandle,
+          &gEfiBlockIoProtocolGuid,
+          &gBlockIo,
+          &gBlockIo
+          );
+    return EFI_MEDIA_CHANGED;
   }
 
   if (EFI_ERROR (Status)) {
     goto Done;
   }
 
-   if (Lba > This->Media->LastBlock) {
+  if (Buffer == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Done;
+  }
+
+  if (Lba > This->Media->LastBlock) {
     Status = EFI_INVALID_PARAMETER;
     goto Done;
   }
@@ -957,68 +1186,71 @@ SdReadWrite (
     goto Done;
   }
 
-  //Populate the command information based on the operation type.
-  if (OperationType == READ) {
-    Cmd = CMD17; //Single block read
-    CmdInterruptEnable = CMD17_INT_EN;
-  } else if (OperationType == WRITE) { 
-    Cmd = CMD24; //Single block write
-    CmdInterruptEnable = CMD24_INT_EN;
-  }
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 
-  //Calculate total number of blocks its going to read.
-  NumBlocks = (BufferSize + (This->Media->BlockSize - 1))/This->Media->BlockSize;
+  BytesRemainingToBeTransfered = BufferSize;
+  while (BytesRemainingToBeTransfered > 0) {
 
-  //Set command argument based on the card access mode (Byte mode or Block mode)
-  if (gCardInfo.OCRData.AccessMode & BIT1) {
-    CmdArgument = (UINTN)Lba;
-  } else {
-    CmdArgument = (UINTN)Lba * This->Media->BlockSize;
-  }
+    if (gMediaChange) {
+      Status = EFI_NO_MEDIA;
+      DEBUG ((EFI_D_INFO, "SdReadWrite() EFI_NO_MEDIA due to gMediaChange\n"));
+      goto DoneRestoreTPL;
+    }
 
-  while(NumBlocks) {
-    //Send Command.
-    Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
-    if (EFI_ERROR(Status)) {
-      DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
-      goto Done;
+    // Turn OFF DMA path until it is debugged
+    // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_MMCHS_TRANSFER_SIZE) ? MAX_MMCHS_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+    BytesToBeTranferedThisPass   = This->Media->BlockSize;
+
+    BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+
+    if (BlockCount > 1) {
+      Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);
+    } else {
+      //Transfer a block worth of data.
+      Status = TransferBlock (This, Lba, Buffer, OperationType);
     }
 
-    //Transfer a block worth of data.
-    Status = TransferBlockData(This, Buffer, OperationType);
     if (EFI_ERROR(Status)) {
       DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
-      goto Done;
+      goto DoneRestoreTPL;
     }
 
-    //Adjust command argument.
-    if (gCardInfo.OCRData.AccessMode & BIT1) {
-      CmdArgument++; //Increase BlockIndex by one.
-    } else {
-      CmdArgument += This->Media->BlockSize; //Increase BlockIndex by BlockSize
-    }
-
-    //Adjust Buffer.
+    BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+    Lba    += BlockCount;
     Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
-    NumBlocks--;
   }
 
-Done:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
+DoneRestoreTPL:
+
+  gBS->RestoreTPL (OldTpl);
+
+Done:
+
+  return Status;
+
 }
 
 
-/**\r
-  Reset the Block Device.\r
-\r
-  @param  This                 Indicates a pointer to the calling context.\r
-  @param  ExtendedVerification Driver may perform diagnostics on reset.\r
-\r
-  @retval EFI_SUCCESS          The device was reset.\r
-  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could\r
-                               not be reset.\r
-\r
+/**
+
+  Reset the Block Device.
+
+
+
+  @param  This                 Indicates a pointer to the calling context.
+
+  @param  ExtendedVerification Driver may perform diagnostics on reset.
+
+
+
+  @retval EFI_SUCCESS          The device was reset.
+
+  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
+
+                               not be reset.
+
+
+
 **/
 EFI_STATUS
 EFIAPI
@@ -1031,23 +1263,40 @@ MMCHSReset (
 }
 
 
-/**\r
-  Read BufferSize bytes from Lba into Buffer.\r
-\r
-  @param  This       Indicates a pointer to the calling context.\r
-  @param  MediaId    Id of the media, changes every time the media is replaced.\r
-  @param  Lba        The starting Logical Block Address to read from\r
-  @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
-  @param  Buffer     A pointer to the destination buffer for the data. The caller is\r
-                     responsible for either having implicit or explicit ownership of the buffer.\r
-\r
-  @retval EFI_SUCCESS           The data was read correctly from the device.\r
-  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.\r
-  @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.\r
-  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
-  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
-                                or the buffer is not on proper alignment.\r
+/**
+
+  Read BufferSize bytes from Lba into Buffer.
+
+
+
+  @param  This       Indicates a pointer to the calling context.
+
+  @param  MediaId    Id of the media, changes every time the media is replaced.
+
+  @param  Lba        The starting Logical Block Address to read from
+
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+
+  @param  Buffer     A pointer to the destination buffer for the data. The caller is
+
+                     responsible for either having implicit or explicit ownership of the buffer.
+
+
+
+  @retval EFI_SUCCESS           The data was read correctly from the device.
+
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
+
+  @retval EFI_NO_MEDIA          There is no media in the device.
+
+  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
+
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 
+
+                                or the buffer is not on proper alignment.
+
 EFI_STATUS
 
 **/
@@ -1066,29 +1315,49 @@ MMCHSReadBlocks (
   //Perform Read operation.
   Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
 
-  return Status;\r
+  return Status;
+
 }
 
 
-/**\r
-  Write BufferSize bytes from Lba into Buffer.\r
-\r
-  @param  This       Indicates a pointer to the calling context.\r
-  @param  MediaId    The media ID that the write request is for.\r
-  @param  Lba        The starting logical block address to be written. The caller is\r
-                     responsible for writing to only legitimate locations.\r
-  @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
-  @param  Buffer     A pointer to the source buffer for the data.\r
-\r
-  @retval EFI_SUCCESS           The data was written correctly to the device.\r
-  @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
-  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
-  @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
-  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
-  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
-                                or the buffer is not on proper alignment.\r
-\r
+/**
+
+  Write BufferSize bytes from Lba into Buffer.
+
+
+
+  @param  This       Indicates a pointer to the calling context.
+
+  @param  MediaId    The media ID that the write request is for.
+
+  @param  Lba        The starting logical block address to be written. The caller is
+
+                     responsible for writing to only legitimate locations.
+
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+
+  @param  Buffer     A pointer to the source buffer for the data.
+
+
+
+  @retval EFI_SUCCESS           The data was written correctly to the device.
+
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.
+
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
+
+  @retval EFI_NO_MEDIA          There is no media in the device.
+
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
+
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 
+
+                                or the buffer is not on proper alignment.
+
+
+
 **/
 EFI_STATUS
 EFIAPI
@@ -1104,20 +1373,31 @@ MMCHSWriteBlocks (
 
   //Perform write operation.
   Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
-\r
-  return Status;\r
+
+
+  return Status;
+
 }
 
 
-/**\r
-  Flush the Block Device.\r
-\r
-  @param  This              Indicates a pointer to the calling context.\r
-\r
-  @retval EFI_SUCCESS       All outstanding data was written to the device\r
-  @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data\r
-  @retval EFI_NO_MEDIA      There is no media in the device.\r
-\r
+/**
+
+  Flush the Block Device.
+
+
+
+  @param  This              Indicates a pointer to the calling context.
+
+
+
+  @retval EFI_SUCCESS       All outstanding data was written to the device
+
+  @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
+
+  @retval EFI_NO_MEDIA      There is no media in the device.
+
+
+
 **/
 EFI_STATUS
 EFIAPI
@@ -1139,17 +1419,28 @@ EFI_BLOCK_IO_PROTOCOL gBlockIo = {
 };
 
 
-/**\r
-  Timer callback to convert card present hardware into a boolean that indicates\r
-  a media change event has happened. If you just check the GPIO you could see \r
-  card 1 and then check again after card 1 was removed and card 2 was inserted\r
-  and you would still see media present. Thus you need the timer tick to catch\r
-  the toggle event.\r
-\r
-  @param  Event                 Event whose notification function is being invoked.\r
-  @param  Context               The pointer to the notification function's context,\r
-                                which is implementation-dependent. Not used.\r
-\r
+/**
+
+  Timer callback to convert card present hardware into a boolean that indicates
+
+  a media change event has happened. If you just check the GPIO you could see 
+
+  card 1 and then check again after card 1 was removed and card 2 was inserted
+
+  and you would still see media present. Thus you need the timer tick to catch
+
+  the toggle event.
+
+
+
+  @param  Event                 Event whose notification function is being invoked.
+
+  @param  Context               The pointer to the notification function's context,
+
+                                which is implementation-dependent. Not used.
+
+
+
 **/
 VOID
 EFIAPI
@@ -1186,11 +1477,11 @@ MMCHSInitialize (
   ASSERT_EFI_ERROR(Status);
 
   ZeroMem (&gCardInfo, sizeof (CARD_INFO));
+
   Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, TimerCallback, NULL, &gTimerEvent);
   ASSERT_EFI_ERROR (Status);
  
-  Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, 1000000); // make me a PCD
+  Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, FixedPcdGet32 (PcdMmchsTimerFreq100NanoSeconds)); 
   ASSERT_EFI_ERROR (Status);
 
   //Publish BlockIO.