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