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