Home | History | Annotate | Download | only in SDMediaDeviceDxe
      1 /** @file
      2 
      3 Block I/O protocol for CE-ATA device
      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   Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
     21 
     22   @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.
     23   @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive.
     24                                  verification operation of the device during reset.
     25                                  (This parameter is ingored in this driver.)
     26 
     27   @retval EFI_SUCCESS                Success
     28 **/
     29 EFI_STATUS
     30 EFIAPI
     31 CEATABlockReset (
     32   IN  EFI_BLOCK_IO_PROTOCOL   *This,
     33   IN  BOOLEAN                 ExtendedVerification
     34   )
     35 {
     36   EFI_STATUS                 Status;
     37   CARD_DATA                  *CardData;
     38   EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;
     39 
     40   CardData  = CARD_DATA_FROM_THIS(This);
     41   SDHostIo = CardData->SDHostIo;
     42 
     43   if (!ExtendedVerification) {
     44     Status = SoftwareReset (CardData);
     45   } else {
     46     Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);
     47     if (EFI_ERROR (Status)) {
     48     DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));
     49       return Status;
     50     }
     51     Status = MMCSDCardInit (CardData);
     52   }
     53 
     54 
     55   return Status;
     56 
     57  }
     58 
     59 /**
     60   Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
     61 
     62   @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.
     63   @param  MediaId                The media id that the write request is for.
     64   @param  LBA                    The starting logical block address to read from on the device.
     65                                  The caller is responsible for writing to only legitimate locations.
     66   @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the
     67                                  intrinsic block size of the device.
     68   @param  Buffer                 A pointer to the destination buffer for the data. The caller
     69                                  is responsible for either having implicit or explicit ownership
     70                                  of the buffer.
     71 
     72   @retval EFI_SUCCESS                Success
     73   @retval EFI_DEVICE_ERROR           Hardware Error
     74   @retval EFI_INVALID_PARAMETER      Parameter is error
     75   @retval EFI_NO_MEDIA               No media
     76   @retval EFI_MEDIA_CHANGED          Media Change
     77   @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad
     78 **/
     79 EFI_STATUS
     80 EFIAPI
     81 CEATABlockReadBlocks (
     82   IN  EFI_BLOCK_IO_PROTOCOL   *This,
     83   IN  UINT32                  MediaId,
     84   IN  EFI_LBA                 LBA,
     85   IN  UINTN                   BufferSize,
     86   OUT VOID                    *Buffer
     87   )
     88 {
     89   EFI_STATUS                  Status;
     90   CARD_DATA                   *CardData;
     91   UINT32                      TransferSize;
     92   UINT8                       *pBuf;
     93   UINT32                      Index;
     94   UINT64                      Address;
     95   UINT32                      Remainder;
     96   UINT64                      CEATALBA;
     97   UINT32                      BoundarySize;
     98 
     99   Status       = EFI_SUCCESS;
    100   CardData     = CARD_DATA_FROM_THIS(This);
    101   pBuf         = Buffer;
    102   Index        = 0;
    103   Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
    104   BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
    105 
    106   if (!Buffer) {
    107     Status = EFI_INVALID_PARAMETER;
    108     DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
    109     goto Exit;
    110   }
    111 
    112   if (MediaId != CardData->BlockIoMedia.MediaId) {
    113     Status = EFI_MEDIA_CHANGED;
    114   DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));
    115     goto Exit;
    116   }
    117 
    118   if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
    119     Status = EFI_BAD_BUFFER_SIZE;
    120   DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));
    121     goto Exit;
    122   }
    123 
    124   if (BufferSize == 0) {
    125     Status = EFI_SUCCESS;
    126     goto Exit;
    127   }
    128 
    129   if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
    130     Status = EFI_INVALID_PARAMETER;
    131     DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
    132     goto Exit;
    133   }
    134 
    135 
    136   do {
    137     if (BufferSize < BoundarySize) {
    138       TransferSize = (UINT32)BufferSize;
    139     } else {
    140       TransferSize = BoundarySize;
    141     }
    142 
    143     Address += Index * TransferSize;
    144     CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
    145     ASSERT(Remainder == 0);
    146 
    147     Status = ReadDMAExt (
    148                CardData,
    149                CEATALBA,
    150                pBuf,
    151                (UINT16)(TransferSize / DATA_UNIT_SIZE)
    152                );
    153     if (EFI_ERROR (Status)) {
    154      DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
    155      This->Reset (This, TRUE);
    156      goto Exit;
    157     }
    158     BufferSize -= TransferSize;
    159     pBuf       += TransferSize;
    160     Index ++;
    161   } while (BufferSize != 0);
    162 
    163 
    164 Exit:
    165   return Status;
    166 }
    167 
    168 /**
    169   Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
    170 
    171   @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.
    172   @param  MediaId                The media id that the write request is for.
    173   @param  LBA                    The starting logical block address to read from on the device.
    174                                  The caller is responsible for writing to only legitimate locations.
    175   @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the
    176                                  intrinsic block size of the device.
    177   @param  Buffer                 A pointer to the destination buffer for the data. The caller
    178                                  is responsible for either having implicit or explicit ownership
    179                                  of the buffer.
    180 
    181   @retval EFI_SUCCESS                Success
    182   @retval EFI_DEVICE_ERROR           Hardware Error
    183   @retval EFI_INVALID_PARAMETER      Parameter is error
    184   @retval EFI_NO_MEDIA               No media
    185   @retval EFI_MEDIA_CHANGED          Media Change
    186   @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad
    187 **/
    188 EFI_STATUS
    189 EFIAPI
    190 CEATABlockWriteBlocks (
    191   IN  EFI_BLOCK_IO_PROTOCOL   *This,
    192   IN  UINT32                  MediaId,
    193   IN  EFI_LBA                 LBA,
    194   IN  UINTN                   BufferSize,
    195   IN  VOID                    *Buffer
    196   )
    197 {
    198   EFI_STATUS                  Status;
    199   CARD_DATA                   *CardData;
    200   UINT32                      TransferSize;
    201   UINT8                       *pBuf;
    202   UINT32                      Index;
    203   UINT64                      Address;
    204   UINT32                      Remainder;
    205   UINT64                      CEATALBA;
    206   UINT32                      BoundarySize;
    207 
    208 
    209   Status       = EFI_SUCCESS;
    210   CardData     = CARD_DATA_FROM_THIS(This);
    211   pBuf         = Buffer;
    212   Index        = 0;
    213   Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
    214   BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
    215 
    216 
    217   if (!Buffer) {
    218     Status = EFI_INVALID_PARAMETER;
    219     goto Exit;
    220   }
    221 
    222   if (MediaId != CardData->BlockIoMedia.MediaId) {
    223     Status = EFI_MEDIA_CHANGED;
    224     goto Exit;
    225   }
    226 
    227   if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
    228     Status = EFI_BAD_BUFFER_SIZE;
    229     goto Exit;
    230   }
    231 
    232   if (BufferSize == 0) {
    233     Status = EFI_SUCCESS;
    234     goto Exit;
    235   }
    236 
    237   if (CardData->BlockIoMedia.ReadOnly) {
    238     Status = EFI_WRITE_PROTECTED;
    239     goto Exit;
    240   }
    241 
    242   if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
    243     Status = EFI_INVALID_PARAMETER;
    244     goto Exit;
    245   }
    246 
    247   CardData->NeedFlush = TRUE;
    248 
    249   do {
    250     if (BufferSize < BoundarySize) {
    251       TransferSize = (UINT32)BufferSize;
    252     } else {
    253       TransferSize = BoundarySize;
    254     }
    255 
    256     Address += Index * TransferSize;
    257     CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
    258     ASSERT(Remainder == 0);
    259 
    260     Status = WriteDMAExt (
    261                CardData,
    262                CEATALBA,
    263                pBuf,
    264                (UINT16)(TransferSize / DATA_UNIT_SIZE)
    265                );
    266     if (EFI_ERROR (Status)) {
    267      DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
    268      This->Reset (This, TRUE);
    269      goto Exit;
    270     }
    271     BufferSize -= TransferSize;
    272     pBuf       += TransferSize;
    273     Index ++;
    274   } while (BufferSize != 0);
    275 
    276 
    277 Exit:
    278   return Status;
    279 }
    280 
    281 /**
    282   Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
    283     (In this driver, this function just returns EFI_SUCCESS.)
    284 
    285   @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.
    286 
    287   @retval EFI_SUCCESS
    288   @retval Others
    289 **/
    290 EFI_STATUS
    291 EFIAPI
    292 CEATABlockFlushBlocks (
    293   IN  EFI_BLOCK_IO_PROTOCOL   *This
    294   )
    295 {
    296 
    297   EFI_STATUS                  Status;
    298   CARD_DATA                   *CardData;
    299 
    300   CardData  = CARD_DATA_FROM_THIS(This);
    301 
    302   if (CardData->NeedFlush) {
    303     CardData->NeedFlush = FALSE;
    304     Status = FlushCache (CardData);
    305   }
    306 
    307   return EFI_SUCCESS;
    308 }
    309 
    310 
    311 /**
    312   CEATA card BlockIo init function.
    313 
    314   @param  CardData               Pointer to CARD_DATA.
    315 
    316   @retval EFI_SUCCESS
    317   @retval Others
    318 **/
    319 EFI_STATUS
    320 CEATABlockIoInit (
    321   IN  CARD_DATA    *CardData
    322   )
    323 /*++
    324 
    325   Routine Description:
    326     CEATA card BlockIo init function
    327 
    328   Arguments:
    329     CardData  -   Pointer to CARD_DATA
    330 
    331   Returns:
    332     EFI_SUCCESS - Success
    333 --*/
    334 {
    335   EFI_STATUS   Status;
    336   UINT64       MaxSize;
    337   UINT32       Remainder;
    338   //
    339   //BlockIO protocol
    340   //
    341   CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;
    342   CardData->BlockIo.Media       = &(CardData->BlockIoMedia);
    343   CardData->BlockIo.Reset       = CEATABlockReset;
    344   CardData->BlockIo.ReadBlocks  = CEATABlockReadBlocks ;
    345   CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;
    346   CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;
    347 
    348   CardData->BlockIoMedia.MediaId          = 0;
    349   CardData->BlockIoMedia.RemovableMedia   = FALSE;
    350   CardData->BlockIoMedia.MediaPresent     = TRUE;
    351   CardData->BlockIoMedia.LogicalPartition = FALSE;
    352 
    353   if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {
    354     CardData->BlockIoMedia.ReadOnly       = TRUE;
    355   } else {
    356     CardData->BlockIoMedia.ReadOnly       = FALSE;
    357   }
    358 
    359 
    360   CardData->BlockIoMedia.WriteCaching     = FALSE;
    361   CardData->BlockIoMedia.IoAlign          = 1;
    362 
    363   Status = IndentifyDevice (CardData);
    364   if (EFI_ERROR (Status)) {
    365    goto Exit;
    366   }
    367 
    368   //
    369   //Some device does not support this feature
    370   //
    371 
    372   if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {
    373     CardData->BlockIoMedia.ReadOnly       = TRUE;
    374   }
    375 
    376   CardData->BlockIoMedia.BlockSize        = (1 << CardData->IndentifyDeviceData.Sectorsize);
    377   ASSERT(CardData->BlockIoMedia.BlockSize >= 12);
    378 
    379 
    380   MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);
    381   MaxSize = MultU64x32 (MaxSize, 512);
    382 
    383   Remainder = 0;
    384   CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);
    385   ASSERT(Remainder == 0);
    386 
    387   CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);
    388 
    389 
    390 Exit:
    391   return Status;
    392 
    393 }
    394 
    395 
    396 
    397