PcAtChipsetPkg/IsaAcpiDxe: Restore PCI attributes correctly
[mirror_edk2.git] / PcAtChipsetPkg / IsaAcpiDxe / PcatIsaAcpi.c
1 /** @file
2 EFI PCAT ISA ACPI Driver for a Generic PC Platform
3
4 Copyright (c) 2006 - 2017, 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 Success or not for installing driver binding protocol
36 **/
37 EFI_STATUS
38 EFIAPI
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
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
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 UINT64 OriginalAttributes;
176 BOOLEAN Enabled;
177
178 Enabled = FALSE;
179 Supports = 0;
180 PcatIsaAcpiDev = NULL;
181 //
182 // Open the PCI I/O Protocol Interface
183 //
184 PciIo = NULL;
185 Status = gBS->OpenProtocol (
186 Controller,
187 &gEfiPciIoProtocolGuid,
188 (VOID**)&PciIo,
189 This->DriverBindingHandle,
190 Controller,
191 EFI_OPEN_PROTOCOL_BY_DRIVER
192 );
193 if (EFI_ERROR (Status)) {
194 goto Done;
195 }
196
197 //
198 // Get supported PCI attributes
199 //
200 Status = PciIo->Attributes (
201 PciIo,
202 EfiPciIoAttributeOperationSupported,
203 0,
204 &Supports
205 );
206 if (EFI_ERROR (Status)) {
207 goto Done;
208 }
209
210 Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
211 if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) {
212 Status = EFI_UNSUPPORTED;
213 goto Done;
214 }
215
216 Status = PciIo->Attributes (
217 PciIo,
218 EfiPciIoAttributeOperationGet,
219 0,
220 &OriginalAttributes
221 );
222 if (EFI_ERROR (Status)) {
223 goto Done;
224 }
225
226 Status = PciIo->Attributes (
227 PciIo,
228 EfiPciIoAttributeOperationEnable,
229 EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
230 NULL
231 );
232 if (EFI_ERROR (Status)) {
233 goto Done;
234 }
235
236 Enabled = TRUE;
237 //
238 // Allocate memory for the PCAT ISA ACPI Device structure
239 //
240 PcatIsaAcpiDev = NULL;
241 Status = gBS->AllocatePool (
242 EfiBootServicesData,
243 sizeof(PCAT_ISA_ACPI_DEV),
244 (VOID**)&PcatIsaAcpiDev
245 );
246 if (EFI_ERROR (Status)) {
247 goto Done;
248 }
249
250 //
251 // Initialize the PCAT ISA ACPI Device structure
252 //
253 PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE;
254 PcatIsaAcpiDev->Handle = Controller;
255 PcatIsaAcpiDev->PciIo = PciIo;
256 PcatIsaAcpiDev->OriginalAttributes = OriginalAttributes;
257
258 //
259 // Initialize PcatIsaAcpiDeviceList
260 //
261 InitializePcatIsaAcpiDeviceList ();
262
263 //
264 // IsaAcpi interface
265 //
266 (PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate = IsaDeviceEnumerate;
267 (PcatIsaAcpiDev->IsaAcpi).SetPower = IsaDeviceSetPower;
268 (PcatIsaAcpiDev->IsaAcpi).GetCurResource = IsaGetCurrentResource;
269 (PcatIsaAcpiDev->IsaAcpi).GetPosResource = IsaGetPossibleResource;
270 (PcatIsaAcpiDev->IsaAcpi).SetResource = IsaSetResource;
271 (PcatIsaAcpiDev->IsaAcpi).EnableDevice = IsaEnableDevice;
272 (PcatIsaAcpiDev->IsaAcpi).InitDevice = IsaInitDevice;
273 (PcatIsaAcpiDev->IsaAcpi).InterfaceInit = IsaInterfaceInit;
274
275 //
276 // Install the ISA ACPI Protocol interface
277 //
278 Status = gBS->InstallMultipleProtocolInterfaces (
279 &Controller,
280 &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi,
281 NULL
282 );
283
284 Done:
285 if (EFI_ERROR (Status)) {
286 if (PciIo != NULL && Enabled) {
287 PciIo->Attributes (
288 PciIo,
289 EfiPciIoAttributeOperationSet,
290 OriginalAttributes,
291 NULL
292 );
293 }
294 gBS->CloseProtocol (
295 Controller,
296 &gEfiPciIoProtocolGuid,
297 This->DriverBindingHandle,
298 Controller
299 );
300 if (PcatIsaAcpiDev != NULL) {
301 gBS->FreePool (PcatIsaAcpiDev);
302 }
303 return Status;
304 }
305
306 return EFI_SUCCESS;
307 }
308
309
310 /**
311 Stop this driver on ControllerHandle. Support stopping any child handles
312 created by this driver.
313
314 @param This Protocol instance pointer.
315 @param ControllerHandle Handle of device to stop driver on
316 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
317 children is zero stop the entire bus driver.
318 @param ChildHandleBuffer List of Child Handles to Stop.
319
320 @retval EFI_SUCCESS This driver is removed ControllerHandle
321 @retval other This driver was not removed from this device
322
323 **/
324 EFI_STATUS
325 EFIAPI
326 PcatIsaAcpiDriverBindingStop (
327 IN EFI_DRIVER_BINDING_PROTOCOL *This,
328 IN EFI_HANDLE Controller,
329 IN UINTN NumberOfChildren,
330 IN EFI_HANDLE *ChildHandleBuffer
331 )
332 {
333 EFI_STATUS Status;
334 EFI_ISA_ACPI_PROTOCOL *IsaAcpi;
335 PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;
336
337 //
338 // Get the ISA ACPI Protocol Interface
339 //
340 Status = gBS->OpenProtocol (
341 Controller,
342 &gEfiIsaAcpiProtocolGuid,
343 (VOID**)&IsaAcpi,
344 This->DriverBindingHandle,
345 Controller,
346 EFI_OPEN_PROTOCOL_GET_PROTOCOL
347 );
348 if (EFI_ERROR (Status)) {
349 return Status;
350 }
351
352 //
353 // Get the PCAT ISA ACPI Device structure from the ISA ACPI Protocol
354 //
355 PcatIsaAcpiDev = PCAT_ISA_ACPI_DEV_FROM_THIS (IsaAcpi);
356
357 //
358 // Restore PCI attributes
359 //
360 Status = PcatIsaAcpiDev->PciIo->Attributes (
361 PcatIsaAcpiDev->PciIo,
362 EfiPciIoAttributeOperationSet,
363 PcatIsaAcpiDev->OriginalAttributes,
364 NULL
365 );
366 if (EFI_ERROR (Status)) {
367 return Status;
368 }
369
370 //
371 // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL
372 //
373 Status = gBS->UninstallProtocolInterface (
374 Controller,
375 &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi
376 );
377 if (EFI_ERROR (Status)) {
378 return Status;
379 }
380
381 gBS->CloseProtocol (
382 Controller,
383 &gEfiPciIoProtocolGuid,
384 This->DriverBindingHandle,
385 Controller
386 );
387
388 gBS->FreePool (PcatIsaAcpiDev);
389
390 return EFI_SUCCESS;
391 }