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