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