1 /** @file
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
7   is able to function.
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.
13 
14   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
15   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
19 
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.
22 
23 **/
24 
25 //
26 // Cirrus Logic 5430 Controller Driver
27 //
28 #include "CirrusLogic5430.h"
29 
30 EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding = {
31   CirrusLogic5430ControllerDriverSupported,
32   CirrusLogic5430ControllerDriverStart,
33   CirrusLogic5430ControllerDriverStop,
34   0x10,
35   NULL,
36   NULL
37 };
38 
39 ///
40 /// Generic Attribute Controller Register Settings
41 ///
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
46 };
47 
48 ///
49 /// Generic Graphics Controller Register Settings
50 ///
51 UINT8 GraphicsController[9] = {
52   0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
53 };
54 
55 //
56 // 640 x 480 x 256 color @ 60 Hertz
57 //
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
63 };
64 
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
68 };
69 
70 //
71 // 800 x 600 x 256 color @ 60 Hertz
72 //
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
78 };
79 
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
83 };
84 
85 //
86 // 1024 x 768 x 256 color @ 60 Hertz
87 //
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
93 };
94 
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
98 };
99 
100 ///
101 /// Table of supported video modes
102 ///
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 }
107 };
108 
109 
110 /**
111   CirrusLogic5430ControllerDriverSupported
112 
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
116 **/
117 EFI_STATUS
118 EFIAPI
CirrusLogic5430ControllerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)119 CirrusLogic5430ControllerDriverSupported (
120   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
121   IN EFI_HANDLE                     Controller,
122   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
123   )
124 {
125   EFI_STATUS          Status;
126   EFI_PCI_IO_PROTOCOL *PciIo;
127   PCI_TYPE00          Pci;
128   EFI_DEV_PATH        *Node;
129 
130   //
131   // Open the PCI I/O Protocol
132   //
133   Status = gBS->OpenProtocol (
134                   Controller,
135                   &gEfiPciIoProtocolGuid,
136                   (VOID **) &PciIo,
137                   This->DriverBindingHandle,
138                   Controller,
139                   EFI_OPEN_PROTOCOL_BY_DRIVER
140                   );
141   if (EFI_ERROR (Status)) {
142     return Status;
143   }
144 
145   //
146   // Read the PCI Configuration Header from the PCI Device
147   //
148   Status = PciIo->Pci.Read (
149                         PciIo,
150                         EfiPciIoWidthUint32,
151                         0,
152                         sizeof (Pci) / sizeof (UINT32),
153                         &Pci
154                         );
155   if (EFI_ERROR (Status)) {
156     goto Done;
157   }
158 
159   Status = EFI_UNSUPPORTED;
160   //
161   // See if the I/O enable is on.  Most systems only allow one VGA device to be turned on
162   // at a time, so see if this is one that is turned on.
163   //
164   //  if (((Pci.Hdr.Command & 0x01) == 0x01)) {
165   //
166   // See if this is a Cirrus Logic PCI controller
167   //
168   if (Pci.Hdr.VendorId == CIRRUS_LOGIC_VENDOR_ID) {
169     //
170     // See if this is a 5430 or a 5446 PCI controller
171     //
172     if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_DEVICE_ID ||
173         Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID ||
174         Pci.Hdr.DeviceId == CIRRUS_LOGIC_5446_DEVICE_ID) {
175 
176       Status = EFI_SUCCESS;
177       //
178       // If this is an Intel 945 graphics controller,
179       // go further check RemainingDevicePath validation
180       //
181       if (RemainingDevicePath != NULL) {
182         Node = (EFI_DEV_PATH *) RemainingDevicePath;
183         //
184         // Check if RemainingDevicePath is the End of Device Path Node,
185         // if yes, return EFI_SUCCESS
186         //
187         if (!IsDevicePathEnd (Node)) {
188           //
189           // If RemainingDevicePath isn't the End of Device Path Node,
190           // check its validation
191           //
192           if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
193               Node->DevPath.SubType != ACPI_ADR_DP ||
194               DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {
195             Status = EFI_UNSUPPORTED;
196           }
197         }
198       }
199     }
200   }
201 
202 Done:
203   //
204   // Close the PCI I/O Protocol
205   //
206   gBS->CloseProtocol (
207         Controller,
208         &gEfiPciIoProtocolGuid,
209         This->DriverBindingHandle,
210         Controller
211         );
212 
213   return Status;
214 }
215 
216 /**
217   CirrusLogic5430ControllerDriverStart
218 
219   TODO:    This - add argument and description to function comment
220   TODO:    Controller - add argument and description to function comment
221   TODO:    RemainingDevicePath - add argument and description to function comment
222 **/
223 EFI_STATUS
224 EFIAPI
CirrusLogic5430ControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)225 CirrusLogic5430ControllerDriverStart (
226   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
227   IN EFI_HANDLE                     Controller,
228   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
229   )
230 {
231   EFI_STATUS                      Status;
232   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
233   BOOLEAN                         PciAttributesSaved;
234   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
235   ACPI_ADR_DEVICE_PATH            AcpiDeviceNode;
236   UINT64                          Supports;
237 
238   PciAttributesSaved = FALSE;
239   //
240   // Allocate Private context data for UGA Draw inteface.
241   //
242   Private = AllocateZeroPool (sizeof (CIRRUS_LOGIC_5430_PRIVATE_DATA));
243   if (Private == NULL) {
244     Status = EFI_OUT_OF_RESOURCES;
245     goto Error;
246   }
247 
248   //
249   // Set up context record
250   //
251   Private->Signature  = CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE;
252   Private->Handle     = NULL;
253 
254   //
255   // Open PCI I/O Protocol
256   //
257   Status = gBS->OpenProtocol (
258                   Controller,
259                   &gEfiPciIoProtocolGuid,
260                   (VOID **) &Private->PciIo,
261                   This->DriverBindingHandle,
262                   Controller,
263                   EFI_OPEN_PROTOCOL_BY_DRIVER
264                   );
265   if (EFI_ERROR (Status)) {
266     goto Error;
267   }
268 
269   //
270   // Get supported PCI attributes
271   //
272   Status = Private->PciIo->Attributes (
273                              Private->PciIo,
274                              EfiPciIoAttributeOperationSupported,
275                              0,
276                              &Supports
277                              );
278   if (EFI_ERROR (Status)) {
279     goto Error;
280   }
281 
282   Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
283   if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
284     Status = EFI_UNSUPPORTED;
285     goto Error;
286   }
287 
288   //
289   // Save original PCI attributes
290   //
291   Status = Private->PciIo->Attributes (
292                     Private->PciIo,
293                     EfiPciIoAttributeOperationGet,
294                     0,
295                     &Private->OriginalPciAttributes
296                     );
297 
298   if (EFI_ERROR (Status)) {
299     goto Error;
300   }
301   PciAttributesSaved = TRUE;
302 
303   Status = Private->PciIo->Attributes (
304                              Private->PciIo,
305                              EfiPciIoAttributeOperationEnable,
306                              EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,
307                              NULL
308                              );
309   if (EFI_ERROR (Status)) {
310     goto Error;
311   }
312 
313   //
314   // Get ParentDevicePath
315   //
316   Status = gBS->HandleProtocol (
317                   Controller,
318                   &gEfiDevicePathProtocolGuid,
319                   (VOID **) &ParentDevicePath
320                   );
321   if (EFI_ERROR (Status)) {
322     goto Error;
323   }
324 
325   if (FeaturePcdGet (PcdSupportGop)) {
326     //
327     // Set Gop Device Path
328     //
329     if (RemainingDevicePath == NULL) {
330       ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
331       AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
332       AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
333       AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
334       SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
335 
336       Private->GopDevicePath = AppendDevicePathNode (
337                                           ParentDevicePath,
338                                           (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
339                                           );
340     } else if (!IsDevicePathEnd (RemainingDevicePath)) {
341       //
342       // If RemainingDevicePath isn't the End of Device Path Node,
343       // only scan the specified device by RemainingDevicePath
344       //
345       Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
346     } else {
347       //
348       // If RemainingDevicePath is the End of Device Path Node,
349       // don't create child device and return EFI_SUCCESS
350       //
351       Private->GopDevicePath = NULL;
352     }
353 
354     if (Private->GopDevicePath != NULL) {
355       //
356       // Creat child handle and device path protocol firstly
357       //
358       Private->Handle = NULL;
359       Status = gBS->InstallMultipleProtocolInterfaces (
360                       &Private->Handle,
361                       &gEfiDevicePathProtocolGuid,
362                       Private->GopDevicePath,
363                       NULL
364                       );
365     }
366   }
367 
368   //
369   // Construct video mode buffer
370   //
371   Status = CirrusLogic5430VideoModeSetup (Private);
372   if (EFI_ERROR (Status)) {
373     goto Error;
374   }
375 
376   if (FeaturePcdGet (PcdSupportUga)) {
377     //
378     // Start the UGA Draw software stack.
379     //
380     Status = CirrusLogic5430UgaDrawConstructor (Private);
381     ASSERT_EFI_ERROR (Status);
382 
383     Private->UgaDevicePath = ParentDevicePath;
384     Status = gBS->InstallMultipleProtocolInterfaces (
385                     &Controller,
386                     &gEfiUgaDrawProtocolGuid,
387                     &Private->UgaDraw,
388                     &gEfiDevicePathProtocolGuid,
389                     Private->UgaDevicePath,
390                     NULL
391                     );
392 
393   } else if (FeaturePcdGet (PcdSupportGop)) {
394     if (Private->GopDevicePath == NULL) {
395       //
396       // If RemainingDevicePath is the End of Device Path Node,
397       // don't create child device and return EFI_SUCCESS
398       //
399       Status = EFI_SUCCESS;
400     } else {
401 
402       //
403       // Start the GOP software stack.
404       //
405       Status = CirrusLogic5430GraphicsOutputConstructor (Private);
406       ASSERT_EFI_ERROR (Status);
407 
408       Status = gBS->InstallMultipleProtocolInterfaces (
409                       &Private->Handle,
410                       &gEfiGraphicsOutputProtocolGuid,
411                       &Private->GraphicsOutput,
412                       &gEfiEdidDiscoveredProtocolGuid,
413                       &Private->EdidDiscovered,
414                       &gEfiEdidActiveProtocolGuid,
415                       &Private->EdidActive,
416                       NULL
417                       );
418     }
419   } else {
420     //
421     // This driver must support eithor GOP or UGA or both.
422     //
423     ASSERT (FALSE);
424     Status = EFI_UNSUPPORTED;
425   }
426 
427 
428 Error:
429   if (EFI_ERROR (Status)) {
430     if (Private) {
431       if (Private->PciIo) {
432         if (PciAttributesSaved == TRUE) {
433           //
434           // Restore original PCI attributes
435           //
436           Private->PciIo->Attributes (
437                           Private->PciIo,
438                           EfiPciIoAttributeOperationSet,
439                           Private->OriginalPciAttributes,
440                           NULL
441                           );
442         }
443         //
444         // Close the PCI I/O Protocol
445         //
446         gBS->CloseProtocol (
447               Private->Handle,
448               &gEfiPciIoProtocolGuid,
449               This->DriverBindingHandle,
450               Private->Handle
451               );
452       }
453 
454       gBS->FreePool (Private);
455     }
456   }
457 
458   return Status;
459 }
460 
461 /**
462   CirrusLogic5430ControllerDriverStop
463 
464   TODO:    This - add argument and description to function comment
465   TODO:    Controller - add argument and description to function comment
466   TODO:    NumberOfChildren - add argument and description to function comment
467   TODO:    ChildHandleBuffer - add argument and description to function comment
468   TODO:    EFI_SUCCESS - add return value to function comment
469 **/
470 EFI_STATUS
471 EFIAPI
CirrusLogic5430ControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)472 CirrusLogic5430ControllerDriverStop (
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_UGA_DRAW_PROTOCOL           *UgaDraw;
480   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
481 
482   EFI_STATUS                      Status;
483   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
484 
485   if (FeaturePcdGet (PcdSupportUga)) {
486     Status = gBS->OpenProtocol (
487                     Controller,
488                     &gEfiUgaDrawProtocolGuid,
489                     (VOID **) &UgaDraw,
490                     This->DriverBindingHandle,
491                     Controller,
492                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
493                     );
494     if (EFI_ERROR (Status)) {
495       return Status;
496     }
497     //
498     // Get our private context information
499     //
500     Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw);
501     CirrusLogic5430UgaDrawDestructor (Private);
502 
503     if (FeaturePcdGet (PcdSupportGop)) {
504       CirrusLogic5430GraphicsOutputDestructor (Private);
505       //
506       // Remove the UGA and GOP protocol interface from the system
507       //
508       Status = gBS->UninstallMultipleProtocolInterfaces (
509                       Private->Handle,
510                       &gEfiUgaDrawProtocolGuid,
511                       &Private->UgaDraw,
512                       &gEfiGraphicsOutputProtocolGuid,
513                       &Private->GraphicsOutput,
514                       NULL
515                       );
516     } else {
517       //
518       // Remove the UGA Draw interface from the system
519       //
520       Status = gBS->UninstallMultipleProtocolInterfaces (
521                       Private->Handle,
522                       &gEfiUgaDrawProtocolGuid,
523                       &Private->UgaDraw,
524                       NULL
525                       );
526     }
527   } else {
528     Status = gBS->OpenProtocol (
529                     Controller,
530                     &gEfiGraphicsOutputProtocolGuid,
531                     (VOID **) &GraphicsOutput,
532                     This->DriverBindingHandle,
533                     Controller,
534                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
535                     );
536     if (EFI_ERROR (Status)) {
537       return Status;
538     }
539 
540     //
541     // Get our private context information
542     //
543     Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
544 
545     CirrusLogic5430GraphicsOutputDestructor (Private);
546     //
547     // Remove the GOP protocol interface from the system
548     //
549     Status = gBS->UninstallMultipleProtocolInterfaces (
550                     Private->Handle,
551                     &gEfiUgaDrawProtocolGuid,
552                     &Private->UgaDraw,
553                     &gEfiGraphicsOutputProtocolGuid,
554                     &Private->GraphicsOutput,
555                     NULL
556                     );
557   }
558 
559   if (EFI_ERROR (Status)) {
560     return Status;
561   }
562 
563   //
564   // Restore original PCI attributes
565   //
566   Private->PciIo->Attributes (
567                   Private->PciIo,
568                   EfiPciIoAttributeOperationSet,
569                   Private->OriginalPciAttributes,
570                   NULL
571                   );
572 
573   //
574   // Close the PCI I/O Protocol
575   //
576   gBS->CloseProtocol (
577         Controller,
578         &gEfiPciIoProtocolGuid,
579         This->DriverBindingHandle,
580         Controller
581         );
582 
583   //
584   // Free our instance data
585   //
586   gBS->FreePool (Private);
587 
588   return EFI_SUCCESS;
589 }
590 
591 /**
592   CirrusLogic5430UgaDrawDestructor
593 
594   TODO:    Private - add argument and description to function comment
595   TODO:    EFI_SUCCESS - add return value to function comment
596 **/
597 EFI_STATUS
CirrusLogic5430UgaDrawDestructor(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private)598 CirrusLogic5430UgaDrawDestructor (
599   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
600   )
601 {
602   return EFI_SUCCESS;
603 }
604 
605 /**
606   TODO: Add function description
607 
608   @param  Private TODO: add argument description
609   @param  Address TODO: add argument description
610   @param  Data TODO: add argument description
611 
612   TODO: add return values
613 
614 **/
615 VOID
outb(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN Address,UINT8 Data)616 outb (
617   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
618   UINTN                           Address,
619   UINT8                           Data
620   )
621 {
622   Private->PciIo->Io.Write (
623                       Private->PciIo,
624                       EfiPciIoWidthUint8,
625                       EFI_PCI_IO_PASS_THROUGH_BAR,
626                       Address,
627                       1,
628                       &Data
629                       );
630 }
631 
632 /**
633   TODO: Add function description
634 
635   @param  Private TODO: add argument description
636   @param  Address TODO: add argument description
637   @param  Data TODO: add argument description
638 
639   TODO: add return values
640 
641 **/
642 VOID
outw(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN Address,UINT16 Data)643 outw (
644   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
645   UINTN                           Address,
646   UINT16                          Data
647   )
648 {
649   Private->PciIo->Io.Write (
650                       Private->PciIo,
651                       EfiPciIoWidthUint16,
652                       EFI_PCI_IO_PASS_THROUGH_BAR,
653                       Address,
654                       1,
655                       &Data
656                       );
657 }
658 
659 /**
660   TODO: Add function description
661 
662   @param  Private TODO: add argument description
663   @param  Address TODO: add argument description
664 
665   TODO: add return values
666 
667 **/
668 UINT8
inb(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN Address)669 inb (
670   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
671   UINTN                           Address
672   )
673 {
674   UINT8 Data;
675 
676   Private->PciIo->Io.Read (
677                       Private->PciIo,
678                       EfiPciIoWidthUint8,
679                       EFI_PCI_IO_PASS_THROUGH_BAR,
680                       Address,
681                       1,
682                       &Data
683                       );
684   return Data;
685 }
686 
687 /**
688   TODO: Add function description
689 
690   @param  Private TODO: add argument description
691   @param  Address TODO: add argument description
692 
693   TODO: add return values
694 
695 **/
696 UINT16
inw(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN Address)697 inw (
698   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
699   UINTN                           Address
700   )
701 {
702   UINT16  Data;
703 
704   Private->PciIo->Io.Read (
705                       Private->PciIo,
706                       EfiPciIoWidthUint16,
707                       EFI_PCI_IO_PASS_THROUGH_BAR,
708                       Address,
709                       1,
710                       &Data
711                       );
712   return Data;
713 }
714 
715 /**
716   TODO: Add function description
717 
718   @param  Private TODO: add argument description
719   @param  Index TODO: add argument description
720   @param  Red TODO: add argument description
721   @param  Green TODO: add argument description
722   @param  Blue TODO: add argument description
723 
724   TODO: add return values
725 
726 **/
727 VOID
SetPaletteColor(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN Index,UINT8 Red,UINT8 Green,UINT8 Blue)728 SetPaletteColor (
729   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
730   UINTN                           Index,
731   UINT8                           Red,
732   UINT8                           Green,
733   UINT8                           Blue
734   )
735 {
736   outb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
737   outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
738   outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
739   outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
740 }
741 
742 /**
743   TODO: Add function description
744 
745   @param  Private TODO: add argument description
746 
747   TODO: add return values
748 
749 **/
750 VOID
SetDefaultPalette(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private)751 SetDefaultPalette (
752   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
753   )
754 {
755   UINTN Index;
756   UINTN RedIndex;
757   UINTN GreenIndex;
758   UINTN BlueIndex;
759 
760   Index = 0;
761   for (RedIndex = 0; RedIndex < 8; RedIndex++) {
762     for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
763       for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
764         SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
765         Index++;
766       }
767     }
768   }
769 }
770 
771 /**
772   TODO: Add function description
773 
774   @param  Private TODO: add argument description
775 
776   TODO: add return values
777 
778 **/
779 VOID
ClearScreen(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private)780 ClearScreen (
781   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
782   )
783 {
784   UINT32  Color;
785 
786   Color = 0;
787   Private->PciIo->Mem.Write (
788                         Private->PciIo,
789                         EfiPciIoWidthFillUint32,
790                         0,
791                         0,
792                         0x100000 >> 2,
793                         &Color
794                         );
795 }
796 
797 /**
798   TODO: Add function description
799 
800   @param  Private TODO: add argument description
801 
802   TODO: add return values
803 
804 **/
805 VOID
DrawLogo(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,UINTN ScreenWidth,UINTN ScreenHeight)806 DrawLogo (
807   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
808   UINTN                           ScreenWidth,
809   UINTN                           ScreenHeight
810   )
811 {
812 }
813 
814 /**
815   TODO: Add function description
816 
817   @param  Private TODO: add argument description
818   @param  ModeData TODO: add argument description
819 
820   TODO: add return values
821 
822 **/
823 VOID
InitializeGraphicsMode(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,CIRRUS_LOGIC_5430_VIDEO_MODES * ModeData)824 InitializeGraphicsMode (
825   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private,
826   CIRRUS_LOGIC_5430_VIDEO_MODES   *ModeData
827   )
828 {
829   UINT8 Byte;
830   UINTN Index;
831   UINT16 DeviceId;
832   EFI_STATUS Status;
833 
834   Status = Private->PciIo->Pci.Read (
835              Private->PciIo,
836              EfiPciIoWidthUint16,
837              PCI_DEVICE_ID_OFFSET,
838              1,
839              &DeviceId
840              );
841   //
842   // Read the PCI Configuration Header from the PCI Device
843   //
844   ASSERT_EFI_ERROR (Status);
845 
846   outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
847   outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
848 
849   for (Index = 0; Index < 15; Index++) {
850     outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
851   }
852 
853   if (DeviceId != CIRRUS_LOGIC_5446_DEVICE_ID) {
854     outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
855     Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
856     outb (Private, SEQ_DATA_REGISTER, Byte);
857   }
858 
859   outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
860   outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
861   outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
862   outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
863 
864   for (Index = 0; Index < 28; Index++) {
865     outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
866   }
867 
868   for (Index = 0; Index < 9; Index++) {
869     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
870   }
871 
872   inb (Private, INPUT_STATUS_1_REGISTER);
873 
874   for (Index = 0; Index < 21; Index++) {
875     outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
876     outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
877   }
878 
879   outb (Private, ATT_ADDRESS_REGISTER, 0x20);
880 
881   outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
882   outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
883   outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
884   outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
885 
886   SetDefaultPalette (Private);
887   ClearScreen (Private);
888 }
889 
890 EFI_STATUS
891 EFIAPI
InitializeCirrusLogic5430(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)892 InitializeCirrusLogic5430 (
893   IN EFI_HANDLE           ImageHandle,
894   IN EFI_SYSTEM_TABLE     *SystemTable
895   )
896 {
897   EFI_STATUS              Status;
898 
899   Status = EfiLibInstallDriverBindingComponentName2 (
900              ImageHandle,
901              SystemTable,
902              &gCirrusLogic5430DriverBinding,
903              ImageHandle,
904              &gCirrusLogic5430ComponentName,
905              &gCirrusLogic5430ComponentName2
906              );
907   ASSERT_EFI_ERROR (Status);
908 
909   //
910   // Install EFI Driver Supported EFI Version Protocol required for
911   // EFI drivers that are on PCI and other plug in cards.
912   //
913   gCirrusLogic5430DriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
914   Status = gBS->InstallMultipleProtocolInterfaces (
915                   &ImageHandle,
916                   &gEfiDriverSupportedEfiVersionProtocolGuid,
917                   &gCirrusLogic5430DriverSupportedEfiVersion,
918                   NULL
919                   );
920   ASSERT_EFI_ERROR (Status);
921 
922   return Status;
923 }
924