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