]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c
QuarkPlatformPkg: Add new package for Galileo boards
[mirror_edk2.git] / QuarkPlatformPkg / Acpi / Dxe / AcpiPlatform / AcpiPciUpdate.c
CommitLineData
b303605e
MK
1/** @file\r
2Update the _PRT and _PRW method for pci devices\r
3\r
4Copyright (c) 2013-2015 Intel Corporation.\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14\r
15**/\r
16#include "AcpiPlatform.h"\r
17\r
18PCI_DEVICE_INFO *mQNCPciInfo = NULL;\r
19\r
20/**\r
21 Init Pci Device Structure\r
22 @param mConfigData - Pointer of Pci Device information Structure\r
23\r
24**/\r
25VOID\r
26InitPciDeviceInfoStructure (\r
27 PCI_DEVICE_SETTING *mConfigData\r
28 )\r
29{\r
30 //\r
31 // Return 0 given that function unsupported.\r
32 // Would need to parse ACPI tables and build mQNCPciInfo above\r
33 // with found _PRT & _PRW methods for PCI devices.\r
34 //\r
35 mConfigData->PciDeviceInfoNumber = 0;\r
36}\r
37\r
38/**\r
39 return Integer value.\r
40\r
41 @param Data - AML data buffer\r
42 @param Integer - integer value.\r
43\r
44 @return Data size processed.\r
45**/\r
46UINTN\r
47SdtGetInteger (\r
48 IN UINT8 *Data,\r
49 OUT UINT64 *Integer\r
50 )\r
51{\r
52 *Integer = 0;\r
53 switch (*Data) {\r
54 case AML_ZERO_OP:\r
55 return 1;\r
56 case AML_ONE_OP:\r
57 *Integer = 1;\r
58 return 1;\r
59 case AML_ONES_OP:\r
60 *Integer = (UINTN)-1;\r
61 return 1;\r
62 case AML_BYTE_PREFIX:\r
63 CopyMem (Integer, Data + 1, sizeof(UINT8));\r
64 return 1 + sizeof(UINT8);\r
65 case AML_WORD_PREFIX:\r
66 CopyMem (Integer, Data + 1, sizeof(UINT16));\r
67 return 1 + sizeof(UINT16);\r
68 case AML_DWORD_PREFIX:\r
69 CopyMem (Integer, Data + 1, sizeof(UINT32));\r
70 return 1 + sizeof(UINT32);\r
71 case AML_QWORD_PREFIX:\r
72 CopyMem (Integer, Data + 1, sizeof(UINT64));\r
73 return 1 + sizeof(UINT64);\r
74 default:\r
75 // Something wrong\r
76 ASSERT (FALSE);\r
77 return 1;\r
78 }\r
79}\r
80\r
81\r
82/**\r
83 Check if this handle has expected opcode.\r
84\r
85 @param AcpiSdt Pointer to Acpi SDT protocol\r
86 @param Handle ACPI handle\r
87 @param OpCode Expected OpCode\r
88 @param SubOpCode Expected SubOpCode\r
89\r
90 @retval TURE This handle has expected opcode\r
91 @retval FALSE This handle does not have expected opcode\r
92**/\r
93BOOLEAN\r
94SdtIsThisTypeObject (\r
95 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
96 IN EFI_ACPI_HANDLE Handle,\r
97 IN UINT8 OpCode,\r
98 IN UINT8 SubOpCode\r
99 )\r
100{\r
101 EFI_STATUS Status;\r
102 EFI_ACPI_DATA_TYPE DataType;\r
103 UINT8 *Data;\r
104 UINTN DataSize;\r
105\r
106 Status = AcpiSdt->GetOption (Handle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
107 ASSERT_EFI_ERROR (Status);\r
108 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
109\r
110 if (OpCode == AML_EXT_OP) {\r
111 if (Data[1] == SubOpCode) {\r
112 return TRUE;\r
113 }\r
114 } else {\r
115 if (Data[0] == OpCode) {\r
116 return TRUE;\r
117 }\r
118 }\r
119 return FALSE;\r
120}\r
121\r
122/**\r
123 Check if this handle has expected name and name value.\r
124\r
125 @param AcpiSdt Pointer to Acpi SDT protocol\r
126 @param Handle ACPI handle\r
127 @param Name Expected name\r
128 @param Value Expected name value\r
129\r
130 @retval TURE This handle has expected name and name value.\r
131 @retval FALSE This handle does not have expected name and name value.\r
132**/\r
133BOOLEAN\r
134SdtIsNameIntegerValueEqual (\r
135 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
136 IN EFI_ACPI_HANDLE Handle,\r
137 IN CHAR8 *Name,\r
138 IN UINT64 Value\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142 EFI_ACPI_DATA_TYPE DataType;\r
143 UINT8 *Data;\r
144 UINTN DataSize;\r
145 UINT64 Integer;\r
146\r
147 Status = AcpiSdt->GetOption (Handle, 1, &DataType, (CONST VOID **)&Data, &DataSize);\r
148 ASSERT_EFI_ERROR (Status);\r
149 ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);\r
150\r
151 if (CompareMem (Data, Name, 4) != 0) {\r
152 return FALSE;\r
153 }\r
154\r
155 //\r
156 // Name match check object\r
157 //\r
158 Status = AcpiSdt->GetOption (Handle, 2, &DataType, (CONST VOID **)&Data, &DataSize);\r
159 ASSERT_EFI_ERROR (Status);\r
160\r
161 Integer = 0;\r
162 SdtGetInteger (Data, &Integer);\r
163 if (Integer != Value) {\r
164 return FALSE;\r
165 }\r
166\r
167 // All match\r
168 return TRUE;\r
169}\r
170\r
171/**\r
172 Check if this handle's children has expected name and name value.\r
173\r
174 @param AcpiSdt Pointer to Acpi SDT protocol\r
175 @param ParentHandle ACPI parent handle\r
176 @param Name Expected name\r
177 @param Value Expected name value\r
178\r
179 @retval TURE This handle's children has expected name and name value.\r
180 @retval FALSE This handle's children does not have expected name and name value.\r
181**/\r
182BOOLEAN\r
183SdtCheckNameIntegerValue (\r
184 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
185 IN EFI_ACPI_HANDLE ParentHandle,\r
186 IN CHAR8 *Name,\r
187 IN UINT64 Value\r
188 )\r
189{\r
190 EFI_ACPI_HANDLE PreviousHandle;\r
191 EFI_ACPI_HANDLE Handle;\r
192 EFI_STATUS Status;\r
193\r
194 Handle = NULL;\r
195 while (TRUE) {\r
196 PreviousHandle = Handle;\r
197 Status = AcpiSdt->GetChild (ParentHandle, &Handle);\r
198 ASSERT_EFI_ERROR (Status);\r
199\r
200 if (PreviousHandle != NULL) {\r
201 Status = AcpiSdt->Close (PreviousHandle);\r
202 ASSERT_EFI_ERROR (Status);\r
203 }\r
204\r
205 //\r
206 // Done\r
207 //\r
208 if (Handle == NULL) {\r
209 return FALSE;\r
210 }\r
211\r
212 //\r
213 // Check this name\r
214 //\r
215 if (SdtIsThisTypeObject (AcpiSdt, Handle, AML_NAME_OP, 0)) {\r
216 if (SdtIsNameIntegerValueEqual (AcpiSdt, Handle, Name, Value)) {\r
217 return TRUE;\r
218 }\r
219 }\r
220 }\r
221\r
222 //\r
223 // Should not run here\r
224 //\r
225}\r
226\r
227/**\r
228 Convert the pci address from VPD (bus,dev,fun) into the address that acpi table\r
229 can recognize.\r
230\r
231 @param PciAddress Pci address from VPD\r
232\r
233 @retval return the address that acpi table can recognize\r
234**/\r
235UINT32\r
236SdtConvertToAcpiPciAdress (\r
237 IN UINT32 PciAddress\r
238 )\r
239{\r
240 UINT32 ReturnAddress;\r
241\r
242 ReturnAddress = ((PciAddress & 0x0000FF00) << 8) | (PciAddress & 0x000000FF);\r
243\r
244 if ((PciAddress & 0x000000FF) == 0x000000FF)\r
245 ReturnAddress |= 0x0000FFFF;\r
246\r
247 return ReturnAddress;\r
248}\r
249\r
250/**\r
251 return AML NameString size.\r
252\r
253 @param Buffer - AML name string\r
254\r
255 @return AML name string size\r
256**/\r
257UINTN\r
258SdtGetNameStringSize (\r
259 IN UINT8 *Buffer\r
260 )\r
261{\r
262 UINTN SegCount;\r
263 UINTN Length;\r
264 UINT8 *Name;\r
265\r
266 Name = Buffer;\r
267 Length = 0;\r
268\r
269 //\r
270 // Parse root or prefix\r
271 //\r
272 if (*Buffer == AML_ROOT_CHAR) {\r
273 //\r
274 // RootChar\r
275 //\r
276 Buffer ++;\r
277 Length ++;\r
278 } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
279 //\r
280 // ParentPrefixChar\r
281 //\r
282 Buffer ++;\r
283 Length ++;\r
284 while (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
285 Buffer ++;\r
286 Length ++;\r
287 }\r
288 }\r
289\r
290 //\r
291 // Parse name segment\r
292 //\r
293 if (*Buffer == AML_DUAL_NAME_PREFIX) {\r
294 //\r
295 // DualName\r
296 //\r
297 Buffer ++;\r
298 Length ++;\r
299 SegCount = 2;\r
300 } else if (*Buffer == AML_MULTI_NAME_PREFIX) {\r
301 //\r
302 // MultiName\r
303 //\r
304 Buffer ++;\r
305 Length ++;\r
306 SegCount = *Buffer;\r
307 Buffer ++;\r
308 Length ++;\r
309 } else if (*Buffer == 0) {\r
310 //\r
311 // NULL Name\r
312 //\r
313 SegCount = 0;\r
314 Length ++;\r
315 } else {\r
316 //\r
317 // NameSeg\r
318 //\r
319 SegCount = 1;\r
320 }\r
321\r
322 Buffer += 4 * SegCount;\r
323 Length += 4 * SegCount;\r
324\r
325 return Length;\r
326}\r
327\r
328/**\r
329 The routine to check if this device is PCI root bridge.\r
330\r
331 @param AcpiSdt Pointer to Acpi SDT protocol\r
332 @param DeviceHandle ACPI device handle\r
333 @param Context Context info - not used here\r
334\r
335 @retval TRUE This is PCI root bridge\r
336 @retval FALSE This is not PCI root bridge\r
337**/\r
338BOOLEAN\r
339SdtFindRootBridgeHandle (\r
340 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
341 IN EFI_ACPI_HANDLE CheckHandle,\r
342 IN VOID *Context\r
343 )\r
344{\r
345 BOOLEAN Result;\r
346 EFI_ACPI_DATA_TYPE DataType;\r
347 UINT8 *Data;\r
348 UINTN DataSize;\r
349 EFI_STATUS Status;\r
350\r
351 if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))\r
352 return FALSE;\r
353\r
354 Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_HID", (UINT64)0x080AD041); // PNP0A08\r
355 if (!Result) {\r
356 Result = SdtCheckNameIntegerValue (AcpiSdt, CheckHandle, "_CID", (UINT64)0x030AD041); // PNP0A03\r
357 if (!Result) {\r
358 return Result;\r
359 }\r
360 }\r
361\r
362 //\r
363 // Found\r
364 //\r
365 Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);\r
366 ASSERT_EFI_ERROR (Status);\r
367 ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);\r
368\r
369 return Result;\r
370}\r
371\r
372\r
373/**\r
374 The routine to check if this device is wanted.\r
375\r
376 @param AcpiSdt Pointer to Acpi SDT protocol\r
377 @param DeviceHandle ACPI device handle\r
378 @param Context Context info - not used here\r
379\r
380 @retval TRUE This is PCI device wanted\r
381 @retval FALSE This is not PCI device wanted\r
382**/\r
383BOOLEAN\r
384SdtFindPciDeviceHandle (\r
385 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
386 IN EFI_ACPI_HANDLE CheckHandle,\r
387 IN VOID *Context\r
388 )\r
389{\r
390 BOOLEAN Result;\r
391 EFI_ACPI_DATA_TYPE DataType;\r
392 UINT8 *Data;\r
393 UINTN DataSize;\r
394 EFI_STATUS Status;\r
395\r
396 if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))\r
397 return FALSE;\r
398\r
399 Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_ADR", (UINT64)*(UINT32 *)Context);\r
400 if (!Result) {\r
401 return Result;\r
402 }\r
403\r
404 //\r
405 // Found\r
406 //\r
407 Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);\r
408 ASSERT_EFI_ERROR (Status);\r
409 ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);\r
410\r
411 return Result;\r
412}\r
413\r
414/**\r
415 Go through the parent handle and find the handle which pass CheckHandleInfo.\r
416\r
417 @param AcpiSdt Pointer to Acpi SDT protocol\r
418 @param ParentHandle ACPI parent handle\r
419 @param CheckHandleInfo The callback routine to check if this handle meet the requirement\r
420 @param Context The context of CheckHandleInfo\r
421\r
422 @return the handle which is first one can pass CheckHandleInfo.\r
423**/\r
424EFI_ACPI_HANDLE\r
425SdtGetHandleByScanAllChilds (\r
426 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
427 IN EFI_ACPI_HANDLE ParentHandle,\r
428 IN CHECK_HANDLE_INFO CheckHandleInfo,\r
429 IN VOID *Context\r
430 )\r
431{\r
432 EFI_ACPI_HANDLE PreviousHandle;\r
433 EFI_ACPI_HANDLE Handle;\r
434 EFI_STATUS Status;\r
435 EFI_ACPI_HANDLE ReturnHandle;\r
436\r
437 //\r
438 // Use deep first algo to enumerate all ACPI object\r
439 //\r
440 Handle = NULL;\r
441 while (TRUE) {\r
442 PreviousHandle = Handle;\r
443 Status = AcpiSdt->GetChild (ParentHandle, &Handle);\r
444 ASSERT_EFI_ERROR (Status);\r
445\r
446 if (PreviousHandle != NULL) {\r
447 Status = AcpiSdt->Close (PreviousHandle);\r
448 ASSERT_EFI_ERROR (Status);\r
449 }\r
450\r
451 //\r
452 // Done\r
453 //\r
454 if (Handle == NULL) {\r
455 return NULL;\r
456 }\r
457\r
458 //\r
459 // Check this handle\r
460 //\r
461 if (CheckHandleInfo (AcpiSdt, Handle, Context)) {\r
462 return Handle;\r
463 }\r
464\r
465 //\r
466 // Enumerate\r
467 //\r
468 ReturnHandle = SdtGetHandleByScanAllChilds (AcpiSdt, Handle, CheckHandleInfo, Context);\r
469 if (ReturnHandle != NULL) {\r
470 return ReturnHandle;\r
471 }\r
472 }\r
473\r
474 //\r
475 // Should not run here\r
476 //\r
477}\r
478\r
479\r
480/**\r
481 Check whether the INTx package is matched\r
482\r
483 @param AcpiSdt Pointer to Acpi SDT protocol\r
484 @param INTxPkgHandle ACPI INTx package handle\r
485 @param PciAddress Acpi pci address\r
486 @param INTx Index of INTx pin\r
487 @param IsAPIC Tell whether the returned INTx package is for APIC or not\r
488\r
489 @retval TRUE the INTx package is matched\r
490 @retval FALSE the INTx package is not matched\r
491\r
492**/\r
493BOOLEAN\r
494SdtCheckINTxPkgIsMatch (\r
495 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
496 IN EFI_ACPI_HANDLE INTxPkgHandle,\r
497 IN UINT32 PciAddress,\r
498 IN UINT8 INTx,\r
499 IN BOOLEAN *IsAPIC\r
500 )\r
501{\r
502 EFI_ACPI_HANDLE PreviousHandle;\r
503 EFI_STATUS Status;\r
504 EFI_ACPI_HANDLE MemberHandle;\r
505 EFI_ACPI_DATA_TYPE DataType;\r
506 UINT8 *Data;\r
507 UINTN DataSize;\r
508 UINT64 CurrentPciAddress;\r
509 UINT64 CurrentINTx;\r
510 UINTN ChildSize;\r
511\r
512\r
513 //\r
514 // Check the pci address\r
515 //\r
516 MemberHandle = NULL;\r
517 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
518 ASSERT_EFI_ERROR (Status);\r
519 ASSERT (MemberHandle != NULL);\r
520\r
521 Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
522 ASSERT_EFI_ERROR (Status);\r
523 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
524\r
525 CurrentPciAddress = 0;\r
526 SdtGetInteger (Data, &CurrentPciAddress);\r
527\r
528 if (CurrentPciAddress != PciAddress) {\r
529\r
530 Status = AcpiSdt->Close (MemberHandle);\r
531 ASSERT_EFI_ERROR (Status);\r
532 return FALSE;\r
533 }\r
534\r
535 //\r
536 // Check the pci interrupt pin\r
537 //\r
538 PreviousHandle = MemberHandle;\r
539 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
540 ASSERT_EFI_ERROR (Status);\r
541 ASSERT (MemberHandle != NULL);\r
542\r
543 if (PreviousHandle != NULL) {\r
544 Status = AcpiSdt->Close (PreviousHandle);\r
545 ASSERT_EFI_ERROR (Status);\r
546 }\r
547\r
548 Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
549 ASSERT_EFI_ERROR (Status);\r
550 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
551\r
552 CurrentINTx = 0;\r
553 ChildSize = SdtGetInteger (Data, &CurrentINTx);\r
554\r
555 Status = AcpiSdt->Close (MemberHandle);\r
556 ASSERT_EFI_ERROR (Status);\r
557\r
558 if (CurrentINTx != INTx)\r
559 return FALSE;\r
560\r
561 Data += ChildSize;\r
562\r
563 if (*Data == AML_BYTE_PREFIX)\r
564 Data += 1;\r
565\r
566 //\r
567 // Check the pci interrupt source\r
568 //\r
569 if (*Data != 0)\r
570 *IsAPIC = FALSE;\r
571 else\r
572 *IsAPIC = TRUE;\r
573\r
574 return TRUE;\r
575}\r
576\r
577\r
578\r
579\r
580/**\r
581 Get the wanted INTx package inside the parent package\r
582\r
583 @param AcpiSdt Pointer to Acpi SDT protocol\r
584 @param ParentPkgHandle ACPI parent package handle\r
585 @param PciAddress Acpi pci address\r
586 @param INTx Index of INTx pin\r
587 @param INTxPkgHandle ACPI INTx package handle\r
588 @param IsAPIC Tell whether the returned INTx package is for APIC or not\r
589\r
590**/\r
591VOID\r
592SdtGetINTxPkgHandle (\r
593 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
594 IN EFI_ACPI_HANDLE ParentPkgHandle,\r
595 IN UINT32 PciAddress,\r
596 IN UINT8 INTx,\r
597 IN EFI_ACPI_HANDLE *INTxPkgHandle,\r
598 IN BOOLEAN *IsAPIC\r
599 )\r
600{\r
601 EFI_ACPI_HANDLE PreviousHandle;\r
602 EFI_STATUS Status;\r
603 EFI_ACPI_HANDLE ChildPkgHandle;\r
604\r
605 ChildPkgHandle = NULL;\r
606 while (TRUE) {\r
607 PreviousHandle = ChildPkgHandle;\r
608 Status = AcpiSdt->GetChild (ParentPkgHandle, &ChildPkgHandle);\r
609 ASSERT_EFI_ERROR (Status);\r
610\r
611 if (PreviousHandle != NULL) {\r
612 Status = AcpiSdt->Close (PreviousHandle);\r
613 ASSERT_EFI_ERROR (Status);\r
614 }\r
615\r
616 if (ChildPkgHandle == NULL) {\r
617 break;\r
618 }\r
619\r
620 if (SdtCheckINTxPkgIsMatch(AcpiSdt, ChildPkgHandle, PciAddress, INTx, IsAPIC)) {\r
621 *INTxPkgHandle = ChildPkgHandle;\r
622 return;\r
623 }\r
624 }\r
625\r
626 return;\r
627}\r
628\r
629/**\r
630 Update the INTx package with the correct pirq value\r
631\r
632 @param AcpiSdt Pointer to Acpi SDT protocol\r
633 @param INTxPkgHandle ACPI INTx package handle\r
634 @param PirqValue Correct pirq value\r
635 @param IsAPIC Tell whether the INTx package is for APIC or not\r
636\r
637**/\r
638VOID\r
639SdtUpdateINTxPkg (\r
640 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
641 IN EFI_ACPI_HANDLE INTxPkgHandle,\r
642 IN UINT8 PirqValue,\r
643 IN BOOLEAN IsAPIC\r
644 )\r
645{\r
646 EFI_ACPI_HANDLE PreviousHandle;\r
647 EFI_STATUS Status;\r
648 EFI_ACPI_HANDLE MemberHandle;\r
649 EFI_ACPI_DATA_TYPE DataType;\r
650 UINT8 *Data;\r
651 UINTN DataSize;\r
652 UINT64 TempValue;\r
653 UINTN ChildSize;\r
654\r
655\r
656 //\r
657 // Check the pci address\r
658 //\r
659 MemberHandle = NULL;\r
660 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
661 ASSERT_EFI_ERROR (Status);\r
662 ASSERT (MemberHandle != NULL);\r
663\r
664 //\r
665 // Check the pci interrupt pin\r
666 //\r
667 PreviousHandle = MemberHandle;\r
668 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
669 ASSERT_EFI_ERROR (Status);\r
670 ASSERT (MemberHandle != NULL);\r
671\r
672 if (PreviousHandle != NULL) {\r
673 Status = AcpiSdt->Close (PreviousHandle);\r
674 ASSERT_EFI_ERROR (Status);\r
675 }\r
676\r
677 Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
678 ASSERT_EFI_ERROR (Status);\r
679 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
680\r
681 ChildSize = SdtGetInteger (Data, &TempValue);\r
682\r
683 Status = AcpiSdt->Close (MemberHandle);\r
684 ASSERT_EFI_ERROR (Status);\r
685\r
686 Data += ChildSize;\r
687\r
688 //\r
689 // update the pci interrupt source or source index\r
690 //\r
691 if (!IsAPIC) {\r
692 ChildSize = SdtGetNameStringSize (Data);\r
693 Data += (ChildSize - 1);\r
694\r
695 PirqValue += 0x40; // change to ascii char\r
696 if (*Data != PirqValue)\r
697 *Data = PirqValue;\r
698 } else {\r
699\r
700 ChildSize = SdtGetInteger (Data, &TempValue);\r
701 Data += ChildSize;\r
702\r
703 Data += 1;\r
704\r
705 if (*Data != PirqValue)\r
706 *Data = PirqValue;\r
707 }\r
708}\r
709\r
710/**\r
711 Check every child package inside this interested parent package for update PRT\r
712\r
713 @param AcpiSdt Pointer to Acpi SDT protocol\r
714 @param ParentPkgHandle ACPI parent package handle\r
715 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
716\r
717**/\r
718VOID\r
719SdtCheckParentPackage (\r
720 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
721 IN EFI_ACPI_HANDLE ParentPkgHandle,\r
722 IN PCI_DEVICE_INFO *PciDeviceInfo\r
723 )\r
724{\r
725 EFI_ACPI_HANDLE INTAPkgHandle;\r
726 EFI_ACPI_HANDLE INTBPkgHandle;\r
727 EFI_ACPI_HANDLE INTCPkgHandle;\r
728 EFI_ACPI_HANDLE INTDPkgHandle;\r
729 UINT32 PciAddress = 0;\r
730 BOOLEAN IsAllFunctions = FALSE;\r
731 UINT8 IsAPIC = 0;\r
732 EFI_STATUS Status;\r
733\r
734 INTAPkgHandle = INTBPkgHandle = INTCPkgHandle = INTDPkgHandle = NULL;\r
735\r
736 PciAddress = SdtConvertToAcpiPciAdress(PciDeviceInfo->DeviceAddress);\r
737\r
738 if ((PciAddress & 0xFFFF) == 0xFFFF) {\r
739 IsAllFunctions = TRUE;\r
740 } else {\r
741 IsAllFunctions = FALSE;\r
742 PciAddress = (PciAddress | 0xFFFF);\r
743 }\r
744\r
745 SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 0, &INTAPkgHandle, (BOOLEAN *)&IsAPIC);\r
746 SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 1, &INTBPkgHandle, (BOOLEAN *)&IsAPIC);\r
747 SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 2, &INTCPkgHandle, (BOOLEAN *)&IsAPIC);\r
748 SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 3, &INTDPkgHandle, (BOOLEAN *)&IsAPIC);\r
749\r
750 //\r
751 // Check INTA\r
752 //\r
753 if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle != NULL)) {\r
754 //\r
755 // Find INTA package and there is valid INTA update item, update it\r
756 //\r
757 SdtUpdateINTxPkg (AcpiSdt, INTAPkgHandle, (PciDeviceInfo->INTA[IsAPIC]), IsAPIC);\r
758 } else if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle == NULL)) {\r
759 //\r
760 // There is valid INTA update item, but no INA package exist, should add it\r
761 //\r
762 DEBUG ((EFI_D_ERROR, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress));\r
763\r
764 } else if ((PciDeviceInfo->INTA[IsAPIC] == 0xFF) && (INTAPkgHandle != NULL) && IsAllFunctions) {\r
765 //\r
766 // For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it\r
767 //\r
768 DEBUG ((EFI_D_ERROR, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress));\r
769\r
770 }\r
771\r
772 //\r
773 // Check INTB\r
774 //\r
775 if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle != NULL)) {\r
776 //\r
777 // Find INTB package and there is valid INTB update item, update it\r
778 //\r
779 SdtUpdateINTxPkg (AcpiSdt, INTBPkgHandle, (PciDeviceInfo->INTB[IsAPIC]), IsAPIC);\r
780 } else if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle == NULL)) {\r
781 //\r
782 // There is valid INTB update item, but no INTB package exist, should add it\r
783 //\r
784 DEBUG ((EFI_D_ERROR, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress));\r
785\r
786 } else if ((PciDeviceInfo->INTB[IsAPIC] == 0xFF) && (INTBPkgHandle != NULL) && IsAllFunctions) {\r
787 //\r
788 // For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it\r
789 //\r
790 DEBUG ((EFI_D_ERROR, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress));\r
791\r
792 }\r
793\r
794 //\r
795 // Check INTC\r
796 //\r
797 if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle != NULL)) {\r
798 //\r
799 // Find INTC package and there is valid INTC update item, update it\r
800 //\r
801 SdtUpdateINTxPkg (AcpiSdt, INTCPkgHandle, (PciDeviceInfo->INTC[IsAPIC]), IsAPIC);\r
802 } else if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle == NULL)) {\r
803 //\r
804 // There is valid INTC update item, but no INTC package exist, should add it\r
805 //\r
806 DEBUG ((EFI_D_ERROR, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress));\r
807\r
808 } else if ((PciDeviceInfo->INTC[IsAPIC] == 0xFF) && (INTCPkgHandle != NULL) && IsAllFunctions) {\r
809 //\r
810 // For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it\r
811 //\r
812 DEBUG ((EFI_D_ERROR, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress));\r
813 }\r
814\r
815 //\r
816 // Check INTD\r
817 //\r
818 if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle != NULL)) {\r
819 //\r
820 // Find INTD package and there is valid INTD update item, update it\r
821 //\r
822 SdtUpdateINTxPkg (AcpiSdt, INTDPkgHandle, (PciDeviceInfo->INTD[IsAPIC]), IsAPIC);\r
823 } else if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle == NULL)) {\r
824 //\r
825 // There is valid INTD update item, but no INTD package exist, should add it\r
826 //\r
827 DEBUG ((EFI_D_ERROR, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress));\r
828\r
829 } else if ((PciDeviceInfo->INTD[IsAPIC] == 0xFF) && (INTDPkgHandle != NULL) && IsAllFunctions) {\r
830 //\r
831 // For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it\r
832 //\r
833 DEBUG ((EFI_D_ERROR, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress));\r
834 }\r
835\r
836\r
837 if (INTAPkgHandle != NULL) {\r
838 Status = AcpiSdt->Close (INTAPkgHandle);\r
839 ASSERT_EFI_ERROR (Status);\r
840 }\r
841\r
842 if (INTBPkgHandle != NULL) {\r
843 Status = AcpiSdt->Close (INTBPkgHandle);\r
844 ASSERT_EFI_ERROR (Status);\r
845 }\r
846\r
847 if (INTCPkgHandle != NULL) {\r
848 Status = AcpiSdt->Close (INTCPkgHandle);\r
849 ASSERT_EFI_ERROR (Status);\r
850 }\r
851\r
852 if (INTDPkgHandle != NULL) {\r
853 Status = AcpiSdt->Close (INTDPkgHandle);\r
854 ASSERT_EFI_ERROR (Status);\r
855 }\r
856\r
857 return;\r
858}\r
859\r
860/**\r
861 Check every return package for update PRT\r
862\r
863 @param AcpiSdt Pointer to Acpi SDT protocol\r
864 @param ParentHandle ACPI pci device handle\r
865 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
866\r
867**/\r
868VOID\r
869SdtCheckReturnPackage (\r
870 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
871 IN EFI_ACPI_HANDLE MethodHandle,\r
872 IN PCI_DEVICE_INFO *PciDeviceInfo\r
873 )\r
874{\r
875 EFI_ACPI_HANDLE PreviousHandle;\r
876 EFI_ACPI_HANDLE ReturnHandle;\r
877 EFI_ACPI_HANDLE PackageHandle;\r
878 EFI_ACPI_HANDLE NamePkgHandle;\r
879 EFI_STATUS Status;\r
880 EFI_ACPI_DATA_TYPE DataType;\r
881 UINT8 *Data;\r
882 UINTN DataSize;\r
883 CHAR8 NameStr[128];\r
884\r
885 ReturnHandle = NULL;\r
886 while (TRUE) {\r
887 PreviousHandle = ReturnHandle;\r
888 Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle);\r
889 ASSERT_EFI_ERROR (Status);\r
890\r
891 if (PreviousHandle != NULL) {\r
892 Status = AcpiSdt->Close (PreviousHandle);\r
893 ASSERT_EFI_ERROR (Status);\r
894 }\r
895\r
896 if (ReturnHandle == NULL) {\r
897 break;\r
898 }\r
899\r
900 Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
901 ASSERT_EFI_ERROR (Status);\r
902 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
903\r
904 if (*Data == AML_RETURN_OP) {\r
905 //\r
906 // Find the return method handle, then look for the returned package data\r
907 //\r
908 Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);\r
909 ASSERT_EFI_ERROR (Status);\r
910\r
911\r
912 if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {\r
913 ZeroMem (NameStr, 128);\r
914 AsciiStrCpy (NameStr, "\\_SB.");\r
915 DataSize = SdtGetNameStringSize (Data);\r
916 AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize);\r
917\r
918 NamePkgHandle = NULL;\r
919 Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle);\r
920 ASSERT_EFI_ERROR (Status);\r
921 ASSERT (NamePkgHandle != NULL);\r
922\r
923 Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
924 ASSERT_EFI_ERROR (Status);\r
925 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
926 ASSERT (*Data == AML_NAME_OP);\r
927\r
928 Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);\r
929 ASSERT_EFI_ERROR (Status);\r
930 ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);\r
931 }\r
932\r
933 ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);\r
934\r
935 //\r
936 // Get the parent package handle\r
937 //\r
938 PackageHandle = NULL;\r
939 Status = AcpiSdt->Open (Data, &PackageHandle);\r
940 ASSERT_EFI_ERROR (Status);\r
941\r
942 //\r
943 // Check the parent package for update pci routing\r
944 //\r
945 SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo);\r
946\r
947 Status = AcpiSdt->Close (PackageHandle);\r
948 ASSERT_EFI_ERROR (Status);\r
949\r
950 Status = AcpiSdt->Close (ReturnHandle);\r
951 ASSERT_EFI_ERROR (Status);\r
952\r
953 break;\r
954 }\r
955\r
956 //\r
957 // Not ReturnOp, search it as parent\r
958 //\r
959 SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo);\r
960 }\r
961\r
962 //\r
963 // Done\r
964 //\r
965 return;\r
966\r
967}\r
968\r
969/**\r
970 update interrupt info inside the PRT method for the given pci device handle\r
971\r
972 @param AcpiSdt Pointer to Acpi SDT protocol\r
973 @param PciHandle ACPI pci device handle\r
974 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
975\r
976**/\r
977EFI_STATUS\r
978SdtUpdatePrtMethod (\r
979 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
980 IN EFI_ACPI_HANDLE PciHandle,\r
981 IN PCI_DEVICE_INFO *PciDeviceInfo\r
982 )\r
983{\r
984 EFI_STATUS Status;\r
985 EFI_ACPI_HANDLE PrtMethodHandle;\r
986\r
987 //\r
988 // Find the PRT method under this pci device\r
989 //\r
990 PrtMethodHandle = NULL;\r
991 Status = AcpiSdt->FindPath (PciHandle, "_PRT", &PrtMethodHandle);\r
992\r
993 if (EFI_ERROR (Status)) {\r
994 return EFI_INVALID_PARAMETER;\r
995 }\r
996\r
997 if (PrtMethodHandle == NULL) {\r
998 return EFI_INVALID_PARAMETER;\r
999 }\r
1000\r
1001 SdtCheckReturnPackage(AcpiSdt, PrtMethodHandle, PciDeviceInfo);\r
1002\r
1003 Status = AcpiSdt->Close (PrtMethodHandle);\r
1004 ASSERT_EFI_ERROR (Status);\r
1005\r
1006 return Status;\r
1007}\r
1008\r
1009\r
1010/**\r
1011 Update the package inside name op with correct wakeup resources\r
1012\r
1013 @param AcpiSdt Pointer to Acpi SDT protocol\r
1014 @param InPkgHandle ACPI inside package handle\r
1015 @param GPEPin Correct gpe pin\r
1016 @param SxNum Correct system state the device can wake up from\r
1017\r
1018**/\r
1019VOID\r
1020SdtUpdatePackageInName (\r
1021 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1022 IN EFI_ACPI_HANDLE INTxPkgHandle,\r
1023 IN UINT8 GPEPin,\r
1024 IN UINT8 SxNum\r
1025 )\r
1026{\r
1027 EFI_ACPI_HANDLE PreviousHandle;\r
1028 EFI_STATUS Status;\r
1029 EFI_ACPI_HANDLE MemberHandle;\r
1030 EFI_ACPI_DATA_TYPE DataType;\r
1031 UINT8 *Data;\r
1032 UINTN DataSize;\r
1033\r
1034 //\r
1035 // Check the gpe pin\r
1036 //\r
1037 MemberHandle = NULL;\r
1038 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
1039 ASSERT_EFI_ERROR (Status);\r
1040 ASSERT (MemberHandle != NULL);\r
1041\r
1042 Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
1043 ASSERT_EFI_ERROR (Status);\r
1044 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
1045\r
1046 //\r
1047 // Skip byte prefix\r
1048 //\r
1049 Data += 1;\r
1050\r
1051 if (*Data != GPEPin) {\r
1052\r
1053 *Data = GPEPin;\r
1054 }\r
1055\r
1056 //\r
1057 // Check the sx number\r
1058 //\r
1059 PreviousHandle = MemberHandle;\r
1060 Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);\r
1061 ASSERT_EFI_ERROR (Status);\r
1062 ASSERT (MemberHandle != NULL);\r
1063\r
1064 if (PreviousHandle != NULL) {\r
1065 Status = AcpiSdt->Close (PreviousHandle);\r
1066 ASSERT_EFI_ERROR (Status);\r
1067 }\r
1068\r
1069 Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
1070 ASSERT_EFI_ERROR (Status);\r
1071 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
1072\r
1073 //\r
1074 // Skip byte prefix\r
1075 //\r
1076 Data += 1;\r
1077\r
1078 if (*Data != SxNum) {\r
1079\r
1080 *Data = SxNum;\r
1081 }\r
1082\r
1083 Status = AcpiSdt->Close (MemberHandle);\r
1084 ASSERT_EFI_ERROR (Status);\r
1085\r
1086}\r
1087\r
1088/**\r
1089 Check the name package belonged to PRW\r
1090\r
1091 @param AcpiSdt Pointer to Acpi SDT protocol\r
1092 @param PrwPkgHandle ACPI PRW package handle\r
1093 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
1094\r
1095**/\r
1096VOID\r
1097SdtCheckNamePackage (\r
1098 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1099 IN EFI_ACPI_HANDLE PrwPkgHandle,\r
1100 IN PCI_DEVICE_INFO *PciDeviceInfo\r
1101 )\r
1102{\r
1103 EFI_ACPI_HANDLE InPkgHandle;\r
1104 EFI_STATUS Status;\r
1105 EFI_ACPI_DATA_TYPE DataType;\r
1106 UINT8 *Data;\r
1107 UINTN DataSize;\r
1108\r
1109 Status = AcpiSdt->GetOption (PrwPkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);\r
1110 ASSERT_EFI_ERROR (Status);\r
1111 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
1112 ASSERT (*Data == AML_NAME_OP);\r
1113\r
1114 Status = AcpiSdt->GetOption (PrwPkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);\r
1115 ASSERT_EFI_ERROR (Status);\r
1116 ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);\r
1117\r
1118 //\r
1119 // Get the inside package handle\r
1120 //\r
1121 InPkgHandle = NULL;\r
1122 Status = AcpiSdt->Open (Data, &InPkgHandle);\r
1123 ASSERT_EFI_ERROR (Status);\r
1124\r
1125 //\r
1126 // update the package in name op for wakeup info\r
1127 //\r
1128 if ((PciDeviceInfo->GPEPin != 0xFF) && (PciDeviceInfo->SxNum != 0xFF))\r
1129 SdtUpdatePackageInName (AcpiSdt, InPkgHandle, PciDeviceInfo->GPEPin, PciDeviceInfo->SxNum);\r
1130\r
1131 Status = AcpiSdt->Close (InPkgHandle);\r
1132 ASSERT_EFI_ERROR (Status);\r
1133\r
1134 return;\r
1135\r
1136}\r
1137\r
1138/**\r
1139 update wakeup info inside the PRW method for the given pci device handle\r
1140\r
1141 @param AcpiSdt Pointer to Acpi SDT protocol\r
1142 @param PciHandle ACPI pci device handle\r
1143 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
1144\r
1145**/\r
1146EFI_STATUS\r
1147SdtUpdatePrwPackage (\r
1148 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1149 IN EFI_ACPI_HANDLE PciHandle,\r
1150 IN PCI_DEVICE_INFO *PciDeviceInfo\r
1151 )\r
1152{\r
1153 EFI_STATUS Status;\r
1154 EFI_ACPI_HANDLE PrwPkgHandle;\r
1155\r
1156 //\r
1157 // Find the PRT method under this pci device\r
1158 //\r
1159 PrwPkgHandle = NULL;\r
1160 Status = AcpiSdt->FindPath (PciHandle, "_PRW", &PrwPkgHandle);\r
1161\r
1162 if (EFI_ERROR (Status)) {\r
1163 return EFI_INVALID_PARAMETER;\r
1164 }\r
1165\r
1166 if (PrwPkgHandle == NULL) {\r
1167 return EFI_INVALID_PARAMETER;\r
1168 }\r
1169\r
1170 SdtCheckNamePackage(AcpiSdt, PrwPkgHandle, PciDeviceInfo);\r
1171\r
1172 Status = AcpiSdt->Close (PrwPkgHandle);\r
1173 ASSERT_EFI_ERROR (Status);\r
1174\r
1175 return Status;\r
1176}\r
1177\r
1178/**\r
1179 update pci routing information in acpi table based on pcd settings\r
1180\r
1181 @param AcpiSdt Pointer to Acpi SDT protocol\r
1182 @param PciRootHandle ACPI root bridge handle\r
1183 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
1184\r
1185**/\r
1186EFI_STATUS\r
1187SdtUpdatePciRouting (\r
1188 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1189 IN EFI_ACPI_HANDLE PciRootHandle,\r
1190 IN PCI_DEVICE_INFO *PciDeviceInfo\r
1191 )\r
1192{\r
1193 EFI_STATUS Status;\r
1194 EFI_ACPI_HANDLE PciBridgeHandle;\r
1195 UINT32 PciAddress;\r
1196\r
1197\r
1198 PciBridgeHandle = NULL;\r
1199 if (PciDeviceInfo->BridgeAddress == 0x00000000) {\r
1200 //\r
1201 // Its bridge is the host root bridge\r
1202 //\r
1203 PciBridgeHandle = PciRootHandle;\r
1204\r
1205 } else {\r
1206\r
1207 //\r
1208 // Its bridge is just a pci device under the host bridge\r
1209 //\r
1210\r
1211 //\r
1212 // Conver the bridge address into one that acpi table can recognize\r
1213 //\r
1214 PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);\r
1215\r
1216 //\r
1217 // Scan the whole table to find the pci device\r
1218 //\r
1219 PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);\r
1220 if (PciBridgeHandle == NULL) {\r
1221\r
1222 return EFI_INVALID_PARAMETER;\r
1223 }\r
1224 }\r
1225\r
1226 Status = SdtUpdatePrtMethod(AcpiSdt, PciBridgeHandle, PciDeviceInfo);\r
1227\r
1228 if (PciDeviceInfo->BridgeAddress != 0x00000000) {\r
1229 Status = AcpiSdt->Close (PciBridgeHandle);\r
1230 ASSERT_EFI_ERROR (Status);\r
1231 }\r
1232\r
1233 return Status;\r
1234}\r
1235\r
1236\r
1237/**\r
1238 update power resource wake up information in acpi table based on pcd settings\r
1239\r
1240 @param AcpiSdt Pointer to Acpi SDT protocol\r
1241 @param PciRootHandle ACPI root bridge handle\r
1242 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
1243\r
1244**/\r
1245EFI_STATUS\r
1246SdtUpdatePowerWake (\r
1247 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1248 IN EFI_ACPI_HANDLE PciRootHandle,\r
1249 IN PCI_DEVICE_INFO *PciDeviceInfo\r
1250 )\r
1251{\r
1252 EFI_STATUS Status;\r
1253 EFI_ACPI_HANDLE PciBridgeHandle;\r
1254 EFI_ACPI_HANDLE PciDeviceHandle;\r
1255 UINT32 PciAddress;\r
1256\r
1257 PciBridgeHandle = NULL;\r
1258 if (PciDeviceInfo->BridgeAddress == 0x00000000) {\r
1259 //\r
1260 // Its bridge is the host root bridge\r
1261 //\r
1262 PciBridgeHandle = PciRootHandle;\r
1263\r
1264 } else {\r
1265\r
1266 //\r
1267 // Its bridge is just a pci device under the host bridge\r
1268 //\r
1269\r
1270 //\r
1271 // Conver the bridge address into one that acpi table can recognize\r
1272 //\r
1273 PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);\r
1274\r
1275 //\r
1276 // Scan the whole table to find the pci device\r
1277 //\r
1278 PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);\r
1279\r
1280 if (PciBridgeHandle == NULL) {\r
1281\r
1282 Status = AcpiSdt->Close (PciRootHandle);\r
1283 ASSERT_EFI_ERROR (Status);\r
1284\r
1285 return EFI_INVALID_PARAMETER;\r
1286 }\r
1287 }\r
1288\r
1289 PciDeviceHandle = NULL;\r
1290\r
1291 //\r
1292 // Conver the device address into one that acpi table can recognize\r
1293 //\r
1294 PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->DeviceAddress);\r
1295\r
1296 //\r
1297 // Scan the whole table to find the pci device\r
1298 //\r
1299 PciDeviceHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciBridgeHandle, SdtFindPciDeviceHandle, &PciAddress);\r
1300\r
1301 if (PciDeviceHandle == NULL) {\r
1302 if (PciDeviceInfo->BridgeAddress != 0x00000000) {\r
1303 Status = AcpiSdt->Close (PciBridgeHandle);\r
1304 ASSERT_EFI_ERROR (Status);\r
1305 }\r
1306\r
1307 return EFI_INVALID_PARAMETER;\r
1308 }\r
1309\r
1310 Status = SdtUpdatePrwPackage(AcpiSdt, PciDeviceHandle, PciDeviceInfo);\r
1311\r
1312 Status = AcpiSdt->Close (PciDeviceHandle);\r
1313 ASSERT_EFI_ERROR (Status);\r
1314\r
1315 if (PciDeviceInfo->BridgeAddress != 0x00000000) {\r
1316 Status = AcpiSdt->Close (PciBridgeHandle);\r
1317 ASSERT_EFI_ERROR (Status);\r
1318 }\r
1319\r
1320 return Status;\r
1321}\r
1322\r
1323\r
1324/**\r
1325 Get the root bridge handle by scanning the acpi table\r
1326\r
1327 @param AcpiSdt Pointer to Acpi SDT protocol\r
1328 @param DsdtHandle ACPI root handle\r
1329\r
1330 @retval EFI_ACPI_HANDLE the handle of the root bridge\r
1331**/\r
1332EFI_ACPI_HANDLE\r
1333SdtGetRootBridgeHandle (\r
1334 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,\r
1335 IN EFI_ACPI_HANDLE DsdtHandle\r
1336 )\r
1337{\r
1338 EFI_ACPI_HANDLE PciRootHandle;\r
1339\r
1340 //\r
1341 // Scan the whole table to find the root bridge\r
1342 //\r
1343 PciRootHandle = NULL;\r
1344 PciRootHandle = SdtGetHandleByScanAllChilds(AcpiSdt, DsdtHandle, SdtFindRootBridgeHandle, NULL);\r
1345 ASSERT (PciRootHandle != NULL);\r
1346\r
1347 return PciRootHandle;\r
1348}\r
1349\r
1350\r
1351/**\r
1352 Check input Pci device info is changed from the default values\r
1353 @param PciDeviceInfo Pointer to PCI_DEVICE_INFO\r
1354 @param UpdatePRT Pointer to BOOLEAN\r
1355 @param UpdatePRW Pointer to BOOLEAN\r
1356\r
1357**/\r
1358VOID\r
1359SdtCheckPciDeviceInfoChanged (\r
1360 IN PCI_DEVICE_INFO *PciDeviceInfo,\r
1361 IN BOOLEAN *UpdatePRT,\r
1362 IN BOOLEAN *UpdatePRW\r
1363 )\r
1364{\r
1365 UINTN Index = 0;\r
1366\r
1367 if (mQNCPciInfo == NULL) {\r
1368 *UpdatePRT = FALSE;\r
1369 *UpdatePRW = FALSE;\r
1370 return;\r
1371 }\r
1372\r
1373 *UpdatePRT = TRUE;\r
1374 *UpdatePRW = TRUE;\r
1375\r
1376 for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {\r
1377 if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)\r
1378 && (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {\r
1379 //\r
1380 // Find one matched entry\r
1381 //\r
1382 if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {\r
1383 *UpdatePRT = FALSE;\r
1384 *UpdatePRW = FALSE;\r
1385 //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));\r
1386 } else {\r
1387 if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)\r
1388 *UpdatePRT = FALSE;\r
1389\r
1390 if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)\r
1391 *UpdatePRW = FALSE;\r
1392\r
1393 if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFFULL)\r
1394 *UpdatePRT = FALSE;\r
1395\r
1396 if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)\r
1397 *UpdatePRW = FALSE;\r
1398\r
1399 //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));\r
1400 }\r
1401 break;\r
1402 }\r
1403 }\r
1404\r
1405 //if (Index == 42) {\r
1406 // DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));\r
1407 //}\r
1408\r
1409 return;\r
1410}\r