]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Driver.c
Revert "OvmfPkg/QemuVideoDxe: VMWare SVGA device support"
[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
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
6\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
c137d950 17#include "Qemu.h"\r
98856a72 18#include <IndustryStandard/Acpi.h>\r
eaf4f336 19\r
20EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
21 QemuVideoControllerDriverSupported,\r
22 QemuVideoControllerDriverStart,\r
23 QemuVideoControllerDriverStop,\r
24 0x10,\r
25 NULL,\r
26 NULL\r
27};\r
28\r
212aac55 29QEMU_VIDEO_CARD gQemuVideoCardList[] = {\r
30 {\r
70dbd163 31 PCI_CLASS_DISPLAY_VGA,\r
212aac55 32 CIRRUS_LOGIC_VENDOR_ID,\r
33 CIRRUS_LOGIC_5430_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_5430_ALTERNATE_DEVICE_ID,\r
40 QEMU_VIDEO_CIRRUS_5430,\r
41 L"Cirrus 5430"\r
42 },{\r
70dbd163 43 PCI_CLASS_DISPLAY_VGA,\r
212aac55 44 CIRRUS_LOGIC_VENDOR_ID,\r
45 CIRRUS_LOGIC_5446_DEVICE_ID,\r
46 QEMU_VIDEO_CIRRUS_5446,\r
47 L"Cirrus 5446"\r
54f9b9ac 48 },{\r
70dbd163 49 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 50 0x1234,\r
51 0x1111,\r
cdb4f5dc 52 QEMU_VIDEO_BOCHS_MMIO,\r
54f9b9ac 53 L"QEMU Standard VGA"\r
333f32ec
GH
54 },{\r
55 PCI_CLASS_DISPLAY_OTHER,\r
56 0x1234,\r
57 0x1111,\r
58 QEMU_VIDEO_BOCHS_MMIO,\r
59 L"QEMU Standard VGA (secondary)"\r
54f9b9ac 60 },{\r
70dbd163 61 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 62 0x1b36,\r
63 0x0100,\r
64 QEMU_VIDEO_BOCHS,\r
65 L"QEMU QXL VGA"\r
94210dc9 66 },{\r
70dbd163 67 PCI_CLASS_DISPLAY_VGA,\r
94210dc9
GH
68 0x1af4,\r
69 0x1050,\r
70 QEMU_VIDEO_BOCHS_MMIO,\r
71 L"QEMU VirtIO VGA"\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
54f9b9ac 319 //\r
320 // Check if accessing the bochs interface works.\r
321 //\r
cdb4f5dc 322 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
323 Private->Variant == QEMU_VIDEO_BOCHS) {\r
54f9b9ac 324 UINT16 BochsId;\r
325 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);\r
326 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
327 DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
328 Status = EFI_DEVICE_ERROR;\r
d89186bc 329 goto RestoreAttributes;\r
54f9b9ac 330 }\r
331 }\r
332\r
eaf4f336 333 //\r
334 // Get ParentDevicePath\r
335 //\r
336 Status = gBS->HandleProtocol (\r
337 Controller,\r
338 &gEfiDevicePathProtocolGuid,\r
339 (VOID **) &ParentDevicePath\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
d89186bc 342 goto RestoreAttributes;\r
eaf4f336 343 }\r
344\r
345 //\r
346 // Set Gop Device Path\r
347 //\r
42d0cad7
LE
348 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
349 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
350 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
351 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
352 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
353\r
354 Private->GopDevicePath = AppendDevicePathNode (\r
355 ParentDevicePath,\r
356 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
357 );\r
358 if (Private->GopDevicePath == NULL) {\r
359 Status = EFI_OUT_OF_RESOURCES;\r
360 goto RestoreAttributes;\r
eaf4f336 361 }\r
d89186bc
LE
362\r
363 //\r
42d0cad7 364 // Create new child handle and install the device path protocol on it.\r
d89186bc 365 //\r
42d0cad7
LE
366 Status = gBS->InstallMultipleProtocolInterfaces (\r
367 &Private->Handle,\r
368 &gEfiDevicePathProtocolGuid,\r
369 Private->GopDevicePath,\r
370 NULL\r
371 );\r
372 if (EFI_ERROR (Status)) {\r
373 goto FreeGopDevicePath;\r
eaf4f336 374 }\r
375\r
376 //\r
377 // Construct video mode buffer\r
378 //\r
212aac55 379 switch (Private->Variant) {\r
380 case QEMU_VIDEO_CIRRUS_5430:\r
381 case QEMU_VIDEO_CIRRUS_5446:\r
382 Status = QemuVideoCirrusModeSetup (Private);\r
383 break;\r
cdb4f5dc 384 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 385 case QEMU_VIDEO_BOCHS:\r
b37bcfd6 386 Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
54f9b9ac 387 break;\r
212aac55 388 default:\r
389 ASSERT (FALSE);\r
390 Status = EFI_DEVICE_ERROR;\r
391 break;\r
392 }\r
eaf4f336 393 if (EFI_ERROR (Status)) {\r
d89186bc 394 goto UninstallGopDevicePath;\r
eaf4f336 395 }\r
396\r
d89186bc
LE
397 //\r
398 // Start the GOP software stack.\r
399 //\r
400 Status = QemuVideoGraphicsOutputConstructor (Private);\r
401 if (EFI_ERROR (Status)) {\r
402 goto FreeModeData;\r
403 }\r
4374c2e5 404\r
d89186bc
LE
405 Status = gBS->InstallMultipleProtocolInterfaces (\r
406 &Private->Handle,\r
407 &gEfiGraphicsOutputProtocolGuid,\r
408 &Private->GraphicsOutput,\r
409 NULL\r
4374c2e5 410 );\r
d89186bc
LE
411 if (EFI_ERROR (Status)) {\r
412 goto DestructQemuVideoGraphics;\r
eaf4f336 413 }\r
414\r
d89186bc
LE
415 //\r
416 // Reference parent handle from child handle.\r
417 //\r
418 Status = gBS->OpenProtocol (\r
419 Controller,\r
420 &gEfiPciIoProtocolGuid,\r
421 (VOID **) &ChildPciIo,\r
422 This->DriverBindingHandle,\r
423 Private->Handle,\r
424 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
425 );\r
eaf4f336 426 if (EFI_ERROR (Status)) {\r
d89186bc
LE
427 goto UninstallGop;\r
428 }\r
eaf4f336 429\r
84a75f70 430#if defined MDE_CPU_IA32 || defined MDE_CPU_X64\r
90803342
LE
431 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
432 Private->Variant == QEMU_VIDEO_BOCHS) {\r
433 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);\r
434 }\r
84a75f70 435#endif\r
90803342 436\r
9c08bbe5 437 gBS->RestoreTPL (OldTpl);\r
d89186bc
LE
438 return EFI_SUCCESS;\r
439\r
440UninstallGop:\r
441 gBS->UninstallProtocolInterface (Private->Handle,\r
442 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
443\r
444DestructQemuVideoGraphics:\r
445 QemuVideoGraphicsOutputDestructor (Private);\r
446\r
447FreeModeData:\r
448 FreePool (Private->ModeData);\r
449\r
450UninstallGopDevicePath:\r
d89186bc
LE
451 gBS->UninstallProtocolInterface (Private->Handle,\r
452 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
453\r
454FreeGopDevicePath:\r
42d0cad7 455 FreePool (Private->GopDevicePath);\r
eaf4f336 456\r
d89186bc
LE
457RestoreAttributes:\r
458 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
459 Private->OriginalPciAttributes, NULL);\r
460\r
461ClosePciIo:\r
462 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
463 This->DriverBindingHandle, Controller);\r
464\r
465FreePrivate:\r
466 FreePool (Private);\r
467\r
9c08bbe5
LE
468RestoreTpl:\r
469 gBS->RestoreTPL (OldTpl);\r
470\r
eaf4f336 471 return Status;\r
472}\r
473\r
474/**\r
475 Stop this device\r
476\r
477 @param This The USB bus driver binding protocol.\r
478 @param Controller The controller to release.\r
479 @param NumberOfChildren The number of children of this device that\r
480 opened the controller BY_CHILD.\r
481 @param ChildHandleBuffer The array of child handle.\r
482\r
483 @retval EFI_SUCCESS The controller or children are stopped.\r
484 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
485\r
486**/\r
487EFI_STATUS\r
488EFIAPI\r
489QemuVideoControllerDriverStop (\r
490 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
491 IN EFI_HANDLE Controller,\r
492 IN UINTN NumberOfChildren,\r
493 IN EFI_HANDLE *ChildHandleBuffer\r
494 )\r
495{\r
496 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
497\r
498 EFI_STATUS Status;\r
499 QEMU_VIDEO_PRIVATE_DATA *Private;\r
500\r
99a6dce3
LE
501 if (NumberOfChildren == 0) {\r
502 //\r
503 // Close the PCI I/O Protocol\r
504 //\r
505 gBS->CloseProtocol (\r
506 Controller,\r
507 &gEfiPciIoProtocolGuid,\r
508 This->DriverBindingHandle,\r
509 Controller\r
510 );\r
511 return EFI_SUCCESS;\r
512 }\r
513\r
514 //\r
515 // free all resources for whose access we need the child handle, because the\r
516 // child handle is going away\r
517 //\r
518 ASSERT (NumberOfChildren == 1);\r
eaf4f336 519 Status = gBS->OpenProtocol (\r
99a6dce3 520 ChildHandleBuffer[0],\r
eaf4f336 521 &gEfiGraphicsOutputProtocolGuid,\r
522 (VOID **) &GraphicsOutput,\r
523 This->DriverBindingHandle,\r
524 Controller,\r
525 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
526 );\r
527 if (EFI_ERROR (Status)) {\r
528 return Status;\r
529 }\r
530\r
531 //\r
532 // Get our private context information\r
533 //\r
534 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
99a6dce3 535 ASSERT (Private->Handle == ChildHandleBuffer[0]);\r
eaf4f336 536\r
537 QemuVideoGraphicsOutputDestructor (Private);\r
538 //\r
539 // Remove the GOP protocol interface from the system\r
540 //\r
541 Status = gBS->UninstallMultipleProtocolInterfaces (\r
542 Private->Handle,\r
543 &gEfiGraphicsOutputProtocolGuid,\r
544 &Private->GraphicsOutput,\r
545 NULL\r
546 );\r
547\r
548 if (EFI_ERROR (Status)) {\r
549 return Status;\r
550 }\r
551\r
552 //\r
553 // Restore original PCI attributes\r
554 //\r
555 Private->PciIo->Attributes (\r
556 Private->PciIo,\r
557 EfiPciIoAttributeOperationSet,\r
558 Private->OriginalPciAttributes,\r
559 NULL\r
560 );\r
561\r
4374c2e5
CR
562 gBS->CloseProtocol (\r
563 Controller,\r
564 &gEfiPciIoProtocolGuid,\r
565 This->DriverBindingHandle,\r
566 Private->Handle\r
567 );\r
568\r
847e4c34
LE
569 FreePool (Private->ModeData);\r
570 gBS->UninstallProtocolInterface (Private->Handle,\r
571 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
572 FreePool (Private->GopDevicePath);\r
573\r
eaf4f336 574 //\r
575 // Free our instance data\r
576 //\r
577 gBS->FreePool (Private);\r
578\r
579 return EFI_SUCCESS;\r
580}\r
581\r
582/**\r
583 TODO: Add function description\r
584\r
585 @param Private TODO: add argument description\r
586 @param Address TODO: add argument description\r
587 @param Data TODO: add argument description\r
588\r
589 TODO: add return values\r
590\r
591**/\r
592VOID\r
593outb (\r
594 QEMU_VIDEO_PRIVATE_DATA *Private,\r
595 UINTN Address,\r
596 UINT8 Data\r
597 )\r
598{\r
599 Private->PciIo->Io.Write (\r
600 Private->PciIo,\r
601 EfiPciIoWidthUint8,\r
602 EFI_PCI_IO_PASS_THROUGH_BAR,\r
603 Address,\r
604 1,\r
605 &Data\r
606 );\r
607}\r
608\r
609/**\r
610 TODO: Add function description\r
611\r
612 @param Private TODO: add argument description\r
613 @param Address TODO: add argument description\r
614 @param Data TODO: add argument description\r
615\r
616 TODO: add return values\r
617\r
618**/\r
619VOID\r
620outw (\r
621 QEMU_VIDEO_PRIVATE_DATA *Private,\r
622 UINTN Address,\r
623 UINT16 Data\r
624 )\r
625{\r
626 Private->PciIo->Io.Write (\r
627 Private->PciIo,\r
628 EfiPciIoWidthUint16,\r
629 EFI_PCI_IO_PASS_THROUGH_BAR,\r
630 Address,\r
631 1,\r
632 &Data\r
633 );\r
634}\r
635\r
636/**\r
637 TODO: Add function description\r
638\r
639 @param Private TODO: add argument description\r
640 @param Address TODO: add argument description\r
641\r
642 TODO: add return values\r
643\r
644**/\r
645UINT8\r
646inb (\r
647 QEMU_VIDEO_PRIVATE_DATA *Private,\r
648 UINTN Address\r
649 )\r
650{\r
651 UINT8 Data;\r
652\r
653 Private->PciIo->Io.Read (\r
654 Private->PciIo,\r
655 EfiPciIoWidthUint8,\r
656 EFI_PCI_IO_PASS_THROUGH_BAR,\r
657 Address,\r
658 1,\r
659 &Data\r
660 );\r
661 return Data;\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
673UINT16\r
674inw (\r
675 QEMU_VIDEO_PRIVATE_DATA *Private,\r
676 UINTN Address\r
677 )\r
678{\r
679 UINT16 Data;\r
680\r
681 Private->PciIo->Io.Read (\r
682 Private->PciIo,\r
683 EfiPciIoWidthUint16,\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 Index TODO: add argument description\r
697 @param Red TODO: add argument description\r
698 @param Green TODO: add argument description\r
699 @param Blue TODO: add argument description\r
700\r
701 TODO: add return values\r
702\r
703**/\r
704VOID\r
705SetPaletteColor (\r
706 QEMU_VIDEO_PRIVATE_DATA *Private,\r
707 UINTN Index,\r
708 UINT8 Red,\r
709 UINT8 Green,\r
710 UINT8 Blue\r
711 )\r
712{\r
cdb4f5dc 713 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);\r
714 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));\r
715 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));\r
716 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));\r
eaf4f336 717}\r
718\r
719/**\r
720 TODO: Add function description\r
721\r
722 @param Private TODO: add argument description\r
723\r
724 TODO: add return values\r
725\r
726**/\r
727VOID\r
728SetDefaultPalette (\r
729 QEMU_VIDEO_PRIVATE_DATA *Private\r
730 )\r
731{\r
732 UINTN Index;\r
733 UINTN RedIndex;\r
734 UINTN GreenIndex;\r
735 UINTN BlueIndex;\r
736\r
737 Index = 0;\r
738 for (RedIndex = 0; RedIndex < 8; RedIndex++) {\r
739 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {\r
740 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {\r
741 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));\r
742 Index++;\r
743 }\r
744 }\r
745 }\r
746}\r
747\r
748/**\r
749 TODO: Add function description\r
750\r
751 @param Private TODO: add argument description\r
752\r
753 TODO: add return values\r
754\r
755**/\r
756VOID\r
757ClearScreen (\r
758 QEMU_VIDEO_PRIVATE_DATA *Private\r
759 )\r
760{\r
761 UINT32 Color;\r
762\r
763 Color = 0;\r
764 Private->PciIo->Mem.Write (\r
765 Private->PciIo,\r
766 EfiPciIoWidthFillUint32,\r
98856a72 767 0,\r
eaf4f336 768 0,\r
769 0x400000 >> 2,\r
770 &Color\r
771 );\r
772}\r
773\r
774/**\r
775 TODO: Add function description\r
776\r
777 @param Private TODO: add argument description\r
778\r
779 TODO: add return values\r
780\r
781**/\r
782VOID\r
783DrawLogo (\r
784 QEMU_VIDEO_PRIVATE_DATA *Private,\r
785 UINTN ScreenWidth,\r
786 UINTN ScreenHeight\r
787 )\r
788{\r
789}\r
790\r
791/**\r
792 TODO: Add function description\r
793\r
794 @param Private TODO: add argument description\r
795 @param ModeData TODO: add argument description\r
796\r
797 TODO: add return values\r
798\r
799**/\r
800VOID\r
212aac55 801InitializeCirrusGraphicsMode (\r
eaf4f336 802 QEMU_VIDEO_PRIVATE_DATA *Private,\r
212aac55 803 QEMU_VIDEO_CIRRUS_MODES *ModeData\r
eaf4f336 804 )\r
805{\r
806 UINT8 Byte;\r
807 UINTN Index;\r
eaf4f336 808\r
809 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);\r
810 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);\r
811\r
812 for (Index = 0; Index < 15; Index++) {\r
813 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);\r
814 }\r
815\r
212aac55 816 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {\r
eaf4f336 817 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);\r
818 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);\r
819 outb (Private, SEQ_DATA_REGISTER, Byte);\r
820 }\r
821\r
822 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);\r
823 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);\r
824 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);\r
825 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);\r
826\r
827 for (Index = 0; Index < 28; Index++) {\r
828 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));\r
829 }\r
830\r
831 for (Index = 0; Index < 9; Index++) {\r
832 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));\r
833 }\r
834\r
835 inb (Private, INPUT_STATUS_1_REGISTER);\r
836\r
837 for (Index = 0; Index < 21; Index++) {\r
838 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);\r
839 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);\r
840 }\r
841\r
842 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
843\r
844 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);\r
845 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);\r
846 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);\r
847 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);\r
848\r
54f9b9ac 849 SetDefaultPalette (Private);\r
850 ClearScreen (Private);\r
851}\r
852\r
853VOID\r
854BochsWrite (\r
855 QEMU_VIDEO_PRIVATE_DATA *Private,\r
856 UINT16 Reg,\r
857 UINT16 Data\r
858 )\r
859{\r
cdb4f5dc 860 EFI_STATUS Status;\r
861\r
862 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
863 Status = Private->PciIo->Mem.Write (\r
864 Private->PciIo,\r
865 EfiPciIoWidthUint16,\r
866 PCI_BAR_IDX2,\r
867 0x500 + (Reg << 1),\r
868 1,\r
869 &Data\r
870 );\r
871 ASSERT_EFI_ERROR (Status);\r
872 } else {\r
873 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
874 outw (Private, VBE_DISPI_IOPORT_DATA, Data);\r
875 }\r
54f9b9ac 876}\r
877\r
878UINT16\r
879BochsRead (\r
880 QEMU_VIDEO_PRIVATE_DATA *Private,\r
881 UINT16 Reg\r
882 )\r
883{\r
cdb4f5dc 884 EFI_STATUS Status;\r
885 UINT16 Data;\r
886\r
887 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
888 Status = Private->PciIo->Mem.Read (\r
889 Private->PciIo,\r
890 EfiPciIoWidthUint16,\r
891 PCI_BAR_IDX2,\r
892 0x500 + (Reg << 1),\r
893 1,\r
894 &Data\r
895 );\r
896 ASSERT_EFI_ERROR (Status);\r
897 } else {\r
898 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
899 Data = inw (Private, VBE_DISPI_IOPORT_DATA);\r
900 }\r
54f9b9ac 901 return Data;\r
902}\r
903\r
cdb4f5dc 904VOID\r
905VgaOutb (\r
906 QEMU_VIDEO_PRIVATE_DATA *Private,\r
907 UINTN Reg,\r
908 UINT8 Data\r
909 )\r
910{\r
911 EFI_STATUS Status;\r
912\r
913 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
914 Status = Private->PciIo->Mem.Write (\r
915 Private->PciIo,\r
916 EfiPciIoWidthUint8,\r
917 PCI_BAR_IDX2,\r
918 0x400 - 0x3c0 + Reg,\r
919 1,\r
920 &Data\r
921 );\r
922 ASSERT_EFI_ERROR (Status);\r
923 } else {\r
924 outb (Private, Reg, Data);\r
925 }\r
926}\r
927\r
54f9b9ac 928VOID\r
929InitializeBochsGraphicsMode (\r
930 QEMU_VIDEO_PRIVATE_DATA *Private,\r
931 QEMU_VIDEO_BOCHS_MODES *ModeData\r
932 )\r
933{\r
934 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",\r
935 ModeData->Width, ModeData->Height, ModeData->ColorDepth));\r
936\r
937 /* unblank */\r
cdb4f5dc 938 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
54f9b9ac 939\r
940 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);\r
941 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);\r
942 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);\r
943 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);\r
944\r
945 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);\r
946 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);\r
947 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);\r
948 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);\r
949 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);\r
950\r
951 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,\r
952 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);\r
953\r
eaf4f336 954 SetDefaultPalette (Private);\r
955 ClearScreen (Private);\r
956}\r
957\r
958EFI_STATUS\r
959EFIAPI\r
960InitializeQemuVideo (\r
961 IN EFI_HANDLE ImageHandle,\r
962 IN EFI_SYSTEM_TABLE *SystemTable\r
963 )\r
964{\r
965 EFI_STATUS Status;\r
966\r
967 Status = EfiLibInstallDriverBindingComponentName2 (\r
968 ImageHandle,\r
969 SystemTable,\r
970 &gQemuVideoDriverBinding,\r
971 ImageHandle,\r
972 &gQemuVideoComponentName,\r
973 &gQemuVideoComponentName2\r
974 );\r
975 ASSERT_EFI_ERROR (Status);\r
976\r
977 //\r
978 // Install EFI Driver Supported EFI Version Protocol required for\r
979 // EFI drivers that are on PCI and other plug in cards.\r
980 //\r
981 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);\r
982 Status = gBS->InstallMultipleProtocolInterfaces (\r
983 &ImageHandle,\r
984 &gEfiDriverSupportedEfiVersionProtocolGuid,\r
985 &gQemuVideoDriverSupportedEfiVersion,\r
986 NULL\r
987 );\r
988 ASSERT_EFI_ERROR (Status);\r
989\r
990 return Status;\r
991}\r