]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
OvmfPkg/VirtioPciDeviceDxe: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices over PCI
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciFunctions.c
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 }