Home | History | Annotate | Download | only in VirtioMmioDeviceLib
      1 /** @file
      2 
      3   This driver produces Virtio Device Protocol instances for Virtio MMIO 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 
     19 #include "VirtioMmioDevice.h"
     20 
     21 EFI_STATUS
     22 EFIAPI
     23 VirtioMmioGetDeviceFeatures (
     24   IN VIRTIO_DEVICE_PROTOCOL *This,
     25   OUT UINT64                *DeviceFeatures
     26   )
     27 {
     28   VIRTIO_MMIO_DEVICE *Device;
     29 
     30   if (DeviceFeatures == NULL) {
     31     return EFI_INVALID_PARAMETER;
     32   }
     33 
     34   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
     35 
     36   *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);
     37 
     38   return EFI_SUCCESS;
     39 }
     40 
     41 EFI_STATUS
     42 EFIAPI
     43 VirtioMmioGetQueueSize (
     44   IN  VIRTIO_DEVICE_PROTOCOL  *This,
     45   OUT UINT16                  *QueueNumMax
     46   )
     47 {
     48   VIRTIO_MMIO_DEVICE *Device;
     49 
     50   if (QueueNumMax == NULL) {
     51     return EFI_INVALID_PARAMETER;
     52   }
     53 
     54   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
     55 
     56   *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;
     57 
     58   return EFI_SUCCESS;
     59 }
     60 
     61 EFI_STATUS
     62 EFIAPI
     63 VirtioMmioGetDeviceStatus (
     64   IN  VIRTIO_DEVICE_PROTOCOL  *This,
     65   OUT UINT8                   *DeviceStatus
     66   )
     67 {
     68   VIRTIO_MMIO_DEVICE *Device;
     69 
     70   if (DeviceStatus == NULL) {
     71     return EFI_INVALID_PARAMETER;
     72   }
     73 
     74   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
     75 
     76   *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;
     77 
     78   return EFI_SUCCESS;
     79 }
     80 
     81 EFI_STATUS
     82 EFIAPI
     83 VirtioMmioSetQueueSize (
     84   VIRTIO_DEVICE_PROTOCOL *This,
     85   UINT16                  QueueSize
     86   )
     87 {
     88   VIRTIO_MMIO_DEVICE *Device;
     89 
     90   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
     91 
     92   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);
     93 
     94   return EFI_SUCCESS;
     95 }
     96 
     97 EFI_STATUS
     98 EFIAPI
     99 VirtioMmioSetDeviceStatus (
    100   VIRTIO_DEVICE_PROTOCOL *This,
    101   UINT8                   DeviceStatus
    102   )
    103 {
    104   VIRTIO_MMIO_DEVICE *Device;
    105 
    106   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    107 
    108   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);
    109 
    110   return EFI_SUCCESS;
    111 }
    112 
    113 EFI_STATUS
    114 EFIAPI
    115 VirtioMmioSetQueueNotify (
    116   VIRTIO_DEVICE_PROTOCOL *This,
    117   UINT16                  QueueNotify
    118   )
    119 {
    120   VIRTIO_MMIO_DEVICE *Device;
    121 
    122   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    123 
    124   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);
    125 
    126   return EFI_SUCCESS;
    127 }
    128 
    129 EFI_STATUS
    130 EFIAPI
    131 VirtioMmioSetQueueAlignment (
    132   VIRTIO_DEVICE_PROTOCOL *This,
    133   UINT32                  Alignment
    134   )
    135 {
    136   VIRTIO_MMIO_DEVICE *Device;
    137 
    138   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    139 
    140   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);
    141 
    142   return EFI_SUCCESS;
    143 }
    144 
    145 EFI_STATUS
    146 EFIAPI
    147 VirtioMmioSetPageSize (
    148   VIRTIO_DEVICE_PROTOCOL *This,
    149   UINT32                  PageSize
    150   )
    151 {
    152   VIRTIO_MMIO_DEVICE *Device;
    153 
    154   if (PageSize != EFI_PAGE_SIZE) {
    155     return EFI_UNSUPPORTED;
    156   }
    157 
    158   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    159 
    160   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);
    161 
    162   return EFI_SUCCESS;
    163 }
    164 
    165 EFI_STATUS
    166 EFIAPI
    167 VirtioMmioSetQueueSel (
    168   VIRTIO_DEVICE_PROTOCOL *This,
    169   UINT16                  Sel
    170   )
    171 {
    172   VIRTIO_MMIO_DEVICE *Device;
    173 
    174   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    175 
    176   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);
    177 
    178   return EFI_SUCCESS;
    179 }
    180 
    181 EFI_STATUS
    182 VirtioMmioSetQueueAddress (
    183   IN VIRTIO_DEVICE_PROTOCOL  *This,
    184   IN VRING                   *Ring
    185   )
    186 {
    187   VIRTIO_MMIO_DEVICE *Device;
    188 
    189   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    190 
    191   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,
    192     (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
    193 
    194   return EFI_SUCCESS;
    195 }
    196 
    197 EFI_STATUS
    198 EFIAPI
    199 VirtioMmioSetGuestFeatures (
    200   VIRTIO_DEVICE_PROTOCOL *This,
    201   UINT64                  Features
    202   )
    203 {
    204   VIRTIO_MMIO_DEVICE *Device;
    205 
    206   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    207 
    208   if (Features > MAX_UINT32) {
    209     return EFI_UNSUPPORTED;
    210   }
    211   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES,
    212     (UINT32)Features);
    213 
    214   return EFI_SUCCESS;
    215 }
    216 
    217 EFI_STATUS
    218 EFIAPI
    219 VirtioMmioDeviceWrite (
    220   IN VIRTIO_DEVICE_PROTOCOL *This,
    221   IN UINTN                  FieldOffset,
    222   IN UINTN                  FieldSize,
    223   IN UINT64                 Value
    224   )
    225 {
    226   UINTN                     DstBaseAddress;
    227   VIRTIO_MMIO_DEVICE       *Device;
    228 
    229   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    230 
    231   //
    232   // Double-check fieldsize
    233   //
    234   if ((FieldSize != 1) && (FieldSize != 2) &&
    235       (FieldSize != 4) && (FieldSize != 8)) {
    236     return EFI_INVALID_PARAMETER;
    237   }
    238 
    239   //
    240   // Compute base address
    241   //
    242   DstBaseAddress = Device->BaseAddress +
    243       VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
    244 
    245   //
    246   // The device-specific memory area of Virtio-MMIO can only be written in
    247   // byte accesses. This is not currently in the Virtio spec.
    248   //
    249   MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);
    250 
    251   return EFI_SUCCESS;
    252 }
    253 
    254 EFI_STATUS
    255 EFIAPI
    256 VirtioMmioDeviceRead (
    257   IN  VIRTIO_DEVICE_PROTOCOL    *This,
    258   IN  UINTN                     FieldOffset,
    259   IN  UINTN                     FieldSize,
    260   IN  UINTN                     BufferSize,
    261   OUT VOID                      *Buffer
    262   )
    263 {
    264   UINTN                     SrcBaseAddress;
    265   VIRTIO_MMIO_DEVICE       *Device;
    266 
    267   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
    268 
    269   //
    270   // Parameter validation
    271   //
    272   ASSERT (FieldSize == BufferSize);
    273 
    274   //
    275   // Double-check fieldsize
    276   //
    277   if ((FieldSize != 1) && (FieldSize != 2) &&
    278       (FieldSize != 4) && (FieldSize != 8)) {
    279     return EFI_INVALID_PARAMETER;
    280   }
    281 
    282   //
    283   // Compute base address
    284   //
    285   SrcBaseAddress = Device->BaseAddress +
    286       VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
    287 
    288   //
    289   // The device-specific memory area of Virtio-MMIO can only be read in
    290   // byte reads. This is not currently in the Virtio spec.
    291   //
    292   MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);
    293 
    294   return EFI_SUCCESS;
    295 }
    296