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