]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Driver.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Driver.c
CommitLineData
eaf4f336 1/** @file\r
2 This driver is a sample implementation of the Graphics Output Protocol for\r
3 the QEMU (Cirrus Logic 5446) video controller.\r
4\r
cd514773 5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
eaf4f336 6\r
b26f0cf9 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
eaf4f336 8\r
9**/\r
10\r
2e77f0e7 11#include "Qemu.h"\r
1358ecb7 12#include <IndustryStandard/Acpi.h>\r
eaf4f336 13\r
14EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
15 QemuVideoControllerDriverSupported,\r
16 QemuVideoControllerDriverStart,\r
17 QemuVideoControllerDriverStop,\r
18 0x10,\r
19 NULL,\r
20 NULL\r
21};\r
22\r
212aac55 23QEMU_VIDEO_CARD gQemuVideoCardList[] = {\r
24 {\r
70dbd163 25 PCI_CLASS_DISPLAY_VGA,\r
212aac55 26 CIRRUS_LOGIC_VENDOR_ID,\r
27 CIRRUS_LOGIC_5430_DEVICE_ID,\r
28 QEMU_VIDEO_CIRRUS_5430,\r
29 L"Cirrus 5430"\r
30 },{\r
70dbd163 31 PCI_CLASS_DISPLAY_VGA,\r
212aac55 32 CIRRUS_LOGIC_VENDOR_ID,\r
33 CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,\r
34 QEMU_VIDEO_CIRRUS_5430,\r
35 L"Cirrus 5430"\r
36 },{\r
70dbd163 37 PCI_CLASS_DISPLAY_VGA,\r
212aac55 38 CIRRUS_LOGIC_VENDOR_ID,\r
39 CIRRUS_LOGIC_5446_DEVICE_ID,\r
40 QEMU_VIDEO_CIRRUS_5446,\r
41 L"Cirrus 5446"\r
54f9b9ac 42 },{\r
70dbd163 43 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 44 0x1234,\r
45 0x1111,\r
cdb4f5dc 46 QEMU_VIDEO_BOCHS_MMIO,\r
54f9b9ac 47 L"QEMU Standard VGA"\r
333f32ec
GH
48 },{\r
49 PCI_CLASS_DISPLAY_OTHER,\r
50 0x1234,\r
51 0x1111,\r
52 QEMU_VIDEO_BOCHS_MMIO,\r
53 L"QEMU Standard VGA (secondary)"\r
54f9b9ac 54 },{\r
70dbd163 55 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 56 0x1b36,\r
57 0x0100,\r
58 QEMU_VIDEO_BOCHS,\r
59 L"QEMU QXL VGA"\r
94210dc9 60 },{\r
70dbd163 61 PCI_CLASS_DISPLAY_VGA,\r
94210dc9
GH
62 0x1af4,\r
63 0x1050,\r
64 QEMU_VIDEO_BOCHS_MMIO,\r
65 L"QEMU VirtIO VGA"\r
d021868c
YCL
66 },{\r
67 PCI_CLASS_DISPLAY_VGA,\r
68 0x15ad,\r
69 0x0405,\r
70 QEMU_VIDEO_VMWARE_SVGA,\r
71 L"QEMU VMWare SVGA"\r
212aac55 72 },{\r
73 0 /* end of list */\r
74 }\r
75};\r
76\r
77static QEMU_VIDEO_CARD*\r
78QemuVideoDetect(\r
70dbd163 79 IN UINT8 SubClass,\r
212aac55 80 IN UINT16 VendorId,\r
81 IN UINT16 DeviceId\r
82 )\r
83{\r
84 UINTN Index = 0;\r
85\r
86 while (gQemuVideoCardList[Index].VendorId != 0) {\r
70dbd163
GH
87 if (gQemuVideoCardList[Index].SubClass == SubClass &&\r
88 gQemuVideoCardList[Index].VendorId == VendorId &&\r
212aac55 89 gQemuVideoCardList[Index].DeviceId == DeviceId) {\r
90 return gQemuVideoCardList + Index;\r
91 }\r
92 Index++;\r
93 }\r
94 return NULL;\r
95}\r
96\r
eaf4f336 97/**\r
98 Check if this device is supported.\r
99\r
100 @param This The driver binding protocol.\r
101 @param Controller The controller handle to check.\r
102 @param RemainingDevicePath The remaining device path.\r
103\r
104 @retval EFI_SUCCESS The bus supports this controller.\r
105 @retval EFI_UNSUPPORTED This device isn't supported.\r
106\r
107**/\r
108EFI_STATUS\r
109EFIAPI\r
110QemuVideoControllerDriverSupported (\r
111 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
112 IN EFI_HANDLE Controller,\r
113 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
114 )\r
115{\r
116 EFI_STATUS Status;\r
117 EFI_PCI_IO_PROTOCOL *PciIo;\r
118 PCI_TYPE00 Pci;\r
212aac55 119 QEMU_VIDEO_CARD *Card;\r
eaf4f336 120\r
121 //\r
122 // Open the PCI I/O Protocol\r
123 //\r
124 Status = gBS->OpenProtocol (\r
125 Controller,\r
126 &gEfiPciIoProtocolGuid,\r
127 (VOID **) &PciIo,\r
128 This->DriverBindingHandle,\r
129 Controller,\r
130 EFI_OPEN_PROTOCOL_BY_DRIVER\r
131 );\r
132 if (EFI_ERROR (Status)) {\r
133 return Status;\r
134 }\r
135\r
136 //\r
137 // Read the PCI Configuration Header from the PCI Device\r
138 //\r
139 Status = PciIo->Pci.Read (\r
140 PciIo,\r
141 EfiPciIoWidthUint32,\r
142 0,\r
143 sizeof (Pci) / sizeof (UINT32),\r
144 &Pci\r
145 );\r
146 if (EFI_ERROR (Status)) {\r
147 goto Done;\r
148 }\r
149\r
150 Status = EFI_UNSUPPORTED;\r
70dbd163 151 if (!IS_PCI_DISPLAY (&Pci)) {\r
442c2ab8
LE
152 goto Done;\r
153 }\r
70dbd163 154 Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
212aac55 155 if (Card != NULL) {\r
70d5086c 156 DEBUG ((DEBUG_INFO, "QemuVideo: %s detected\n", Card->Name));\r
212aac55 157 Status = EFI_SUCCESS;\r
eaf4f336 158 }\r
159\r
160Done:\r
161 //\r
162 // Close the PCI I/O Protocol\r
163 //\r
164 gBS->CloseProtocol (\r
165 Controller,\r
166 &gEfiPciIoProtocolGuid,\r
167 This->DriverBindingHandle,\r
168 Controller\r
169 );\r
170\r
171 return Status;\r
172}\r
173\r
174/**\r
175 Start to process the controller.\r
176\r
177 @param This The USB bus driver binding instance.\r
178 @param Controller The controller to check.\r
179 @param RemainingDevicePath The remaining device patch.\r
180\r
181 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
182 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
183 bus.\r
184 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
185\r
186**/\r
187EFI_STATUS\r
188EFIAPI\r
189QemuVideoControllerDriverStart (\r
190 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
191 IN EFI_HANDLE Controller,\r
192 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
193 )\r
194{\r
9c08bbe5 195 EFI_TPL OldTpl;\r
cdb4f5dc 196 EFI_STATUS Status;\r
197 QEMU_VIDEO_PRIVATE_DATA *Private;\r
b37bcfd6 198 BOOLEAN IsQxl;\r
cdb4f5dc 199 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
42d0cad7 200 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
cdb4f5dc 201 PCI_TYPE00 Pci;\r
202 QEMU_VIDEO_CARD *Card;\r
4374c2e5 203 EFI_PCI_IO_PROTOCOL *ChildPciIo;\r
662bd0da 204 UINT64 SupportedVgaIo;\r
54f9b9ac 205\r
9c08bbe5
LE
206 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
207\r
eaf4f336 208 //\r
a2e75595 209 // Allocate Private context data for GOP interface.\r
eaf4f336 210 //\r
211 Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
212 if (Private == NULL) {\r
9c08bbe5
LE
213 Status = EFI_OUT_OF_RESOURCES;\r
214 goto RestoreTpl;\r
eaf4f336 215 }\r
216\r
217 //\r
218 // Set up context record\r
219 //\r
220 Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
eaf4f336 221\r
222 //\r
223 // Open PCI I/O Protocol\r
224 //\r
225 Status = gBS->OpenProtocol (\r
226 Controller,\r
227 &gEfiPciIoProtocolGuid,\r
228 (VOID **) &Private->PciIo,\r
229 This->DriverBindingHandle,\r
230 Controller,\r
231 EFI_OPEN_PROTOCOL_BY_DRIVER\r
232 );\r
233 if (EFI_ERROR (Status)) {\r
d89186bc 234 goto FreePrivate;\r
eaf4f336 235 }\r
236\r
212aac55 237 //\r
238 // Read the PCI Configuration Header from the PCI Device\r
239 //\r
240 Status = Private->PciIo->Pci.Read (\r
241 Private->PciIo,\r
242 EfiPciIoWidthUint32,\r
243 0,\r
244 sizeof (Pci) / sizeof (UINT32),\r
245 &Pci\r
246 );\r
247 if (EFI_ERROR (Status)) {\r
d89186bc 248 goto ClosePciIo;\r
212aac55 249 }\r
250\r
d89186bc
LE
251 //\r
252 // Determine card variant.\r
253 //\r
70dbd163 254 Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
212aac55 255 if (Card == NULL) {\r
256 Status = EFI_DEVICE_ERROR;\r
d89186bc 257 goto ClosePciIo;\r
212aac55 258 }\r
259 Private->Variant = Card->Variant;\r
260\r
b37bcfd6
LE
261 //\r
262 // IsQxl is based on the detected Card->Variant, which at a later point might\r
263 // not match Private->Variant.\r
264 //\r
265 IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);\r
266\r
eaf4f336 267 //\r
268 // Save original PCI attributes\r
269 //\r
270 Status = Private->PciIo->Attributes (\r
271 Private->PciIo,\r
272 EfiPciIoAttributeOperationGet,\r
273 0,\r
274 &Private->OriginalPciAttributes\r
275 );\r
276\r
277 if (EFI_ERROR (Status)) {\r
d89186bc 278 goto ClosePciIo;\r
eaf4f336 279 }\r
eaf4f336 280\r
662bd0da
MC
281 //\r
282 // Get supported PCI attributes\r
283 //\r
284 Status = Private->PciIo->Attributes (\r
285 Private->PciIo,\r
286 EfiPciIoAttributeOperationSupported,\r
287 0,\r
288 &SupportedVgaIo\r
289 );\r
290 if (EFI_ERROR (Status)) {\r
291 goto ClosePciIo;\r
292 }\r
293\r
294 SupportedVgaIo &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
edfe16a6 295 if (SupportedVgaIo == 0 && IS_PCI_VGA (&Pci)) {\r
662bd0da
MC
296 Status = EFI_UNSUPPORTED;\r
297 goto ClosePciIo;\r
298 }\r
299\r
d89186bc
LE
300 //\r
301 // Set new PCI attributes\r
302 //\r
eaf4f336 303 Status = Private->PciIo->Attributes (\r
304 Private->PciIo,\r
305 EfiPciIoAttributeOperationEnable,\r
662bd0da 306 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | SupportedVgaIo,\r
eaf4f336 307 NULL\r
308 );\r
309 if (EFI_ERROR (Status)) {\r
d89186bc 310 goto ClosePciIo;\r
eaf4f336 311 }\r
312\r
cdb4f5dc 313 //\r
314 // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).\r
315 //\r
316 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
d89186bc
LE
317 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
318\r
cdb4f5dc 319 Status = Private->PciIo->GetBarAttributes (\r
320 Private->PciIo,\r
321 PCI_BAR_IDX2,\r
322 NULL,\r
323 (VOID**) &MmioDesc\r
324 );\r
325 if (EFI_ERROR (Status) ||\r
326 MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
70d5086c 327 DEBUG ((DEBUG_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));\r
cdb4f5dc 328 Private->Variant = QEMU_VIDEO_BOCHS;\r
329 } else {\r
70d5086c 330 DEBUG ((DEBUG_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",\r
cdb4f5dc 331 MmioDesc->AddrRangeMin));\r
332 }\r
5cdb96fa
LE
333\r
334 if (!EFI_ERROR (Status)) {\r
335 FreePool (MmioDesc);\r
336 }\r
cdb4f5dc 337 }\r
338\r
d021868c
YCL
339 //\r
340 // VMWare SVGA is handled like Bochs (with port IO only).\r
341 //\r
342 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
343 Private->Variant = QEMU_VIDEO_BOCHS;\r
344 Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;\r
345 }\r
346\r
54f9b9ac 347 //\r
348 // Check if accessing the bochs interface works.\r
349 //\r
cdb4f5dc 350 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
351 Private->Variant == QEMU_VIDEO_BOCHS) {\r
54f9b9ac 352 UINT16 BochsId;\r
353 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);\r
354 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
70d5086c 355 DEBUG ((DEBUG_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
54f9b9ac 356 Status = EFI_DEVICE_ERROR;\r
d89186bc 357 goto RestoreAttributes;\r
54f9b9ac 358 }\r
359 }\r
360\r
eaf4f336 361 //\r
362 // Get ParentDevicePath\r
363 //\r
364 Status = gBS->HandleProtocol (\r
365 Controller,\r
366 &gEfiDevicePathProtocolGuid,\r
367 (VOID **) &ParentDevicePath\r
368 );\r
369 if (EFI_ERROR (Status)) {\r
d89186bc 370 goto RestoreAttributes;\r
eaf4f336 371 }\r
372\r
373 //\r
374 // Set Gop Device Path\r
375 //\r
42d0cad7
LE
376 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
377 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
378 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
379 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
380 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
381\r
382 Private->GopDevicePath = AppendDevicePathNode (\r
383 ParentDevicePath,\r
384 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
385 );\r
386 if (Private->GopDevicePath == NULL) {\r
387 Status = EFI_OUT_OF_RESOURCES;\r
388 goto RestoreAttributes;\r
eaf4f336 389 }\r
d89186bc
LE
390\r
391 //\r
42d0cad7 392 // Create new child handle and install the device path protocol on it.\r
d89186bc 393 //\r
42d0cad7
LE
394 Status = gBS->InstallMultipleProtocolInterfaces (\r
395 &Private->Handle,\r
396 &gEfiDevicePathProtocolGuid,\r
397 Private->GopDevicePath,\r
398 NULL\r
399 );\r
400 if (EFI_ERROR (Status)) {\r
401 goto FreeGopDevicePath;\r
eaf4f336 402 }\r
403\r
404 //\r
405 // Construct video mode buffer\r
406 //\r
212aac55 407 switch (Private->Variant) {\r
408 case QEMU_VIDEO_CIRRUS_5430:\r
409 case QEMU_VIDEO_CIRRUS_5446:\r
410 Status = QemuVideoCirrusModeSetup (Private);\r
411 break;\r
cdb4f5dc 412 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 413 case QEMU_VIDEO_BOCHS:\r
b37bcfd6 414 Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
54f9b9ac 415 break;\r
212aac55 416 default:\r
417 ASSERT (FALSE);\r
418 Status = EFI_DEVICE_ERROR;\r
419 break;\r
420 }\r
eaf4f336 421 if (EFI_ERROR (Status)) {\r
d89186bc 422 goto UninstallGopDevicePath;\r
eaf4f336 423 }\r
424\r
d89186bc
LE
425 //\r
426 // Start the GOP software stack.\r
427 //\r
428 Status = QemuVideoGraphicsOutputConstructor (Private);\r
429 if (EFI_ERROR (Status)) {\r
430 goto FreeModeData;\r
431 }\r
4374c2e5 432\r
d89186bc
LE
433 Status = gBS->InstallMultipleProtocolInterfaces (\r
434 &Private->Handle,\r
435 &gEfiGraphicsOutputProtocolGuid,\r
436 &Private->GraphicsOutput,\r
437 NULL\r
4374c2e5 438 );\r
d89186bc
LE
439 if (EFI_ERROR (Status)) {\r
440 goto DestructQemuVideoGraphics;\r
eaf4f336 441 }\r
442\r
d89186bc
LE
443 //\r
444 // Reference parent handle from child handle.\r
445 //\r
446 Status = gBS->OpenProtocol (\r
447 Controller,\r
448 &gEfiPciIoProtocolGuid,\r
449 (VOID **) &ChildPciIo,\r
450 This->DriverBindingHandle,\r
451 Private->Handle,\r
452 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
453 );\r
eaf4f336 454 if (EFI_ERROR (Status)) {\r
d89186bc
LE
455 goto UninstallGop;\r
456 }\r
eaf4f336 457\r
84a75f70 458#if defined MDE_CPU_IA32 || defined MDE_CPU_X64\r
90803342
LE
459 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
460 Private->Variant == QEMU_VIDEO_BOCHS) {\r
461 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);\r
462 }\r
84a75f70 463#endif\r
90803342 464\r
9c08bbe5 465 gBS->RestoreTPL (OldTpl);\r
d89186bc
LE
466 return EFI_SUCCESS;\r
467\r
468UninstallGop:\r
469 gBS->UninstallProtocolInterface (Private->Handle,\r
470 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
471\r
472DestructQemuVideoGraphics:\r
473 QemuVideoGraphicsOutputDestructor (Private);\r
474\r
475FreeModeData:\r
476 FreePool (Private->ModeData);\r
477\r
478UninstallGopDevicePath:\r
d89186bc
LE
479 gBS->UninstallProtocolInterface (Private->Handle,\r
480 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
481\r
482FreeGopDevicePath:\r
42d0cad7 483 FreePool (Private->GopDevicePath);\r
eaf4f336 484\r
d89186bc
LE
485RestoreAttributes:\r
486 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
487 Private->OriginalPciAttributes, NULL);\r
488\r
489ClosePciIo:\r
490 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
491 This->DriverBindingHandle, Controller);\r
492\r
493FreePrivate:\r
494 FreePool (Private);\r
495\r
9c08bbe5
LE
496RestoreTpl:\r
497 gBS->RestoreTPL (OldTpl);\r
498\r
eaf4f336 499 return Status;\r
500}\r
501\r
502/**\r
503 Stop this device\r
504\r
505 @param This The USB bus driver binding protocol.\r
506 @param Controller The controller to release.\r
507 @param NumberOfChildren The number of children of this device that\r
508 opened the controller BY_CHILD.\r
509 @param ChildHandleBuffer The array of child handle.\r
510\r
511 @retval EFI_SUCCESS The controller or children are stopped.\r
512 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517QemuVideoControllerDriverStop (\r
518 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
519 IN EFI_HANDLE Controller,\r
520 IN UINTN NumberOfChildren,\r
521 IN EFI_HANDLE *ChildHandleBuffer\r
522 )\r
523{\r
524 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
525\r
526 EFI_STATUS Status;\r
527 QEMU_VIDEO_PRIVATE_DATA *Private;\r
528\r
99a6dce3
LE
529 if (NumberOfChildren == 0) {\r
530 //\r
531 // Close the PCI I/O Protocol\r
532 //\r
533 gBS->CloseProtocol (\r
534 Controller,\r
535 &gEfiPciIoProtocolGuid,\r
536 This->DriverBindingHandle,\r
537 Controller\r
538 );\r
539 return EFI_SUCCESS;\r
540 }\r
541\r
542 //\r
543 // free all resources for whose access we need the child handle, because the\r
544 // child handle is going away\r
545 //\r
546 ASSERT (NumberOfChildren == 1);\r
eaf4f336 547 Status = gBS->OpenProtocol (\r
99a6dce3 548 ChildHandleBuffer[0],\r
eaf4f336 549 &gEfiGraphicsOutputProtocolGuid,\r
550 (VOID **) &GraphicsOutput,\r
551 This->DriverBindingHandle,\r
552 Controller,\r
553 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
554 );\r
555 if (EFI_ERROR (Status)) {\r
556 return Status;\r
557 }\r
558\r
559 //\r
560 // Get our private context information\r
561 //\r
562 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
99a6dce3 563 ASSERT (Private->Handle == ChildHandleBuffer[0]);\r
eaf4f336 564\r
565 QemuVideoGraphicsOutputDestructor (Private);\r
566 //\r
567 // Remove the GOP protocol interface from the system\r
568 //\r
569 Status = gBS->UninstallMultipleProtocolInterfaces (\r
570 Private->Handle,\r
571 &gEfiGraphicsOutputProtocolGuid,\r
572 &Private->GraphicsOutput,\r
573 NULL\r
574 );\r
575\r
576 if (EFI_ERROR (Status)) {\r
577 return Status;\r
578 }\r
579\r
580 //\r
581 // Restore original PCI attributes\r
582 //\r
583 Private->PciIo->Attributes (\r
584 Private->PciIo,\r
585 EfiPciIoAttributeOperationSet,\r
586 Private->OriginalPciAttributes,\r
587 NULL\r
588 );\r
589\r
4374c2e5
CR
590 gBS->CloseProtocol (\r
591 Controller,\r
592 &gEfiPciIoProtocolGuid,\r
593 This->DriverBindingHandle,\r
594 Private->Handle\r
595 );\r
596\r
847e4c34
LE
597 FreePool (Private->ModeData);\r
598 gBS->UninstallProtocolInterface (Private->Handle,\r
599 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
600 FreePool (Private->GopDevicePath);\r
601\r
eaf4f336 602 //\r
603 // Free our instance data\r
604 //\r
605 gBS->FreePool (Private);\r
606\r
607 return EFI_SUCCESS;\r
608}\r
609\r
610/**\r
611 TODO: Add function description\r
612\r
613 @param Private TODO: add argument description\r
614 @param Address TODO: add argument description\r
615 @param Data TODO: add argument description\r
616\r
617 TODO: add return values\r
618\r
619**/\r
620VOID\r
621outb (\r
622 QEMU_VIDEO_PRIVATE_DATA *Private,\r
623 UINTN Address,\r
624 UINT8 Data\r
625 )\r
626{\r
627 Private->PciIo->Io.Write (\r
628 Private->PciIo,\r
629 EfiPciIoWidthUint8,\r
630 EFI_PCI_IO_PASS_THROUGH_BAR,\r
631 Address,\r
632 1,\r
633 &Data\r
634 );\r
635}\r
636\r
637/**\r
638 TODO: Add function description\r
639\r
640 @param Private TODO: add argument description\r
641 @param Address TODO: add argument description\r
642 @param Data TODO: add argument description\r
643\r
644 TODO: add return values\r
645\r
646**/\r
647VOID\r
648outw (\r
649 QEMU_VIDEO_PRIVATE_DATA *Private,\r
650 UINTN Address,\r
651 UINT16 Data\r
652 )\r
653{\r
654 Private->PciIo->Io.Write (\r
655 Private->PciIo,\r
656 EfiPciIoWidthUint16,\r
657 EFI_PCI_IO_PASS_THROUGH_BAR,\r
658 Address,\r
659 1,\r
660 &Data\r
661 );\r
662}\r
663\r
664/**\r
665 TODO: Add function description\r
666\r
667 @param Private TODO: add argument description\r
668 @param Address TODO: add argument description\r
669\r
670 TODO: add return values\r
671\r
672**/\r
673UINT8\r
674inb (\r
675 QEMU_VIDEO_PRIVATE_DATA *Private,\r
676 UINTN Address\r
677 )\r
678{\r
679 UINT8 Data;\r
680\r
681 Private->PciIo->Io.Read (\r
682 Private->PciIo,\r
683 EfiPciIoWidthUint8,\r
684 EFI_PCI_IO_PASS_THROUGH_BAR,\r
685 Address,\r
686 1,\r
687 &Data\r
688 );\r
689 return Data;\r
690}\r
691\r
692/**\r
693 TODO: Add function description\r
694\r
695 @param Private TODO: add argument description\r
696 @param Address TODO: add argument description\r
697\r
698 TODO: add return values\r
699\r
700**/\r
701UINT16\r
702inw (\r
703 QEMU_VIDEO_PRIVATE_DATA *Private,\r
704 UINTN Address\r
705 )\r
706{\r
707 UINT16 Data;\r
708\r
709 Private->PciIo->Io.Read (\r
710 Private->PciIo,\r
711 EfiPciIoWidthUint16,\r
712 EFI_PCI_IO_PASS_THROUGH_BAR,\r
713 Address,\r
714 1,\r
715 &Data\r
716 );\r
717 return Data;\r
718}\r
719\r
720/**\r
721 TODO: Add function description\r
722\r
723 @param Private TODO: add argument description\r
724 @param Index TODO: add argument description\r
725 @param Red TODO: add argument description\r
726 @param Green TODO: add argument description\r
727 @param Blue TODO: add argument description\r
728\r
729 TODO: add return values\r
730\r
731**/\r
732VOID\r
733SetPaletteColor (\r
734 QEMU_VIDEO_PRIVATE_DATA *Private,\r
735 UINTN Index,\r
736 UINT8 Red,\r
737 UINT8 Green,\r
738 UINT8 Blue\r
739 )\r
740{\r
cdb4f5dc 741 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);\r
742 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));\r
743 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));\r
744 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));\r
eaf4f336 745}\r
746\r
747/**\r
748 TODO: Add function description\r
749\r
750 @param Private TODO: add argument description\r
751\r
752 TODO: add return values\r
753\r
754**/\r
755VOID\r
756SetDefaultPalette (\r
757 QEMU_VIDEO_PRIVATE_DATA *Private\r
758 )\r
759{\r
760 UINTN Index;\r
761 UINTN RedIndex;\r
762 UINTN GreenIndex;\r
763 UINTN BlueIndex;\r
764\r
765 Index = 0;\r
766 for (RedIndex = 0; RedIndex < 8; RedIndex++) {\r
767 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {\r
768 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {\r
769 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));\r
770 Index++;\r
771 }\r
772 }\r
773 }\r
774}\r
775\r
776/**\r
777 TODO: Add function description\r
778\r
779 @param Private TODO: add argument description\r
780\r
781 TODO: add return values\r
782\r
783**/\r
784VOID\r
785ClearScreen (\r
786 QEMU_VIDEO_PRIVATE_DATA *Private\r
787 )\r
788{\r
789 UINT32 Color;\r
790\r
791 Color = 0;\r
792 Private->PciIo->Mem.Write (\r
793 Private->PciIo,\r
794 EfiPciIoWidthFillUint32,\r
d021868c 795 Private->FrameBufferVramBarIndex,\r
eaf4f336 796 0,\r
797 0x400000 >> 2,\r
798 &Color\r
799 );\r
800}\r
801\r
802/**\r
803 TODO: Add function description\r
804\r
805 @param Private TODO: add argument description\r
806\r
807 TODO: add return values\r
808\r
809**/\r
810VOID\r
811DrawLogo (\r
812 QEMU_VIDEO_PRIVATE_DATA *Private,\r
813 UINTN ScreenWidth,\r
814 UINTN ScreenHeight\r
815 )\r
816{\r
817}\r
818\r
819/**\r
820 TODO: Add function description\r
821\r
822 @param Private TODO: add argument description\r
823 @param ModeData TODO: add argument description\r
824\r
825 TODO: add return values\r
826\r
827**/\r
828VOID\r
212aac55 829InitializeCirrusGraphicsMode (\r
eaf4f336 830 QEMU_VIDEO_PRIVATE_DATA *Private,\r
212aac55 831 QEMU_VIDEO_CIRRUS_MODES *ModeData\r
eaf4f336 832 )\r
833{\r
834 UINT8 Byte;\r
835 UINTN Index;\r
eaf4f336 836\r
837 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);\r
838 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);\r
839\r
840 for (Index = 0; Index < 15; Index++) {\r
841 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);\r
842 }\r
843\r
212aac55 844 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {\r
eaf4f336 845 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);\r
846 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);\r
847 outb (Private, SEQ_DATA_REGISTER, Byte);\r
848 }\r
849\r
850 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);\r
851 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);\r
852 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);\r
853 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);\r
854\r
855 for (Index = 0; Index < 28; Index++) {\r
856 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));\r
857 }\r
858\r
859 for (Index = 0; Index < 9; Index++) {\r
860 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));\r
861 }\r
862\r
863 inb (Private, INPUT_STATUS_1_REGISTER);\r
864\r
865 for (Index = 0; Index < 21; Index++) {\r
866 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);\r
867 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);\r
868 }\r
869\r
870 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
871\r
872 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);\r
873 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);\r
874 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);\r
875 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);\r
876\r
54f9b9ac 877 SetDefaultPalette (Private);\r
878 ClearScreen (Private);\r
879}\r
880\r
881VOID\r
882BochsWrite (\r
883 QEMU_VIDEO_PRIVATE_DATA *Private,\r
884 UINT16 Reg,\r
885 UINT16 Data\r
886 )\r
887{\r
cdb4f5dc 888 EFI_STATUS Status;\r
889\r
890 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
891 Status = Private->PciIo->Mem.Write (\r
892 Private->PciIo,\r
893 EfiPciIoWidthUint16,\r
894 PCI_BAR_IDX2,\r
895 0x500 + (Reg << 1),\r
896 1,\r
897 &Data\r
898 );\r
899 ASSERT_EFI_ERROR (Status);\r
900 } else {\r
901 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
902 outw (Private, VBE_DISPI_IOPORT_DATA, Data);\r
903 }\r
54f9b9ac 904}\r
905\r
906UINT16\r
907BochsRead (\r
908 QEMU_VIDEO_PRIVATE_DATA *Private,\r
909 UINT16 Reg\r
910 )\r
911{\r
cdb4f5dc 912 EFI_STATUS Status;\r
913 UINT16 Data;\r
914\r
915 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
916 Status = Private->PciIo->Mem.Read (\r
917 Private->PciIo,\r
918 EfiPciIoWidthUint16,\r
919 PCI_BAR_IDX2,\r
920 0x500 + (Reg << 1),\r
921 1,\r
922 &Data\r
923 );\r
924 ASSERT_EFI_ERROR (Status);\r
925 } else {\r
926 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
927 Data = inw (Private, VBE_DISPI_IOPORT_DATA);\r
928 }\r
54f9b9ac 929 return Data;\r
930}\r
931\r
cdb4f5dc 932VOID\r
933VgaOutb (\r
934 QEMU_VIDEO_PRIVATE_DATA *Private,\r
935 UINTN Reg,\r
936 UINT8 Data\r
937 )\r
938{\r
939 EFI_STATUS Status;\r
940\r
941 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
942 Status = Private->PciIo->Mem.Write (\r
943 Private->PciIo,\r
944 EfiPciIoWidthUint8,\r
945 PCI_BAR_IDX2,\r
946 0x400 - 0x3c0 + Reg,\r
947 1,\r
948 &Data\r
949 );\r
950 ASSERT_EFI_ERROR (Status);\r
951 } else {\r
952 outb (Private, Reg, Data);\r
953 }\r
954}\r
955\r
54f9b9ac 956VOID\r
957InitializeBochsGraphicsMode (\r
958 QEMU_VIDEO_PRIVATE_DATA *Private,\r
959 QEMU_VIDEO_BOCHS_MODES *ModeData\r
960 )\r
961{\r
70d5086c 962 DEBUG ((DEBUG_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",\r
54f9b9ac 963 ModeData->Width, ModeData->Height, ModeData->ColorDepth));\r
964\r
965 /* unblank */\r
cdb4f5dc 966 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
54f9b9ac 967\r
968 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);\r
969 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);\r
970 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);\r
971 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);\r
972\r
973 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);\r
974 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);\r
975 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);\r
976 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);\r
977 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);\r
978\r
979 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,\r
980 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);\r
981\r
eaf4f336 982 SetDefaultPalette (Private);\r
983 ClearScreen (Private);\r
984}\r
985\r
986EFI_STATUS\r
987EFIAPI\r
988InitializeQemuVideo (\r
989 IN EFI_HANDLE ImageHandle,\r
990 IN EFI_SYSTEM_TABLE *SystemTable\r
991 )\r
992{\r
993 EFI_STATUS Status;\r
994\r
995 Status = EfiLibInstallDriverBindingComponentName2 (\r
996 ImageHandle,\r
997 SystemTable,\r
998 &gQemuVideoDriverBinding,\r
999 ImageHandle,\r
1000 &gQemuVideoComponentName,\r
1001 &gQemuVideoComponentName2\r
1002 );\r
1003 ASSERT_EFI_ERROR (Status);\r
1004\r
eaf4f336 1005 return Status;\r
1006}\r