]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Driver.c
NetworkPkg: Move Network library header file from MdeModulePkg to NetworkPkg
[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
156 DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));\r
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
54f9b9ac 204\r
9c08bbe5
LE
205 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
206\r
eaf4f336 207 //\r
208 // Allocate Private context data for GOP inteface.\r
209 //\r
210 Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
211 if (Private == NULL) {\r
9c08bbe5
LE
212 Status = EFI_OUT_OF_RESOURCES;\r
213 goto RestoreTpl;\r
eaf4f336 214 }\r
215\r
216 //\r
217 // Set up context record\r
218 //\r
219 Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
eaf4f336 220\r
221 //\r
222 // Open PCI I/O Protocol\r
223 //\r
224 Status = gBS->OpenProtocol (\r
225 Controller,\r
226 &gEfiPciIoProtocolGuid,\r
227 (VOID **) &Private->PciIo,\r
228 This->DriverBindingHandle,\r
229 Controller,\r
230 EFI_OPEN_PROTOCOL_BY_DRIVER\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
d89186bc 233 goto FreePrivate;\r
eaf4f336 234 }\r
235\r
212aac55 236 //\r
237 // Read the PCI Configuration Header from the PCI Device\r
238 //\r
239 Status = Private->PciIo->Pci.Read (\r
240 Private->PciIo,\r
241 EfiPciIoWidthUint32,\r
242 0,\r
243 sizeof (Pci) / sizeof (UINT32),\r
244 &Pci\r
245 );\r
246 if (EFI_ERROR (Status)) {\r
d89186bc 247 goto ClosePciIo;\r
212aac55 248 }\r
249\r
d89186bc
LE
250 //\r
251 // Determine card variant.\r
252 //\r
70dbd163 253 Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
212aac55 254 if (Card == NULL) {\r
255 Status = EFI_DEVICE_ERROR;\r
d89186bc 256 goto ClosePciIo;\r
212aac55 257 }\r
258 Private->Variant = Card->Variant;\r
259\r
b37bcfd6
LE
260 //\r
261 // IsQxl is based on the detected Card->Variant, which at a later point might\r
262 // not match Private->Variant.\r
263 //\r
264 IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);\r
265\r
eaf4f336 266 //\r
267 // Save original PCI attributes\r
268 //\r
269 Status = Private->PciIo->Attributes (\r
270 Private->PciIo,\r
271 EfiPciIoAttributeOperationGet,\r
272 0,\r
273 &Private->OriginalPciAttributes\r
274 );\r
275\r
276 if (EFI_ERROR (Status)) {\r
d89186bc 277 goto ClosePciIo;\r
eaf4f336 278 }\r
eaf4f336 279\r
d89186bc
LE
280 //\r
281 // Set new PCI attributes\r
282 //\r
eaf4f336 283 Status = Private->PciIo->Attributes (\r
284 Private->PciIo,\r
285 EfiPciIoAttributeOperationEnable,\r
286 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,\r
287 NULL\r
288 );\r
289 if (EFI_ERROR (Status)) {\r
d89186bc 290 goto ClosePciIo;\r
eaf4f336 291 }\r
292\r
cdb4f5dc 293 //\r
294 // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).\r
295 //\r
296 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
d89186bc
LE
297 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
298\r
cdb4f5dc 299 Status = Private->PciIo->GetBarAttributes (\r
300 Private->PciIo,\r
301 PCI_BAR_IDX2,\r
302 NULL,\r
303 (VOID**) &MmioDesc\r
304 );\r
305 if (EFI_ERROR (Status) ||\r
306 MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
307 DEBUG ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));\r
308 Private->Variant = QEMU_VIDEO_BOCHS;\r
309 } else {\r
310 DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",\r
311 MmioDesc->AddrRangeMin));\r
312 }\r
5cdb96fa
LE
313\r
314 if (!EFI_ERROR (Status)) {\r
315 FreePool (MmioDesc);\r
316 }\r
cdb4f5dc 317 }\r
318\r
d021868c
YCL
319 //\r
320 // VMWare SVGA is handled like Bochs (with port IO only).\r
321 //\r
322 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
323 Private->Variant = QEMU_VIDEO_BOCHS;\r
324 Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;\r
325 }\r
326\r
54f9b9ac 327 //\r
328 // Check if accessing the bochs interface works.\r
329 //\r
cdb4f5dc 330 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
331 Private->Variant == QEMU_VIDEO_BOCHS) {\r
54f9b9ac 332 UINT16 BochsId;\r
333 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);\r
334 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
335 DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
336 Status = EFI_DEVICE_ERROR;\r
d89186bc 337 goto RestoreAttributes;\r
54f9b9ac 338 }\r
339 }\r
340\r
eaf4f336 341 //\r
342 // Get ParentDevicePath\r
343 //\r
344 Status = gBS->HandleProtocol (\r
345 Controller,\r
346 &gEfiDevicePathProtocolGuid,\r
347 (VOID **) &ParentDevicePath\r
348 );\r
349 if (EFI_ERROR (Status)) {\r
d89186bc 350 goto RestoreAttributes;\r
eaf4f336 351 }\r
352\r
353 //\r
354 // Set Gop Device Path\r
355 //\r
42d0cad7
LE
356 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
357 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
358 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
359 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
360 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
361\r
362 Private->GopDevicePath = AppendDevicePathNode (\r
363 ParentDevicePath,\r
364 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
365 );\r
366 if (Private->GopDevicePath == NULL) {\r
367 Status = EFI_OUT_OF_RESOURCES;\r
368 goto RestoreAttributes;\r
eaf4f336 369 }\r
d89186bc
LE
370\r
371 //\r
42d0cad7 372 // Create new child handle and install the device path protocol on it.\r
d89186bc 373 //\r
42d0cad7
LE
374 Status = gBS->InstallMultipleProtocolInterfaces (\r
375 &Private->Handle,\r
376 &gEfiDevicePathProtocolGuid,\r
377 Private->GopDevicePath,\r
378 NULL\r
379 );\r
380 if (EFI_ERROR (Status)) {\r
381 goto FreeGopDevicePath;\r
eaf4f336 382 }\r
383\r
384 //\r
385 // Construct video mode buffer\r
386 //\r
212aac55 387 switch (Private->Variant) {\r
388 case QEMU_VIDEO_CIRRUS_5430:\r
389 case QEMU_VIDEO_CIRRUS_5446:\r
390 Status = QemuVideoCirrusModeSetup (Private);\r
391 break;\r
cdb4f5dc 392 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 393 case QEMU_VIDEO_BOCHS:\r
b37bcfd6 394 Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
54f9b9ac 395 break;\r
212aac55 396 default:\r
397 ASSERT (FALSE);\r
398 Status = EFI_DEVICE_ERROR;\r
399 break;\r
400 }\r
eaf4f336 401 if (EFI_ERROR (Status)) {\r
d89186bc 402 goto UninstallGopDevicePath;\r
eaf4f336 403 }\r
404\r
d89186bc
LE
405 //\r
406 // Start the GOP software stack.\r
407 //\r
408 Status = QemuVideoGraphicsOutputConstructor (Private);\r
409 if (EFI_ERROR (Status)) {\r
410 goto FreeModeData;\r
411 }\r
4374c2e5 412\r
d89186bc
LE
413 Status = gBS->InstallMultipleProtocolInterfaces (\r
414 &Private->Handle,\r
415 &gEfiGraphicsOutputProtocolGuid,\r
416 &Private->GraphicsOutput,\r
417 NULL\r
4374c2e5 418 );\r
d89186bc
LE
419 if (EFI_ERROR (Status)) {\r
420 goto DestructQemuVideoGraphics;\r
eaf4f336 421 }\r
422\r
d89186bc
LE
423 //\r
424 // Reference parent handle from child handle.\r
425 //\r
426 Status = gBS->OpenProtocol (\r
427 Controller,\r
428 &gEfiPciIoProtocolGuid,\r
429 (VOID **) &ChildPciIo,\r
430 This->DriverBindingHandle,\r
431 Private->Handle,\r
432 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
433 );\r
eaf4f336 434 if (EFI_ERROR (Status)) {\r
d89186bc
LE
435 goto UninstallGop;\r
436 }\r
eaf4f336 437\r
84a75f70 438#if defined MDE_CPU_IA32 || defined MDE_CPU_X64\r
90803342
LE
439 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
440 Private->Variant == QEMU_VIDEO_BOCHS) {\r
441 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);\r
442 }\r
84a75f70 443#endif\r
90803342 444\r
9c08bbe5 445 gBS->RestoreTPL (OldTpl);\r
d89186bc
LE
446 return EFI_SUCCESS;\r
447\r
448UninstallGop:\r
449 gBS->UninstallProtocolInterface (Private->Handle,\r
450 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
451\r
452DestructQemuVideoGraphics:\r
453 QemuVideoGraphicsOutputDestructor (Private);\r
454\r
455FreeModeData:\r
456 FreePool (Private->ModeData);\r
457\r
458UninstallGopDevicePath:\r
d89186bc
LE
459 gBS->UninstallProtocolInterface (Private->Handle,\r
460 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
461\r
462FreeGopDevicePath:\r
42d0cad7 463 FreePool (Private->GopDevicePath);\r
eaf4f336 464\r
d89186bc
LE
465RestoreAttributes:\r
466 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
467 Private->OriginalPciAttributes, NULL);\r
468\r
469ClosePciIo:\r
470 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
471 This->DriverBindingHandle, Controller);\r
472\r
473FreePrivate:\r
474 FreePool (Private);\r
475\r
9c08bbe5
LE
476RestoreTpl:\r
477 gBS->RestoreTPL (OldTpl);\r
478\r
eaf4f336 479 return Status;\r
480}\r
481\r
482/**\r
483 Stop this device\r
484\r
485 @param This The USB bus driver binding protocol.\r
486 @param Controller The controller to release.\r
487 @param NumberOfChildren The number of children of this device that\r
488 opened the controller BY_CHILD.\r
489 @param ChildHandleBuffer The array of child handle.\r
490\r
491 @retval EFI_SUCCESS The controller or children are stopped.\r
492 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
493\r
494**/\r
495EFI_STATUS\r
496EFIAPI\r
497QemuVideoControllerDriverStop (\r
498 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
499 IN EFI_HANDLE Controller,\r
500 IN UINTN NumberOfChildren,\r
501 IN EFI_HANDLE *ChildHandleBuffer\r
502 )\r
503{\r
504 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
505\r
506 EFI_STATUS Status;\r
507 QEMU_VIDEO_PRIVATE_DATA *Private;\r
508\r
99a6dce3
LE
509 if (NumberOfChildren == 0) {\r
510 //\r
511 // Close the PCI I/O Protocol\r
512 //\r
513 gBS->CloseProtocol (\r
514 Controller,\r
515 &gEfiPciIoProtocolGuid,\r
516 This->DriverBindingHandle,\r
517 Controller\r
518 );\r
519 return EFI_SUCCESS;\r
520 }\r
521\r
522 //\r
523 // free all resources for whose access we need the child handle, because the\r
524 // child handle is going away\r
525 //\r
526 ASSERT (NumberOfChildren == 1);\r
eaf4f336 527 Status = gBS->OpenProtocol (\r
99a6dce3 528 ChildHandleBuffer[0],\r
eaf4f336 529 &gEfiGraphicsOutputProtocolGuid,\r
530 (VOID **) &GraphicsOutput,\r
531 This->DriverBindingHandle,\r
532 Controller,\r
533 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
534 );\r
535 if (EFI_ERROR (Status)) {\r
536 return Status;\r
537 }\r
538\r
539 //\r
540 // Get our private context information\r
541 //\r
542 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
99a6dce3 543 ASSERT (Private->Handle == ChildHandleBuffer[0]);\r
eaf4f336 544\r
545 QemuVideoGraphicsOutputDestructor (Private);\r
546 //\r
547 // Remove the GOP protocol interface from the system\r
548 //\r
549 Status = gBS->UninstallMultipleProtocolInterfaces (\r
550 Private->Handle,\r
551 &gEfiGraphicsOutputProtocolGuid,\r
552 &Private->GraphicsOutput,\r
553 NULL\r
554 );\r
555\r
556 if (EFI_ERROR (Status)) {\r
557 return Status;\r
558 }\r
559\r
560 //\r
561 // Restore original PCI attributes\r
562 //\r
563 Private->PciIo->Attributes (\r
564 Private->PciIo,\r
565 EfiPciIoAttributeOperationSet,\r
566 Private->OriginalPciAttributes,\r
567 NULL\r
568 );\r
569\r
4374c2e5
CR
570 gBS->CloseProtocol (\r
571 Controller,\r
572 &gEfiPciIoProtocolGuid,\r
573 This->DriverBindingHandle,\r
574 Private->Handle\r
575 );\r
576\r
847e4c34
LE
577 FreePool (Private->ModeData);\r
578 gBS->UninstallProtocolInterface (Private->Handle,\r
579 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
580 FreePool (Private->GopDevicePath);\r
581\r
eaf4f336 582 //\r
583 // Free our instance data\r
584 //\r
585 gBS->FreePool (Private);\r
586\r
587 return EFI_SUCCESS;\r
588}\r
589\r
590/**\r
591 TODO: Add function description\r
592\r
593 @param Private TODO: add argument description\r
594 @param Address TODO: add argument description\r
595 @param Data TODO: add argument description\r
596\r
597 TODO: add return values\r
598\r
599**/\r
600VOID\r
601outb (\r
602 QEMU_VIDEO_PRIVATE_DATA *Private,\r
603 UINTN Address,\r
604 UINT8 Data\r
605 )\r
606{\r
607 Private->PciIo->Io.Write (\r
608 Private->PciIo,\r
609 EfiPciIoWidthUint8,\r
610 EFI_PCI_IO_PASS_THROUGH_BAR,\r
611 Address,\r
612 1,\r
613 &Data\r
614 );\r
615}\r
616\r
617/**\r
618 TODO: Add function description\r
619\r
620 @param Private TODO: add argument description\r
621 @param Address TODO: add argument description\r
622 @param Data TODO: add argument description\r
623\r
624 TODO: add return values\r
625\r
626**/\r
627VOID\r
628outw (\r
629 QEMU_VIDEO_PRIVATE_DATA *Private,\r
630 UINTN Address,\r
631 UINT16 Data\r
632 )\r
633{\r
634 Private->PciIo->Io.Write (\r
635 Private->PciIo,\r
636 EfiPciIoWidthUint16,\r
637 EFI_PCI_IO_PASS_THROUGH_BAR,\r
638 Address,\r
639 1,\r
640 &Data\r
641 );\r
642}\r
643\r
644/**\r
645 TODO: Add function description\r
646\r
647 @param Private TODO: add argument description\r
648 @param Address TODO: add argument description\r
649\r
650 TODO: add return values\r
651\r
652**/\r
653UINT8\r
654inb (\r
655 QEMU_VIDEO_PRIVATE_DATA *Private,\r
656 UINTN Address\r
657 )\r
658{\r
659 UINT8 Data;\r
660\r
661 Private->PciIo->Io.Read (\r
662 Private->PciIo,\r
663 EfiPciIoWidthUint8,\r
664 EFI_PCI_IO_PASS_THROUGH_BAR,\r
665 Address,\r
666 1,\r
667 &Data\r
668 );\r
669 return Data;\r
670}\r
671\r
672/**\r
673 TODO: Add function description\r
674\r
675 @param Private TODO: add argument description\r
676 @param Address TODO: add argument description\r
677\r
678 TODO: add return values\r
679\r
680**/\r
681UINT16\r
682inw (\r
683 QEMU_VIDEO_PRIVATE_DATA *Private,\r
684 UINTN Address\r
685 )\r
686{\r
687 UINT16 Data;\r
688\r
689 Private->PciIo->Io.Read (\r
690 Private->PciIo,\r
691 EfiPciIoWidthUint16,\r
692 EFI_PCI_IO_PASS_THROUGH_BAR,\r
693 Address,\r
694 1,\r
695 &Data\r
696 );\r
697 return Data;\r
698}\r
699\r
700/**\r
701 TODO: Add function description\r
702\r
703 @param Private TODO: add argument description\r
704 @param Index TODO: add argument description\r
705 @param Red TODO: add argument description\r
706 @param Green TODO: add argument description\r
707 @param Blue TODO: add argument description\r
708\r
709 TODO: add return values\r
710\r
711**/\r
712VOID\r
713SetPaletteColor (\r
714 QEMU_VIDEO_PRIVATE_DATA *Private,\r
715 UINTN Index,\r
716 UINT8 Red,\r
717 UINT8 Green,\r
718 UINT8 Blue\r
719 )\r
720{\r
cdb4f5dc 721 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);\r
722 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));\r
723 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));\r
724 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));\r
eaf4f336 725}\r
726\r
727/**\r
728 TODO: Add function description\r
729\r
730 @param Private TODO: add argument description\r
731\r
732 TODO: add return values\r
733\r
734**/\r
735VOID\r
736SetDefaultPalette (\r
737 QEMU_VIDEO_PRIVATE_DATA *Private\r
738 )\r
739{\r
740 UINTN Index;\r
741 UINTN RedIndex;\r
742 UINTN GreenIndex;\r
743 UINTN BlueIndex;\r
744\r
745 Index = 0;\r
746 for (RedIndex = 0; RedIndex < 8; RedIndex++) {\r
747 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {\r
748 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {\r
749 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));\r
750 Index++;\r
751 }\r
752 }\r
753 }\r
754}\r
755\r
756/**\r
757 TODO: Add function description\r
758\r
759 @param Private TODO: add argument description\r
760\r
761 TODO: add return values\r
762\r
763**/\r
764VOID\r
765ClearScreen (\r
766 QEMU_VIDEO_PRIVATE_DATA *Private\r
767 )\r
768{\r
769 UINT32 Color;\r
770\r
771 Color = 0;\r
772 Private->PciIo->Mem.Write (\r
773 Private->PciIo,\r
774 EfiPciIoWidthFillUint32,\r
d021868c 775 Private->FrameBufferVramBarIndex,\r
eaf4f336 776 0,\r
777 0x400000 >> 2,\r
778 &Color\r
779 );\r
780}\r
781\r
782/**\r
783 TODO: Add function description\r
784\r
785 @param Private TODO: add argument description\r
786\r
787 TODO: add return values\r
788\r
789**/\r
790VOID\r
791DrawLogo (\r
792 QEMU_VIDEO_PRIVATE_DATA *Private,\r
793 UINTN ScreenWidth,\r
794 UINTN ScreenHeight\r
795 )\r
796{\r
797}\r
798\r
799/**\r
800 TODO: Add function description\r
801\r
802 @param Private TODO: add argument description\r
803 @param ModeData TODO: add argument description\r
804\r
805 TODO: add return values\r
806\r
807**/\r
808VOID\r
212aac55 809InitializeCirrusGraphicsMode (\r
eaf4f336 810 QEMU_VIDEO_PRIVATE_DATA *Private,\r
212aac55 811 QEMU_VIDEO_CIRRUS_MODES *ModeData\r
eaf4f336 812 )\r
813{\r
814 UINT8 Byte;\r
815 UINTN Index;\r
eaf4f336 816\r
817 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);\r
818 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);\r
819\r
820 for (Index = 0; Index < 15; Index++) {\r
821 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);\r
822 }\r
823\r
212aac55 824 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {\r
eaf4f336 825 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);\r
826 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);\r
827 outb (Private, SEQ_DATA_REGISTER, Byte);\r
828 }\r
829\r
830 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);\r
831 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);\r
832 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);\r
833 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);\r
834\r
835 for (Index = 0; Index < 28; Index++) {\r
836 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));\r
837 }\r
838\r
839 for (Index = 0; Index < 9; Index++) {\r
840 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));\r
841 }\r
842\r
843 inb (Private, INPUT_STATUS_1_REGISTER);\r
844\r
845 for (Index = 0; Index < 21; Index++) {\r
846 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);\r
847 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);\r
848 }\r
849\r
850 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
851\r
852 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);\r
853 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);\r
854 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);\r
855 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);\r
856\r
54f9b9ac 857 SetDefaultPalette (Private);\r
858 ClearScreen (Private);\r
859}\r
860\r
861VOID\r
862BochsWrite (\r
863 QEMU_VIDEO_PRIVATE_DATA *Private,\r
864 UINT16 Reg,\r
865 UINT16 Data\r
866 )\r
867{\r
cdb4f5dc 868 EFI_STATUS Status;\r
869\r
870 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
871 Status = Private->PciIo->Mem.Write (\r
872 Private->PciIo,\r
873 EfiPciIoWidthUint16,\r
874 PCI_BAR_IDX2,\r
875 0x500 + (Reg << 1),\r
876 1,\r
877 &Data\r
878 );\r
879 ASSERT_EFI_ERROR (Status);\r
880 } else {\r
881 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
882 outw (Private, VBE_DISPI_IOPORT_DATA, Data);\r
883 }\r
54f9b9ac 884}\r
885\r
886UINT16\r
887BochsRead (\r
888 QEMU_VIDEO_PRIVATE_DATA *Private,\r
889 UINT16 Reg\r
890 )\r
891{\r
cdb4f5dc 892 EFI_STATUS Status;\r
893 UINT16 Data;\r
894\r
895 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
896 Status = Private->PciIo->Mem.Read (\r
897 Private->PciIo,\r
898 EfiPciIoWidthUint16,\r
899 PCI_BAR_IDX2,\r
900 0x500 + (Reg << 1),\r
901 1,\r
902 &Data\r
903 );\r
904 ASSERT_EFI_ERROR (Status);\r
905 } else {\r
906 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
907 Data = inw (Private, VBE_DISPI_IOPORT_DATA);\r
908 }\r
54f9b9ac 909 return Data;\r
910}\r
911\r
cdb4f5dc 912VOID\r
913VgaOutb (\r
914 QEMU_VIDEO_PRIVATE_DATA *Private,\r
915 UINTN Reg,\r
916 UINT8 Data\r
917 )\r
918{\r
919 EFI_STATUS Status;\r
920\r
921 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
922 Status = Private->PciIo->Mem.Write (\r
923 Private->PciIo,\r
924 EfiPciIoWidthUint8,\r
925 PCI_BAR_IDX2,\r
926 0x400 - 0x3c0 + Reg,\r
927 1,\r
928 &Data\r
929 );\r
930 ASSERT_EFI_ERROR (Status);\r
931 } else {\r
932 outb (Private, Reg, Data);\r
933 }\r
934}\r
935\r
54f9b9ac 936VOID\r
937InitializeBochsGraphicsMode (\r
938 QEMU_VIDEO_PRIVATE_DATA *Private,\r
939 QEMU_VIDEO_BOCHS_MODES *ModeData\r
940 )\r
941{\r
942 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",\r
943 ModeData->Width, ModeData->Height, ModeData->ColorDepth));\r
944\r
945 /* unblank */\r
cdb4f5dc 946 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
54f9b9ac 947\r
948 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);\r
949 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);\r
950 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);\r
951 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);\r
952\r
953 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);\r
954 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);\r
955 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);\r
956 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);\r
957 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);\r
958\r
959 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,\r
960 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);\r
961\r
eaf4f336 962 SetDefaultPalette (Private);\r
963 ClearScreen (Private);\r
964}\r
965\r
966EFI_STATUS\r
967EFIAPI\r
968InitializeQemuVideo (\r
969 IN EFI_HANDLE ImageHandle,\r
970 IN EFI_SYSTEM_TABLE *SystemTable\r
971 )\r
972{\r
973 EFI_STATUS Status;\r
974\r
975 Status = EfiLibInstallDriverBindingComponentName2 (\r
976 ImageHandle,\r
977 SystemTable,\r
978 &gQemuVideoDriverBinding,\r
979 ImageHandle,\r
980 &gQemuVideoComponentName,\r
981 &gQemuVideoComponentName2\r
982 );\r
983 ASSERT_EFI_ERROR (Status);\r
984\r
eaf4f336 985 return Status;\r
986}\r