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