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
724 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
730 Private
->PciIo
->Mem
.Write (
732 EfiPciIoWidthFillUint32
,
741 TODO: Add function description
743 @param Private TODO: add argument description
745 TODO: add return values
750 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
761 for (Y
= 0; Y
< ScreenHeight
; Y
++) {
762 for (X
= 0; X
< ScreenWidth
; X
++) {
763 Color
= (UINT8
) (256 * (X
+ Y
) / (ScreenWidth
+ ScreenHeight
));
764 Private
->LineBuffer
[X
] = Color
;
767 Private
->PciIo
->Mem
.Write (
771 Offset
+ (Y
* ScreenWidth
),
779 TODO: Add function description
781 @param Private TODO: add argument description
782 @param ModeData TODO: add argument description
784 TODO: add return values
788 InitializeGraphicsMode (
789 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
790 CIRRUS_LOGIC_5430_VIDEO_MODES
*ModeData
796 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x1206);
797 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0012);
799 for (Index
= 0; Index
< 15; Index
++) {
800 outw (Private
, SEQ_ADDRESS_REGISTER
, ModeData
->SeqSettings
[Index
]);
803 outb (Private
, SEQ_ADDRESS_REGISTER
, 0x0f);
804 Byte
= (UINT8
) ((inb (Private
, SEQ_DATA_REGISTER
) & 0xc7) ^ 0x30);
805 outb (Private
, SEQ_DATA_REGISTER
, Byte
);
807 outb (Private
, MISC_OUTPUT_REGISTER
, ModeData
->MiscSetting
);
808 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0506);
809 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0300);
810 outw (Private
, CRTC_ADDRESS_REGISTER
, 0x2011);
812 for (Index
= 0; Index
< 28; Index
++) {
813 outw (Private
, CRTC_ADDRESS_REGISTER
, (UINT16
) ((ModeData
->CrtcSettings
[Index
] << 8) | Index
));
816 for (Index
= 0; Index
< 9; Index
++) {
817 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((GraphicsController
[Index
] << 8) | Index
));
820 inb (Private
, INPUT_STATUS_1_REGISTER
);
822 for (Index
= 0; Index
< 21; Index
++) {
823 outb (Private
, ATT_ADDRESS_REGISTER
, (UINT8
) Index
);
824 outb (Private
, ATT_ADDRESS_REGISTER
, AttributeController
[Index
]);
827 outb (Private
, ATT_ADDRESS_REGISTER
, 0x20);
829 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0009);
830 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000a);
831 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000b);
832 outb (Private
, DAC_PIXEL_MASK_REGISTER
, 0xff);
834 SetDefaultPalette (Private
);
835 ClearScreen (Private
);
840 InitializeCirrusLogic5430 (
841 IN EFI_HANDLE ImageHandle
,
842 IN EFI_SYSTEM_TABLE
*SystemTable
847 Status
= EfiLibInstallDriverBindingComponentName2 (
850 &gCirrusLogic5430DriverBinding
,
852 &gCirrusLogic5430ComponentName
,
853 &gCirrusLogic5430ComponentName2
855 ASSERT_EFI_ERROR (Status
);
858 // Install EFI Driver Supported EFI Version Protocol required for
859 // EFI drivers that are on PCI and other plug in cards.
861 gCirrusLogic5430DriverSupportedEfiVersion
.FirmwareVersion
= PcdGet32 (PcdDriverSupportedEfiVersion
);
862 Status
= gBS
->InstallMultipleProtocolInterfaces (
864 &gEfiDriverSupportedEfiVersionProtocolGuid
,
865 &gCirrusLogic5430DriverSupportedEfiVersion
,
868 ASSERT_EFI_ERROR (Status
);