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