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