]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
d8d30f9af63d6d7638928020c0e02bae462d320a
[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 UINT64 *DeviceFeatures
105 )
106 {
107 VIRTIO_PCI_DEVICE *Dev;
108 EFI_STATUS Status;
109 UINT32 Features32;
110
111 if (DeviceFeatures == NULL) {
112 return EFI_INVALID_PARAMETER;
113 }
114
115 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
116
117 Status = VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES,
118 sizeof (UINT32), sizeof (UINT32), &Features32);
119 if (!EFI_ERROR (Status)) {
120 *DeviceFeatures = Features32;
121 }
122 return Status;
123 }
124
125 EFI_STATUS
126 EFIAPI
127 VirtioPciGetQueueAddress (
128 IN VIRTIO_DEVICE_PROTOCOL *This,
129 OUT UINT32 *QueueAddress
130 )
131 {
132 VIRTIO_PCI_DEVICE *Dev;
133
134 if (QueueAddress == NULL) {
135 return EFI_INVALID_PARAMETER;
136 }
137
138 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
139
140 return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
141 sizeof (UINT32), QueueAddress);
142 }
143
144 EFI_STATUS
145 EFIAPI
146 VirtioPciGetQueueSize (
147 IN VIRTIO_DEVICE_PROTOCOL *This,
148 OUT UINT16 *QueueNumMax
149 )
150 {
151 VIRTIO_PCI_DEVICE *Dev;
152
153 if (QueueNumMax == NULL) {
154 return EFI_INVALID_PARAMETER;
155 }
156
157 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
158
159 return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
160 sizeof (UINT16), QueueNumMax);
161 }
162
163 EFI_STATUS
164 EFIAPI
165 VirtioPciGetDeviceStatus (
166 IN VIRTIO_DEVICE_PROTOCOL *This,
167 OUT UINT8 *DeviceStatus
168 )
169 {
170 VIRTIO_PCI_DEVICE *Dev;
171
172 if (DeviceStatus == NULL) {
173 return EFI_INVALID_PARAMETER;
174 }
175
176 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
177
178 return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
179 sizeof (UINT8), sizeof (UINT8), DeviceStatus);
180 }
181
182 EFI_STATUS
183 EFIAPI
184 VirtioPciSetGuestFeatures (
185 IN VIRTIO_DEVICE_PROTOCOL *This,
186 IN UINT64 Features
187 )
188 {
189 VIRTIO_PCI_DEVICE *Dev;
190
191 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
192
193 if (Features > MAX_UINT32) {
194 return EFI_UNSUPPORTED;
195 }
196 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
197 sizeof (UINT32), Features);
198 }
199
200 EFI_STATUS
201 EFIAPI
202 VirtioPciSetQueueAddress (
203 VIRTIO_DEVICE_PROTOCOL *This,
204 UINT32 Address
205 )
206 {
207 VIRTIO_PCI_DEVICE *Dev;
208
209 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
210
211 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
212 Address);
213 }
214
215 EFI_STATUS
216 EFIAPI
217 VirtioPciSetQueueSel (
218 VIRTIO_DEVICE_PROTOCOL *This,
219 UINT16 Sel
220 )
221 {
222 VIRTIO_PCI_DEVICE *Dev;
223
224 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
225
226 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
227 Sel);
228 }
229
230 EFI_STATUS
231 EFIAPI
232 VirtioPciSetQueueAlignment (
233 VIRTIO_DEVICE_PROTOCOL *This,
234 UINT32 Alignment
235 )
236 {
237 return EFI_SUCCESS;
238 }
239
240 EFI_STATUS
241 EFIAPI
242 VirtioPciSetPageSize (
243 VIRTIO_DEVICE_PROTOCOL *This,
244 UINT32 PageSize
245 )
246 {
247 return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
248 }
249
250 EFI_STATUS
251 EFIAPI
252 VirtioPciSetQueueNotify (
253 VIRTIO_DEVICE_PROTOCOL *This,
254 UINT16 Index
255 )
256 {
257 VIRTIO_PCI_DEVICE *Dev;
258
259 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
260
261 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
262 Index);
263 }
264
265 EFI_STATUS
266 EFIAPI
267 VirtioPciSetQueueSize (
268 VIRTIO_DEVICE_PROTOCOL *This,
269 UINT16 Size
270 )
271 {
272 //
273 // This function is only applicable in Virtio-MMIO.
274 // (The QueueSize field is read-only in Virtio proper (PCI))
275 //
276 return EFI_SUCCESS;
277 }
278
279 EFI_STATUS
280 EFIAPI
281 VirtioPciSetDeviceStatus (
282 VIRTIO_DEVICE_PROTOCOL *This,
283 UINT8 DeviceStatus
284 )
285 {
286 VIRTIO_PCI_DEVICE *Dev;
287
288 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
289
290 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
291 sizeof (UINT8), DeviceStatus);
292 }