]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioGpuDxe/Commands.c
OvmfPkg/VirtioGpuDxe: initialize and tear down VirtIo GPU device
[mirror_edk2.git] / OvmfPkg / VirtioGpuDxe / Commands.c
1 /** @file
2
3 VirtIo GPU initialization, and commands (primitives) for the GPU device.
4
5 Copyright (C) 2016, Red Hat, Inc.
6
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include <IndustryStandard/VirtioGpu.h>
18 #include <Library/VirtioLib.h>
19
20 #include "VirtioGpu.h"
21
22 /**
23 Configure the VirtIo GPU device that underlies VgpuDev.
24
25 @param[in,out] VgpuDev The VGPU_DEV object to set up VirtIo messaging for.
26 On input, the caller is responsible for having
27 initialized VgpuDev->VirtIo. On output, VgpuDev->Ring
28 has been initialized, and synchronous VirtIo GPU
29 commands (primitives) can be submitted to the device.
30
31 @retval EFI_SUCCESS VirtIo GPU configuration successful.
32
33 @retval EFI_UNSUPPORTED The host-side configuration of the VirtIo GPU is not
34 supported by this driver.
35
36 @retval Error codes from underlying functions.
37 **/
38 EFI_STATUS
39 VirtioGpuInit (
40 IN OUT VGPU_DEV *VgpuDev
41 )
42 {
43 UINT8 NextDevStat;
44 EFI_STATUS Status;
45 UINT64 Features;
46 UINT16 QueueSize;
47
48 //
49 // Execute virtio-v1.0-cs04, 3.1.1 Driver Requirements: Device
50 // Initialization.
51 //
52 // 1. Reset the device.
53 //
54 NextDevStat = 0;
55 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
56 if (EFI_ERROR (Status)) {
57 goto Failed;
58 }
59
60 //
61 // 2. Set the ACKNOWLEDGE status bit [...]
62 //
63 NextDevStat |= VSTAT_ACK;
64 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
65 if (EFI_ERROR (Status)) {
66 goto Failed;
67 }
68
69 //
70 // 3. Set the DRIVER status bit [...]
71 //
72 NextDevStat |= VSTAT_DRIVER;
73 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
74 if (EFI_ERROR (Status)) {
75 goto Failed;
76 }
77
78 //
79 // 4. Read device feature bits...
80 //
81 Status = VgpuDev->VirtIo->GetDeviceFeatures (VgpuDev->VirtIo, &Features);
82 if (EFI_ERROR (Status)) {
83 goto Failed;
84 }
85 if ((Features & VIRTIO_F_VERSION_1) == 0) {
86 Status = EFI_UNSUPPORTED;
87 goto Failed;
88 }
89 //
90 // We only want the most basic 2D features.
91 //
92 Features &= VIRTIO_F_VERSION_1;
93
94 //
95 // ... and write the subset of feature bits understood by the [...] driver to
96 // the device. [...]
97 // 5. Set the FEATURES_OK status bit.
98 // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
99 //
100 Status = Virtio10WriteFeatures (VgpuDev->VirtIo, Features, &NextDevStat);
101 if (EFI_ERROR (Status)) {
102 goto Failed;
103 }
104
105 //
106 // 7. Perform device-specific setup, including discovery of virtqueues for
107 // the device [...]
108 //
109 Status = VgpuDev->VirtIo->SetQueueSel (VgpuDev->VirtIo,
110 VIRTIO_GPU_CONTROL_QUEUE);
111 if (EFI_ERROR (Status)) {
112 goto Failed;
113 }
114 Status = VgpuDev->VirtIo->GetQueueNumMax (VgpuDev->VirtIo, &QueueSize);
115 if (EFI_ERROR (Status)) {
116 goto Failed;
117 }
118
119 //
120 // We implement each VirtIo GPU command that we use with two descriptors:
121 // request, response.
122 //
123 if (QueueSize < 2) {
124 Status = EFI_UNSUPPORTED;
125 goto Failed;
126 }
127
128 //
129 // [...] population of virtqueues [...]
130 //
131 Status = VirtioRingInit (QueueSize, &VgpuDev->Ring);
132 if (EFI_ERROR (Status)) {
133 goto Failed;
134 }
135 Status = VgpuDev->VirtIo->SetQueueAddress (VgpuDev->VirtIo, &VgpuDev->Ring);
136 if (EFI_ERROR (Status)) {
137 goto ReleaseQueue;
138 }
139
140 //
141 // 8. Set the DRIVER_OK status bit.
142 //
143 NextDevStat |= VSTAT_DRIVER_OK;
144 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
145 if (EFI_ERROR (Status)) {
146 goto ReleaseQueue;
147 }
148
149 return EFI_SUCCESS;
150
151 ReleaseQueue:
152 VirtioRingUninit (&VgpuDev->Ring);
153
154 Failed:
155 //
156 // If any of these steps go irrecoverably wrong, the driver SHOULD set the
157 // FAILED status bit to indicate that it has given up on the device (it can
158 // reset the device later to restart if desired). [...]
159 //
160 // VirtIo access failure here should not mask the original error.
161 //
162 NextDevStat |= VSTAT_FAILED;
163 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
164
165 return Status;
166 }
167
168 /**
169 De-configure the VirtIo GPU device that underlies VgpuDev.
170
171 @param[in,out] VgpuDev The VGPU_DEV object to tear down VirtIo messaging
172 for. On input, the caller is responsible for having
173 called VirtioGpuInit(). On output, VgpuDev->Ring has
174 been uninitialized; VirtIo GPU commands (primitives)
175 can no longer be submitted to the device.
176 **/
177 VOID
178 VirtioGpuUninit (
179 IN OUT VGPU_DEV *VgpuDev
180 )
181 {
182 //
183 // Resetting the VirtIo device makes it release its resources and forget its
184 // configuration.
185 //
186 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
187 VirtioRingUninit (&VgpuDev->Ring);
188 }
189
190 /**
191 EFI_EVENT_NOTIFY function for the VGPU_DEV.ExitBoot event. It resets the
192 VirtIo device, causing it to release its resources and to forget its
193 configuration.
194
195 This function may only be called (that is, VGPU_DEV.ExitBoot may only be
196 signaled) after VirtioGpuInit() returns and before VirtioGpuUninit() is
197 called.
198
199 @param[in] Event Event whose notification function is being invoked.
200
201 @param[in] Context Pointer to the associated VGPU_DEV object.
202 **/
203 VOID
204 EFIAPI
205 VirtioGpuExitBoot (
206 IN EFI_EVENT Event,
207 IN VOID *Context
208 )
209 {
210 VGPU_DEV *VgpuDev;
211
212 VgpuDev = Context;
213 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
214 }