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