]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Driver.c
Revert "OvmfPkg/QemuVideoDxe: VMWare SVGA device support"
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Driver.c
1 /** @file
2 This driver is a sample implementation of the Graphics Output Protocol for
3 the QEMU (Cirrus Logic 5446) video controller.
4
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "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 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 // Check if accessing the bochs interface works.
321 //
322 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
323 Private->Variant == QEMU_VIDEO_BOCHS) {
324 UINT16 BochsId;
325 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);
326 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {
327 DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));
328 Status = EFI_DEVICE_ERROR;
329 goto RestoreAttributes;
330 }
331 }
332
333 //
334 // Get ParentDevicePath
335 //
336 Status = gBS->HandleProtocol (
337 Controller,
338 &gEfiDevicePathProtocolGuid,
339 (VOID **) &ParentDevicePath
340 );
341 if (EFI_ERROR (Status)) {
342 goto RestoreAttributes;
343 }
344
345 //
346 // Set Gop Device Path
347 //
348 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
349 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
350 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
351 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
352 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
353
354 Private->GopDevicePath = AppendDevicePathNode (
355 ParentDevicePath,
356 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
357 );
358 if (Private->GopDevicePath == NULL) {
359 Status = EFI_OUT_OF_RESOURCES;
360 goto RestoreAttributes;
361 }
362
363 //
364 // Create new child handle and install the device path protocol on it.
365 //
366 Status = gBS->InstallMultipleProtocolInterfaces (
367 &Private->Handle,
368 &gEfiDevicePathProtocolGuid,
369 Private->GopDevicePath,
370 NULL
371 );
372 if (EFI_ERROR (Status)) {
373 goto FreeGopDevicePath;
374 }
375
376 //
377 // Construct video mode buffer
378 //
379 switch (Private->Variant) {
380 case QEMU_VIDEO_CIRRUS_5430:
381 case QEMU_VIDEO_CIRRUS_5446:
382 Status = QemuVideoCirrusModeSetup (Private);
383 break;
384 case QEMU_VIDEO_BOCHS_MMIO:
385 case QEMU_VIDEO_BOCHS:
386 Status = QemuVideoBochsModeSetup (Private, IsQxl);
387 break;
388 default:
389 ASSERT (FALSE);
390 Status = EFI_DEVICE_ERROR;
391 break;
392 }
393 if (EFI_ERROR (Status)) {
394 goto UninstallGopDevicePath;
395 }
396
397 //
398 // Start the GOP software stack.
399 //
400 Status = QemuVideoGraphicsOutputConstructor (Private);
401 if (EFI_ERROR (Status)) {
402 goto FreeModeData;
403 }
404
405 Status = gBS->InstallMultipleProtocolInterfaces (
406 &Private->Handle,
407 &gEfiGraphicsOutputProtocolGuid,
408 &Private->GraphicsOutput,
409 NULL
410 );
411 if (EFI_ERROR (Status)) {
412 goto DestructQemuVideoGraphics;
413 }
414
415 //
416 // Reference parent handle from child handle.
417 //
418 Status = gBS->OpenProtocol (
419 Controller,
420 &gEfiPciIoProtocolGuid,
421 (VOID **) &ChildPciIo,
422 This->DriverBindingHandle,
423 Private->Handle,
424 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
425 );
426 if (EFI_ERROR (Status)) {
427 goto UninstallGop;
428 }
429
430 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
431 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
432 Private->Variant == QEMU_VIDEO_BOCHS) {
433 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
434 }
435 #endif
436
437 gBS->RestoreTPL (OldTpl);
438 return EFI_SUCCESS;
439
440 UninstallGop:
441 gBS->UninstallProtocolInterface (Private->Handle,
442 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
443
444 DestructQemuVideoGraphics:
445 QemuVideoGraphicsOutputDestructor (Private);
446
447 FreeModeData:
448 FreePool (Private->ModeData);
449
450 UninstallGopDevicePath:
451 gBS->UninstallProtocolInterface (Private->Handle,
452 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
453
454 FreeGopDevicePath:
455 FreePool (Private->GopDevicePath);
456
457 RestoreAttributes:
458 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
459 Private->OriginalPciAttributes, NULL);
460
461 ClosePciIo:
462 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
463 This->DriverBindingHandle, Controller);
464
465 FreePrivate:
466 FreePool (Private);
467
468 RestoreTpl:
469 gBS->RestoreTPL (OldTpl);
470
471 return Status;
472 }
473
474 /**
475 Stop this device
476
477 @param This The USB bus driver binding protocol.
478 @param Controller The controller to release.
479 @param NumberOfChildren The number of children of this device that
480 opened the controller BY_CHILD.
481 @param ChildHandleBuffer The array of child handle.
482
483 @retval EFI_SUCCESS The controller or children are stopped.
484 @retval EFI_DEVICE_ERROR Failed to stop the driver.
485
486 **/
487 EFI_STATUS
488 EFIAPI
489 QemuVideoControllerDriverStop (
490 IN EFI_DRIVER_BINDING_PROTOCOL *This,
491 IN EFI_HANDLE Controller,
492 IN UINTN NumberOfChildren,
493 IN EFI_HANDLE *ChildHandleBuffer
494 )
495 {
496 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
497
498 EFI_STATUS Status;
499 QEMU_VIDEO_PRIVATE_DATA *Private;
500
501 if (NumberOfChildren == 0) {
502 //
503 // Close the PCI I/O Protocol
504 //
505 gBS->CloseProtocol (
506 Controller,
507 &gEfiPciIoProtocolGuid,
508 This->DriverBindingHandle,
509 Controller
510 );
511 return EFI_SUCCESS;
512 }
513
514 //
515 // free all resources for whose access we need the child handle, because the
516 // child handle is going away
517 //
518 ASSERT (NumberOfChildren == 1);
519 Status = gBS->OpenProtocol (
520 ChildHandleBuffer[0],
521 &gEfiGraphicsOutputProtocolGuid,
522 (VOID **) &GraphicsOutput,
523 This->DriverBindingHandle,
524 Controller,
525 EFI_OPEN_PROTOCOL_GET_PROTOCOL
526 );
527 if (EFI_ERROR (Status)) {
528 return Status;
529 }
530
531 //
532 // Get our private context information
533 //
534 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
535 ASSERT (Private->Handle == ChildHandleBuffer[0]);
536
537 QemuVideoGraphicsOutputDestructor (Private);
538 //
539 // Remove the GOP protocol interface from the system
540 //
541 Status = gBS->UninstallMultipleProtocolInterfaces (
542 Private->Handle,
543 &gEfiGraphicsOutputProtocolGuid,
544 &Private->GraphicsOutput,
545 NULL
546 );
547
548 if (EFI_ERROR (Status)) {
549 return Status;
550 }
551
552 //
553 // Restore original PCI attributes
554 //
555 Private->PciIo->Attributes (
556 Private->PciIo,
557 EfiPciIoAttributeOperationSet,
558 Private->OriginalPciAttributes,
559 NULL
560 );
561
562 gBS->CloseProtocol (
563 Controller,
564 &gEfiPciIoProtocolGuid,
565 This->DriverBindingHandle,
566 Private->Handle
567 );
568
569 FreePool (Private->ModeData);
570 gBS->UninstallProtocolInterface (Private->Handle,
571 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
572 FreePool (Private->GopDevicePath);
573
574 //
575 // Free our instance data
576 //
577 gBS->FreePool (Private);
578
579 return EFI_SUCCESS;
580 }
581
582 /**
583 TODO: Add function description
584
585 @param Private TODO: add argument description
586 @param Address TODO: add argument description
587 @param Data TODO: add argument description
588
589 TODO: add return values
590
591 **/
592 VOID
593 outb (
594 QEMU_VIDEO_PRIVATE_DATA *Private,
595 UINTN Address,
596 UINT8 Data
597 )
598 {
599 Private->PciIo->Io.Write (
600 Private->PciIo,
601 EfiPciIoWidthUint8,
602 EFI_PCI_IO_PASS_THROUGH_BAR,
603 Address,
604 1,
605 &Data
606 );
607 }
608
609 /**
610 TODO: Add function description
611
612 @param Private TODO: add argument description
613 @param Address TODO: add argument description
614 @param Data TODO: add argument description
615
616 TODO: add return values
617
618 **/
619 VOID
620 outw (
621 QEMU_VIDEO_PRIVATE_DATA *Private,
622 UINTN Address,
623 UINT16 Data
624 )
625 {
626 Private->PciIo->Io.Write (
627 Private->PciIo,
628 EfiPciIoWidthUint16,
629 EFI_PCI_IO_PASS_THROUGH_BAR,
630 Address,
631 1,
632 &Data
633 );
634 }
635
636 /**
637 TODO: Add function description
638
639 @param Private TODO: add argument description
640 @param Address TODO: add argument description
641
642 TODO: add return values
643
644 **/
645 UINT8
646 inb (
647 QEMU_VIDEO_PRIVATE_DATA *Private,
648 UINTN Address
649 )
650 {
651 UINT8 Data;
652
653 Private->PciIo->Io.Read (
654 Private->PciIo,
655 EfiPciIoWidthUint8,
656 EFI_PCI_IO_PASS_THROUGH_BAR,
657 Address,
658 1,
659 &Data
660 );
661 return Data;
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 UINT16
674 inw (
675 QEMU_VIDEO_PRIVATE_DATA *Private,
676 UINTN Address
677 )
678 {
679 UINT16 Data;
680
681 Private->PciIo->Io.Read (
682 Private->PciIo,
683 EfiPciIoWidthUint16,
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 Index TODO: add argument description
697 @param Red TODO: add argument description
698 @param Green TODO: add argument description
699 @param Blue TODO: add argument description
700
701 TODO: add return values
702
703 **/
704 VOID
705 SetPaletteColor (
706 QEMU_VIDEO_PRIVATE_DATA *Private,
707 UINTN Index,
708 UINT8 Red,
709 UINT8 Green,
710 UINT8 Blue
711 )
712 {
713 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
714 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
715 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
716 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
717 }
718
719 /**
720 TODO: Add function description
721
722 @param Private TODO: add argument description
723
724 TODO: add return values
725
726 **/
727 VOID
728 SetDefaultPalette (
729 QEMU_VIDEO_PRIVATE_DATA *Private
730 )
731 {
732 UINTN Index;
733 UINTN RedIndex;
734 UINTN GreenIndex;
735 UINTN BlueIndex;
736
737 Index = 0;
738 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
739 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
740 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
741 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
742 Index++;
743 }
744 }
745 }
746 }
747
748 /**
749 TODO: Add function description
750
751 @param Private TODO: add argument description
752
753 TODO: add return values
754
755 **/
756 VOID
757 ClearScreen (
758 QEMU_VIDEO_PRIVATE_DATA *Private
759 )
760 {
761 UINT32 Color;
762
763 Color = 0;
764 Private->PciIo->Mem.Write (
765 Private->PciIo,
766 EfiPciIoWidthFillUint32,
767 0,
768 0,
769 0x400000 >> 2,
770 &Color
771 );
772 }
773
774 /**
775 TODO: Add function description
776
777 @param Private TODO: add argument description
778
779 TODO: add return values
780
781 **/
782 VOID
783 DrawLogo (
784 QEMU_VIDEO_PRIVATE_DATA *Private,
785 UINTN ScreenWidth,
786 UINTN ScreenHeight
787 )
788 {
789 }
790
791 /**
792 TODO: Add function description
793
794 @param Private TODO: add argument description
795 @param ModeData TODO: add argument description
796
797 TODO: add return values
798
799 **/
800 VOID
801 InitializeCirrusGraphicsMode (
802 QEMU_VIDEO_PRIVATE_DATA *Private,
803 QEMU_VIDEO_CIRRUS_MODES *ModeData
804 )
805 {
806 UINT8 Byte;
807 UINTN Index;
808
809 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
810 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
811
812 for (Index = 0; Index < 15; Index++) {
813 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
814 }
815
816 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
817 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
818 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
819 outb (Private, SEQ_DATA_REGISTER, Byte);
820 }
821
822 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
823 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
824 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
825 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
826
827 for (Index = 0; Index < 28; Index++) {
828 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
829 }
830
831 for (Index = 0; Index < 9; Index++) {
832 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
833 }
834
835 inb (Private, INPUT_STATUS_1_REGISTER);
836
837 for (Index = 0; Index < 21; Index++) {
838 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
839 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
840 }
841
842 outb (Private, ATT_ADDRESS_REGISTER, 0x20);
843
844 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
845 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
846 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
847 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
848
849 SetDefaultPalette (Private);
850 ClearScreen (Private);
851 }
852
853 VOID
854 BochsWrite (
855 QEMU_VIDEO_PRIVATE_DATA *Private,
856 UINT16 Reg,
857 UINT16 Data
858 )
859 {
860 EFI_STATUS Status;
861
862 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
863 Status = Private->PciIo->Mem.Write (
864 Private->PciIo,
865 EfiPciIoWidthUint16,
866 PCI_BAR_IDX2,
867 0x500 + (Reg << 1),
868 1,
869 &Data
870 );
871 ASSERT_EFI_ERROR (Status);
872 } else {
873 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
874 outw (Private, VBE_DISPI_IOPORT_DATA, Data);
875 }
876 }
877
878 UINT16
879 BochsRead (
880 QEMU_VIDEO_PRIVATE_DATA *Private,
881 UINT16 Reg
882 )
883 {
884 EFI_STATUS Status;
885 UINT16 Data;
886
887 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
888 Status = Private->PciIo->Mem.Read (
889 Private->PciIo,
890 EfiPciIoWidthUint16,
891 PCI_BAR_IDX2,
892 0x500 + (Reg << 1),
893 1,
894 &Data
895 );
896 ASSERT_EFI_ERROR (Status);
897 } else {
898 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
899 Data = inw (Private, VBE_DISPI_IOPORT_DATA);
900 }
901 return Data;
902 }
903
904 VOID
905 VgaOutb (
906 QEMU_VIDEO_PRIVATE_DATA *Private,
907 UINTN Reg,
908 UINT8 Data
909 )
910 {
911 EFI_STATUS Status;
912
913 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
914 Status = Private->PciIo->Mem.Write (
915 Private->PciIo,
916 EfiPciIoWidthUint8,
917 PCI_BAR_IDX2,
918 0x400 - 0x3c0 + Reg,
919 1,
920 &Data
921 );
922 ASSERT_EFI_ERROR (Status);
923 } else {
924 outb (Private, Reg, Data);
925 }
926 }
927
928 VOID
929 InitializeBochsGraphicsMode (
930 QEMU_VIDEO_PRIVATE_DATA *Private,
931 QEMU_VIDEO_BOCHS_MODES *ModeData
932 )
933 {
934 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
935 ModeData->Width, ModeData->Height, ModeData->ColorDepth));
936
937 /* unblank */
938 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
939
940 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
941 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
942 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
943 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
944
945 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);
946 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);
947 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);
948 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);
949 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
950
951 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
952 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
953
954 SetDefaultPalette (Private);
955 ClearScreen (Private);
956 }
957
958 EFI_STATUS
959 EFIAPI
960 InitializeQemuVideo (
961 IN EFI_HANDLE ImageHandle,
962 IN EFI_SYSTEM_TABLE *SystemTable
963 )
964 {
965 EFI_STATUS Status;
966
967 Status = EfiLibInstallDriverBindingComponentName2 (
968 ImageHandle,
969 SystemTable,
970 &gQemuVideoDriverBinding,
971 ImageHandle,
972 &gQemuVideoComponentName,
973 &gQemuVideoComponentName2
974 );
975 ASSERT_EFI_ERROR (Status);
976
977 //
978 // Install EFI Driver Supported EFI Version Protocol required for
979 // EFI drivers that are on PCI and other plug in cards.
980 //
981 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
982 Status = gBS->InstallMultipleProtocolInterfaces (
983 &ImageHandle,
984 &gEfiDriverSupportedEfiVersionProtocolGuid,
985 &gQemuVideoDriverSupportedEfiVersion,
986 NULL
987 );
988 ASSERT_EFI_ERROR (Status);
989
990 return Status;
991 }