]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioGpuDxe/Commands.c
OvmfPkg: replace old EFI_D_ debug levels with new DEBUG_ ones
[mirror_edk2.git] / OvmfPkg / VirtioGpuDxe / Commands.c
CommitLineData
c5f235bb
LE
1/** @file\r
2\r
3 VirtIo GPU initialization, and commands (primitives) for the GPU device.\r
4\r
5 Copyright (C) 2016, Red Hat, Inc.\r
fc2c1543 6 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
c5f235bb 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
c5f235bb
LE
9\r
10**/\r
11\r
c5f235bb
LE
12#include <Library/VirtioLib.h>\r
13\r
14#include "VirtioGpu.h"\r
15\r
16/**\r
17 Configure the VirtIo GPU device that underlies VgpuDev.\r
18\r
19 @param[in,out] VgpuDev The VGPU_DEV object to set up VirtIo messaging for.\r
20 On input, the caller is responsible for having\r
21 initialized VgpuDev->VirtIo. On output, VgpuDev->Ring\r
22 has been initialized, and synchronous VirtIo GPU\r
23 commands (primitives) can be submitted to the device.\r
24\r
25 @retval EFI_SUCCESS VirtIo GPU configuration successful.\r
26\r
27 @retval EFI_UNSUPPORTED The host-side configuration of the VirtIo GPU is not\r
28 supported by this driver.\r
29\r
30 @retval Error codes from underlying functions.\r
31**/\r
32EFI_STATUS\r
33VirtioGpuInit (\r
34 IN OUT VGPU_DEV *VgpuDev\r
35 )\r
36{\r
37 UINT8 NextDevStat;\r
38 EFI_STATUS Status;\r
39 UINT64 Features;\r
40 UINT16 QueueSize;\r
9bc5026c 41 UINT64 RingBaseShift;\r
c5f235bb
LE
42\r
43 //\r
44 // Execute virtio-v1.0-cs04, 3.1.1 Driver Requirements: Device\r
45 // Initialization.\r
46 //\r
47 // 1. Reset the device.\r
48 //\r
49 NextDevStat = 0;\r
50 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);\r
51 if (EFI_ERROR (Status)) {\r
52 goto Failed;\r
53 }\r
54\r
55 //\r
56 // 2. Set the ACKNOWLEDGE status bit [...]\r
57 //\r
58 NextDevStat |= VSTAT_ACK;\r
59 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);\r
60 if (EFI_ERROR (Status)) {\r
61 goto Failed;\r
62 }\r
63\r
64 //\r
65 // 3. Set the DRIVER status bit [...]\r
66 //\r
67 NextDevStat |= VSTAT_DRIVER;\r
68 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);\r
69 if (EFI_ERROR (Status)) {\r
70 goto Failed;\r
71 }\r
72\r
73 //\r
74 // 4. Read device feature bits...\r
75 //\r
76 Status = VgpuDev->VirtIo->GetDeviceFeatures (VgpuDev->VirtIo, &Features);\r
77 if (EFI_ERROR (Status)) {\r
78 goto Failed;\r
79 }\r
80 if ((Features & VIRTIO_F_VERSION_1) == 0) {\r
81 Status = EFI_UNSUPPORTED;\r
82 goto Failed;\r
83 }\r
84 //\r
85 // We only want the most basic 2D features.\r
86 //\r
db528909 87 Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;\r
c5f235bb
LE
88\r
89 //\r
90 // ... and write the subset of feature bits understood by the [...] driver to\r
91 // the device. [...]\r
92 // 5. Set the FEATURES_OK status bit.\r
93 // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]\r
94 //\r
95 Status = Virtio10WriteFeatures (VgpuDev->VirtIo, Features, &NextDevStat);\r
96 if (EFI_ERROR (Status)) {\r
97 goto Failed;\r
98 }\r
99\r
100 //\r
101 // 7. Perform device-specific setup, including discovery of virtqueues for\r
102 // the device [...]\r
103 //\r
104 Status = VgpuDev->VirtIo->SetQueueSel (VgpuDev->VirtIo,\r
105 VIRTIO_GPU_CONTROL_QUEUE);\r
106 if (EFI_ERROR (Status)) {\r
107 goto Failed;\r
108 }\r
109 Status = VgpuDev->VirtIo->GetQueueNumMax (VgpuDev->VirtIo, &QueueSize);\r
110 if (EFI_ERROR (Status)) {\r
111 goto Failed;\r
112 }\r
113\r
114 //\r
115 // We implement each VirtIo GPU command that we use with two descriptors:\r
116 // request, response.\r
117 //\r
118 if (QueueSize < 2) {\r
119 Status = EFI_UNSUPPORTED;\r
120 goto Failed;\r
121 }\r
122\r
123 //\r
124 // [...] population of virtqueues [...]\r
125 //\r
fc2c1543 126 Status = VirtioRingInit (VgpuDev->VirtIo, QueueSize, &VgpuDev->Ring);\r
c5f235bb
LE
127 if (EFI_ERROR (Status)) {\r
128 goto Failed;\r
129 }\r
9bc5026c
LE
130 //\r
131 // If anything fails from here on, we have to release the ring.\r
132 //\r
133 Status = VirtioRingMap (\r
134 VgpuDev->VirtIo,\r
135 &VgpuDev->Ring,\r
136 &RingBaseShift,\r
137 &VgpuDev->RingMap\r
138 );\r
139 if (EFI_ERROR (Status)) {\r
140 goto ReleaseQueue;\r
141 }\r
142 //\r
143 // If anything fails from here on, we have to unmap the ring.\r
144 //\r
53a4c604
BS
145 Status = VgpuDev->VirtIo->SetQueueAddress (\r
146 VgpuDev->VirtIo,\r
147 &VgpuDev->Ring,\r
9bc5026c 148 RingBaseShift\r
53a4c604 149 );\r
c5f235bb 150 if (EFI_ERROR (Status)) {\r
9bc5026c 151 goto UnmapQueue;\r
c5f235bb
LE
152 }\r
153\r
154 //\r
155 // 8. Set the DRIVER_OK status bit.\r
156 //\r
157 NextDevStat |= VSTAT_DRIVER_OK;\r
158 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);\r
159 if (EFI_ERROR (Status)) {\r
9bc5026c 160 goto UnmapQueue;\r
c5f235bb
LE
161 }\r
162\r
163 return EFI_SUCCESS;\r
164\r
9bc5026c
LE
165UnmapQueue:\r
166 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);\r
167\r
c5f235bb 168ReleaseQueue:\r
fc2c1543 169 VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);\r
c5f235bb
LE
170\r
171Failed:\r
172 //\r
173 // If any of these steps go irrecoverably wrong, the driver SHOULD set the\r
174 // FAILED status bit to indicate that it has given up on the device (it can\r
175 // reset the device later to restart if desired). [...]\r
176 //\r
177 // VirtIo access failure here should not mask the original error.\r
178 //\r
179 NextDevStat |= VSTAT_FAILED;\r
180 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);\r
181\r
182 return Status;\r
183}\r
184\r
185/**\r
186 De-configure the VirtIo GPU device that underlies VgpuDev.\r
187\r
188 @param[in,out] VgpuDev The VGPU_DEV object to tear down VirtIo messaging\r
189 for. On input, the caller is responsible for having\r
190 called VirtioGpuInit(). On output, VgpuDev->Ring has\r
191 been uninitialized; VirtIo GPU commands (primitives)\r
192 can no longer be submitted to the device.\r
193**/\r
194VOID\r
195VirtioGpuUninit (\r
196 IN OUT VGPU_DEV *VgpuDev\r
197 )\r
198{\r
199 //\r
200 // Resetting the VirtIo device makes it release its resources and forget its\r
201 // configuration.\r
202 //\r
203 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);\r
9bc5026c 204 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);\r
fc2c1543 205 VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);\r
c5f235bb
LE
206}\r
207\r
5c8f091b
LE
208/**\r
209 Allocate, zero and map memory, for bus master common buffer operation, to be\r
210 attached as backing store to a host-side VirtIo GPU resource.\r
211\r
212 @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
213 device.\r
214\r
215 @param[in] NumberOfPages The number of whole pages to allocate and map.\r
216\r
217 @param[out] HostAddress The system memory address of the allocated area.\r
218\r
219 @param[out] DeviceAddress The bus master device address of the allocated\r
220 area. The VirtIo GPU device may be programmed to\r
221 access the allocated area through DeviceAddress;\r
222 DeviceAddress is to be passed to the\r
223 VirtioGpuResourceAttachBacking() function, as the\r
224 BackingStoreDeviceAddress parameter.\r
225\r
226 @param[out] Mapping A resulting token to pass to\r
227 VirtioGpuUnmapAndFreeBackingStore().\r
228\r
229 @retval EFI_SUCCESS The requested number of pages has been allocated, zeroed\r
230 and mapped.\r
231\r
232 @return Status codes propagated from\r
233 VgpuDev->VirtIo->AllocateSharedPages() and\r
234 VirtioMapAllBytesInSharedBuffer().\r
235**/\r
236EFI_STATUS\r
237VirtioGpuAllocateZeroAndMapBackingStore (\r
238 IN VGPU_DEV *VgpuDev,\r
239 IN UINTN NumberOfPages,\r
240 OUT VOID **HostAddress,\r
241 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
242 OUT VOID **Mapping\r
243 )\r
244{\r
245 EFI_STATUS Status;\r
246 VOID *NewHostAddress;\r
247\r
248 Status = VgpuDev->VirtIo->AllocateSharedPages (\r
249 VgpuDev->VirtIo,\r
250 NumberOfPages,\r
251 &NewHostAddress\r
252 );\r
253 if (EFI_ERROR (Status)) {\r
254 return Status;\r
255 }\r
256\r
257 //\r
258 // Avoid exposing stale data to the device even temporarily: zero the area\r
259 // before mapping it.\r
260 //\r
261 ZeroMem (NewHostAddress, EFI_PAGES_TO_SIZE (NumberOfPages));\r
262\r
263 Status = VirtioMapAllBytesInSharedBuffer (\r
264 VgpuDev->VirtIo, // VirtIo\r
265 VirtioOperationBusMasterCommonBuffer, // Operation\r
266 NewHostAddress, // HostAddress\r
267 EFI_PAGES_TO_SIZE (NumberOfPages), // NumberOfBytes\r
268 DeviceAddress, // DeviceAddress\r
269 Mapping // Mapping\r
270 );\r
271 if (EFI_ERROR (Status)) {\r
272 goto FreeSharedPages;\r
273 }\r
274\r
275 *HostAddress = NewHostAddress;\r
276 return EFI_SUCCESS;\r
277\r
278FreeSharedPages:\r
279 VgpuDev->VirtIo->FreeSharedPages (\r
280 VgpuDev->VirtIo,\r
281 NumberOfPages,\r
282 NewHostAddress\r
283 );\r
284 return Status;\r
285}\r
286\r
287/**\r
288 Unmap and free memory originally allocated and mapped with\r
289 VirtioGpuAllocateZeroAndMapBackingStore().\r
290\r
291 If the memory allocated and mapped with\r
292 VirtioGpuAllocateZeroAndMapBackingStore() was attached to a host-side VirtIo\r
293 GPU resource with VirtioGpuResourceAttachBacking(), then the caller is\r
294 responsible for detaching the backing store from the same resource, with\r
295 VirtioGpuResourceDetachBacking(), before calling this function.\r
296\r
297 @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
298 device.\r
299\r
300 @param[in] NumberOfPages The NumberOfPages parameter originally passed to\r
301 VirtioGpuAllocateZeroAndMapBackingStore().\r
302\r
303 @param[in] HostAddress The HostAddress value originally output by\r
304 VirtioGpuAllocateZeroAndMapBackingStore().\r
305\r
306 @param[in] Mapping The token that was originally output by\r
307 VirtioGpuAllocateZeroAndMapBackingStore().\r
308**/\r
309VOID\r
310VirtioGpuUnmapAndFreeBackingStore (\r
311 IN VGPU_DEV *VgpuDev,\r
312 IN UINTN NumberOfPages,\r
313 IN VOID *HostAddress,\r
314 IN VOID *Mapping\r
315 )\r
316{\r
317 VgpuDev->VirtIo->UnmapSharedBuffer (\r
318 VgpuDev->VirtIo,\r
319 Mapping\r
320 );\r
321 VgpuDev->VirtIo->FreeSharedPages (\r
322 VgpuDev->VirtIo,\r
323 NumberOfPages,\r
324 HostAddress\r
325 );\r
326}\r
327\r
c5f235bb
LE
328/**\r
329 EFI_EVENT_NOTIFY function for the VGPU_DEV.ExitBoot event. It resets the\r
330 VirtIo device, causing it to release its resources and to forget its\r
331 configuration.\r
332\r
333 This function may only be called (that is, VGPU_DEV.ExitBoot may only be\r
334 signaled) after VirtioGpuInit() returns and before VirtioGpuUninit() is\r
335 called.\r
336\r
337 @param[in] Event Event whose notification function is being invoked.\r
338\r
339 @param[in] Context Pointer to the associated VGPU_DEV object.\r
340**/\r
341VOID\r
342EFIAPI\r
343VirtioGpuExitBoot (\r
344 IN EFI_EVENT Event,\r
345 IN VOID *Context\r
346 )\r
347{\r
348 VGPU_DEV *VgpuDev;\r
349\r
8ddd12e5 350 DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));\r
c5f235bb
LE
351 VgpuDev = Context;\r
352 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);\r
353}\r
a66ea3b5
LE
354\r
355/**\r
356 Internal utility function that sends a request to the VirtIo GPU device\r
357 model, awaits the answer from the host, and returns a status.\r
358\r
359 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
360 device. The caller is responsible to have\r
361 successfully invoked VirtioGpuInit() on VgpuDev\r
362 previously, while VirtioGpuUninit() must not have\r
363 been called on VgpuDev.\r
364\r
365 @param[in] RequestType The type of the request. The caller is responsible\r
366 for providing a VirtioGpuCmd* RequestType which, on\r
367 success, elicits a VirtioGpuRespOkNodata response\r
368 from the host.\r
369\r
370 @param[in] Fence Whether to enable fencing for this request. Fencing\r
371 forces the host to complete the command before\r
372 producing a response. If Fence is TRUE, then\r
373 VgpuDev->FenceId is consumed, and incremented.\r
374\r
375 @param[in,out] Header Pointer to the caller-allocated request object. The\r
376 request must start with VIRTIO_GPU_CONTROL_HEADER.\r
377 This function overwrites all fields of Header before\r
378 submitting the request to the host:\r
379\r
380 - it sets Type from RequestType,\r
381\r
382 - it sets Flags and FenceId based on Fence,\r
383\r
384 - it zeroes CtxId and Padding.\r
385\r
386 @param[in] RequestSize Size of the entire caller-allocated request object,\r
387 including the leading VIRTIO_GPU_CONTROL_HEADER.\r
388\r
389 @retval EFI_SUCCESS Operation successful.\r
390\r
391 @retval EFI_DEVICE_ERROR The host rejected the request. The host error\r
70d5086c 392 code has been logged on the DEBUG_ERROR level.\r
a66ea3b5
LE
393\r
394 @return Codes for unexpected errors in VirtIo\r
067b6483
LE
395 messaging, or request/response\r
396 mapping/unmapping.\r
a66ea3b5
LE
397**/\r
398STATIC\r
399EFI_STATUS\r
400VirtioGpuSendCommand (\r
401 IN OUT VGPU_DEV *VgpuDev,\r
402 IN VIRTIO_GPU_CONTROL_TYPE RequestType,\r
403 IN BOOLEAN Fence,\r
404 IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,\r
405 IN UINTN RequestSize\r
406 )\r
407{\r
408 DESC_INDICES Indices;\r
409 volatile VIRTIO_GPU_CONTROL_HEADER Response;\r
410 EFI_STATUS Status;\r
411 UINT32 ResponseSize;\r
067b6483
LE
412 EFI_PHYSICAL_ADDRESS RequestDeviceAddress;\r
413 VOID *RequestMap;\r
414 EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;\r
415 VOID *ResponseMap;\r
a66ea3b5
LE
416\r
417 //\r
418 // Initialize Header.\r
419 //\r
420 Header->Type = RequestType;\r
421 if (Fence) {\r
422 Header->Flags = VIRTIO_GPU_FLAG_FENCE;\r
423 Header->FenceId = VgpuDev->FenceId++;\r
424 } else {\r
425 Header->Flags = 0;\r
426 Header->FenceId = 0;\r
427 }\r
428 Header->CtxId = 0;\r
429 Header->Padding = 0;\r
430\r
431 ASSERT (RequestSize >= sizeof *Header);\r
7f1bf51b 432 ASSERT (RequestSize <= MAX_UINT32);\r
a66ea3b5 433\r
067b6483
LE
434 //\r
435 // Map request and response to bus master device addresses.\r
436 //\r
437 Status = VirtioMapAllBytesInSharedBuffer (\r
438 VgpuDev->VirtIo,\r
439 VirtioOperationBusMasterRead,\r
440 (VOID *)Header,\r
441 RequestSize,\r
442 &RequestDeviceAddress,\r
443 &RequestMap\r
444 );\r
445 if (EFI_ERROR (Status)) {\r
446 return Status;\r
447 }\r
448 Status = VirtioMapAllBytesInSharedBuffer (\r
449 VgpuDev->VirtIo,\r
450 VirtioOperationBusMasterWrite,\r
451 (VOID *)&Response,\r
452 sizeof Response,\r
453 &ResponseDeviceAddress,\r
454 &ResponseMap\r
455 );\r
456 if (EFI_ERROR (Status)) {\r
457 goto UnmapRequest;\r
458 }\r
459\r
a66ea3b5
LE
460 //\r
461 // Compose the descriptor chain.\r
462 //\r
463 VirtioPrepare (&VgpuDev->Ring, &Indices);\r
067b6483
LE
464 VirtioAppendDesc (\r
465 &VgpuDev->Ring,\r
466 RequestDeviceAddress,\r
467 (UINT32)RequestSize,\r
468 VRING_DESC_F_NEXT,\r
469 &Indices\r
470 );\r
471 VirtioAppendDesc (\r
472 &VgpuDev->Ring,\r
473 ResponseDeviceAddress,\r
474 (UINT32)sizeof Response,\r
475 VRING_DESC_F_WRITE,\r
476 &Indices\r
477 );\r
a66ea3b5
LE
478\r
479 //\r
480 // Send the command.\r
481 //\r
482 Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,\r
483 &VgpuDev->Ring, &Indices, &ResponseSize);\r
484 if (EFI_ERROR (Status)) {\r
067b6483 485 goto UnmapResponse;\r
a66ea3b5
LE
486 }\r
487\r
488 //\r
067b6483 489 // Verify response size.\r
a66ea3b5
LE
490 //\r
491 if (ResponseSize != sizeof Response) {\r
70d5086c 492 DEBUG ((DEBUG_ERROR, "%a: malformed response to Request=0x%x\n",\r
a66ea3b5 493 __FUNCTION__, (UINT32)RequestType));\r
067b6483
LE
494 Status = EFI_PROTOCOL_ERROR;\r
495 goto UnmapResponse;\r
a66ea3b5
LE
496 }\r
497\r
067b6483
LE
498 //\r
499 // Unmap response and request, in reverse order of mapping. On error, the\r
500 // respective mapping is invalidated anyway, only the data may not have been\r
501 // committed to system memory (in case of VirtioOperationBusMasterWrite).\r
502 //\r
503 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);\r
504 if (EFI_ERROR (Status)) {\r
505 goto UnmapRequest;\r
506 }\r
507 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);\r
508 if (EFI_ERROR (Status)) {\r
509 return Status;\r
510 }\r
511\r
512 //\r
513 // Parse the response.\r
514 //\r
a66ea3b5
LE
515 if (Response.Type == VirtioGpuRespOkNodata) {\r
516 return EFI_SUCCESS;\r
517 }\r
518\r
70d5086c 519 DEBUG ((DEBUG_ERROR, "%a: Request=0x%x Response=0x%x\n", __FUNCTION__,\r
a66ea3b5
LE
520 (UINT32)RequestType, Response.Type));\r
521 return EFI_DEVICE_ERROR;\r
067b6483
LE
522\r
523UnmapResponse:\r
524 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);\r
525\r
526UnmapRequest:\r
527 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);\r
528\r
529 return Status;\r
a66ea3b5
LE
530}\r
531\r
532/**\r
533 The following functions send requests to the VirtIo GPU device model, await\r
534 the answer from the host, and return a status. They share the following\r
535 interface details:\r
536\r
537 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
538 device. The caller is responsible to have\r
539 successfully invoked VirtioGpuInit() on VgpuDev\r
540 previously, while VirtioGpuUninit() must not have\r
541 been called on VgpuDev.\r
542\r
543 @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were\r
544 detected by this driver.\r
545\r
546 @retval EFI_SUCCESS Operation successful.\r
547\r
548 @retval EFI_DEVICE_ERROR The host rejected the request. The host error\r
70d5086c 549 code has been logged on the DEBUG_ERROR level.\r
a66ea3b5
LE
550\r
551 @return Codes for unexpected errors in VirtIo\r
552 messaging.\r
553\r
554 For the command-specific parameters, please consult the GPU Device section of\r
555 the VirtIo 1.0 specification (see references in\r
556 "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").\r
557**/\r
558EFI_STATUS\r
559VirtioGpuResourceCreate2d (\r
560 IN OUT VGPU_DEV *VgpuDev,\r
561 IN UINT32 ResourceId,\r
562 IN VIRTIO_GPU_FORMATS Format,\r
563 IN UINT32 Width,\r
564 IN UINT32 Height\r
565 )\r
566{\r
567 volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;\r
568\r
569 if (ResourceId == 0) {\r
570 return EFI_INVALID_PARAMETER;\r
571 }\r
572\r
573 Request.ResourceId = ResourceId;\r
574 Request.Format = (UINT32)Format;\r
575 Request.Width = Width;\r
576 Request.Height = Height;\r
577\r
578 return VirtioGpuSendCommand (\r
579 VgpuDev,\r
580 VirtioGpuCmdResourceCreate2d,\r
581 FALSE, // Fence\r
582 &Request.Header,\r
583 sizeof Request\r
584 );\r
585}\r
586\r
587EFI_STATUS\r
588VirtioGpuResourceUnref (\r
589 IN OUT VGPU_DEV *VgpuDev,\r
590 IN UINT32 ResourceId\r
591 )\r
592{\r
593 volatile VIRTIO_GPU_RESOURCE_UNREF Request;\r
594\r
595 if (ResourceId == 0) {\r
596 return EFI_INVALID_PARAMETER;\r
597 }\r
598\r
599 Request.ResourceId = ResourceId;\r
600 Request.Padding = 0;\r
601\r
602 return VirtioGpuSendCommand (\r
603 VgpuDev,\r
604 VirtioGpuCmdResourceUnref,\r
605 FALSE, // Fence\r
606 &Request.Header,\r
607 sizeof Request\r
608 );\r
609}\r
610\r
611EFI_STATUS\r
612VirtioGpuResourceAttachBacking (\r
5409c6ab
LE
613 IN OUT VGPU_DEV *VgpuDev,\r
614 IN UINT32 ResourceId,\r
615 IN EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress,\r
616 IN UINTN NumberOfPages\r
a66ea3b5
LE
617 )\r
618{\r
619 volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;\r
620\r
621 if (ResourceId == 0) {\r
622 return EFI_INVALID_PARAMETER;\r
623 }\r
624\r
625 Request.ResourceId = ResourceId;\r
626 Request.NrEntries = 1;\r
5409c6ab 627 Request.Entry.Addr = BackingStoreDeviceAddress;\r
a66ea3b5
LE
628 Request.Entry.Length = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);\r
629 Request.Entry.Padding = 0;\r
630\r
631 return VirtioGpuSendCommand (\r
632 VgpuDev,\r
633 VirtioGpuCmdResourceAttachBacking,\r
634 FALSE, // Fence\r
635 &Request.Header,\r
636 sizeof Request\r
637 );\r
638}\r
639\r
640EFI_STATUS\r
641VirtioGpuResourceDetachBacking (\r
642 IN OUT VGPU_DEV *VgpuDev,\r
643 IN UINT32 ResourceId\r
644 )\r
645{\r
646 volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;\r
647\r
648 if (ResourceId == 0) {\r
649 return EFI_INVALID_PARAMETER;\r
650 }\r
651\r
652 Request.ResourceId = ResourceId;\r
653 Request.Padding = 0;\r
654\r
655 //\r
656 // In this case, we set Fence to TRUE, because after this function returns,\r
657 // the caller might reasonably want to repurpose the backing pages\r
658 // immediately. Thus we should ensure that the host releases all references\r
659 // to the backing pages before we return.\r
660 //\r
661 return VirtioGpuSendCommand (\r
662 VgpuDev,\r
663 VirtioGpuCmdResourceDetachBacking,\r
664 TRUE, // Fence\r
665 &Request.Header,\r
666 sizeof Request\r
667 );\r
668}\r
669\r
670EFI_STATUS\r
671VirtioGpuSetScanout (\r
672 IN OUT VGPU_DEV *VgpuDev,\r
673 IN UINT32 X,\r
674 IN UINT32 Y,\r
675 IN UINT32 Width,\r
676 IN UINT32 Height,\r
677 IN UINT32 ScanoutId,\r
678 IN UINT32 ResourceId\r
679 )\r
680{\r
681 volatile VIRTIO_GPU_SET_SCANOUT Request;\r
682\r
683 //\r
684 // Unlike for most other commands, ResourceId=0 is valid; it\r
685 // is used to disable a scanout.\r
686 //\r
687 Request.Rectangle.X = X;\r
688 Request.Rectangle.Y = Y;\r
689 Request.Rectangle.Width = Width;\r
690 Request.Rectangle.Height = Height;\r
691 Request.ScanoutId = ScanoutId;\r
692 Request.ResourceId = ResourceId;\r
693\r
694 return VirtioGpuSendCommand (\r
695 VgpuDev,\r
696 VirtioGpuCmdSetScanout,\r
697 FALSE, // Fence\r
698 &Request.Header,\r
699 sizeof Request\r
700 );\r
701}\r
702\r
703EFI_STATUS\r
704VirtioGpuTransferToHost2d (\r
705 IN OUT VGPU_DEV *VgpuDev,\r
706 IN UINT32 X,\r
707 IN UINT32 Y,\r
708 IN UINT32 Width,\r
709 IN UINT32 Height,\r
710 IN UINT64 Offset,\r
711 IN UINT32 ResourceId\r
712 )\r
713{\r
714 volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;\r
715\r
716 if (ResourceId == 0) {\r
717 return EFI_INVALID_PARAMETER;\r
718 }\r
719\r
720 Request.Rectangle.X = X;\r
721 Request.Rectangle.Y = Y;\r
722 Request.Rectangle.Width = Width;\r
723 Request.Rectangle.Height = Height;\r
724 Request.Offset = Offset;\r
725 Request.ResourceId = ResourceId;\r
726 Request.Padding = 0;\r
727\r
728 return VirtioGpuSendCommand (\r
729 VgpuDev,\r
730 VirtioGpuCmdTransferToHost2d,\r
731 FALSE, // Fence\r
732 &Request.Header,\r
733 sizeof Request\r
734 );\r
735}\r
736\r
737EFI_STATUS\r
738VirtioGpuResourceFlush (\r
739 IN OUT VGPU_DEV *VgpuDev,\r
740 IN UINT32 X,\r
741 IN UINT32 Y,\r
742 IN UINT32 Width,\r
743 IN UINT32 Height,\r
744 IN UINT32 ResourceId\r
745 )\r
746{\r
747 volatile VIRTIO_GPU_RESOURCE_FLUSH Request;\r
748\r
749 if (ResourceId == 0) {\r
750 return EFI_INVALID_PARAMETER;\r
751 }\r
752\r
753 Request.Rectangle.X = X;\r
754 Request.Rectangle.Y = Y;\r
755 Request.Rectangle.Width = Width;\r
756 Request.Rectangle.Height = Height;\r
757 Request.ResourceId = ResourceId;\r
758 Request.Padding = 0;\r
759\r
760 return VirtioGpuSendCommand (\r
761 VgpuDev,\r
762 VirtioGpuCmdResourceFlush,\r
763 FALSE, // Fence\r
764 &Request.Header,\r
765 sizeof Request\r
766 );\r
767}\r