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