Home | History | Annotate | Download | only in VirtioPciDeviceDxe
      1 /** @file
      2 
      3   This driver produces Virtio Device Protocol instances for Virtio PCI devices.
      4 
      5   Copyright (C) 2012, Red Hat, Inc.
      6   Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
      7   Copyright (C) 2013, ARM Ltd.
      8 
      9   This program and the accompanying materials are licensed and made available
     10   under the terms and conditions of the BSD License which accompanies this
     11   distribution. The full text of the license may be found at
     12   http://opensource.org/licenses/bsd-license.php
     13 
     14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
     15   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17 **/
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/DebugLib.h>
     20 #include <Library/MemoryAllocationLib.h>
     21 #include <Library/UefiBootServicesTableLib.h>
     22 #include <Library/UefiLib.h>
     23 #include "VirtioPciDevice.h"
     24 
     25 /**
     26 
     27   Read a word from Region 0 of the device specified by VirtIo Device protocol.
     28 
     29   The function implements the ReadDevice protocol member of
     30   VIRTIO_DEVICE_PROTOCOL.
     31 
     32   @param[in] This         VirtIo Device protocol.
     33 
     34   @param[in] FieldOffset  Source offset.
     35 
     36   @param[in] FieldSize    Source field size, must be in { 1, 2, 4, 8 }.
     37 
     38   @param[in] BufferSize   Number of bytes available in the target buffer. Must
     39                           equal FieldSize.
     40 
     41   @param[out] Buffer      Target buffer.
     42 
     43 
     44   @return  Status code returned by PciIo->Io.Read().
     45 
     46 **/
     47 EFI_STATUS
     48 EFIAPI
     49 VirtioPciDeviceRead (
     50   IN  VIRTIO_DEVICE_PROTOCOL    *This,
     51   IN  UINTN                     FieldOffset,
     52   IN  UINTN                     FieldSize,
     53   IN  UINTN                     BufferSize,
     54   OUT VOID                      *Buffer
     55   )
     56 {
     57   VIRTIO_PCI_DEVICE         *Dev;
     58 
     59   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
     60 
     61   return VirtioPciIoRead (Dev,
     62       Dev->DeviceSpecificConfigurationOffset + FieldOffset,
     63       FieldSize, BufferSize, Buffer);
     64 }
     65 
     66 /**
     67 
     68   Write a word into Region 0 of the device specified by VirtIo Device protocol.
     69 
     70   @param[in] This         VirtIo Device protocol.
     71 
     72   @param[in] FieldOffset  Destination offset.
     73 
     74   @param[in] FieldSize    Destination field size, must be in { 1, 2, 4, 8 }.
     75 
     76   @param[in] Value        Little endian value to write, converted to UINT64.
     77                           The least significant FieldSize bytes will be used.
     78 
     79 
     80   @return  Status code returned by PciIo->Io.Write().
     81 
     82 **/
     83 EFI_STATUS
     84 EFIAPI
     85 VirtioPciDeviceWrite (
     86   IN VIRTIO_DEVICE_PROTOCOL *This,
     87   IN UINTN                  FieldOffset,
     88   IN UINTN                  FieldSize,
     89   IN UINT64                 Value
     90   )
     91 {
     92   VIRTIO_PCI_DEVICE         *Dev;
     93 
     94   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
     95 
     96   return VirtioPciIoWrite (Dev,
     97       Dev->DeviceSpecificConfigurationOffset + FieldOffset, FieldSize, Value);
     98 }
     99 
    100 EFI_STATUS
    101 EFIAPI
    102 VirtioPciGetDeviceFeatures (
    103   IN VIRTIO_DEVICE_PROTOCOL *This,
    104   OUT UINT32                *DeviceFeatures
    105   )
    106 {
    107   VIRTIO_PCI_DEVICE         *Dev;
    108 
    109   if (DeviceFeatures == NULL) {
    110     return EFI_INVALID_PARAMETER;
    111   }
    112 
    113   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    114 
    115   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES, sizeof (UINT32),
    116       sizeof (UINT32), DeviceFeatures);
    117 }
    118 
    119 EFI_STATUS
    120 EFIAPI
    121 VirtioPciGetQueueAddress (
    122   IN  VIRTIO_DEVICE_PROTOCOL *This,
    123   OUT UINT32                 *QueueAddress
    124   )
    125 {
    126   VIRTIO_PCI_DEVICE         *Dev;
    127 
    128   if (QueueAddress == NULL) {
    129     return EFI_INVALID_PARAMETER;
    130   }
    131 
    132   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    133 
    134   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
    135       sizeof (UINT32), QueueAddress);
    136 }
    137 
    138 EFI_STATUS
    139 EFIAPI
    140 VirtioPciGetQueueSize (
    141   IN  VIRTIO_DEVICE_PROTOCOL  *This,
    142   OUT UINT16                  *QueueNumMax
    143   )
    144 {
    145   VIRTIO_PCI_DEVICE         *Dev;
    146 
    147   if (QueueNumMax == NULL) {
    148     return EFI_INVALID_PARAMETER;
    149   }
    150 
    151   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    152 
    153   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
    154       sizeof (UINT16), QueueNumMax);
    155 }
    156 
    157 EFI_STATUS
    158 EFIAPI
    159 VirtioPciGetDeviceStatus (
    160   IN  VIRTIO_DEVICE_PROTOCOL  *This,
    161   OUT UINT8                   *DeviceStatus
    162   )
    163 {
    164   VIRTIO_PCI_DEVICE         *Dev;
    165 
    166   if (DeviceStatus == NULL) {
    167     return EFI_INVALID_PARAMETER;
    168   }
    169 
    170   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    171 
    172   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
    173       sizeof (UINT8), sizeof (UINT8), DeviceStatus);
    174 }
    175 
    176 EFI_STATUS
    177 EFIAPI
    178 VirtioPciSetGuestFeatures (
    179   IN VIRTIO_DEVICE_PROTOCOL  *This,
    180   IN UINT32                   Features
    181   )
    182 {
    183   VIRTIO_PCI_DEVICE *Dev;
    184 
    185   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    186 
    187   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
    188       sizeof (UINT32), Features);
    189 }
    190 
    191 EFI_STATUS
    192 EFIAPI
    193 VirtioPciSetQueueAddress (
    194   VIRTIO_DEVICE_PROTOCOL    *This,
    195   UINT32                    Address
    196   )
    197 {
    198   VIRTIO_PCI_DEVICE *Dev;
    199 
    200   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    201 
    202   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
    203       Address);
    204 }
    205 
    206 EFI_STATUS
    207 EFIAPI
    208 VirtioPciSetQueueSel (
    209   VIRTIO_DEVICE_PROTOCOL    *This,
    210   UINT16                    Sel
    211   )
    212 {
    213   VIRTIO_PCI_DEVICE *Dev;
    214 
    215   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    216 
    217   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
    218       Sel);
    219 }
    220 
    221 EFI_STATUS
    222 EFIAPI
    223 VirtioPciSetQueueAlignment (
    224   VIRTIO_DEVICE_PROTOCOL *This,
    225   UINT32                  Alignment
    226   )
    227 {
    228   return EFI_SUCCESS;
    229 }
    230 
    231 EFI_STATUS
    232 EFIAPI
    233 VirtioPciSetPageSize (
    234   VIRTIO_DEVICE_PROTOCOL *This,
    235   UINT32                  PageSize
    236   )
    237 {
    238   return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
    239 }
    240 
    241 EFI_STATUS
    242 EFIAPI
    243 VirtioPciSetQueueNotify (
    244   VIRTIO_DEVICE_PROTOCOL *This,
    245   UINT16                 Index
    246   )
    247 {
    248   VIRTIO_PCI_DEVICE *Dev;
    249 
    250   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    251 
    252   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
    253       Index);
    254 }
    255 
    256 EFI_STATUS
    257 EFIAPI
    258 VirtioPciSetQueueSize (
    259   VIRTIO_DEVICE_PROTOCOL *This,
    260   UINT16                 Size
    261   )
    262 {
    263   //
    264   // This function is only applicable in Virtio-MMIO.
    265   // (The QueueSize field is read-only in Virtio proper (PCI))
    266   //
    267   return EFI_SUCCESS;
    268 }
    269 
    270 EFI_STATUS
    271 EFIAPI
    272 VirtioPciSetDeviceStatus (
    273   VIRTIO_DEVICE_PROTOCOL *This,
    274   UINT8                  DeviceStatus
    275   )
    276 {
    277   VIRTIO_PCI_DEVICE *Dev;
    278 
    279   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
    280 
    281   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
    282       sizeof (UINT8), DeviceStatus);
    283 }
    284