]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Driver.c
OvmfPkg: QemuVideoDxe: serialize Start() against callbacks
[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 gBS->RestoreTPL (OldTpl);
402 return EFI_SUCCESS;
403
404 UninstallGop:
405 gBS->UninstallProtocolInterface (Private->Handle,
406 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
407
408 DestructQemuVideoGraphics:
409 QemuVideoGraphicsOutputDestructor (Private);
410
411 FreeModeData:
412 FreePool (Private->ModeData);
413
414 UninstallGopDevicePath:
415 gBS->UninstallProtocolInterface (Private->Handle,
416 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
417
418 FreeGopDevicePath:
419 FreePool (Private->GopDevicePath);
420
421 RestoreAttributes:
422 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
423 Private->OriginalPciAttributes, NULL);
424
425 ClosePciIo:
426 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
427 This->DriverBindingHandle, Controller);
428
429 FreePrivate:
430 FreePool (Private);
431
432 RestoreTpl:
433 gBS->RestoreTPL (OldTpl);
434
435 return Status;
436 }
437
438 /**
439 Stop this device
440
441 @param This The USB bus driver binding protocol.
442 @param Controller The controller to release.
443 @param NumberOfChildren The number of children of this device that
444 opened the controller BY_CHILD.
445 @param ChildHandleBuffer The array of child handle.
446
447 @retval EFI_SUCCESS The controller or children are stopped.
448 @retval EFI_DEVICE_ERROR Failed to stop the driver.
449
450 **/
451 EFI_STATUS
452 EFIAPI
453 QemuVideoControllerDriverStop (
454 IN EFI_DRIVER_BINDING_PROTOCOL *This,
455 IN EFI_HANDLE Controller,
456 IN UINTN NumberOfChildren,
457 IN EFI_HANDLE *ChildHandleBuffer
458 )
459 {
460 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
461
462 EFI_STATUS Status;
463 QEMU_VIDEO_PRIVATE_DATA *Private;
464
465 if (NumberOfChildren == 0) {
466 //
467 // Close the PCI I/O Protocol
468 //
469 gBS->CloseProtocol (
470 Controller,
471 &gEfiPciIoProtocolGuid,
472 This->DriverBindingHandle,
473 Controller
474 );
475 return EFI_SUCCESS;
476 }
477
478 //
479 // free all resources for whose access we need the child handle, because the
480 // child handle is going away
481 //
482 ASSERT (NumberOfChildren == 1);
483 Status = gBS->OpenProtocol (
484 ChildHandleBuffer[0],
485 &gEfiGraphicsOutputProtocolGuid,
486 (VOID **) &GraphicsOutput,
487 This->DriverBindingHandle,
488 Controller,
489 EFI_OPEN_PROTOCOL_GET_PROTOCOL
490 );
491 if (EFI_ERROR (Status)) {
492 return Status;
493 }
494
495 //
496 // Get our private context information
497 //
498 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
499 ASSERT (Private->Handle == ChildHandleBuffer[0]);
500
501 QemuVideoGraphicsOutputDestructor (Private);
502 //
503 // Remove the GOP protocol interface from the system
504 //
505 Status = gBS->UninstallMultipleProtocolInterfaces (
506 Private->Handle,
507 &gEfiGraphicsOutputProtocolGuid,
508 &Private->GraphicsOutput,
509 NULL
510 );
511
512 if (EFI_ERROR (Status)) {
513 return Status;
514 }
515
516 //
517 // Restore original PCI attributes
518 //
519 Private->PciIo->Attributes (
520 Private->PciIo,
521 EfiPciIoAttributeOperationSet,
522 Private->OriginalPciAttributes,
523 NULL
524 );
525
526 gBS->CloseProtocol (
527 Controller,
528 &gEfiPciIoProtocolGuid,
529 This->DriverBindingHandle,
530 Private->Handle
531 );
532
533 FreePool (Private->ModeData);
534 gBS->UninstallProtocolInterface (Private->Handle,
535 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
536 FreePool (Private->GopDevicePath);
537
538 //
539 // Free our instance data
540 //
541 gBS->FreePool (Private);
542
543 return EFI_SUCCESS;
544 }
545
546 /**
547 TODO: Add function description
548
549 @param Private TODO: add argument description
550 @param Address TODO: add argument description
551 @param Data TODO: add argument description
552
553 TODO: add return values
554
555 **/
556 VOID
557 outb (
558 QEMU_VIDEO_PRIVATE_DATA *Private,
559 UINTN Address,
560 UINT8 Data
561 )
562 {
563 Private->PciIo->Io.Write (
564 Private->PciIo,
565 EfiPciIoWidthUint8,
566 EFI_PCI_IO_PASS_THROUGH_BAR,
567 Address,
568 1,
569 &Data
570 );
571 }
572
573 /**
574 TODO: Add function description
575
576 @param Private TODO: add argument description
577 @param Address TODO: add argument description
578 @param Data TODO: add argument description
579
580 TODO: add return values
581
582 **/
583 VOID
584 outw (
585 QEMU_VIDEO_PRIVATE_DATA *Private,
586 UINTN Address,
587 UINT16 Data
588 )
589 {
590 Private->PciIo->Io.Write (
591 Private->PciIo,
592 EfiPciIoWidthUint16,
593 EFI_PCI_IO_PASS_THROUGH_BAR,
594 Address,
595 1,
596 &Data
597 );
598 }
599
600 /**
601 TODO: Add function description
602
603 @param Private TODO: add argument description
604 @param Address TODO: add argument description
605
606 TODO: add return values
607
608 **/
609 UINT8
610 inb (
611 QEMU_VIDEO_PRIVATE_DATA *Private,
612 UINTN Address
613 )
614 {
615 UINT8 Data;
616
617 Private->PciIo->Io.Read (
618 Private->PciIo,
619 EfiPciIoWidthUint8,
620 EFI_PCI_IO_PASS_THROUGH_BAR,
621 Address,
622 1,
623 &Data
624 );
625 return Data;
626 }
627
628 /**
629 TODO: Add function description
630
631 @param Private TODO: add argument description
632 @param Address TODO: add argument description
633
634 TODO: add return values
635
636 **/
637 UINT16
638 inw (
639 QEMU_VIDEO_PRIVATE_DATA *Private,
640 UINTN Address
641 )
642 {
643 UINT16 Data;
644
645 Private->PciIo->Io.Read (
646 Private->PciIo,
647 EfiPciIoWidthUint16,
648 EFI_PCI_IO_PASS_THROUGH_BAR,
649 Address,
650 1,
651 &Data
652 );
653 return Data;
654 }
655
656 /**
657 TODO: Add function description
658
659 @param Private TODO: add argument description
660 @param Index TODO: add argument description
661 @param Red TODO: add argument description
662 @param Green TODO: add argument description
663 @param Blue TODO: add argument description
664
665 TODO: add return values
666
667 **/
668 VOID
669 SetPaletteColor (
670 QEMU_VIDEO_PRIVATE_DATA *Private,
671 UINTN Index,
672 UINT8 Red,
673 UINT8 Green,
674 UINT8 Blue
675 )
676 {
677 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
678 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
679 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
680 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
681 }
682
683 /**
684 TODO: Add function description
685
686 @param Private TODO: add argument description
687
688 TODO: add return values
689
690 **/
691 VOID
692 SetDefaultPalette (
693 QEMU_VIDEO_PRIVATE_DATA *Private
694 )
695 {
696 UINTN Index;
697 UINTN RedIndex;
698 UINTN GreenIndex;
699 UINTN BlueIndex;
700
701 Index = 0;
702 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
703 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
704 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
705 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
706 Index++;
707 }
708 }
709 }
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 ClearScreen (
722 QEMU_VIDEO_PRIVATE_DATA *Private
723 )
724 {
725 UINT32 Color;
726
727 Color = 0;
728 Private->PciIo->Mem.Write (
729 Private->PciIo,
730 EfiPciIoWidthFillUint32,
731 0,
732 0,
733 0x400000 >> 2,
734 &Color
735 );
736 }
737
738 /**
739 TODO: Add function description
740
741 @param Private TODO: add argument description
742
743 TODO: add return values
744
745 **/
746 VOID
747 DrawLogo (
748 QEMU_VIDEO_PRIVATE_DATA *Private,
749 UINTN ScreenWidth,
750 UINTN ScreenHeight
751 )
752 {
753 }
754
755 /**
756 TODO: Add function description
757
758 @param Private TODO: add argument description
759 @param ModeData TODO: add argument description
760
761 TODO: add return values
762
763 **/
764 VOID
765 InitializeCirrusGraphicsMode (
766 QEMU_VIDEO_PRIVATE_DATA *Private,
767 QEMU_VIDEO_CIRRUS_MODES *ModeData
768 )
769 {
770 UINT8 Byte;
771 UINTN Index;
772
773 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
774 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
775
776 for (Index = 0; Index < 15; Index++) {
777 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
778 }
779
780 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
781 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
782 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
783 outb (Private, SEQ_DATA_REGISTER, Byte);
784 }
785
786 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
787 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
788 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
789 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
790
791 for (Index = 0; Index < 28; Index++) {
792 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
793 }
794
795 for (Index = 0; Index < 9; Index++) {
796 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
797 }
798
799 inb (Private, INPUT_STATUS_1_REGISTER);
800
801 for (Index = 0; Index < 21; Index++) {
802 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
803 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
804 }
805
806 outb (Private, ATT_ADDRESS_REGISTER, 0x20);
807
808 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
809 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
810 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
811 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
812
813 SetDefaultPalette (Private);
814 ClearScreen (Private);
815 }
816
817 VOID
818 BochsWrite (
819 QEMU_VIDEO_PRIVATE_DATA *Private,
820 UINT16 Reg,
821 UINT16 Data
822 )
823 {
824 EFI_STATUS Status;
825
826 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
827 Status = Private->PciIo->Mem.Write (
828 Private->PciIo,
829 EfiPciIoWidthUint16,
830 PCI_BAR_IDX2,
831 0x500 + (Reg << 1),
832 1,
833 &Data
834 );
835 ASSERT_EFI_ERROR (Status);
836 } else {
837 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
838 outw (Private, VBE_DISPI_IOPORT_DATA, Data);
839 }
840 }
841
842 UINT16
843 BochsRead (
844 QEMU_VIDEO_PRIVATE_DATA *Private,
845 UINT16 Reg
846 )
847 {
848 EFI_STATUS Status;
849 UINT16 Data;
850
851 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
852 Status = Private->PciIo->Mem.Read (
853 Private->PciIo,
854 EfiPciIoWidthUint16,
855 PCI_BAR_IDX2,
856 0x500 + (Reg << 1),
857 1,
858 &Data
859 );
860 ASSERT_EFI_ERROR (Status);
861 } else {
862 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
863 Data = inw (Private, VBE_DISPI_IOPORT_DATA);
864 }
865 return Data;
866 }
867
868 VOID
869 VgaOutb (
870 QEMU_VIDEO_PRIVATE_DATA *Private,
871 UINTN Reg,
872 UINT8 Data
873 )
874 {
875 EFI_STATUS Status;
876
877 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
878 Status = Private->PciIo->Mem.Write (
879 Private->PciIo,
880 EfiPciIoWidthUint8,
881 PCI_BAR_IDX2,
882 0x400 - 0x3c0 + Reg,
883 1,
884 &Data
885 );
886 ASSERT_EFI_ERROR (Status);
887 } else {
888 outb (Private, Reg, Data);
889 }
890 }
891
892 VOID
893 InitializeBochsGraphicsMode (
894 QEMU_VIDEO_PRIVATE_DATA *Private,
895 QEMU_VIDEO_BOCHS_MODES *ModeData
896 )
897 {
898 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
899 ModeData->Width, ModeData->Height, ModeData->ColorDepth));
900
901 /* unblank */
902 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
903
904 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
905 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
906 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
907 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
908
909 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);
910 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);
911 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);
912 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);
913 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
914
915 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
916 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
917
918 SetDefaultPalette (Private);
919 ClearScreen (Private);
920 }
921
922 EFI_STATUS
923 EFIAPI
924 InitializeQemuVideo (
925 IN EFI_HANDLE ImageHandle,
926 IN EFI_SYSTEM_TABLE *SystemTable
927 )
928 {
929 EFI_STATUS Status;
930
931 Status = EfiLibInstallDriverBindingComponentName2 (
932 ImageHandle,
933 SystemTable,
934 &gQemuVideoDriverBinding,
935 ImageHandle,
936 &gQemuVideoComponentName,
937 &gQemuVideoComponentName2
938 );
939 ASSERT_EFI_ERROR (Status);
940
941 //
942 // Install EFI Driver Supported EFI Version Protocol required for
943 // EFI drivers that are on PCI and other plug in cards.
944 //
945 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
946 Status = gBS->InstallMultipleProtocolInterfaces (
947 &ImageHandle,
948 &gEfiDriverSupportedEfiVersionProtocolGuid,
949 &gQemuVideoDriverSupportedEfiVersion,
950 NULL
951 );
952 ASSERT_EFI_ERROR (Status);
953
954 return Status;
955 }