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