2 This driver is a sample implementation of the Graphics Output Protocol for
3 the QEMU (Cirrus Logic 5446) video controller.
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
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
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.
19 EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding
= {
20 QemuVideoControllerDriverSupported
,
21 QemuVideoControllerDriverStart
,
22 QemuVideoControllerDriverStop
,
29 Check if this device is supported.
31 @param This The driver binding protocol.
32 @param Controller The controller handle to check.
33 @param RemainingDevicePath The remaining device path.
35 @retval EFI_SUCCESS The bus supports this controller.
36 @retval EFI_UNSUPPORTED This device isn't supported.
41 QemuVideoControllerDriverSupported (
42 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
43 IN EFI_HANDLE Controller
,
44 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
48 EFI_PCI_IO_PROTOCOL
*PciIo
;
53 // Open the PCI I/O Protocol
55 Status
= gBS
->OpenProtocol (
57 &gEfiPciIoProtocolGuid
,
59 This
->DriverBindingHandle
,
61 EFI_OPEN_PROTOCOL_BY_DRIVER
63 if (EFI_ERROR (Status
)) {
68 // Read the PCI Configuration Header from the PCI Device
70 Status
= PciIo
->Pci
.Read (
74 sizeof (Pci
) / sizeof (UINT32
),
77 if (EFI_ERROR (Status
)) {
81 Status
= EFI_UNSUPPORTED
;
83 // See if the I/O enable is on. Most systems only allow one VGA device to be turned on
84 // at a time, so see if this is one that is turned on.
86 // if (((Pci.Hdr.Command & 0x01) == 0x01)) {
88 // See if this is a Cirrus Logic PCI controller
90 if (Pci
.Hdr
.VendorId
== CIRRUS_LOGIC_VENDOR_ID
) {
92 // See if this is a 5430 or a 5446 PCI controller
94 if (Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5430_DEVICE_ID
||
95 Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID
||
96 Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5446_DEVICE_ID
) {
100 // If this is an Intel 945 graphics controller,
101 // go further check RemainingDevicePath validation
103 if (RemainingDevicePath
!= NULL
) {
104 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
106 // Check if RemainingDevicePath is the End of Device Path Node,
107 // if yes, return EFI_SUCCESS
109 if (!IsDevicePathEnd (Node
)) {
111 // If RemainingDevicePath isn't the End of Device Path Node,
112 // check its validation
114 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
115 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
116 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ACPI_ADR_DEVICE_PATH
)) {
117 Status
= EFI_UNSUPPORTED
;
126 // Close the PCI I/O Protocol
130 &gEfiPciIoProtocolGuid
,
131 This
->DriverBindingHandle
,
139 Start to process the controller.
141 @param This The USB bus driver binding instance.
142 @param Controller The controller to check.
143 @param RemainingDevicePath The remaining device patch.
145 @retval EFI_SUCCESS The controller is controlled by the usb bus.
146 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
148 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
153 QemuVideoControllerDriverStart (
154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
155 IN EFI_HANDLE Controller
,
156 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
160 QEMU_VIDEO_PRIVATE_DATA
*Private
;
161 BOOLEAN PciAttributesSaved
;
162 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
163 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
165 PciAttributesSaved
= FALSE
;
167 // Allocate Private context data for GOP inteface.
169 Private
= AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA
));
170 if (Private
== NULL
) {
171 Status
= EFI_OUT_OF_RESOURCES
;
176 // Set up context record
178 Private
->Signature
= QEMU_VIDEO_PRIVATE_DATA_SIGNATURE
;
179 Private
->Handle
= NULL
;
182 // Open PCI I/O Protocol
184 Status
= gBS
->OpenProtocol (
186 &gEfiPciIoProtocolGuid
,
187 (VOID
**) &Private
->PciIo
,
188 This
->DriverBindingHandle
,
190 EFI_OPEN_PROTOCOL_BY_DRIVER
192 if (EFI_ERROR (Status
)) {
197 // Save original PCI attributes
199 Status
= Private
->PciIo
->Attributes (
201 EfiPciIoAttributeOperationGet
,
203 &Private
->OriginalPciAttributes
206 if (EFI_ERROR (Status
)) {
209 PciAttributesSaved
= TRUE
;
211 Status
= Private
->PciIo
->Attributes (
213 EfiPciIoAttributeOperationEnable
,
214 EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
| EFI_PCI_IO_ATTRIBUTE_VGA_IO
,
217 if (EFI_ERROR (Status
)) {
222 // Get ParentDevicePath
224 Status
= gBS
->HandleProtocol (
226 &gEfiDevicePathProtocolGuid
,
227 (VOID
**) &ParentDevicePath
229 if (EFI_ERROR (Status
)) {
234 // Set Gop Device Path
236 if (RemainingDevicePath
== NULL
) {
237 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
238 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
239 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
240 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
241 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
243 Private
->GopDevicePath
= AppendDevicePathNode (
245 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
247 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
249 // If RemainingDevicePath isn't the End of Device Path Node,
250 // only scan the specified device by RemainingDevicePath
252 Private
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
255 // If RemainingDevicePath is the End of Device Path Node,
256 // don't create child device and return EFI_SUCCESS
258 Private
->GopDevicePath
= NULL
;
261 if (Private
->GopDevicePath
!= NULL
) {
263 // Creat child handle and device path protocol firstly
265 Private
->Handle
= NULL
;
266 Status
= gBS
->InstallMultipleProtocolInterfaces (
268 &gEfiDevicePathProtocolGuid
,
269 Private
->GopDevicePath
,
275 // Construct video mode buffer
277 Status
= QemuVideoVideoModeSetup (Private
);
278 if (EFI_ERROR (Status
)) {
282 if (Private
->GopDevicePath
== NULL
) {
284 // If RemainingDevicePath is the End of Device Path Node,
285 // don't create child device and return EFI_SUCCESS
287 Status
= EFI_SUCCESS
;
291 // Start the GOP software stack.
293 Status
= QemuVideoGraphicsOutputConstructor (Private
);
294 ASSERT_EFI_ERROR (Status
);
296 Status
= gBS
->InstallMultipleProtocolInterfaces (
298 &gEfiGraphicsOutputProtocolGuid
,
299 &Private
->GraphicsOutput
,
305 if (EFI_ERROR (Status
)) {
307 if (Private
->PciIo
) {
308 if (PciAttributesSaved
== TRUE
) {
310 // Restore original PCI attributes
312 Private
->PciIo
->Attributes (
314 EfiPciIoAttributeOperationSet
,
315 Private
->OriginalPciAttributes
,
320 // Close the PCI I/O Protocol
324 &gEfiPciIoProtocolGuid
,
325 This
->DriverBindingHandle
,
330 gBS
->FreePool (Private
);
340 @param This The USB bus driver binding protocol.
341 @param Controller The controller to release.
342 @param NumberOfChildren The number of children of this device that
343 opened the controller BY_CHILD.
344 @param ChildHandleBuffer The array of child handle.
346 @retval EFI_SUCCESS The controller or children are stopped.
347 @retval EFI_DEVICE_ERROR Failed to stop the driver.
352 QemuVideoControllerDriverStop (
353 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
354 IN EFI_HANDLE Controller
,
355 IN UINTN NumberOfChildren
,
356 IN EFI_HANDLE
*ChildHandleBuffer
359 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
362 QEMU_VIDEO_PRIVATE_DATA
*Private
;
364 Status
= gBS
->OpenProtocol (
366 &gEfiGraphicsOutputProtocolGuid
,
367 (VOID
**) &GraphicsOutput
,
368 This
->DriverBindingHandle
,
370 EFI_OPEN_PROTOCOL_GET_PROTOCOL
372 if (EFI_ERROR (Status
)) {
377 // Get our private context information
379 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
381 QemuVideoGraphicsOutputDestructor (Private
);
383 // Remove the GOP protocol interface from the system
385 Status
= gBS
->UninstallMultipleProtocolInterfaces (
387 &gEfiGraphicsOutputProtocolGuid
,
388 &Private
->GraphicsOutput
,
392 if (EFI_ERROR (Status
)) {
397 // Restore original PCI attributes
399 Private
->PciIo
->Attributes (
401 EfiPciIoAttributeOperationSet
,
402 Private
->OriginalPciAttributes
,
407 // Close the PCI I/O Protocol
411 &gEfiPciIoProtocolGuid
,
412 This
->DriverBindingHandle
,
417 // Free our instance data
419 gBS
->FreePool (Private
);
425 TODO: Add function description
427 @param Private TODO: add argument description
428 @param Address TODO: add argument description
429 @param Data TODO: add argument description
431 TODO: add return values
436 QEMU_VIDEO_PRIVATE_DATA
*Private
,
441 Private
->PciIo
->Io
.Write (
444 EFI_PCI_IO_PASS_THROUGH_BAR
,
452 TODO: Add function description
454 @param Private TODO: add argument description
455 @param Address TODO: add argument description
456 @param Data TODO: add argument description
458 TODO: add return values
463 QEMU_VIDEO_PRIVATE_DATA
*Private
,
468 Private
->PciIo
->Io
.Write (
471 EFI_PCI_IO_PASS_THROUGH_BAR
,
479 TODO: Add function description
481 @param Private TODO: add argument description
482 @param Address TODO: add argument description
484 TODO: add return values
489 QEMU_VIDEO_PRIVATE_DATA
*Private
,
495 Private
->PciIo
->Io
.Read (
498 EFI_PCI_IO_PASS_THROUGH_BAR
,
507 TODO: Add function description
509 @param Private TODO: add argument description
510 @param Address TODO: add argument description
512 TODO: add return values
517 QEMU_VIDEO_PRIVATE_DATA
*Private
,
523 Private
->PciIo
->Io
.Read (
526 EFI_PCI_IO_PASS_THROUGH_BAR
,
535 TODO: Add function description
537 @param Private TODO: add argument description
538 @param Index TODO: add argument description
539 @param Red TODO: add argument description
540 @param Green TODO: add argument description
541 @param Blue TODO: add argument description
543 TODO: add return values
548 QEMU_VIDEO_PRIVATE_DATA
*Private
,
555 outb (Private
, PALETTE_INDEX_REGISTER
, (UINT8
) Index
);
556 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Red
>> 2));
557 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Green
>> 2));
558 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Blue
>> 2));
562 TODO: Add function description
564 @param Private TODO: add argument description
566 TODO: add return values
571 QEMU_VIDEO_PRIVATE_DATA
*Private
580 for (RedIndex
= 0; RedIndex
< 8; RedIndex
++) {
581 for (GreenIndex
= 0; GreenIndex
< 8; GreenIndex
++) {
582 for (BlueIndex
= 0; BlueIndex
< 4; BlueIndex
++) {
583 SetPaletteColor (Private
, Index
, (UINT8
) (RedIndex
<< 5), (UINT8
) (GreenIndex
<< 5), (UINT8
) (BlueIndex
<< 6));
591 TODO: Add function description
593 @param Private TODO: add argument description
595 TODO: add return values
600 QEMU_VIDEO_PRIVATE_DATA
*Private
606 Private
->PciIo
->Mem
.Write (
608 EfiPciIoWidthFillUint32
,
617 TODO: Add function description
619 @param Private TODO: add argument description
621 TODO: add return values
626 QEMU_VIDEO_PRIVATE_DATA
*Private
,
634 TODO: Add function description
636 @param Private TODO: add argument description
637 @param ModeData TODO: add argument description
639 TODO: add return values
643 InitializeGraphicsMode (
644 QEMU_VIDEO_PRIVATE_DATA
*Private
,
645 QEMU_VIDEO_VIDEO_MODES
*ModeData
653 Status
= Private
->PciIo
->Pci
.Read (
656 PCI_DEVICE_ID_OFFSET
,
661 // Read the PCI Configuration Header from the PCI Device
663 ASSERT_EFI_ERROR (Status
);
665 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x1206);
666 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0012);
668 for (Index
= 0; Index
< 15; Index
++) {
669 outw (Private
, SEQ_ADDRESS_REGISTER
, ModeData
->SeqSettings
[Index
]);
672 if (DeviceId
!= CIRRUS_LOGIC_5446_DEVICE_ID
) {
673 outb (Private
, SEQ_ADDRESS_REGISTER
, 0x0f);
674 Byte
= (UINT8
) ((inb (Private
, SEQ_DATA_REGISTER
) & 0xc7) ^ 0x30);
675 outb (Private
, SEQ_DATA_REGISTER
, Byte
);
678 outb (Private
, MISC_OUTPUT_REGISTER
, ModeData
->MiscSetting
);
679 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0506);
680 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0300);
681 outw (Private
, CRTC_ADDRESS_REGISTER
, 0x2011);
683 for (Index
= 0; Index
< 28; Index
++) {
684 outw (Private
, CRTC_ADDRESS_REGISTER
, (UINT16
) ((ModeData
->CrtcSettings
[Index
] << 8) | Index
));
687 for (Index
= 0; Index
< 9; Index
++) {
688 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((GraphicsController
[Index
] << 8) | Index
));
691 inb (Private
, INPUT_STATUS_1_REGISTER
);
693 for (Index
= 0; Index
< 21; Index
++) {
694 outb (Private
, ATT_ADDRESS_REGISTER
, (UINT8
) Index
);
695 outb (Private
, ATT_ADDRESS_REGISTER
, AttributeController
[Index
]);
698 outb (Private
, ATT_ADDRESS_REGISTER
, 0x20);
700 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0009);
701 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000a);
702 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000b);
703 outb (Private
, DAC_PIXEL_MASK_REGISTER
, 0xff);
705 SetDefaultPalette (Private
);
706 ClearScreen (Private
);
711 InitializeQemuVideo (
712 IN EFI_HANDLE ImageHandle
,
713 IN EFI_SYSTEM_TABLE
*SystemTable
718 Status
= EfiLibInstallDriverBindingComponentName2 (
721 &gQemuVideoDriverBinding
,
723 &gQemuVideoComponentName
,
724 &gQemuVideoComponentName2
726 ASSERT_EFI_ERROR (Status
);
729 // Install EFI Driver Supported EFI Version Protocol required for
730 // EFI drivers that are on PCI and other plug in cards.
732 gQemuVideoDriverSupportedEfiVersion
.FirmwareVersion
= PcdGet32 (PcdDriverSupportedEfiVersion
);
733 Status
= gBS
->InstallMultipleProtocolInterfaces (
735 &gEfiDriverSupportedEfiVersionProtocolGuid
,
736 &gQemuVideoDriverSupportedEfiVersion
,
739 ASSERT_EFI_ERROR (Status
);