]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / IncompatiblePciDeviceSupportDxe / IncompatiblePciDeviceSupport.c
CommitLineData
9060e3ec 1/** @file\r
2 This module is one template module for Incompatible PCI Device Support protocol.\r
c1a247b8 3 It includes one incompatible pci devices list template.\r
d1102dba 4\r
9060e3ec 5 Incompatible PCI Device Support protocol allows the PCI bus driver to support\r
6 resource allocation for some PCI devices that do not comply with the PCI Specification.\r
7\r
e03a460f 8Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 9This program and the accompanying materials\r
9060e3ec 10are licensed and made available under the terms and conditions of the BSD License\r
11which accompanies this distribution. The full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include <PiDxe.h>\r
20#include <Protocol/IncompatiblePciDeviceSupport.h>\r
21\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/MemoryAllocationLib.h>\r
24#include <Library/DebugLib.h>\r
25\r
26#include <IndustryStandard/Pci.h>\r
27#include <IndustryStandard/Acpi.h>\r
28\r
29typedef struct {\r
30 UINT64 VendorId;\r
31 UINT64 DeviceId;\r
32 UINT64 RevisionId;\r
33 UINT64 SubsystemVendorId;\r
34 UINT64 SubsystemDeviceId;\r
35} EFI_PCI_DEVICE_HEADER_INFO;\r
36\r
37typedef struct {\r
38 UINT64 ResType;\r
39 UINT64 GenFlag;\r
40 UINT64 SpecificFlag;\r
41 UINT64 AddrSpaceGranularity;\r
42 UINT64 AddrRangeMin;\r
43 UINT64 AddrRangeMax;\r
44 UINT64 AddrTranslationOffset;\r
45 UINT64 AddrLen;\r
46} EFI_PCI_RESOUCE_DESCRIPTOR;\r
47\r
48#define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \\r
49 VendorId, DeviceId, Revision, SubVendorId, SubDeviceId\r
50\r
9060e3ec 51#define DEVICE_INF_TAG 0xFFF2\r
52#define DEVICE_RES_TAG 0xFFF1\r
53#define LIST_END_TAG 0x0000\r
54\r
c1a247b8 55#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL\r
9060e3ec 56\r
57/**\r
58 Returns a list of ACPI resource descriptors that detail the special\r
59 resource configuration requirements for an incompatible PCI device.\r
60\r
61 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
62 @param VendorId A unique ID to identify the manufacturer of the PCI device.\r
63 @param DeviceId A unique ID to identify the particular PCI device.\r
64 @param RevisionId A PCI device-specific revision identifier.\r
65 @param SubsystemVendorId Specifies the subsystem vendor ID.\r
66 @param SubsystemDeviceId Specifies the subsystem device ID.\r
67 @param Configuration A list of ACPI resource descriptors returned that detail\r
68 the configuration requirement.\r
69\r
70 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.\r
d1102dba 71 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
9060e3ec 72 @retval EFI_OUT_OF_RESOURCES No memory available.\r
73 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.\r
74\r
75**/\r
76EFI_STATUS\r
77EFIAPI\r
78PCheckDevice (\r
79 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This,\r
80 IN UINTN VendorId,\r
81 IN UINTN DeviceId,\r
82 IN UINTN RevisionId,\r
83 IN UINTN SubsystemVendorId,\r
84 IN UINTN SubsystemDeviceId,\r
85 OUT VOID **Configuration\r
86 );\r
87\r
88//\r
89// Handle onto which the Incompatible PCI Device List is installed\r
90//\r
91EFI_HANDLE mIncompatiblePciDeviceSupportHandle = NULL;\r
92\r
93//\r
94// The Incompatible PCI Device Support Protocol instance produced by this driver\r
95//\r
96EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport = {\r
97 PCheckDevice\r
98};\r
99\r
100//\r
101// The incompatible PCI devices list template\r
102//\r
103GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList[] = {\r
104 //\r
105 // DEVICE_INF_TAG,\r
106 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),\r
107 // DEVICE_RES_TAG,\r
108 // ResType, GFlag , SFlag, Granularity, RangeMin,\r
109 // RangeMax, Offset, AddrLen\r
110 //\r
111 //\r
112 // Device Adaptec 9004\r
113 //\r
114 DEVICE_INF_TAG,\r
c1a247b8 115 PCI_DEVICE_ID(0x9004, MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64),\r
9060e3ec 116 DEVICE_RES_TAG,\r
c1a247b8
RN
117 ACPI_ADDRESS_SPACE_TYPE_IO,\r
118 0,\r
119 0,\r
120 0,\r
121 0,\r
122 EVEN_ALIGN,\r
123 MAX_UINT64,\r
124 0,\r
9060e3ec 125 //\r
126 // Device Adaptec 9005\r
127 //\r
128 DEVICE_INF_TAG,\r
c1a247b8 129 PCI_DEVICE_ID(0x9005, MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64),\r
9060e3ec 130 DEVICE_RES_TAG,\r
c1a247b8
RN
131 ACPI_ADDRESS_SPACE_TYPE_IO,\r
132 0,\r
133 0,\r
134 0,\r
135 0,\r
136 EVEN_ALIGN,\r
137 MAX_UINT64,\r
138 0,\r
9060e3ec 139 //\r
140 // Device QLogic 1007\r
141 //\r
142 DEVICE_INF_TAG,\r
c1a247b8 143 PCI_DEVICE_ID(0x1077, MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64),\r
9060e3ec 144 DEVICE_RES_TAG,\r
c1a247b8
RN
145 ACPI_ADDRESS_SPACE_TYPE_IO,\r
146 0,\r
147 0,\r
148 0,\r
149 0,\r
150 EVEN_ALIGN,\r
151 MAX_UINT64,\r
152 0,\r
9060e3ec 153 //\r
154 // Device Agilent 103C\r
155 //\r
156 DEVICE_INF_TAG,\r
c1a247b8 157 PCI_DEVICE_ID(0x103C, MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64),\r
9060e3ec 158 DEVICE_RES_TAG,\r
c1a247b8
RN
159 ACPI_ADDRESS_SPACE_TYPE_IO,\r
160 0,\r
161 0,\r
162 0,\r
163 0,\r
164 EVEN_ALIGN,\r
165 MAX_UINT64,\r
166 0,\r
9060e3ec 167 //\r
168 // Device Agilent 15BC\r
169 //\r
170 DEVICE_INF_TAG,\r
c1a247b8 171 PCI_DEVICE_ID(0x15BC, MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64),\r
9060e3ec 172 DEVICE_RES_TAG,\r
c1a247b8
RN
173 ACPI_ADDRESS_SPACE_TYPE_IO,\r
174 0,\r
175 0,\r
176 0,\r
177 0,\r
178 EVEN_ALIGN,\r
179 MAX_UINT64,\r
180 0,\r
9060e3ec 181 //\r
182 // The end of the list\r
183 //\r
184 LIST_END_TAG\r
185};\r
186\r
187\r
188/**\r
189 Entry point of the incompatible pci device support code. Setup an incompatible device list template\r
190 and install EFI Incompatible PCI Device Support protocol.\r
191\r
192 @param ImageHandle A handle for the image that is initializing this driver.\r
193 @param SystemTable A pointer to the EFI system table.\r
194\r
195 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.\r
196 @retval others Failed to install protocol.\r
197\r
198**/\r
199EFI_STATUS\r
200EFIAPI\r
201IncompatiblePciDeviceSupportEntryPoint (\r
202 IN EFI_HANDLE ImageHandle,\r
203 IN EFI_SYSTEM_TABLE *SystemTable\r
204 )\r
205{\r
206 EFI_STATUS Status;\r
207\r
208 //\r
209 // Install EFI Incompatible PCI Device Support Protocol on a new handle\r
210 //\r
211 Status = gBS->InstallProtocolInterface (\r
212 &mIncompatiblePciDeviceSupportHandle,\r
213 &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
214 EFI_NATIVE_INTERFACE,\r
215 &mIncompatiblePciDeviceSupport\r
216 );\r
217 ASSERT_EFI_ERROR (Status);\r
218\r
219 return Status;\r
220}\r
221\r
222/**\r
223 Returns a list of ACPI resource descriptors that detail the special\r
224 resource configuration requirements for an incompatible PCI device.\r
225\r
226 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
227 @param VendorId A unique ID to identify the manufacturer of the PCI device.\r
228 @param DeviceId A unique ID to identify the particular PCI device.\r
229 @param RevisionId A PCI device-specific revision identifier.\r
230 @param SubsystemVendorId Specifies the subsystem vendor ID.\r
231 @param SubsystemDeviceId Specifies the subsystem device ID.\r
232 @param Configuration A list of ACPI resource descriptors returned that detail\r
233 the configuration requirement.\r
234\r
235 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.\r
d1102dba 236 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
9060e3ec 237 @retval EFI_OUT_OF_RESOURCES No memory available.\r
238 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.\r
239\r
240**/\r
241EFI_STATUS\r
242EFIAPI\r
243PCheckDevice (\r
244 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This,\r
245 IN UINTN VendorId,\r
246 IN UINTN DeviceId,\r
247 IN UINTN RevisionId,\r
248 IN UINTN SubsystemVendorId,\r
249 IN UINTN SubsystemDeviceId,\r
250 OUT VOID **Configuration\r
251 )\r
252{\r
253 UINT64 Tag;\r
254 UINT64 *ListPtr;\r
255 UINT64 *TempListPtr;\r
256 EFI_PCI_DEVICE_HEADER_INFO *Header;\r
257 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;\r
258 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;\r
259 EFI_PCI_RESOUCE_DESCRIPTOR *Dsc;\r
260 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
261 UINTN Index;\r
262\r
263 //\r
264 // Validate the parameters\r
265 //\r
266 if (Configuration == NULL) {\r
267 return EFI_INVALID_PARAMETER;\r
268 }\r
269 //\r
270 // Initialize the return value to NULL\r
271 //\r
272 * (VOID **) Configuration = NULL;\r
273\r
274 ListPtr = mIncompatiblePciDeviceList;\r
275 while (*ListPtr != LIST_END_TAG) {\r
276\r
277 Tag = *ListPtr;\r
278\r
279 switch (Tag) {\r
280 case DEVICE_INF_TAG:\r
281 Header = (EFI_PCI_DEVICE_HEADER_INFO *) (ListPtr + 1);\r
282 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO) / sizeof (UINT64);\r
283 //\r
284 // See if the Header matches the parameters passed in\r
285 //\r
29dbdcab 286 if ((Header->VendorId != MAX_UINT64) && (VendorId != MAX_UINTN)) {\r
9060e3ec 287 if (Header->VendorId != VendorId) {\r
288 continue;\r
289 }\r
290 }\r
291\r
29dbdcab 292 if ((Header->DeviceId != MAX_UINT64) && (DeviceId != MAX_UINTN)) {\r
9060e3ec 293 if (DeviceId != Header->DeviceId) {\r
294 continue;\r
295 }\r
296 }\r
297\r
29dbdcab 298 if ((Header->RevisionId != MAX_UINT64) && (RevisionId != MAX_UINTN)) {\r
9060e3ec 299 if (RevisionId != Header->RevisionId) {\r
300 continue;\r
301 }\r
302 }\r
303\r
29dbdcab 304 if ((Header->SubsystemVendorId != MAX_UINT64) && (SubsystemVendorId != MAX_UINTN)) {\r
9060e3ec 305 if (SubsystemVendorId != Header->SubsystemVendorId) {\r
306 continue;\r
307 }\r
308 }\r
309\r
29dbdcab 310 if ((Header->SubsystemDeviceId != MAX_UINT64) && (SubsystemDeviceId != MAX_UINTN)) {\r
9060e3ec 311 if (SubsystemDeviceId != Header->SubsystemDeviceId) {\r
312 continue;\r
313 }\r
314 }\r
315 //\r
316 // Matched an item, so construct the ACPI descriptor for the resource.\r
317 //\r
318 //\r
319 // Count the resource items so that to allocate space\r
320 //\r
321 for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {\r
322 TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
323 }\r
324 //\r
325 // If there is at least one type of resource request,\r
326 // allocate an acpi resource node\r
327 //\r
328 if (Index == 0) {\r
329 return EFI_UNSUPPORTED;\r
330 }\r
331\r
332 AcpiPtr = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
333 if (AcpiPtr == NULL) {\r
334 return EFI_OUT_OF_RESOURCES;\r
335 }\r
336\r
337 OldAcpiPtr = AcpiPtr;\r
338 //\r
339 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure\r
340 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure\r
341 //\r
342 for (; *ListPtr == DEVICE_RES_TAG;) {\r
343\r
344 Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);\r
345\r
346 AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
e03a460f 347 AcpiPtr->Len = (UINT16) sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
9060e3ec 348 AcpiPtr->ResType = (UINT8) Dsc->ResType;\r
349 AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;\r
350 AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;\r
351 AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;\r
352 AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;\r
353 AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;\r
354 AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;\r
355 AcpiPtr->AddrLen = Dsc->AddrLen;\r
356\r
357 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
358 AcpiPtr++;\r
359 }\r
360 //\r
361 // Put the checksum\r
362 //\r
363 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);\r
364 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
365 PtrEnd->Checksum = 0;\r
366\r
367 *(VOID **) Configuration = OldAcpiPtr;\r
368\r
369 return EFI_SUCCESS;\r
370\r
371 case DEVICE_RES_TAG:\r
372 //\r
373 // Adjust the pointer to the next PCI resource descriptor item\r
374 //\r
375 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
376 break;\r
377\r
378 default:\r
379 return EFI_UNSUPPORTED;\r
380 }\r
381 }\r
382\r
383 return EFI_UNSUPPORTED;\r
384}\r
385\r