32381b112d0e68f714a8944ac0ba39bd5414ce31
[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 - 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 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 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
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 }