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