• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   EFI PCAT ISA ACPI Driver for a Generic PC Platform
3 
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PcatIsaAcpi.h"
16 
17 //
18 //  PcatIsaAcpi Driver Binding Protocol
19 //
20 EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding = {
21   PcatIsaAcpiDriverBindingSupported,
22   PcatIsaAcpiDriverBindingStart,
23   PcatIsaAcpiDriverBindingStop,
24   0xa,
25   NULL,
26   NULL
27 };
28 
29 /**
30   the entry point of the PcatIsaAcpi driver.
31 
32   @param ImageHandle     Handle for driver image
33   @param SystemTable     Point to EFI_SYSTEM_TABLE
34 
35   @return Sucess or not for installing driver binding protocol
36 **/
37 EFI_STATUS
38 EFIAPI
PcatIsaAcpiDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)39 PcatIsaAcpiDriverEntryPoint (
40   IN EFI_HANDLE        ImageHandle,
41   IN EFI_SYSTEM_TABLE  *SystemTable
42   )
43 {
44   return EfiLibInstallDriverBindingComponentName2 (
45            ImageHandle,
46            SystemTable,
47            &gPcatIsaAcpiDriverBinding,
48            ImageHandle,
49            &gPcatIsaAcpiComponentName,
50            &gPcatIsaAcpiComponentName2
51            );
52 }
53 
54 /**
55   ControllerDriver Protocol Method
56 
57   @param This                 Driver Binding protocol instance pointer.
58   @param Controller           Handle of device to test.
59   @param RemainingDevicePath  Optional parameter use to pick a specific child
60                               device to start.
61   @retval EFI_SUCCESS         This driver supports this device.
62   @retval other               This driver does not support this device.
63 
64 **/
65 EFI_STATUS
66 EFIAPI
PcatIsaAcpiDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)67 PcatIsaAcpiDriverBindingSupported (
68   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
69   IN EFI_HANDLE                   Controller,
70   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
71   )
72 {
73   EFI_STATUS           Status;
74   EFI_PCI_IO_PROTOCOL  *PciIo;
75   PCI_TYPE00           Pci;
76   UINTN                SegmentNumber;
77   UINTN                BusNumber;
78   UINTN                DeviceNumber;
79   UINTN                FunctionNumber;
80 
81   //
82   // Get PciIo protocol instance
83   //
84   Status = gBS->OpenProtocol (
85                   Controller,
86                   &gEfiPciIoProtocolGuid,
87                   (VOID**)&PciIo,
88                   This->DriverBindingHandle,
89                   Controller,
90                   EFI_OPEN_PROTOCOL_BY_DRIVER
91                   );
92   if (EFI_ERROR(Status)) {
93     return Status;
94   }
95 
96   Status = PciIo->Pci.Read (
97                     PciIo,
98                     EfiPciIoWidthUint32,
99                     0,
100                     sizeof(Pci) / sizeof(UINT32),
101                     &Pci);
102 
103   if (!EFI_ERROR (Status)) {
104     Status = EFI_UNSUPPORTED;
105     if ((Pci.Hdr.Command & 0x03) == 0x03) {
106       if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
107         //
108         // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code
109         //
110         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
111           Status = EFI_SUCCESS;
112         }
113 
114         //
115         // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
116         //
117         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE &&
118             Pci.Hdr.VendorId     == 0x8086                          ) {
119           //
120           // See if this is on Function #0 to avoid false positives on
121           // PCI_CLASS_BRIDGE_OTHER that has the same value as
122           // PCI_CLASS_BRIDGE_ISA_PDECODE
123           //
124           Status = PciIo->GetLocation (
125                             PciIo,
126                             &SegmentNumber,
127                             &BusNumber,
128                             &DeviceNumber,
129                             &FunctionNumber
130                             );
131           if (!EFI_ERROR (Status) && FunctionNumber == 0) {
132             Status = EFI_SUCCESS;
133           } else {
134             Status = EFI_UNSUPPORTED;
135           }
136         }
137       }
138     }
139   }
140 
141   gBS->CloseProtocol (
142          Controller,
143          &gEfiPciIoProtocolGuid,
144          This->DriverBindingHandle,
145          Controller
146          );
147 
148   return Status;
149 }
150 
151 /**
152   Install EFI_ISA_ACPI_PROTOCOL.
153 
154   @param  This                 Driver Binding protocol instance pointer.
155   @param  ControllerHandle     Handle of device to bind driver to.
156   @param  RemainingDevicePath  Optional parameter use to pick a specific child
157                                device to start.
158 
159   @retval EFI_SUCCESS          This driver is added to ControllerHandle
160   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
161   @retval other                This driver does not support this device
162 **/
163 EFI_STATUS
164 EFIAPI
PcatIsaAcpiDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)165 PcatIsaAcpiDriverBindingStart (
166   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
167   IN EFI_HANDLE                   Controller,
168   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
169   )
170 {
171   EFI_STATUS           Status;
172   EFI_PCI_IO_PROTOCOL  *PciIo;
173   PCAT_ISA_ACPI_DEV    *PcatIsaAcpiDev;
174   UINT64               Supports;
175   BOOLEAN              Enabled;
176 
177   Enabled = FALSE;
178   Supports = 0;
179   PcatIsaAcpiDev = NULL;
180   //
181   // Open the PCI I/O Protocol Interface
182   //
183   PciIo = NULL;
184   Status = gBS->OpenProtocol (
185                   Controller,
186                   &gEfiPciIoProtocolGuid,
187                   (VOID**)&PciIo,
188                   This->DriverBindingHandle,
189                   Controller,
190                   EFI_OPEN_PROTOCOL_BY_DRIVER
191                   );
192   if (EFI_ERROR (Status)) {
193     goto Done;
194   }
195 
196   //
197   // Get supported PCI attributes
198   //
199   Status = PciIo->Attributes (
200                     PciIo,
201                     EfiPciIoAttributeOperationSupported,
202                     0,
203                     &Supports
204                     );
205   if (EFI_ERROR (Status)) {
206     goto Done;
207   }
208 
209   Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
210   if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) {
211     Status = EFI_UNSUPPORTED;
212     goto Done;
213   }
214 
215   Enabled = TRUE;
216   Status = PciIo->Attributes (
217                     PciIo,
218                     EfiPciIoAttributeOperationEnable,
219                     EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
220                     NULL
221                     );
222   if (EFI_ERROR (Status)) {
223     goto Done;
224   }
225 
226   //
227   // Allocate memory for the PCAT ISA ACPI Device structure
228   //
229   PcatIsaAcpiDev = NULL;
230   Status = gBS->AllocatePool (
231                   EfiBootServicesData,
232                   sizeof(PCAT_ISA_ACPI_DEV),
233                   (VOID**)&PcatIsaAcpiDev
234                   );
235   if (EFI_ERROR (Status)) {
236     goto Done;
237   }
238 
239   //
240   // Initialize the PCAT ISA ACPI Device structure
241   //
242   PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE;
243   PcatIsaAcpiDev->Handle    = Controller;
244   PcatIsaAcpiDev->PciIo     = PciIo;
245 
246   //
247   // Initialize PcatIsaAcpiDeviceList
248   //
249   InitializePcatIsaAcpiDeviceList ();
250 
251   //
252   // IsaAcpi interface
253   //
254   (PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate  = IsaDeviceEnumerate;
255   (PcatIsaAcpiDev->IsaAcpi).SetPower         = IsaDeviceSetPower;
256   (PcatIsaAcpiDev->IsaAcpi).GetCurResource   = IsaGetCurrentResource;
257   (PcatIsaAcpiDev->IsaAcpi).GetPosResource   = IsaGetPossibleResource;
258   (PcatIsaAcpiDev->IsaAcpi).SetResource      = IsaSetResource;
259   (PcatIsaAcpiDev->IsaAcpi).EnableDevice     = IsaEnableDevice;
260   (PcatIsaAcpiDev->IsaAcpi).InitDevice       = IsaInitDevice;
261   (PcatIsaAcpiDev->IsaAcpi).InterfaceInit    = IsaInterfaceInit;
262 
263   //
264   // Install the ISA ACPI Protocol interface
265   //
266   Status = gBS->InstallMultipleProtocolInterfaces (
267                   &Controller,
268                   &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi,
269                   NULL
270                   );
271 
272 Done:
273   if (EFI_ERROR (Status)) {
274     if (PciIo != NULL && Enabled) {
275       PciIo->Attributes (
276                PciIo,
277                EfiPciIoAttributeOperationDisable,
278                EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
279                NULL
280                );
281     }
282     gBS->CloseProtocol (
283            Controller,
284            &gEfiPciIoProtocolGuid,
285            This->DriverBindingHandle,
286            Controller
287            );
288     if (PcatIsaAcpiDev != NULL) {
289       gBS->FreePool (PcatIsaAcpiDev);
290     }
291     return Status;
292   }
293 
294   return EFI_SUCCESS;
295 }
296 
297 
298 /**
299   Stop this driver on ControllerHandle. Support stopping any child handles
300   created by this driver.
301 
302   @param  This              Protocol instance pointer.
303   @param  ControllerHandle  Handle of device to stop driver on
304   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
305                             children is zero stop the entire bus driver.
306   @param  ChildHandleBuffer List of Child Handles to Stop.
307 
308   @retval EFI_SUCCESS       This driver is removed ControllerHandle
309   @retval other             This driver was not removed from this device
310 
311 **/
312 EFI_STATUS
313 EFIAPI
PcatIsaAcpiDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)314 PcatIsaAcpiDriverBindingStop (
315   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
316   IN EFI_HANDLE                   Controller,
317   IN UINTN                        NumberOfChildren,
318   IN EFI_HANDLE                   *ChildHandleBuffer
319   )
320 {
321   EFI_STATUS             Status;
322   EFI_ISA_ACPI_PROTOCOL  *IsaAcpi;
323   PCAT_ISA_ACPI_DEV      *PcatIsaAcpiDev;
324   UINT64                 Supports;
325 
326   //
327   // Get the ISA ACPI Protocol Interface
328   //
329   Status = gBS->OpenProtocol (
330                   Controller,
331                   &gEfiIsaAcpiProtocolGuid,
332                   (VOID**)&IsaAcpi,
333                   This->DriverBindingHandle,
334                   Controller,
335                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
336                   );
337   if (EFI_ERROR (Status)) {
338     return Status;
339   }
340 
341   //
342   // Get the PCAT ISA ACPI Device structure from the ISA ACPI Protocol
343   //
344   PcatIsaAcpiDev = PCAT_ISA_ACPI_DEV_FROM_THIS (IsaAcpi);
345 
346   //
347   // Get supported PCI attributes
348   //
349   Status = PcatIsaAcpiDev->PciIo->Attributes (
350                                     PcatIsaAcpiDev->PciIo,
351                                     EfiPciIoAttributeOperationSupported,
352                                     0,
353                                     &Supports
354                                     );
355   if (EFI_ERROR (Status)) {
356     return Status;
357   }
358 
359   Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
360 
361   PcatIsaAcpiDev->PciIo->Attributes (
362                            PcatIsaAcpiDev->PciIo,
363                            EfiPciIoAttributeOperationDisable,
364                            EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
365                            NULL
366                            );
367 
368   //
369   // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL
370   //
371   Status = gBS->UninstallProtocolInterface (
372                   Controller,
373                   &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi
374                   );
375   if (EFI_ERROR (Status)) {
376     return Status;
377   }
378 
379   gBS->CloseProtocol (
380          Controller,
381          &gEfiPciIoProtocolGuid,
382          This->DriverBindingHandle,
383          Controller
384          );
385 
386   gBS->FreePool (PcatIsaAcpiDev);
387 
388   return EFI_SUCCESS;
389 }
390