]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NonDiscoverablePciDeviceDxe / NonDiscoverablePciDeviceDxe.c
CommitLineData
a42e6d44
AB
1/** @file\r
2\r
3 Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>\r
4\r
5 This program and the accompanying materials are licensed and made available\r
6 under the terms and conditions of the BSD License which accompanies this\r
7 distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
11 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "NonDiscoverablePciDeviceIo.h"\r
16\r
17#include <Protocol/DriverBinding.h>\r
18\r
16296a12
AB
19EFI_CPU_ARCH_PROTOCOL *mCpu;\r
20\r
a42e6d44
AB
21//\r
22// We only support the following device types\r
23//\r
24STATIC\r
25CONST EFI_GUID * CONST\r
26SupportedNonDiscoverableDevices [] = {\r
27 &gEdkiiNonDiscoverableAhciDeviceGuid,\r
28 &gEdkiiNonDiscoverableEhciDeviceGuid,\r
29 &gEdkiiNonDiscoverableNvmeDeviceGuid,\r
30 &gEdkiiNonDiscoverableOhciDeviceGuid,\r
31 &gEdkiiNonDiscoverableSdhciDeviceGuid,\r
32 &gEdkiiNonDiscoverableUfsDeviceGuid,\r
33 &gEdkiiNonDiscoverableUhciDeviceGuid,\r
34 &gEdkiiNonDiscoverableXhciDeviceGuid,\r
35};\r
36\r
37//\r
38// Probe, start and stop functions of this driver, called by the DXE core for\r
39// specific devices.\r
40//\r
41// The following specifications document these interfaces:\r
42// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol\r
43// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol\r
44//\r
45// The implementation follows:\r
46// - Driver Writer's Guide for UEFI 2.3.1 v1.01\r
47// - 5.1.3.4 OpenProtocol() and CloseProtocol()\r
48// - UEFI Spec 2.3.1 + Errata C\r
49// - 6.3 Protocol Handler Services\r
50//\r
51\r
52STATIC\r
53EFI_STATUS\r
54EFIAPI\r
55NonDiscoverablePciDeviceSupported (\r
56 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
57 IN EFI_HANDLE DeviceHandle,\r
58 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
59 )\r
60{\r
61 NON_DISCOVERABLE_DEVICE *Device;\r
62 EFI_STATUS Status;\r
63 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
64 INTN Idx;\r
65\r
66 Status = gBS->OpenProtocol (DeviceHandle,\r
67 &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,\r
68 This->DriverBindingHandle, DeviceHandle,\r
69 EFI_OPEN_PROTOCOL_BY_DRIVER);\r
70 if (EFI_ERROR (Status)) {\r
71 return Status;\r
72 }\r
73\r
a42e6d44 74 Status = EFI_UNSUPPORTED;\r
a42e6d44
AB
75 for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {\r
76 if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {\r
77 Status = EFI_SUCCESS;\r
78 break;\r
79 }\r
80 }\r
81\r
82 if (EFI_ERROR (Status)) {\r
83 goto CloseProtocol;\r
84 }\r
85\r
86 //\r
87 // We only support MMIO devices, so iterate over the resources to ensure\r
88 // that they only describe things that we can handle\r
89 //\r
90 for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;\r
91 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {\r
92 if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||\r
93 Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
94 Status = EFI_UNSUPPORTED;\r
95 break;\r
96 }\r
97 }\r
98\r
99CloseProtocol:\r
100 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,\r
101 This->DriverBindingHandle, DeviceHandle);\r
102\r
103 return Status;\r
104}\r
105\r
106STATIC\r
107EFI_STATUS\r
108EFIAPI\r
109NonDiscoverablePciDeviceStart (\r
110 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
111 IN EFI_HANDLE DeviceHandle,\r
112 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
113 )\r
114{\r
115 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
116 EFI_STATUS Status;\r
117\r
118 Dev = AllocateZeroPool (sizeof *Dev);\r
119 if (Dev == NULL) {\r
120 return EFI_OUT_OF_RESOURCES;\r
121 }\r
122\r
123 Status = gBS->OpenProtocol (DeviceHandle,\r
124 &gEdkiiNonDiscoverableDeviceProtocolGuid,\r
125 (VOID **)&Dev->Device, This->DriverBindingHandle,\r
126 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
127 if (EFI_ERROR (Status)) {\r
128 goto FreeDev;\r
129 }\r
130\r
131 InitializePciIoProtocol (Dev);\r
132\r
133 //\r
134 // Setup complete, attempt to export the driver instance's\r
135 // EFI_PCI_IO_PROTOCOL interface.\r
136 //\r
137 Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;\r
138 Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,\r
139 EFI_NATIVE_INTERFACE, &Dev->PciIo);\r
140 if (EFI_ERROR (Status)) {\r
141 goto CloseProtocol;\r
142 }\r
143\r
144 return EFI_SUCCESS;\r
145\r
146CloseProtocol:\r
147 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,\r
148 This->DriverBindingHandle, DeviceHandle);\r
149\r
150FreeDev:\r
151 FreePool (Dev);\r
152\r
153 return Status;\r
154}\r
155\r
156\r
157STATIC\r
158EFI_STATUS\r
159EFIAPI\r
160NonDiscoverablePciDeviceStop (\r
161 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
162 IN EFI_HANDLE DeviceHandle,\r
163 IN UINTN NumberOfChildren,\r
164 IN EFI_HANDLE *ChildHandleBuffer\r
165 )\r
166{\r
167 EFI_STATUS Status;\r
168 EFI_PCI_IO_PROTOCOL *PciIo;\r
169 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
170\r
171 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
172 (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,\r
173 EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
174 if (EFI_ERROR (Status)) {\r
175 return Status;\r
176 }\r
177\r
178 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);\r
179\r
180 //\r
181 // Handle Stop() requests for in-use driver instances gracefully.\r
182 //\r
183 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
184 &gEfiPciIoProtocolGuid, &Dev->PciIo);\r
185 if (EFI_ERROR (Status)) {\r
186 return Status;\r
187 }\r
188\r
189 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,\r
190 This->DriverBindingHandle, DeviceHandle);\r
191\r
192 FreePool (Dev);\r
193\r
194 return EFI_SUCCESS;\r
195}\r
196\r
197\r
198//\r
199// The static object that groups the Supported() (ie. probe), Start() and\r
200// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
201// C, 10.1 EFI Driver Binding Protocol.\r
202//\r
203STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
204 &NonDiscoverablePciDeviceSupported,\r
205 &NonDiscoverablePciDeviceStart,\r
206 &NonDiscoverablePciDeviceStop,\r
207 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
208 NULL,\r
209 NULL\r
210};\r
211\r
212//\r
213// Entry point of this driver.\r
214//\r
215EFI_STATUS\r
216EFIAPI\r
217NonDiscoverablePciDeviceDxeEntryPoint (\r
218 IN EFI_HANDLE ImageHandle,\r
219 IN EFI_SYSTEM_TABLE *SystemTable\r
220 )\r
221{\r
16296a12
AB
222 EFI_STATUS Status;\r
223\r
224 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);\r
225 ASSERT_EFI_ERROR(Status);\r
226\r
a42e6d44
AB
227 return EfiLibInstallDriverBindingComponentName2 (\r
228 ImageHandle,\r
229 SystemTable,\r
230 &gDriverBinding,\r
231 ImageHandle,\r
232 &gComponentName,\r
233 &gComponentName2\r
234 );\r
235}\r