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   CARD_DATA                   *CardData;
    298 
    299   CardData  = CARD_DATA_FROM_THIS(This);
    300 
    301   if (CardData->NeedFlush) {
    302     CardData->NeedFlush = FALSE;
    303     FlushCache (CardData);
    304   }
    305 
    306   return EFI_SUCCESS;
    307 }
    308 
    309 
    310 /**
    311   CEATA card BlockIo init function.
    312 
    313   @param  CardData               Pointer to CARD_DATA.
    314 
    315   @retval EFI_SUCCESS
    316   @retval Others
    317 **/
    318 EFI_STATUS
    319 CEATABlockIoInit (
    320   IN  CARD_DATA    *CardData
    321   )
    322 /*++
    323 
    324   Routine Description:
    325     CEATA card BlockIo init function
    326 
    327   Arguments:
    328     CardData  -   Pointer to CARD_DATA
    329 
    330   Returns:
    331     EFI_SUCCESS - Success
    332 --*/
    333 {
    334   EFI_STATUS   Status;
    335   UINT64       MaxSize;
    336   UINT32       Remainder;
    337   //
    338   //BlockIO protocol
    339   //
    340   CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;
    341   CardData->BlockIo.Media       = &(CardData->BlockIoMedia);
    342   CardData->BlockIo.Reset       = CEATABlockReset;
    343   CardData->BlockIo.ReadBlocks  = CEATABlockReadBlocks ;
    344   CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;
    345   CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;
    346 
    347   CardData->BlockIoMedia.MediaId          = 0;
    348   CardData->BlockIoMedia.RemovableMedia   = FALSE;
    349   CardData->BlockIoMedia.MediaPresent     = TRUE;
    350   CardData->BlockIoMedia.LogicalPartition = FALSE;
    351 
    352   if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {
    353     CardData->BlockIoMedia.ReadOnly       = TRUE;
    354   } else {
    355     CardData->BlockIoMedia.ReadOnly       = FALSE;
    356   }
    357 
    358 
    359   CardData->BlockIoMedia.WriteCaching     = FALSE;
    360   CardData->BlockIoMedia.IoAlign          = 1;
    361 
    362   Status = IndentifyDevice (CardData);
    363   if (EFI_ERROR (Status)) {
    364    goto Exit;
    365   }
    366 
    367   //
    368   //Some device does not support this feature
    369   //
    370 
    371   if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {
    372     CardData->BlockIoMedia.ReadOnly       = TRUE;
    373   }
    374 
    375   CardData->BlockIoMedia.BlockSize        = (1 << CardData->IndentifyDeviceData.Sectorsize);
    376   ASSERT(CardData->BlockIoMedia.BlockSize >= 12);
    377 
    378 
    379   MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);
    380   MaxSize = MultU64x32 (MaxSize, 512);
    381 
    382   Remainder = 0;
    383   CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);
    384   ASSERT(Remainder == 0);
    385 
    386   CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);
    387 
    388 
    389 Exit:
    390   return Status;
    391 
    392 }
    393 
    394 
    395 
    396