]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.c
Reviewed the code comments in the Include/Protocol directory for typos, grammar issue...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / PciIncompatibleDeviceSupportLib / PciIncompatibleDeviceSupportLib.c
1 /** @file
2 The implementation of PCI incompatible device support libary.
3
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "IncompatiblePciDeviceList.h"
16
17 /**
18 Check whether two PCI devices matched
19
20 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
21 @param Header A pointer to EFI_PCI_DEVICE_INFO.
22
23 @retval returns EFI_SUCCESS if two PCI device matched.
24 **/
25 EFI_STATUS
26 DeviceCheck (
27 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
28 IN EFI_PCI_DEVICE_INFO *Header
29 )
30 {
31 //
32 // See if the Header matches the parameters passed in
33 //
34 if (Header->VendorID != DEVICE_ID_NOCARE) {
35 if (PciDeviceInfo->VendorID != Header->VendorID) {
36 return EFI_UNSUPPORTED;
37 }
38 }
39
40 if (Header->DeviceID != DEVICE_ID_NOCARE) {
41 if (PciDeviceInfo->DeviceID != Header->DeviceID) {
42 return EFI_UNSUPPORTED;
43 }
44 }
45
46 if (Header->RevisionID != DEVICE_ID_NOCARE) {
47 if (PciDeviceInfo->RevisionID != Header->RevisionID) {
48 return EFI_UNSUPPORTED;
49 }
50 }
51
52 if (Header->SubsystemVendorID != DEVICE_ID_NOCARE) {
53 if (PciDeviceInfo->SubsystemVendorID != Header->SubsystemVendorID) {
54 return EFI_UNSUPPORTED;
55 }
56 }
57
58 if (Header->SubsystemID != DEVICE_ID_NOCARE) {
59 if (PciDeviceInfo->SubsystemID != Header->SubsystemID) {
60 return EFI_UNSUPPORTED;
61 }
62 }
63
64 return EFI_SUCCESS;
65 }
66
67
68 /**
69 Check the incompatible device list for ACPI resource update and return
70 the configuration
71
72 This function searches the incompatible device list according to request
73 information. If the PCI device belongs to the devices list, corresponding
74 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
75
76 @param PciDeviceInfo A pointer to PCI device information.
77 @param Configuration Returned information.
78
79 @retval returns EFI_SUCCESS if check incompatible device ok.
80 Otherwise return EFI_UNSUPPORTED.
81 **/
82 RETURN_STATUS
83 EFIAPI
84 PciResourceUpdateCheck (
85 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
86 OUT VOID *Configuration
87 )
88 {
89 UINT64 Tag;
90 UINT64 *ListPtr;
91 UINT64 *TempListPtr;
92 EFI_PCI_DEVICE_INFO *Header;
93 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;
94 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;
95 EFI_PCI_RESOUCE_DESCRIPTOR *Dsc;
96 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
97 UINTN Index;
98
99 ASSERT (PciDeviceInfo != NULL);
100
101 //
102 // Initialize the return value to NULL
103 //
104 * (VOID **) Configuration = NULL;
105
106 ListPtr = IncompatiblePciDeviceListForResource;
107 while (*ListPtr != LIST_END_TAG) {
108
109 Tag = *ListPtr;
110
111 switch (Tag) {
112 case DEVICE_INF_TAG:
113 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
114 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
115
116 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
117 continue;
118 }
119
120 //
121 // Matched an item, so construct the ACPI descriptor for the resource.
122 //
123 //
124 // Count the resource items so that to allocate space
125 //
126 for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {
127 TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
128 }
129 //
130 // If there is at least one type of resource request,
131 // allocate a acpi resource node
132 //
133 if (Index == 0) {
134 return EFI_ABORTED;
135 }
136
137 AcpiPtr = AllocateZeroPool (
138 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
139 );
140 if (AcpiPtr == NULL) {
141 return EFI_OUT_OF_RESOURCES;
142 }
143
144 OldAcpiPtr = AcpiPtr;
145
146 //
147 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
148 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
149 //
150 for (; *ListPtr == DEVICE_RES_TAG;) {
151
152 Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);
153
154 AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
155 AcpiPtr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
156 AcpiPtr->ResType = (UINT8) Dsc->ResType;
157 AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;
158 AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;
159 AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;
160 AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;
161 AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;
162 AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;
163 AcpiPtr->AddrLen = Dsc->AddrLen;
164
165 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
166 AcpiPtr++;
167 }
168 //
169 // put the checksum
170 //
171 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);
172 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
173 PtrEnd->Checksum = 0;
174
175 *(VOID **) Configuration = OldAcpiPtr;
176
177 return EFI_SUCCESS;
178
179 case DEVICE_RES_TAG:
180 //
181 // Adjust the pointer to the next PCI resource descriptor item
182 //
183 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
184 break;
185
186 default:
187 return EFI_UNSUPPORTED;
188 }
189 }
190
191 return EFI_UNSUPPORTED;
192
193 }
194
195 /**
196 Check the incompatible device list and return configuraton register mask values.
197
198 This function searches the incompatible device list according to request
199 information. If the PCI device belongs to the devices list, corresponding
200 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
201
202 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
203 @param AccessType Access Type, READ or WRITE.
204 @param Offset The address within the PCI configuration space.
205 @param Configuration Returned information.
206
207 @retval returns EFI_SUCCESS if check incompatible device ok.
208 Otherwise return EFI_UNSUPPORTED.
209 **/
210 RETURN_STATUS
211 EFIAPI
212 PciRegisterUpdateCheck (
213 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
214 IN UINT64 AccessType,
215 IN UINT64 Offset,
216 OUT VOID *Configuration
217 )
218 {
219 EFI_PCI_DEVICE_INFO *Header;
220 UINT64 Tag;
221 UINT64 *ListPtr;
222 EFI_PCI_REGISTER_VALUE_DATA *RegisterPtr;
223 EFI_PCI_REGISTER_VALUE_DATA *Dsc;
224
225 ASSERT (PciDeviceInfo != NULL);
226
227 ListPtr = IncompatiblePciDeviceListForRegister;
228
229 //
230 // Initialize the return value to NULL
231 //
232 * (VOID **) Configuration = NULL;
233
234 while (*ListPtr != LIST_END_TAG) {
235
236 Tag = *ListPtr;
237
238 switch (Tag) {
239 case DEVICE_INF_TAG:
240 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
241 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
242
243 //
244 // Check whether the PCI device matches the device in the incompatible devices list?
245 // If not, ship next
246 //
247 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
248 continue;
249 }
250
251 //
252 // Matched an item, check whether access matches?
253 //
254 for (; *ListPtr == DEVICE_RES_TAG;) {
255 ListPtr ++;
256 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->Offset == (Offset & 0xfc)) {
257 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->AccessType == AccessType) {
258
259 Dsc = (EFI_PCI_REGISTER_VALUE_DATA *) (ListPtr + 2);
260 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA));
261 if (RegisterPtr == NULL) {
262 return EFI_SUCCESS;
263 }
264
265 RegisterPtr->AndValue = Dsc->AndValue;
266 RegisterPtr->OrValue = Dsc->OrValue;
267
268 *(VOID **) Configuration = RegisterPtr;
269
270 return EFI_SUCCESS;
271 }
272 }
273 ListPtr += sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR) / (sizeof (UINT64));
274 }
275 return EFI_UNSUPPORTED;
276
277 case DEVICE_RES_TAG:
278 //
279 // Adjust the pointer to the next item
280 //
281 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR)) / sizeof (UINT64));
282 break;
283
284 default:
285 return EFI_UNSUPPORTED;
286 }
287 }
288
289 return EFI_UNSUPPORTED;
290 }
291
292 /**
293 Check the incompatible device list for access width incompatibility and
294 return the configuration
295
296 This function searches the incompatible device list for access width
297 incompatibility according to request information. If the PCI device
298 belongs to the devices list, corresponding configuration informtion
299 will be returned, in the meantime return EFI_SUCCESS.
300
301 @param PciDeviceInfo A pointer to PCI device information.
302 @param AccessType Access type, READ or WRITE.
303 @param Offset The address within the PCI configuration space.
304 @param AccessWidth Access width needs to check incompatibility.
305 @param Configuration Returned information.
306
307 @retval returns EFI_SUCCESS if check incompatible device ok.
308 Otherwise return EFI_UNSUPPORTED.
309 **/
310 RETURN_STATUS
311 EFIAPI
312 PciRegisterAccessCheck (
313 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
314 IN UINT64 AccessType,
315 IN UINT64 Offset,
316 IN UINT64 AccessWidth,
317 OUT VOID *Configuration
318 )
319 {
320 EFI_PCI_DEVICE_INFO *Header;
321 UINT64 Tag;
322 UINT64 *ListPtr;
323 EFI_PCI_REGISTER_ACCESS_DATA *RegisterPtr;
324 EFI_PCI_REGISTER_ACCESS_DATA *Dsc;
325
326 ASSERT (PciDeviceInfo != NULL);
327
328 ListPtr = DeviceListForAccessWidth;
329
330 //
331 // Initialize the return value to NULL
332 //
333 * (VOID **) Configuration = NULL;
334
335 while (*ListPtr != LIST_END_TAG) {
336
337 Tag = *ListPtr;
338
339 switch (Tag) {
340 case DEVICE_INF_TAG:
341 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
342 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
343
344 //
345 // Check whether the PCI device matches the device in the incompatible devices list?
346 // If not, ship next
347 //
348 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
349 continue;
350 }
351
352 //
353 // Matched an item, check whether access matches?
354 //
355 for (; *ListPtr == DEVICE_RES_TAG;) {
356 ListPtr ++;
357 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessType == AccessType &&
358 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessWidth == AccessWidth ) {
359
360 Dsc = (EFI_PCI_REGISTER_ACCESS_DATA *) (ListPtr + 2);
361
362 if((Dsc->StartOffset <= Offset) && (Dsc->EndOffset > Offset)) {
363
364 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA));
365 if (RegisterPtr == NULL) {
366 return EFI_OUT_OF_RESOURCES;
367 }
368
369 RegisterPtr->StartOffset = Dsc->StartOffset;
370 RegisterPtr->EndOffset = Dsc->EndOffset;
371 RegisterPtr->Width = Dsc->Width;
372
373 *(VOID **) Configuration = RegisterPtr;
374
375 return EFI_SUCCESS;
376 }
377 }
378 ListPtr += sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR) / (sizeof (UINT64));
379 }
380 return EFI_UNSUPPORTED;
381
382 case DEVICE_RES_TAG:
383 //
384 // Adjust the pointer to the next item
385 //
386 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR)) / sizeof (UINT64));
387 break;
388
389 default:
390 return EFI_UNSUPPORTED;
391 }
392 }
393
394 return EFI_UNSUPPORTED;
395 }
396