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