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