]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Driver.c
Dispatch the UEFI option rom returned from PciPlatform/PciOverride protocol.
[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 (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
409 Private->Variant == QEMU_VIDEO_BOCHS) {
410 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
411 }
412
413 gBS->RestoreTPL (OldTpl);
414 return EFI_SUCCESS;
415
416 UninstallGop:
417 gBS->UninstallProtocolInterface (Private->Handle,
418 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
419
420 DestructQemuVideoGraphics:
421 QemuVideoGraphicsOutputDestructor (Private);
422
423 FreeModeData:
424 FreePool (Private->ModeData);
425
426 UninstallGopDevicePath:
427 gBS->UninstallProtocolInterface (Private->Handle,
428 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
429
430 FreeGopDevicePath:
431 FreePool (Private->GopDevicePath);
432
433 RestoreAttributes:
434 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
435 Private->OriginalPciAttributes, NULL);
436
437 ClosePciIo:
438 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
439 This->DriverBindingHandle, Controller);
440
441 FreePrivate:
442 FreePool (Private);
443
444 RestoreTpl:
445 gBS->RestoreTPL (OldTpl);
446
447 return Status;
448 }
449
450 /**
451 Stop this device
452
453 @param This The USB bus driver binding protocol.
454 @param Controller The controller to release.
455 @param NumberOfChildren The number of children of this device that
456 opened the controller BY_CHILD.
457 @param ChildHandleBuffer The array of child handle.
458
459 @retval EFI_SUCCESS The controller or children are stopped.
460 @retval EFI_DEVICE_ERROR Failed to stop the driver.
461
462 **/
463 EFI_STATUS
464 EFIAPI
465 QemuVideoControllerDriverStop (
466 IN EFI_DRIVER_BINDING_PROTOCOL *This,
467 IN EFI_HANDLE Controller,
468 IN UINTN NumberOfChildren,
469 IN EFI_HANDLE *ChildHandleBuffer
470 )
471 {
472 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
473
474 EFI_STATUS Status;
475 QEMU_VIDEO_PRIVATE_DATA *Private;
476
477 if (NumberOfChildren == 0) {
478 //
479 // Close the PCI I/O Protocol
480 //
481 gBS->CloseProtocol (
482 Controller,
483 &gEfiPciIoProtocolGuid,
484 This->DriverBindingHandle,
485 Controller
486 );
487 return EFI_SUCCESS;
488 }
489
490 //
491 // free all resources for whose access we need the child handle, because the
492 // child handle is going away
493 //
494 ASSERT (NumberOfChildren == 1);
495 Status = gBS->OpenProtocol (
496 ChildHandleBuffer[0],
497 &gEfiGraphicsOutputProtocolGuid,
498 (VOID **) &GraphicsOutput,
499 This->DriverBindingHandle,
500 Controller,
501 EFI_OPEN_PROTOCOL_GET_PROTOCOL
502 );
503 if (EFI_ERROR (Status)) {
504 return Status;
505 }
506
507 //
508 // Get our private context information
509 //
510 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
511 ASSERT (Private->Handle == ChildHandleBuffer[0]);
512
513 QemuVideoGraphicsOutputDestructor (Private);
514 //
515 // Remove the GOP protocol interface from the system
516 //
517 Status = gBS->UninstallMultipleProtocolInterfaces (
518 Private->Handle,
519 &gEfiGraphicsOutputProtocolGuid,
520 &Private->GraphicsOutput,
521 NULL
522 );
523
524 if (EFI_ERROR (Status)) {
525 return Status;
526 }
527
528 //
529 // Restore original PCI attributes
530 //
531 Private->PciIo->Attributes (
532 Private->PciIo,
533 EfiPciIoAttributeOperationSet,
534 Private->OriginalPciAttributes,
535 NULL
536 );
537
538 gBS->CloseProtocol (
539 Controller,
540 &gEfiPciIoProtocolGuid,
541 This->DriverBindingHandle,
542 Private->Handle
543 );
544
545 FreePool (Private->ModeData);
546 gBS->UninstallProtocolInterface (Private->Handle,
547 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
548 FreePool (Private->GopDevicePath);
549
550 //
551 // Free our instance data
552 //
553 gBS->FreePool (Private);
554
555 return EFI_SUCCESS;
556 }
557
558 /**
559 TODO: Add function description
560
561 @param Private TODO: add argument description
562 @param Address TODO: add argument description
563 @param Data TODO: add argument description
564
565 TODO: add return values
566
567 **/
568 VOID
569 outb (
570 QEMU_VIDEO_PRIVATE_DATA *Private,
571 UINTN Address,
572 UINT8 Data
573 )
574 {
575 Private->PciIo->Io.Write (
576 Private->PciIo,
577 EfiPciIoWidthUint8,
578 EFI_PCI_IO_PASS_THROUGH_BAR,
579 Address,
580 1,
581 &Data
582 );
583 }
584
585 /**
586 TODO: Add function description
587
588 @param Private TODO: add argument description
589 @param Address TODO: add argument description
590 @param Data TODO: add argument description
591
592 TODO: add return values
593
594 **/
595 VOID
596 outw (
597 QEMU_VIDEO_PRIVATE_DATA *Private,
598 UINTN Address,
599 UINT16 Data
600 )
601 {
602 Private->PciIo->Io.Write (
603 Private->PciIo,
604 EfiPciIoWidthUint16,
605 EFI_PCI_IO_PASS_THROUGH_BAR,
606 Address,
607 1,
608 &Data
609 );
610 }
611
612 /**
613 TODO: Add function description
614
615 @param Private TODO: add argument description
616 @param Address TODO: add argument description
617
618 TODO: add return values
619
620 **/
621 UINT8
622 inb (
623 QEMU_VIDEO_PRIVATE_DATA *Private,
624 UINTN Address
625 )
626 {
627 UINT8 Data;
628
629 Private->PciIo->Io.Read (
630 Private->PciIo,
631 EfiPciIoWidthUint8,
632 EFI_PCI_IO_PASS_THROUGH_BAR,
633 Address,
634 1,
635 &Data
636 );
637 return Data;
638 }
639
640 /**
641 TODO: Add function description
642
643 @param Private TODO: add argument description
644 @param Address TODO: add argument description
645
646 TODO: add return values
647
648 **/
649 UINT16
650 inw (
651 QEMU_VIDEO_PRIVATE_DATA *Private,
652 UINTN Address
653 )
654 {
655 UINT16 Data;
656
657 Private->PciIo->Io.Read (
658 Private->PciIo,
659 EfiPciIoWidthUint16,
660 EFI_PCI_IO_PASS_THROUGH_BAR,
661 Address,
662 1,
663 &Data
664 );
665 return Data;
666 }
667
668 /**
669 TODO: Add function description
670
671 @param Private TODO: add argument description
672 @param Index TODO: add argument description
673 @param Red TODO: add argument description
674 @param Green TODO: add argument description
675 @param Blue TODO: add argument description
676
677 TODO: add return values
678
679 **/
680 VOID
681 SetPaletteColor (
682 QEMU_VIDEO_PRIVATE_DATA *Private,
683 UINTN Index,
684 UINT8 Red,
685 UINT8 Green,
686 UINT8 Blue
687 )
688 {
689 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
690 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
691 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
692 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
693 }
694
695 /**
696 TODO: Add function description
697
698 @param Private TODO: add argument description
699
700 TODO: add return values
701
702 **/
703 VOID
704 SetDefaultPalette (
705 QEMU_VIDEO_PRIVATE_DATA *Private
706 )
707 {
708 UINTN Index;
709 UINTN RedIndex;
710 UINTN GreenIndex;
711 UINTN BlueIndex;
712
713 Index = 0;
714 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
715 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
716 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
717 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
718 Index++;
719 }
720 }
721 }
722 }
723
724 /**
725 TODO: Add function description
726
727 @param Private TODO: add argument description
728
729 TODO: add return values
730
731 **/
732 VOID
733 ClearScreen (
734 QEMU_VIDEO_PRIVATE_DATA *Private
735 )
736 {
737 UINT32 Color;
738
739 Color = 0;
740 Private->PciIo->Mem.Write (
741 Private->PciIo,
742 EfiPciIoWidthFillUint32,
743 0,
744 0,
745 0x400000 >> 2,
746 &Color
747 );
748 }
749
750 /**
751 TODO: Add function description
752
753 @param Private TODO: add argument description
754
755 TODO: add return values
756
757 **/
758 VOID
759 DrawLogo (
760 QEMU_VIDEO_PRIVATE_DATA *Private,
761 UINTN ScreenWidth,
762 UINTN ScreenHeight
763 )
764 {
765 }
766
767 /**
768 TODO: Add function description
769
770 @param Private TODO: add argument description
771 @param ModeData TODO: add argument description
772
773 TODO: add return values
774
775 **/
776 VOID
777 InitializeCirrusGraphicsMode (
778 QEMU_VIDEO_PRIVATE_DATA *Private,
779 QEMU_VIDEO_CIRRUS_MODES *ModeData
780 )
781 {
782 UINT8 Byte;
783 UINTN Index;
784
785 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
786 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
787
788 for (Index = 0; Index < 15; Index++) {
789 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
790 }
791
792 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
793 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
794 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
795 outb (Private, SEQ_DATA_REGISTER, Byte);
796 }
797
798 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
799 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
800 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
801 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
802
803 for (Index = 0; Index < 28; Index++) {
804 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
805 }
806
807 for (Index = 0; Index < 9; Index++) {
808 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
809 }
810
811 inb (Private, INPUT_STATUS_1_REGISTER);
812
813 for (Index = 0; Index < 21; Index++) {
814 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
815 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
816 }
817
818 outb (Private, ATT_ADDRESS_REGISTER, 0x20);
819
820 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
821 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
822 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
823 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
824
825 SetDefaultPalette (Private);
826 ClearScreen (Private);
827 }
828
829 VOID
830 BochsWrite (
831 QEMU_VIDEO_PRIVATE_DATA *Private,
832 UINT16 Reg,
833 UINT16 Data
834 )
835 {
836 EFI_STATUS Status;
837
838 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
839 Status = Private->PciIo->Mem.Write (
840 Private->PciIo,
841 EfiPciIoWidthUint16,
842 PCI_BAR_IDX2,
843 0x500 + (Reg << 1),
844 1,
845 &Data
846 );
847 ASSERT_EFI_ERROR (Status);
848 } else {
849 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
850 outw (Private, VBE_DISPI_IOPORT_DATA, Data);
851 }
852 }
853
854 UINT16
855 BochsRead (
856 QEMU_VIDEO_PRIVATE_DATA *Private,
857 UINT16 Reg
858 )
859 {
860 EFI_STATUS Status;
861 UINT16 Data;
862
863 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
864 Status = Private->PciIo->Mem.Read (
865 Private->PciIo,
866 EfiPciIoWidthUint16,
867 PCI_BAR_IDX2,
868 0x500 + (Reg << 1),
869 1,
870 &Data
871 );
872 ASSERT_EFI_ERROR (Status);
873 } else {
874 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
875 Data = inw (Private, VBE_DISPI_IOPORT_DATA);
876 }
877 return Data;
878 }
879
880 VOID
881 VgaOutb (
882 QEMU_VIDEO_PRIVATE_DATA *Private,
883 UINTN Reg,
884 UINT8 Data
885 )
886 {
887 EFI_STATUS Status;
888
889 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
890 Status = Private->PciIo->Mem.Write (
891 Private->PciIo,
892 EfiPciIoWidthUint8,
893 PCI_BAR_IDX2,
894 0x400 - 0x3c0 + Reg,
895 1,
896 &Data
897 );
898 ASSERT_EFI_ERROR (Status);
899 } else {
900 outb (Private, Reg, Data);
901 }
902 }
903
904 VOID
905 InitializeBochsGraphicsMode (
906 QEMU_VIDEO_PRIVATE_DATA *Private,
907 QEMU_VIDEO_BOCHS_MODES *ModeData
908 )
909 {
910 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
911 ModeData->Width, ModeData->Height, ModeData->ColorDepth));
912
913 /* unblank */
914 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
915
916 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
917 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
918 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
919 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
920
921 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);
922 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);
923 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);
924 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);
925 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
926
927 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
928 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
929
930 SetDefaultPalette (Private);
931 ClearScreen (Private);
932 }
933
934 EFI_STATUS
935 EFIAPI
936 InitializeQemuVideo (
937 IN EFI_HANDLE ImageHandle,
938 IN EFI_SYSTEM_TABLE *SystemTable
939 )
940 {
941 EFI_STATUS Status;
942
943 Status = EfiLibInstallDriverBindingComponentName2 (
944 ImageHandle,
945 SystemTable,
946 &gQemuVideoDriverBinding,
947 ImageHandle,
948 &gQemuVideoComponentName,
949 &gQemuVideoComponentName2
950 );
951 ASSERT_EFI_ERROR (Status);
952
953 //
954 // Install EFI Driver Supported EFI Version Protocol required for
955 // EFI drivers that are on PCI and other plug in cards.
956 //
957 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
958 Status = gBS->InstallMultipleProtocolInterfaces (
959 &ImageHandle,
960 &gEfiDriverSupportedEfiVersionProtocolGuid,
961 &gQemuVideoDriverSupportedEfiVersion,
962 NULL
963 );
964 ASSERT_EFI_ERROR (Status);
965
966 return Status;
967 }