2 Cirrus Logic 5430 Controller Driver.
3 This driver is a sample implementation of the UGA Draw and Graphics Output
4 Protocols for the Cirrus Logic 5430 family of PCI video controllers.
5 This driver is only usable in the EFI pre-boot environment.
6 This sample is intended to show how the UGA Draw and Graphics output Protocol
8 The UGA I/O Protocol is not implemented in this sample.
9 A fully compliant EFI UGA driver requires both
10 the UGA Draw and the UGA I/O Protocol. Please refer to Microsoft's
11 documentation on UGA for details on how to write a UGA driver that is able
12 to function both in the EFI pre-boot environment and from the OS runtime.
14 Copyright (c) 2006, Intel Corporation
15 All rights reserved. This program and the accompanying materials
16 are licensed and made available under the terms and conditions of the BSD License
17 which accompanies this distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 // Cirrus Logic 5430 Controller Driver
28 #include "CirrusLogic5430.h"
30 EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding
= {
31 CirrusLogic5430ControllerDriverSupported
,
32 CirrusLogic5430ControllerDriverStart
,
33 CirrusLogic5430ControllerDriverStop
,
40 /// Generic Attribute Controller Register Settings
42 UINT8 AttributeController
[21] = {
43 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
44 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
45 0x41, 0x00, 0x0F, 0x00, 0x00
49 /// Generic Graphics Controller Register Settings
51 UINT8 GraphicsController
[9] = {
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
56 // 640 x 480 x 256 color @ 60 Hertz
58 UINT8 Crtc_640_480_256_60
[28] = {
59 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
60 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
62 0xff, 0x00, 0x00, 0x22
65 UINT16 Seq_640_480_256_60
[15] = {
66 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
67 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
71 // 800 x 600 x 256 color @ 60 Hertz
73 UINT8 Crtc_800_600_256_60
[28] = {
74 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
75 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
77 0xFF, 0x00, 0x00, 0x22
80 UINT16 Seq_800_600_256_60
[15] = {
81 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
82 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
86 // 1024 x 768 x 256 color @ 60 Hertz
88 UINT8 Crtc_1024_768_256_60
[28] = {
89 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
90 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
92 0xFF, 0x4A, 0x00, 0x22
95 UINT16 Seq_1024_768_256_60
[15] = {
96 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
97 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
101 /// Table of supported video modes
103 CIRRUS_LOGIC_5430_VIDEO_MODES CirrusLogic5430VideoModes
[] = {
104 { 640, 480, 8, 60, Crtc_640_480_256_60
, Seq_640_480_256_60
, 0xe3 },
105 { 800, 600, 8, 60, Crtc_800_600_256_60
, Seq_800_600_256_60
, 0xef },
106 { 1024, 768, 8, 60, Crtc_1024_768_256_60
, Seq_1024_768_256_60
, 0xef }
111 CirrusLogic5430ControllerDriverSupported
113 TODO: This - add argument and description to function comment
114 TODO: Controller - add argument and description to function comment
115 TODO: RemainingDevicePath - add argument and description to function comment
119 CirrusLogic5430ControllerDriverSupported (
120 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
121 IN EFI_HANDLE Controller
,
122 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
126 EFI_PCI_IO_PROTOCOL
*PciIo
;
130 // Open the PCI I/O Protocol
132 Status
= gBS
->OpenProtocol (
134 &gEfiPciIoProtocolGuid
,
136 This
->DriverBindingHandle
,
138 EFI_OPEN_PROTOCOL_BY_DRIVER
140 if (EFI_ERROR (Status
)) {
145 // Read the PCI Configuration Header from the PCI Device
147 Status
= PciIo
->Pci
.Read (
151 sizeof (Pci
) / sizeof (UINT32
),
154 if (EFI_ERROR (Status
)) {
158 Status
= EFI_UNSUPPORTED
;
160 // See if the I/O enable is on. Most systems only allow one VGA device to be turned on
161 // at a time, so see if this is one that is turned on.
163 // if (((Pci.Hdr.Command & 0x01) == 0x01)) {
165 // See if this is a Cirrus Logic PCI controller
167 if (Pci
.Hdr
.VendorId
== CIRRUS_LOGIC_VENDOR_ID
) {
169 // See if this is a 5430 or a 5446 PCI controller
171 if (Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5430_DEVICE_ID
) {
172 Status
= EFI_SUCCESS
;
175 if (Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID
) {
176 Status
= EFI_SUCCESS
;
179 if (Pci
.Hdr
.DeviceId
== CIRRUS_LOGIC_5446_DEVICE_ID
) {
180 Status
= EFI_SUCCESS
;
186 // Close the PCI I/O Protocol
190 &gEfiPciIoProtocolGuid
,
191 This
->DriverBindingHandle
,
199 CirrusLogic5430ControllerDriverStart
201 TODO: This - add argument and description to function comment
202 TODO: Controller - add argument and description to function comment
203 TODO: RemainingDevicePath - add argument and description to function comment
207 CirrusLogic5430ControllerDriverStart (
208 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
209 IN EFI_HANDLE Controller
,
210 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
214 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
215 BOOLEAN PciAttributesSaved
;
216 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
217 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
219 PciAttributesSaved
= FALSE
;
221 // Allocate Private context data for UGA Draw inteface.
223 Private
= AllocateZeroPool (sizeof (CIRRUS_LOGIC_5430_PRIVATE_DATA
));
224 if (Private
== NULL
) {
225 Status
= EFI_OUT_OF_RESOURCES
;
230 // Set up context record
232 Private
->Signature
= CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE
;
233 Private
->Handle
= NULL
;
236 // Open PCI I/O Protocol
238 Status
= gBS
->OpenProtocol (
240 &gEfiPciIoProtocolGuid
,
241 (VOID
**) &Private
->PciIo
,
242 This
->DriverBindingHandle
,
244 EFI_OPEN_PROTOCOL_BY_DRIVER
246 if (EFI_ERROR (Status
)) {
251 // Save original PCI attributes
253 Status
= Private
->PciIo
->Attributes (
255 EfiPciIoAttributeOperationGet
,
257 &Private
->OriginalPciAttributes
260 if (EFI_ERROR (Status
)) {
263 PciAttributesSaved
= TRUE
;
265 Status
= Private
->PciIo
->Attributes (
267 EfiPciIoAttributeOperationEnable
,
268 EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
| EFI_PCI_IO_ATTRIBUTE_VGA_IO
,
271 if (EFI_ERROR (Status
)) {
276 // Get ParentDevicePath
278 Status
= gBS
->HandleProtocol (
280 &gEfiDevicePathProtocolGuid
,
281 (VOID
**) &ParentDevicePath
283 if (EFI_ERROR (Status
)) {
287 if (FeaturePcdGet (PcdSupportGop
)) {
289 // Set Gop Device Path
291 if (RemainingDevicePath
== NULL
) {
292 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
293 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
294 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
295 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
296 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
298 Private
->GopDevicePath
= AppendDevicePathNode (
300 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
303 Private
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
307 // Creat child handle and device path protocol firstly
309 Private
->Handle
= NULL
;
310 Status
= gBS
->InstallMultipleProtocolInterfaces (
312 &gEfiDevicePathProtocolGuid
,
313 Private
->GopDevicePath
,
319 // Construct video mode buffer
321 Status
= CirrusLogic5430VideoModeSetup (Private
);
322 if (EFI_ERROR (Status
)) {
326 if (FeaturePcdGet (PcdSupportUga
)) {
328 // Start the UGA Draw software stack.
330 Status
= CirrusLogic5430UgaDrawConstructor (Private
);
331 ASSERT_EFI_ERROR (Status
);
333 Private
->UgaDevicePath
= ParentDevicePath
;
334 Status
= gBS
->InstallMultipleProtocolInterfaces (
336 &gEfiUgaDrawProtocolGuid
,
338 &gEfiDevicePathProtocolGuid
,
339 Private
->UgaDevicePath
,
343 } else if (FeaturePcdGet (PcdSupportGop
)) {
345 // Start the GOP software stack.
347 Status
= CirrusLogic5430GraphicsOutputConstructor (Private
);
348 ASSERT_EFI_ERROR (Status
);
350 Status
= gBS
->InstallMultipleProtocolInterfaces (
352 &gEfiGraphicsOutputProtocolGuid
,
353 &Private
->GraphicsOutput
,
354 &gEfiEdidDiscoveredProtocolGuid
,
355 &Private
->EdidDiscovered
,
356 &gEfiEdidActiveProtocolGuid
,
357 &Private
->EdidActive
,
363 // This driver must support eithor GOP or UGA or both.
366 Status
= EFI_UNSUPPORTED
;
371 if (EFI_ERROR (Status
)) {
373 if (Private
->PciIo
) {
374 if (PciAttributesSaved
== TRUE
) {
376 // Restore original PCI attributes
378 Private
->PciIo
->Attributes (
380 EfiPciIoAttributeOperationSet
,
381 Private
->OriginalPciAttributes
,
386 // Close the PCI I/O Protocol
390 &gEfiPciIoProtocolGuid
,
391 This
->DriverBindingHandle
,
396 gBS
->FreePool (Private
);
404 CirrusLogic5430ControllerDriverStop
406 TODO: This - add argument and description to function comment
407 TODO: Controller - add argument and description to function comment
408 TODO: NumberOfChildren - add argument and description to function comment
409 TODO: ChildHandleBuffer - add argument and description to function comment
410 TODO: EFI_SUCCESS - add return value to function comment
414 CirrusLogic5430ControllerDriverStop (
415 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
416 IN EFI_HANDLE Controller
,
417 IN UINTN NumberOfChildren
,
418 IN EFI_HANDLE
*ChildHandleBuffer
421 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
422 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
425 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
427 if (FeaturePcdGet (PcdSupportUga
)) {
428 Status
= gBS
->OpenProtocol (
430 &gEfiUgaDrawProtocolGuid
,
432 This
->DriverBindingHandle
,
434 EFI_OPEN_PROTOCOL_GET_PROTOCOL
436 if (EFI_ERROR (Status
)) {
440 // Get our private context information
442 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw
);
443 CirrusLogic5430UgaDrawDestructor (Private
);
445 if (FeaturePcdGet (PcdSupportGop
)) {
446 CirrusLogic5430GraphicsOutputDestructor (Private
);
448 // Remove the UGA and GOP protocol interface from the system
450 Status
= gBS
->UninstallMultipleProtocolInterfaces (
452 &gEfiUgaDrawProtocolGuid
,
454 &gEfiGraphicsOutputProtocolGuid
,
455 &Private
->GraphicsOutput
,
460 // Remove the UGA Draw interface from the system
462 Status
= gBS
->UninstallMultipleProtocolInterfaces (
464 &gEfiUgaDrawProtocolGuid
,
470 Status
= gBS
->OpenProtocol (
472 &gEfiGraphicsOutputProtocolGuid
,
473 (VOID
**) &GraphicsOutput
,
474 This
->DriverBindingHandle
,
476 EFI_OPEN_PROTOCOL_GET_PROTOCOL
478 if (EFI_ERROR (Status
)) {
483 // Get our private context information
485 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
487 CirrusLogic5430GraphicsOutputDestructor (Private
);
489 // Remove the GOP protocol interface from the system
491 Status
= gBS
->UninstallMultipleProtocolInterfaces (
493 &gEfiUgaDrawProtocolGuid
,
495 &gEfiGraphicsOutputProtocolGuid
,
496 &Private
->GraphicsOutput
,
501 if (EFI_ERROR (Status
)) {
506 // Restore original PCI attributes
508 Private
->PciIo
->Attributes (
510 EfiPciIoAttributeOperationSet
,
511 Private
->OriginalPciAttributes
,
516 // Close the PCI I/O Protocol
520 &gEfiPciIoProtocolGuid
,
521 This
->DriverBindingHandle
,
526 // Free our instance data
528 gBS
->FreePool (Private
);
534 CirrusLogic5430UgaDrawDestructor
536 TODO: Private - add argument and description to function comment
537 TODO: EFI_SUCCESS - add return value to function comment
540 CirrusLogic5430UgaDrawDestructor (
541 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
548 TODO: Add function description
550 @param Private TODO: add argument description
551 @param Address TODO: add argument description
552 @param Data TODO: add argument description
554 TODO: add return values
559 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
564 Private
->PciIo
->Io
.Write (
567 EFI_PCI_IO_PASS_THROUGH_BAR
,
575 TODO: Add function description
577 @param Private TODO: add argument description
578 @param Address TODO: add argument description
579 @param Data TODO: add argument description
581 TODO: add return values
586 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
591 Private
->PciIo
->Io
.Write (
594 EFI_PCI_IO_PASS_THROUGH_BAR
,
602 TODO: Add function description
604 @param Private TODO: add argument description
605 @param Address TODO: add argument description
607 TODO: add return values
612 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
618 Private
->PciIo
->Io
.Read (
621 EFI_PCI_IO_PASS_THROUGH_BAR
,
630 TODO: Add function description
632 @param Private TODO: add argument description
633 @param Address TODO: add argument description
635 TODO: add return values
640 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
646 Private
->PciIo
->Io
.Read (
649 EFI_PCI_IO_PASS_THROUGH_BAR
,
658 TODO: Add function description
660 @param Private TODO: add argument description
661 @param Index TODO: add argument description
662 @param Red TODO: add argument description
663 @param Green TODO: add argument description
664 @param Blue TODO: add argument description
666 TODO: add return values
671 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
678 outb (Private
, PALETTE_INDEX_REGISTER
, (UINT8
) Index
);
679 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Red
>> 2));
680 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Green
>> 2));
681 outb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Blue
>> 2));
685 TODO: Add function description
687 @param Private TODO: add argument description
689 TODO: add return values
694 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
703 for (RedIndex
= 0; RedIndex
< 8; RedIndex
++) {
704 for (GreenIndex
= 0; GreenIndex
< 8; GreenIndex
++) {
705 for (BlueIndex
= 0; BlueIndex
< 4; BlueIndex
++) {
706 SetPaletteColor (Private
, Index
, (UINT8
) (RedIndex
<< 5), (UINT8
) (GreenIndex
<< 5), (UINT8
) (BlueIndex
<< 6));
714 TODO: Add function description
716 @param Private TODO: add argument description
718 TODO: add return values
723 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
729 Private
->PciIo
->Mem
.Write (
731 EfiPciIoWidthFillUint32
,
740 TODO: Add function description
742 @param Private TODO: add argument description
744 TODO: add return values
749 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
757 TODO: Add function description
759 @param Private TODO: add argument description
760 @param ModeData TODO: add argument description
762 TODO: add return values
766 InitializeGraphicsMode (
767 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
768 CIRRUS_LOGIC_5430_VIDEO_MODES
*ModeData
776 Status
= Private
->PciIo
->Pci
.Read (
779 PCI_DEVICE_ID_OFFSET
,
784 // Read the PCI Configuration Header from the PCI Device
786 ASSERT_EFI_ERROR (Status
);
788 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x1206);
789 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0012);
791 for (Index
= 0; Index
< 15; Index
++) {
792 outw (Private
, SEQ_ADDRESS_REGISTER
, ModeData
->SeqSettings
[Index
]);
795 if (DeviceId
!= CIRRUS_LOGIC_5446_DEVICE_ID
) {
796 outb (Private
, SEQ_ADDRESS_REGISTER
, 0x0f);
797 Byte
= (UINT8
) ((inb (Private
, SEQ_DATA_REGISTER
) & 0xc7) ^ 0x30);
798 outb (Private
, SEQ_DATA_REGISTER
, Byte
);
801 outb (Private
, MISC_OUTPUT_REGISTER
, ModeData
->MiscSetting
);
802 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0506);
803 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0300);
804 outw (Private
, CRTC_ADDRESS_REGISTER
, 0x2011);
806 for (Index
= 0; Index
< 28; Index
++) {
807 outw (Private
, CRTC_ADDRESS_REGISTER
, (UINT16
) ((ModeData
->CrtcSettings
[Index
] << 8) | Index
));
810 for (Index
= 0; Index
< 9; Index
++) {
811 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((GraphicsController
[Index
] << 8) | Index
));
814 inb (Private
, INPUT_STATUS_1_REGISTER
);
816 for (Index
= 0; Index
< 21; Index
++) {
817 outb (Private
, ATT_ADDRESS_REGISTER
, (UINT8
) Index
);
818 outb (Private
, ATT_ADDRESS_REGISTER
, AttributeController
[Index
]);
821 outb (Private
, ATT_ADDRESS_REGISTER
, 0x20);
823 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0009);
824 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000a);
825 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000b);
826 outb (Private
, DAC_PIXEL_MASK_REGISTER
, 0xff);
828 SetDefaultPalette (Private
);
829 ClearScreen (Private
);
834 InitializeCirrusLogic5430 (
835 IN EFI_HANDLE ImageHandle
,
836 IN EFI_SYSTEM_TABLE
*SystemTable
841 Status
= EfiLibInstallDriverBindingComponentName2 (
844 &gCirrusLogic5430DriverBinding
,
846 &gCirrusLogic5430ComponentName
,
847 &gCirrusLogic5430ComponentName2
849 ASSERT_EFI_ERROR (Status
);
852 // Install EFI Driver Supported EFI Version Protocol required for
853 // EFI drivers that are on PCI and other plug in cards.
855 gCirrusLogic5430DriverSupportedEfiVersion
.FirmwareVersion
= PcdGet32 (PcdDriverSupportedEfiVersion
);
856 Status
= gBS
->InstallMultipleProtocolInterfaces (
858 &gEfiDriverSupportedEfiVersionProtocolGuid
,
859 &gCirrusLogic5430DriverSupportedEfiVersion
,
862 ASSERT_EFI_ERROR (Status
);