]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Driver.c
OvmfPkg: QemuVideoDxe: disentangle UEFI driver model use 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 //
526 // Free our instance data
527 //
528 gBS->FreePool (Private);
529
530 return EFI_SUCCESS;
531 }
532
533 /**
534 TODO: Add function description
535
536 @param Private TODO: add argument description
537 @param Address TODO: add argument description
538 @param Data TODO: add argument description
539
540 TODO: add return values
541
542 **/
543 VOID
544 outb (
545 QEMU_VIDEO_PRIVATE_DATA *Private,
546 UINTN Address,
547 UINT8 Data
548 )
549 {
550 Private->PciIo->Io.Write (
551 Private->PciIo,
552 EfiPciIoWidthUint8,
553 EFI_PCI_IO_PASS_THROUGH_BAR,
554 Address,
555 1,
556 &Data
557 );
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 outw (
572 QEMU_VIDEO_PRIVATE_DATA *Private,
573 UINTN Address,
574 UINT16 Data
575 )
576 {
577 Private->PciIo->Io.Write (
578 Private->PciIo,
579 EfiPciIoWidthUint16,
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
593 TODO: add return values
594
595 **/
596 UINT8
597 inb (
598 QEMU_VIDEO_PRIVATE_DATA *Private,
599 UINTN Address
600 )
601 {
602 UINT8 Data;
603
604 Private->PciIo->Io.Read (
605 Private->PciIo,
606 EfiPciIoWidthUint8,
607 EFI_PCI_IO_PASS_THROUGH_BAR,
608 Address,
609 1,
610 &Data
611 );
612 return Data;
613 }
614
615 /**
616 TODO: Add function description
617
618 @param Private TODO: add argument description
619 @param Address TODO: add argument description
620
621 TODO: add return values
622
623 **/
624 UINT16
625 inw (
626 QEMU_VIDEO_PRIVATE_DATA *Private,
627 UINTN Address
628 )
629 {
630 UINT16 Data;
631
632 Private->PciIo->Io.Read (
633 Private->PciIo,
634 EfiPciIoWidthUint16,
635 EFI_PCI_IO_PASS_THROUGH_BAR,
636 Address,
637 1,
638 &Data
639 );
640 return Data;
641 }
642
643 /**
644 TODO: Add function description
645
646 @param Private TODO: add argument description
647 @param Index TODO: add argument description
648 @param Red TODO: add argument description
649 @param Green TODO: add argument description
650 @param Blue TODO: add argument description
651
652 TODO: add return values
653
654 **/
655 VOID
656 SetPaletteColor (
657 QEMU_VIDEO_PRIVATE_DATA *Private,
658 UINTN Index,
659 UINT8 Red,
660 UINT8 Green,
661 UINT8 Blue
662 )
663 {
664 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
665 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
666 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
667 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
668 }
669
670 /**
671 TODO: Add function description
672
673 @param Private TODO: add argument description
674
675 TODO: add return values
676
677 **/
678 VOID
679 SetDefaultPalette (
680 QEMU_VIDEO_PRIVATE_DATA *Private
681 )
682 {
683 UINTN Index;
684 UINTN RedIndex;
685 UINTN GreenIndex;
686 UINTN BlueIndex;
687
688 Index = 0;
689 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
690 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
691 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
692 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
693 Index++;
694 }
695 }
696 }
697 }
698
699 /**
700 TODO: Add function description
701
702 @param Private TODO: add argument description
703
704 TODO: add return values
705
706 **/
707 VOID
708 ClearScreen (
709 QEMU_VIDEO_PRIVATE_DATA *Private
710 )
711 {
712 UINT32 Color;
713
714 Color = 0;
715 Private->PciIo->Mem.Write (
716 Private->PciIo,
717 EfiPciIoWidthFillUint32,
718 0,
719 0,
720 0x400000 >> 2,
721 &Color
722 );
723 }
724
725 /**
726 TODO: Add function description
727
728 @param Private TODO: add argument description
729
730 TODO: add return values
731
732 **/
733 VOID
734 DrawLogo (
735 QEMU_VIDEO_PRIVATE_DATA *Private,
736 UINTN ScreenWidth,
737 UINTN ScreenHeight
738 )
739 {
740 }
741
742 /**
743 TODO: Add function description
744
745 @param Private TODO: add argument description
746 @param ModeData TODO: add argument description
747
748 TODO: add return values
749
750 **/
751 VOID
752 InitializeCirrusGraphicsMode (
753 QEMU_VIDEO_PRIVATE_DATA *Private,
754 QEMU_VIDEO_CIRRUS_MODES *ModeData
755 )
756 {
757 UINT8 Byte;
758 UINTN Index;
759
760 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
761 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
762
763 for (Index = 0; Index < 15; Index++) {
764 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
765 }
766
767 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
768 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
769 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
770 outb (Private, SEQ_DATA_REGISTER, Byte);
771 }
772
773 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
774 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
775 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
776 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
777
778 for (Index = 0; Index < 28; Index++) {
779 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
780 }
781
782 for (Index = 0; Index < 9; Index++) {
783 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
784 }
785
786 inb (Private, INPUT_STATUS_1_REGISTER);
787
788 for (Index = 0; Index < 21; Index++) {
789 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
790 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
791 }
792
793 outb (Private, ATT_ADDRESS_REGISTER, 0x20);
794
795 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
796 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
797 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
798 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
799
800 SetDefaultPalette (Private);
801 ClearScreen (Private);
802 }
803
804 VOID
805 BochsWrite (
806 QEMU_VIDEO_PRIVATE_DATA *Private,
807 UINT16 Reg,
808 UINT16 Data
809 )
810 {
811 EFI_STATUS Status;
812
813 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
814 Status = Private->PciIo->Mem.Write (
815 Private->PciIo,
816 EfiPciIoWidthUint16,
817 PCI_BAR_IDX2,
818 0x500 + (Reg << 1),
819 1,
820 &Data
821 );
822 ASSERT_EFI_ERROR (Status);
823 } else {
824 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
825 outw (Private, VBE_DISPI_IOPORT_DATA, Data);
826 }
827 }
828
829 UINT16
830 BochsRead (
831 QEMU_VIDEO_PRIVATE_DATA *Private,
832 UINT16 Reg
833 )
834 {
835 EFI_STATUS Status;
836 UINT16 Data;
837
838 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
839 Status = Private->PciIo->Mem.Read (
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 Data = inw (Private, VBE_DISPI_IOPORT_DATA);
851 }
852 return Data;
853 }
854
855 VOID
856 VgaOutb (
857 QEMU_VIDEO_PRIVATE_DATA *Private,
858 UINTN Reg,
859 UINT8 Data
860 )
861 {
862 EFI_STATUS Status;
863
864 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
865 Status = Private->PciIo->Mem.Write (
866 Private->PciIo,
867 EfiPciIoWidthUint8,
868 PCI_BAR_IDX2,
869 0x400 - 0x3c0 + Reg,
870 1,
871 &Data
872 );
873 ASSERT_EFI_ERROR (Status);
874 } else {
875 outb (Private, Reg, Data);
876 }
877 }
878
879 VOID
880 InitializeBochsGraphicsMode (
881 QEMU_VIDEO_PRIVATE_DATA *Private,
882 QEMU_VIDEO_BOCHS_MODES *ModeData
883 )
884 {
885 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
886 ModeData->Width, ModeData->Height, ModeData->ColorDepth));
887
888 /* unblank */
889 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
890
891 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
892 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
893 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
894 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
895
896 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);
897 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);
898 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);
899 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);
900 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
901
902 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
903 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
904
905 SetDefaultPalette (Private);
906 ClearScreen (Private);
907 }
908
909 EFI_STATUS
910 EFIAPI
911 InitializeQemuVideo (
912 IN EFI_HANDLE ImageHandle,
913 IN EFI_SYSTEM_TABLE *SystemTable
914 )
915 {
916 EFI_STATUS Status;
917
918 Status = EfiLibInstallDriverBindingComponentName2 (
919 ImageHandle,
920 SystemTable,
921 &gQemuVideoDriverBinding,
922 ImageHandle,
923 &gQemuVideoComponentName,
924 &gQemuVideoComponentName2
925 );
926 ASSERT_EFI_ERROR (Status);
927
928 //
929 // Install EFI Driver Supported EFI Version Protocol required for
930 // EFI drivers that are on PCI and other plug in cards.
931 //
932 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
933 Status = gBS->InstallMultipleProtocolInterfaces (
934 &ImageHandle,
935 &gEfiDriverSupportedEfiVersionProtocolGuid,
936 &gQemuVideoDriverSupportedEfiVersion,
937 NULL
938 );
939 ASSERT_EFI_ERROR (Status);
940
941 return Status;
942 }