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