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