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