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