1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 
24 Module Name:
25 
26     LpcDriver.c
27 
28 Abstract:
29 
30     EFI Lpc Driver for a Generic PC Platform
31 
32 
33 
34 --*/
35 
36 #include "LpcDriver.h"
37 #include "IndustryStandard/Pci22.h"
38 
39 //
40 // This driver is for ACPI(PNP0A03,0)/PCI(0x1f,0)
41 //
42 
43 //
44 //  Lpc Driver Global Variables
45 //
46 
47 EFI_DRIVER_BINDING_PROTOCOL gLpcDriver = {
48   LpcDriverSupported,
49   LpcDriverStart,
50   LpcDriverStop,
51   0x10,
52   NULL,
53   NULL
54 };
55 
56 LPC_DEV mLpc = {
57   LPC_DEV_SIGNATURE,
58   NULL,
59   {
60     IsaDeviceEnumerate,
61     IsaDeviceSetPower,
62     IsaGetCurrentResource,
63     IsaGetPossibleResource,
64     IsaSetResource,
65     IsaEnableDevice,
66     IsaInitDevice,
67     LpcInterfaceInit
68   },
69   NULL
70 };
LpcDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)71 
72 BOOLEAN  InitExecuted = FALSE;
73 
74 /**
75     the entry point of the Lpc driver
76 
77 **/
78 EFI_STATUS
79 EFIAPI
80 LpcDriverEntryPoint(
81   IN EFI_HANDLE           ImageHandle,
82   IN EFI_SYSTEM_TABLE     *SystemTable
83   )
84 {
85 
86 
87   return EfiLibInstallDriverBinding (ImageHandle, SystemTable, &gLpcDriver, ImageHandle);
LpcDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)88 }
89 
90 /**
91 
92   ControllerDriver Protocol Method
93 
94 **/
95 EFI_STATUS
96 EFIAPI
97 LpcDriverSupported (
98   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
99   IN EFI_HANDLE                     Controller,
100   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
101   )
102 {
103   EFI_STATUS                Status;
104   EFI_PCI_IO_PROTOCOL       *PciIo;
105   EFI_DEVICE_PATH_PROTOCOL  *IsaBridgeDevicePath;
106 
107   ACPI_HID_DEVICE_PATH      *AcpiNode;
108   PCI_DEVICE_PATH           *PciNode;
109   PCI_TYPE00                Pci;
110 
111   //
112   // Get the ISA bridge's Device Path and test it
113   // the following code is specific
114   //
115   Status = gBS->OpenProtocol (
116                   Controller,
117                   &gEfiDevicePathProtocolGuid,
118                   (VOID **)&IsaBridgeDevicePath,
119                   This->DriverBindingHandle,
120                   Controller,
121                   EFI_OPEN_PROTOCOL_BY_DRIVER
122                   );
123 
124   if (EFI_ERROR (Status)) {
125     return Status;
126   }
127 
128   Status = EFI_SUCCESS;
129   AcpiNode =  (ACPI_HID_DEVICE_PATH *)IsaBridgeDevicePath;
130   if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
131       AcpiNode->Header.SubType != ACPI_DP ||
132       DevicePathNodeLength (&AcpiNode->Header) != sizeof(ACPI_HID_DEVICE_PATH) ||
133       AcpiNode -> HID != EISA_PNP_ID(0x0A03) ||
134       AcpiNode -> UID != 0 ) {
135     Status = EFI_UNSUPPORTED;
136   } else {
137     //
138     // Get the next node
139     //
140     IsaBridgeDevicePath = NextDevicePathNode (IsaBridgeDevicePath);
141     PciNode  = (PCI_DEVICE_PATH *)IsaBridgeDevicePath;
142     if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
143         PciNode->Header.SubType != HW_PCI_DP ||
144         DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH) ||
145         PciNode -> Function != 0x00 ||
146         PciNode -> Device != 0x1f ) {
147       Status = EFI_UNSUPPORTED;
148     }
149   }
150 
151   gBS->CloseProtocol (
152          Controller,
153          &gEfiDevicePathProtocolGuid,
154          This->DriverBindingHandle,
155          Controller
156          );
157 
158   if (EFI_ERROR (Status)) {
159     return EFI_UNSUPPORTED;
160   }
161 
162   //
163   // Get PciIo protocol instance
164   //
165   Status = gBS->OpenProtocol (
166                   Controller,
167                   &gEfiPciIoProtocolGuid,
168                   (VOID **)&PciIo,
169                   This->DriverBindingHandle,
170                   Controller,
171                   EFI_OPEN_PROTOCOL_BY_DRIVER
172                   );
173 
174   if (EFI_ERROR(Status)) {
175     return Status;
176   }
177 
178   Status = PciIo->Pci.Read (
179                         PciIo,
180                         EfiPciIoWidthUint32,
181                         0,
182                         sizeof(Pci) / sizeof(UINT32),
183                         &Pci
184                         );
185 
186   if (!EFI_ERROR (Status)) {
187     Status = EFI_SUCCESS; //TODO: force return success as temp solution EFI_UNSUPPORTED;
188     if ((Pci.Hdr.Command & 0x03) == 0x03) {
189       if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
190         //
191         // See if this is a standard PCI to ISA Bridge from the Base Code
192         // and Class Code
193         //
194         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
195           Status = EFI_SUCCESS;
196         } else {
197         }
198 
199         //
200         // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
201         //
202         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE &&
203             Pci.Hdr.VendorId == 0x8086 &&
204             Pci.Hdr.DeviceId == 0x7110) {
205           Status = EFI_SUCCESS;
206         } else {
207         }
208       } else {
209       }
210     }
211     else {
212     }
213   }
214 
215   gBS->CloseProtocol (
216          Controller,
217          &gEfiPciIoProtocolGuid,
218          This->DriverBindingHandle,
219          Controller
220          );
221   return Status;
222 }
223 
224 
225 /**
226   Install EFI_ISA_ACPI_PROTOCOL
227 
228 **/
229 EFI_STATUS
230 EFIAPI
231 LpcDriverStart (
232   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
233   IN EFI_HANDLE                     Controller,
234   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
235   )
236 {
237   EFI_STATUS             Status;
238   EFI_PCI_IO_PROTOCOL    *PciIo;
239   LPC_DEV                *LpcDev;
240 
241 
242   LpcDev = NULL;
243 
244   //
245   // Get Pci IO
246   //
247   Status = gBS->OpenProtocol (
248                   Controller,
249                   &gEfiPciIoProtocolGuid,
250                   (VOID **)&PciIo,
251                   This->DriverBindingHandle,
252                   Controller,
253                   EFI_OPEN_PROTOCOL_BY_DRIVER
254                   );
255 
256   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
257     return Status;
258   }
259 
260   mLpc.PciIo = PciIo;
261 
262   //
263   // Install IsaAcpi interface, the Sio interface is not installed!
264   //
265   Status = gBS->InstallMultipleProtocolInterfaces (
266                   &Controller,
267                   &gEfiIsaAcpiProtocolGuid,
LpcDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)268                   &mLpc.IsaAcpi,
269                   NULL
270                   );
271   return Status;
272 }
273 
274 
275 EFI_STATUS
276 EFIAPI
277 LpcDriverStop (
278   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
279   IN  EFI_HANDLE                     Controller,
280   IN  UINTN                          NumberOfChildren,
281   IN  EFI_HANDLE                     *ChildHandleBuffer
282   )
283 {
284   EFI_STATUS             Status;
285   EFI_ISA_ACPI_PROTOCOL  *IsaAcpi;
286   LPC_DEV                *LpcDev;
287 
288   //
289   // Get EFI_ISA_ACPI_PROTOCOL interface
290   //
291   Status = gBS->OpenProtocol (
292                   Controller,
293                   &gEfiIsaAcpiProtocolGuid,
294                   (VOID **)&IsaAcpi,
295                   This->DriverBindingHandle,
296                   Controller,
297                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
298                   );
299   if (EFI_ERROR (Status)) {
300     return Status;
301   }
302 
303   LpcDev = LPC_ISA_ACPI_FROM_THIS (IsaAcpi);
304 
305   //
306   // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL
307   //
308   Status = gBS->UninstallProtocolInterface (
309                   Controller,
310                   &gEfiIsaAcpiProtocolGuid,
311                   &LpcDev->IsaAcpi
312                   );
313   if (EFI_ERROR (Status)) {
314     return Status;
315   }
316 
317   gBS->CloseProtocol (
318          Controller,
LpcIoRead8(IN UINT16 Port,OUT UINT8 * Data)319          &gEfiPciIoProtocolGuid,
320          This->DriverBindingHandle,
321          Controller
322          );
323 
324   return EFI_SUCCESS;
325 }
326 
327 VOID
328 LpcIoRead8 (
329   IN  UINT16  Port,
330   OUT UINT8   *Data
331   )
332 {
333   mLpc.PciIo->Io.Read(
334                    mLpc.PciIo,
LpcIoWrite8(IN UINT16 Port,IN UINT8 Data)335                    EfiPciWidthUint8,
336                    EFI_PCI_IO_PASS_THROUGH_BAR,
337                    Port,
338                    1,
339                    Data
340                    );
341 }
342 
343 VOID
344 LpcIoWrite8 (
345   IN  UINT16  Port,
346   IN  UINT8   Data
347   )
348 {
349   mLpc.PciIo->Io.Write(
350                    mLpc.PciIo,
351                    EfiPciWidthUint8,
352                    EFI_PCI_IO_PASS_THROUGH_BAR,
353                    Port,
354                    1,
355                    &Data
356                    );
357 }
358 
359