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