]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Correct all header files for doxygen format and correct the license issue for VgaClas...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciLib.c
CommitLineData
3db51098 1/**@file\r
ead42efc 2\r
3 PCI Bus Driver Lib file\r
4 It abstracts some functions that can be different\r
5 between light PCI bus driver and full PCI bus driver\r
6\r
3db51098 7Copyright (c) 2006, Intel Corporation \r
8All rights reserved. This program and the accompanying materials \r
9are licensed and made available under the terms and conditions of the BSD License \r
10which accompanies this distribution. The full text of the license may be found at \r
11http://opensource.org/licenses/bsd-license.php \r
12 \r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
ead42efc 15\r
3db51098 16**/\r
ead42efc 17\r
18#include "pcibus.h"\r
19\r
20GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {\r
21 PciHotPlugRequestNotify\r
22};\r
23\r
24\r
25VOID\r
26InstallHotPlugRequestProtocol (\r
27 IN EFI_STATUS *Status\r
28 )\r
29/*++\r
30\r
31Routine Description:\r
32\r
33Arguments:\r
34 Status - A pointer to the status.\r
35\r
36Returns:\r
37\r
38 None\r
39\r
40--*/\r
41{\r
42 EFI_HANDLE Handle;\r
43\r
44 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
45 return;\r
46 }\r
47\r
48 Handle = NULL;\r
49 *Status = gBS->InstallProtocolInterface (\r
50 &Handle,\r
51 &gEfiPciHotPlugRequestProtocolGuid,\r
52 EFI_NATIVE_INTERFACE,\r
53 &gPciHotPlugRequest\r
54 );\r
55}\r
56\r
57VOID\r
58InstallPciHotplugGuid (\r
59 IN PCI_IO_DEVICE *PciIoDevice\r
60 )\r
61/*++\r
62\r
63Routine Description:\r
64\r
65Arguments:\r
66\r
67 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
68\r
69Returns:\r
70\r
71 None\r
72\r
73--*/\r
74{\r
75 EFI_STATUS Status;\r
76\r
77 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
78 return;\r
79 }\r
80\r
81 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {\r
82\r
83 Status = gBS->InstallProtocolInterface (\r
84 &PciIoDevice->Handle,\r
85 &gEfiPciHotplugDeviceGuid,\r
86 EFI_NATIVE_INTERFACE,\r
87 NULL\r
88 );\r
89 ASSERT_EFI_ERROR (Status);\r
90 }\r
91}\r
92\r
93VOID\r
94UninstallPciHotplugGuid (\r
95 IN PCI_IO_DEVICE *PciIoDevice\r
96 )\r
97/*++\r
98\r
99Routine Description:\r
100\r
101Arguments:\r
102\r
103 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
104\r
105Returns:\r
106\r
107 None\r
108\r
109--*/\r
110{\r
111 EFI_STATUS Status;\r
112\r
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
114 return;\r
115 }\r
116\r
117 Status = gBS->OpenProtocol (\r
118 PciIoDevice->Handle,\r
119 &gEfiPciHotplugDeviceGuid,\r
120 NULL,\r
121 NULL,\r
122 NULL,\r
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
124 );\r
125\r
126 if (Status == EFI_SUCCESS) {\r
127 //\r
128 // This may triger CardBus driver to stop for\r
129 // Pccard devices opened the GUID via BY_DRIVER\r
130 //\r
131 Status = gBS->UninstallProtocolInterface (\r
132 PciIoDevice->Handle,\r
133 &gEfiPciHotplugDeviceGuid,\r
134 NULL\r
135 );\r
136 }\r
137}\r
138\r
139VOID\r
140GetBackPcCardBar (\r
141 IN PCI_IO_DEVICE *PciIoDevice\r
142 )\r
143/*++\r
144\r
145Routine Description:\r
146\r
147\r
148Arguments:\r
149\r
150 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
151\r
152Returns:\r
153\r
154 None\r
155\r
156--*/\r
157{\r
158 UINT32 Address;\r
159\r
160 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
161 return;\r
162 }\r
163\r
164 //\r
165 // Read PciBar information from the bar register\r
166 //\r
167 if (!gFullEnumeration) {\r
168\r
169 Address = 0;\r
170 PciIoRead (\r
171 &(PciIoDevice->PciIo),\r
172 EfiPciIoWidthUint32,\r
173 0x1c,\r
174 1,\r
175 &Address\r
176 );\r
177\r
178 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
179 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
180 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
181\r
182 Address = 0;\r
183 PciIoRead (\r
184 &(PciIoDevice->PciIo),\r
185 EfiPciIoWidthUint32,\r
186 0x20,\r
187 1,\r
188 &Address\r
189 );\r
190 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
191 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
192 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
193\r
194 Address = 0;\r
195 PciIoRead (\r
196 &(PciIoDevice->PciIo),\r
197 EfiPciIoWidthUint32,\r
198 0x2c,\r
199 1,\r
200 &Address\r
201 );\r
202 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
203 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
204 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
205\r
206 Address = 0;\r
207 PciIoRead (\r
208 &(PciIoDevice->PciIo),\r
209 EfiPciIoWidthUint32,\r
210 0x34,\r
211 1,\r
212 &Address\r
213 );\r
214 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
215 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
216 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
217\r
218 }\r
219\r
220 if (gPciHotPlugInit != NULL) {\r
221 GetResourcePaddingForHpb (PciIoDevice);\r
222 }\r
223}\r
224\r
225EFI_STATUS\r
226RemoveRejectedPciDevices (\r
227 EFI_HANDLE RootBridgeHandle,\r
228 IN PCI_IO_DEVICE *Bridge\r
229 )\r
230/*++\r
231\r
232Routine Description:\r
233\r
234\r
235Arguments:\r
236\r
237 RootBridgeHandle - An efi handle.\r
238 Bridge - An pointer to the PCI_IO_DEVICE.\r
239\r
240Returns:\r
241\r
242 None\r
243\r
244--*/\r
245// TODO: EFI_SUCCESS - add return value to function comment\r
246{\r
247 PCI_IO_DEVICE *Temp;\r
248 LIST_ENTRY *CurrentLink;\r
249 LIST_ENTRY *LastLink;\r
250\r
251 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
252 return EFI_SUCCESS;\r
253 }\r
254\r
255 CurrentLink = Bridge->ChildList.ForwardLink;\r
256\r
257 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
258\r
259 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
260\r
261 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
262 //\r
263 // Remove rejected devices recusively\r
264 //\r
265 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
266 } else {\r
267 //\r
268 // Skip rejection for all PPBs, while detect rejection for others\r
269 //\r
270 if (IsPciDeviceRejected (Temp)) {\r
271\r
272 //\r
273 // For P2C, remove all devices on it\r
274 //\r
275\r
276 if (!IsListEmpty (&Temp->ChildList)) {\r
277 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
278 }\r
279\r
280 //\r
281 // Finally remove itself\r
282 //\r
283\r
284 LastLink = CurrentLink->BackLink;\r
285 RemoveEntryList (CurrentLink);\r
286 FreePciDevice (Temp);\r
287\r
288 CurrentLink = LastLink;\r
289 }\r
290 }\r
291\r
292 CurrentLink = CurrentLink->ForwardLink;\r
293 }\r
294\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298EFI_STATUS\r
299PciHostBridgeResourceAllocator (\r
300 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
301 )\r
302{\r
303 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
304 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (\r
305 PciResAlloc\r
306 );\r
307 } else {\r
308 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (\r
309 PciResAlloc\r
310 );\r
311 }\r
312}\r
313\r
314\r
315EFI_STATUS\r
316PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (\r
317 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
318 )\r
319/*++\r
320\r
321Routine Description:\r
322\r
323Arguments:\r
324\r
325Returns:\r
326\r
327 None\r
328\r
329--*/\r
330// TODO: PciResAlloc - add argument and description to function comment\r
331// TODO: EFI_NOT_FOUND - add return value to function comment\r
332// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
333// TODO: EFI_NOT_FOUND - add return value to function comment\r
334// TODO: EFI_SUCCESS - add return value to function comment\r
335{\r
336 PCI_IO_DEVICE *RootBridgeDev;\r
337 EFI_HANDLE RootBridgeHandle;\r
338 VOID *AcpiConfig;\r
339 EFI_STATUS Status;\r
340 UINT64 IoBase;\r
341 UINT64 Mem32Base;\r
342 UINT64 PMem32Base;\r
343 UINT64 Mem64Base;\r
344 UINT64 PMem64Base;\r
345 UINT64 MaxOptionRomSize;\r
346 PCI_RESOURCE_NODE *IoBridge;\r
347 PCI_RESOURCE_NODE *Mem32Bridge;\r
348 PCI_RESOURCE_NODE *PMem32Bridge;\r
349 PCI_RESOURCE_NODE *Mem64Bridge;\r
350 PCI_RESOURCE_NODE *PMem64Bridge;\r
351 PCI_RESOURCE_NODE IoPool;\r
352 PCI_RESOURCE_NODE Mem32Pool;\r
353 PCI_RESOURCE_NODE PMem32Pool;\r
354 PCI_RESOURCE_NODE Mem64Pool;\r
355 PCI_RESOURCE_NODE PMem64Pool;\r
938f2b4f 356 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData;\r
ead42efc 357\r
358 //\r
359 // Initialize resource pool\r
360 //\r
361\r
362 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
363 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
364 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
365 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
366 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
367\r
368 RootBridgeDev = NULL;\r
369 RootBridgeHandle = 0;\r
370\r
371 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
372 //\r
373 // Get RootBridg Device by handle\r
374 //\r
375 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
376\r
377 if (RootBridgeDev == NULL) {\r
378 return EFI_NOT_FOUND;\r
379 }\r
380\r
381 //\r
382 // Get host bridge handle for status report\r
383 //\r
384 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
385\r
386 //\r
387 // Create the entire system resource map from the information collected by\r
388 // enumerator. Several resource tree was created\r
389 //\r
390\r
391 IoBridge = CreateResourceNode (\r
392 RootBridgeDev,\r
393 0,\r
394 0xFFF,\r
395 0,\r
396 PciBarTypeIo16,\r
397 PciResUsageTypical\r
398 );\r
399\r
400 Mem32Bridge = CreateResourceNode (\r
401 RootBridgeDev,\r
402 0,\r
403 0xFFFFF,\r
404 0,\r
405 PciBarTypeMem32,\r
406 PciResUsageTypical\r
407 );\r
408\r
409 PMem32Bridge = CreateResourceNode (\r
410 RootBridgeDev,\r
411 0,\r
412 0xFFFFF,\r
413 0,\r
414 PciBarTypePMem32,\r
415 PciResUsageTypical\r
416 );\r
417\r
418 Mem64Bridge = CreateResourceNode (\r
419 RootBridgeDev,\r
420 0,\r
421 0xFFFFF,\r
422 0,\r
423 PciBarTypeMem64,\r
424 PciResUsageTypical\r
425 );\r
426\r
427 PMem64Bridge = CreateResourceNode (\r
428 RootBridgeDev,\r
429 0,\r
430 0xFFFFF,\r
431 0,\r
432 PciBarTypePMem64,\r
433 PciResUsageTypical\r
434 );\r
435\r
436 //\r
437 // Create resourcemap by going through all the devices subject to this root bridge\r
438 //\r
439 Status = CreateResourceMap (\r
440 RootBridgeDev,\r
441 IoBridge,\r
442 Mem32Bridge,\r
443 PMem32Bridge,\r
444 Mem64Bridge,\r
445 PMem64Bridge\r
446 );\r
447\r
448 //\r
449 // Get the max ROM size that the root bridge can process\r
450 //\r
451 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
452\r
453 //\r
454 // Get Max Option Rom size for current root bridge\r
455 //\r
456 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
457\r
458 //\r
459 // Enlarger the mem32 resource to accomdate the option rom\r
460 // if the mem32 resource is not enough to hold the rom\r
461 //\r
462 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
463\r
464 Mem32Bridge->Length = MaxOptionRomSize;\r
465 RootBridgeDev->RomSize = MaxOptionRomSize;\r
466\r
467 //\r
468 // Alignment should be adjusted as well\r
469 //\r
470 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
471 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
472 }\r
473 }\r
474\r
475 //\r
476 // Based on the all the resource tree, contruct ACPI resource node to\r
477 // submit the resource aperture to pci host bridge protocol\r
478 //\r
479 Status = ConstructAcpiResourceRequestor (\r
480 RootBridgeDev,\r
481 IoBridge,\r
482 Mem32Bridge,\r
483 PMem32Bridge,\r
484 Mem64Bridge,\r
485 PMem64Bridge,\r
486 &AcpiConfig\r
487 );\r
488\r
489 //\r
490 // Insert these resource nodes into the database\r
491 //\r
492 InsertResourceNode (&IoPool, IoBridge);\r
493 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
494 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
495 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
496 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
497\r
498 if (Status == EFI_SUCCESS) {\r
499 //\r
500 // Submit the resource requirement\r
501 //\r
502 Status = PciResAlloc->SubmitResources (\r
503 PciResAlloc,\r
504 RootBridgeDev->Handle,\r
505 AcpiConfig\r
506 );\r
507 }\r
508 //\r
509 // Free acpi resource node\r
510 //\r
511 if (AcpiConfig != NULL) {\r
512 FreePool (AcpiConfig);\r
513 }\r
514\r
515 if (EFI_ERROR (Status)) {\r
516 //\r
517 // Destroy all the resource tree\r
518 //\r
519 DestroyResourceTree (&IoPool);\r
520 DestroyResourceTree (&Mem32Pool);\r
521 DestroyResourceTree (&PMem32Pool);\r
522 DestroyResourceTree (&Mem64Pool);\r
523 DestroyResourceTree (&PMem64Pool);\r
524 return Status;\r
525 }\r
526 }\r
527 //\r
528 // End while\r
529 //\r
530\r
531 //\r
532 // Notify pci bus driver starts to program the resource\r
533 //\r
534 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
535\r
536 if (EFI_ERROR (Status)) {\r
537 //\r
538 // Allocation failed, then return\r
539 //\r
540 return EFI_OUT_OF_RESOURCES;\r
541 }\r
542 //\r
543 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
544 //\r
545 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
546 EFI_PROGRESS_CODE,\r
547 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
548 (VOID *) &ExtendedData,\r
549 sizeof (ExtendedData)\r
550 );\r
551\r
552 //\r
553 // Notify pci bus driver starts to program the resource\r
554 //\r
555 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
556\r
557 RootBridgeDev = NULL;\r
558\r
559 RootBridgeHandle = 0;\r
560\r
561 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
562 //\r
563 // Get RootBridg Device by handle\r
564 //\r
565 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
566\r
567 if (RootBridgeDev == NULL) {\r
568 return EFI_NOT_FOUND;\r
569 }\r
570\r
571 //\r
572 // Get acpi resource node for all the resource types\r
573 //\r
574 AcpiConfig = NULL;\r
575 Status = PciResAlloc->GetProposedResources (\r
576 PciResAlloc,\r
577 RootBridgeDev->Handle,\r
578 &AcpiConfig\r
579 );\r
580\r
581 if (EFI_ERROR (Status)) {\r
582 return Status;\r
583 }\r
584\r
585 //\r
586 // Get the resource base by interpreting acpi resource node\r
587 //\r
588 //\r
589 GetResourceBase (\r
590 AcpiConfig,\r
591 &IoBase,\r
592 &Mem32Base,\r
593 &PMem32Base,\r
594 &Mem64Base,\r
595 &PMem64Base\r
596 );\r
597\r
598 //\r
599 // Process option rom for this root bridge\r
600 //\r
601 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
602\r
603 //\r
604 // Create the entire system resource map from the information collected by\r
605 // enumerator. Several resource tree was created\r
606 //\r
607 Status = GetResourceMap (\r
608 RootBridgeDev,\r
609 &IoBridge,\r
610 &Mem32Bridge,\r
611 &PMem32Bridge,\r
612 &Mem64Bridge,\r
613 &PMem64Bridge,\r
614 &IoPool,\r
615 &Mem32Pool,\r
616 &PMem32Pool,\r
617 &Mem64Pool,\r
618 &PMem64Pool\r
619 );\r
620\r
621 if (EFI_ERROR (Status)) {\r
622 return Status;\r
623 }\r
624\r
625 //\r
626 // Program IO resources\r
627 //\r
628 ProgramResource (\r
629 IoBase,\r
630 IoBridge\r
631 );\r
632\r
633 //\r
634 // Program Mem32 resources\r
635 //\r
636 ProgramResource (\r
637 Mem32Base,\r
638 Mem32Bridge\r
639 );\r
640\r
641 //\r
642 // Program PMem32 resources\r
643 //\r
644 ProgramResource (\r
645 PMem32Base,\r
646 PMem32Bridge\r
647 );\r
648\r
649 //\r
650 // Program Mem64 resources\r
651 //\r
652 ProgramResource (\r
653 Mem64Base,\r
654 Mem64Bridge\r
655 );\r
656\r
657 //\r
658 // Program PMem64 resources\r
659 //\r
660 ProgramResource (\r
661 PMem64Base,\r
662 PMem64Bridge\r
663 );\r
664\r
665 if (AcpiConfig != NULL) {\r
666 FreePool (AcpiConfig);\r
667 }\r
668 }\r
669\r
670 //\r
671 // Destroy all the resource tree\r
672 //\r
673 DestroyResourceTree (&IoPool);\r
674 DestroyResourceTree (&Mem32Pool);\r
675 DestroyResourceTree (&PMem32Pool);\r
676 DestroyResourceTree (&Mem64Pool);\r
677 DestroyResourceTree (&PMem64Pool);\r
678\r
679 //\r
680 // Notify the resource allocation phase is to end\r
681 //\r
682 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
683\r
684 return EFI_SUCCESS;\r
685}\r
686\r
687\r
688EFI_STATUS\r
689PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (\r
690 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
691 )\r
692/*++\r
693\r
694Routine Description:\r
695\r
696 Host brige resource allocator.\r
697\r
698Arguments:\r
699\r
700 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
701\r
702Returns:\r
703\r
704 EFI Status.\r
705\r
706--*/\r
707// TODO: EFI_NOT_FOUND - add return value to function comment\r
708// TODO: EFI_NOT_FOUND - add return value to function comment\r
709// TODO: EFI_NOT_FOUND - add return value to function comment\r
710// TODO: EFI_SUCCESS - add return value to function comment\r
711{\r
712 PCI_IO_DEVICE *RootBridgeDev;\r
713 EFI_HANDLE RootBridgeHandle;\r
714 VOID *AcpiConfig;\r
715 EFI_STATUS Status;\r
716 UINT64 IoBase;\r
717 UINT64 Mem32Base;\r
718 UINT64 PMem32Base;\r
719 UINT64 Mem64Base;\r
720 UINT64 PMem64Base;\r
721 UINT64 IoResStatus;\r
722 UINT64 Mem32ResStatus;\r
723 UINT64 PMem32ResStatus;\r
724 UINT64 Mem64ResStatus;\r
725 UINT64 PMem64ResStatus;\r
726 UINT64 MaxOptionRomSize;\r
727 PCI_RESOURCE_NODE *IoBridge;\r
728 PCI_RESOURCE_NODE *Mem32Bridge;\r
729 PCI_RESOURCE_NODE *PMem32Bridge;\r
730 PCI_RESOURCE_NODE *Mem64Bridge;\r
731 PCI_RESOURCE_NODE *PMem64Bridge;\r
732 PCI_RESOURCE_NODE IoPool;\r
733 PCI_RESOURCE_NODE Mem32Pool;\r
734 PCI_RESOURCE_NODE PMem32Pool;\r
735 PCI_RESOURCE_NODE Mem64Pool;\r
736 PCI_RESOURCE_NODE PMem64Pool;\r
737 BOOLEAN ReAllocate;\r
938f2b4f 738 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
739 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
ead42efc 740\r
741 //\r
742 // Reallocate flag\r
743 //\r
744 ReAllocate = FALSE;\r
745\r
746 //\r
747 // It will try several times if the resource allocation fails\r
748 //\r
749 while (TRUE) {\r
750\r
751 //\r
752 // Initialize resource pool\r
753 //\r
754 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
755 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
756 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
757 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
758 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
759\r
760 RootBridgeDev = NULL;\r
761 RootBridgeHandle = 0;\r
762\r
763 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
764\r
765 //\r
766 // Get RootBridg Device by handle\r
767 //\r
768 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
769\r
770 if (RootBridgeDev == NULL) {\r
771 return EFI_NOT_FOUND;\r
772 }\r
773\r
774 //\r
775 // Create the entire system resource map from the information collected by\r
776 // enumerator. Several resource tree was created\r
777 //\r
778\r
779 IoBridge = CreateResourceNode (\r
780 RootBridgeDev,\r
781 0,\r
782 0xFFF,\r
783 0,\r
784 PciBarTypeIo16,\r
785 PciResUsageTypical\r
786 );\r
787\r
788 Mem32Bridge = CreateResourceNode (\r
789 RootBridgeDev,\r
790 0,\r
791 0xFFFFF,\r
792 0,\r
793 PciBarTypeMem32,\r
794 PciResUsageTypical\r
795 );\r
796\r
797 PMem32Bridge = CreateResourceNode (\r
798 RootBridgeDev,\r
799 0,\r
800 0xFFFFF,\r
801 0,\r
802 PciBarTypePMem32,\r
803 PciResUsageTypical\r
804 );\r
805\r
806 Mem64Bridge = CreateResourceNode (\r
807 RootBridgeDev,\r
808 0,\r
809 0xFFFFF,\r
810 0,\r
811 PciBarTypeMem64,\r
812 PciResUsageTypical\r
813 );\r
814\r
815 PMem64Bridge = CreateResourceNode (\r
816 RootBridgeDev,\r
817 0,\r
818 0xFFFFF,\r
819 0,\r
820 PciBarTypePMem64,\r
821 PciResUsageTypical\r
822 );\r
823\r
824 //\r
825 // Create resourcemap by going through all the devices subject to this root bridge\r
826 //\r
827 Status = CreateResourceMap (\r
828 RootBridgeDev,\r
829 IoBridge,\r
830 Mem32Bridge,\r
831 PMem32Bridge,\r
832 Mem64Bridge,\r
833 PMem64Bridge\r
834 );\r
835\r
836 //\r
837 // Get the max ROM size that the root bridge can process\r
838 //\r
839 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
840\r
841 //\r
842 // Skip to enlarge the resource request during realloction\r
843 //\r
844 if (!ReAllocate) {\r
845 //\r
846 // Get Max Option Rom size for current root bridge\r
847 //\r
848 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
849\r
850 //\r
851 // Enlarger the mem32 resource to accomdate the option rom\r
852 // if the mem32 resource is not enough to hold the rom\r
853 //\r
854 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
855\r
856 Mem32Bridge->Length = MaxOptionRomSize;\r
857 RootBridgeDev->RomSize = MaxOptionRomSize;\r
858\r
859 //\r
860 // Alignment should be adjusted as well\r
861 //\r
862 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
863 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
864 }\r
865 }\r
866 }\r
867\r
868 //\r
869 // Based on the all the resource tree, contruct ACPI resource node to\r
870 // submit the resource aperture to pci host bridge protocol\r
871 //\r
872 Status = ConstructAcpiResourceRequestor (\r
873 RootBridgeDev,\r
874 IoBridge,\r
875 Mem32Bridge,\r
876 PMem32Bridge,\r
877 Mem64Bridge,\r
878 PMem64Bridge,\r
879 &AcpiConfig\r
880 );\r
881\r
882 //\r
883 // Insert these resource nodes into the database\r
884 //\r
885 InsertResourceNode (&IoPool, IoBridge);\r
886 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
887 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
888 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
889 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
890\r
891 if (Status == EFI_SUCCESS) {\r
892 //\r
893 // Submit the resource requirement\r
894 //\r
895 Status = PciResAlloc->SubmitResources (\r
896 PciResAlloc,\r
897 RootBridgeDev->Handle,\r
898 AcpiConfig\r
899 );\r
900 }\r
901\r
902 //\r
903 // Free acpi resource node\r
904 //\r
905 if (AcpiConfig != NULL) {\r
906 FreePool (AcpiConfig);\r
907 }\r
908\r
909 if (EFI_ERROR (Status)) {\r
910 //\r
911 // Destroy all the resource tree\r
912 //\r
913 DestroyResourceTree (&IoPool);\r
914 DestroyResourceTree (&Mem32Pool);\r
915 DestroyResourceTree (&PMem32Pool);\r
916 DestroyResourceTree (&Mem64Pool);\r
917 DestroyResourceTree (&PMem64Pool);\r
918 return Status;\r
919 }\r
920 }\r
921\r
922 //\r
923 // Notify pci bus driver starts to program the resource\r
924 //\r
925\r
926 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
927\r
928 if (!EFI_ERROR (Status)) {\r
929 //\r
930 // Allocation succeed, then continue the following\r
931 //\r
932 break;\r
933 }\r
934\r
935 //\r
936 // If the resource allocation is unsuccessful, free resources on bridge\r
937 //\r
938\r
939 RootBridgeDev = NULL;\r
940 RootBridgeHandle = 0;\r
941\r
942 IoResStatus = EFI_RESOURCE_SATISFIED;\r
943 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
944 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
945 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
946 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
947\r
948 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
949 //\r
950 // Get RootBridg Device by handle\r
951 //\r
952 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
953 if (RootBridgeDev == NULL) {\r
954 return EFI_NOT_FOUND;\r
955 }\r
956\r
957 //\r
958 // Get host bridge handle for status report\r
959 //\r
960 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
961\r
962 //\r
963 // Get acpi resource node for all the resource types\r
964 //\r
965 AcpiConfig = NULL;\r
966\r
967 Status = PciResAlloc->GetProposedResources (\r
968 PciResAlloc,\r
969 RootBridgeDev->Handle,\r
970 &AcpiConfig\r
971 );\r
972\r
973 if (EFI_ERROR (Status)) {\r
974 return Status;\r
975 }\r
976\r
977 if (AcpiConfig != NULL) {\r
978 //\r
979 // Adjust resource allocation policy for each RB\r
980 //\r
981 GetResourceAllocationStatus (\r
982 AcpiConfig,\r
983 &IoResStatus,\r
984 &Mem32ResStatus,\r
985 &PMem32ResStatus,\r
986 &Mem64ResStatus,\r
987 &PMem64ResStatus\r
988 );\r
989 FreePool (AcpiConfig);\r
990 }\r
991 }\r
992 //\r
993 // End while\r
994 //\r
995\r
996 //\r
997 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
998 //\r
999 //\r
1000 // It is very difficult to follow the spec here\r
1001 // Device path , Bar index can not be get here\r
1002 //\r
1003 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
1004\r
1005 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1006 EFI_PROGRESS_CODE,\r
1007 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
1008 (VOID *) &AllocFailExtendedData,\r
1009 sizeof (AllocFailExtendedData)\r
1010 );\r
1011\r
1012 Status = PciHostBridgeAdjustAllocation (\r
1013 &IoPool,\r
1014 &Mem32Pool,\r
1015 &PMem32Pool,\r
1016 &Mem64Pool,\r
1017 &PMem64Pool,\r
1018 IoResStatus,\r
1019 Mem32ResStatus,\r
1020 PMem32ResStatus,\r
1021 Mem64ResStatus,\r
1022 PMem64ResStatus\r
1023 );\r
1024\r
1025 //\r
1026 // Destroy all the resource tree\r
1027 //\r
1028 DestroyResourceTree (&IoPool);\r
1029 DestroyResourceTree (&Mem32Pool);\r
1030 DestroyResourceTree (&PMem32Pool);\r
1031 DestroyResourceTree (&Mem64Pool);\r
1032 DestroyResourceTree (&PMem64Pool);\r
1033\r
1034 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
1035\r
1036 if (EFI_ERROR (Status)) {\r
1037 return Status;\r
1038 }\r
1039\r
1040 ReAllocate = TRUE;\r
1041\r
1042 }\r
1043 //\r
1044 // End main while\r
1045 //\r
1046\r
1047 //\r
1048 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
1049 //\r
1050 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1051 EFI_PROGRESS_CODE,\r
1052 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
1053 (VOID *) &HandleExtendedData,\r
1054 sizeof (HandleExtendedData)\r
1055 );\r
1056\r
1057 //\r
1058 // Notify pci bus driver starts to program the resource\r
1059 //\r
1060 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
1061\r
1062 RootBridgeDev = NULL;\r
1063\r
1064 RootBridgeHandle = 0;\r
1065\r
1066 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1067\r
1068 //\r
1069 // Get RootBridg Device by handle\r
1070 //\r
1071 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1072\r
1073 if (RootBridgeDev == NULL) {\r
1074 return EFI_NOT_FOUND;\r
1075 }\r
1076\r
1077 //\r
1078 // Get acpi resource node for all the resource types\r
1079 //\r
1080 AcpiConfig = NULL;\r
1081 Status = PciResAlloc->GetProposedResources (\r
1082 PciResAlloc,\r
1083 RootBridgeDev->Handle,\r
1084 &AcpiConfig\r
1085 );\r
1086\r
1087 if (EFI_ERROR (Status)) {\r
1088 return Status;\r
1089 }\r
1090\r
1091 //\r
1092 // Get the resource base by interpreting acpi resource node\r
1093 //\r
1094 //\r
1095 GetResourceBase (\r
1096 AcpiConfig,\r
1097 &IoBase,\r
1098 &Mem32Base,\r
1099 &PMem32Base,\r
1100 &Mem64Base,\r
1101 &PMem64Base\r
1102 );\r
1103\r
1104 //\r
1105 // Process option rom for this root bridge\r
1106 //\r
1107 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
1108\r
1109 //\r
1110 // Create the entire system resource map from the information collected by\r
1111 // enumerator. Several resource tree was created\r
1112 //\r
1113 Status = GetResourceMap (\r
1114 RootBridgeDev,\r
1115 &IoBridge,\r
1116 &Mem32Bridge,\r
1117 &PMem32Bridge,\r
1118 &Mem64Bridge,\r
1119 &PMem64Bridge,\r
1120 &IoPool,\r
1121 &Mem32Pool,\r
1122 &PMem32Pool,\r
1123 &Mem64Pool,\r
1124 &PMem64Pool\r
1125 );\r
1126\r
1127 if (EFI_ERROR (Status)) {\r
1128 return Status;\r
1129 }\r
1130\r
1131 //\r
1132 // Program IO resources\r
1133 //\r
1134 ProgramResource (\r
1135 IoBase,\r
1136 IoBridge\r
1137 );\r
1138\r
1139 //\r
1140 // Program Mem32 resources\r
1141 //\r
1142 ProgramResource (\r
1143 Mem32Base,\r
1144 Mem32Bridge\r
1145 );\r
1146\r
1147 //\r
1148 // Program PMem32 resources\r
1149 //\r
1150 ProgramResource (\r
1151 PMem32Base,\r
1152 PMem32Bridge\r
1153 );\r
1154\r
1155 //\r
1156 // Program Mem64 resources\r
1157 //\r
1158 ProgramResource (\r
1159 Mem64Base,\r
1160 Mem64Bridge\r
1161 );\r
1162\r
1163 //\r
1164 // Program PMem64 resources\r
1165 //\r
1166 ProgramResource (\r
1167 PMem64Base,\r
1168 PMem64Bridge\r
1169 );\r
1170\r
1171 if (AcpiConfig != NULL) {\r
1172 gBS->FreePool (AcpiConfig);\r
1173 }\r
1174 }\r
1175\r
1176 //\r
1177 // Destroy all the resource tree\r
1178 //\r
1179 DestroyResourceTree (&IoPool);\r
1180 DestroyResourceTree (&Mem32Pool);\r
1181 DestroyResourceTree (&PMem32Pool);\r
1182 DestroyResourceTree (&Mem64Pool);\r
1183 DestroyResourceTree (&PMem64Pool);\r
1184\r
1185 //\r
1186 // Notify the resource allocation phase is to end\r
1187 //\r
1188 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
1189\r
1190 return EFI_SUCCESS;\r
1191}\r
1192\r
1193\r
1194EFI_STATUS\r
1195PciScanBus (\r
1196 IN PCI_IO_DEVICE *Bridge,\r
1197 IN UINT8 StartBusNumber,\r
1198 OUT UINT8 *SubBusNumber,\r
1199 OUT UINT8 *PaddedBusRange\r
1200 )\r
1201{\r
1202 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1203 return PciScanBus_WithHotPlugDeviceSupport (\r
1204 Bridge,\r
1205 StartBusNumber,\r
1206 SubBusNumber,\r
1207 PaddedBusRange\r
1208 );\r
1209 } else {\r
1210 return PciScanBus_WithoutHotPlugDeviceSupport (\r
1211 Bridge,\r
1212 StartBusNumber,\r
1213 SubBusNumber,\r
1214 PaddedBusRange\r
1215 );\r
1216 }\r
1217}\r
1218\r
1219\r
1220EFI_STATUS\r
1221PciScanBus_WithoutHotPlugDeviceSupport (\r
1222 IN PCI_IO_DEVICE *Bridge,\r
1223 IN UINT8 StartBusNumber,\r
1224 OUT UINT8 *SubBusNumber,\r
1225 OUT UINT8 *PaddedBusRange\r
1226 )\r
1227/*++\r
1228\r
1229Routine Description:\r
1230\r
1231 This routine is used to assign bus number to the given PCI bus system\r
1232\r
1233Arguments:\r
1234\r
1235Returns:\r
1236\r
1237 None\r
1238\r
1239--*/\r
1240// TODO: Bridge - add argument and description to function comment\r
1241// TODO: StartBusNumber - add argument and description to function comment\r
1242// TODO: SubBusNumber - add argument and description to function comment\r
1243// TODO: PaddedBusRange - add argument and description to function comment\r
1244// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1245// TODO: EFI_SUCCESS - add return value to function comment\r
1246{\r
1247 EFI_STATUS Status;\r
1248 PCI_TYPE00 Pci;\r
1249 UINT8 Device;\r
1250 UINT8 Func;\r
1251 UINT64 Address;\r
1252 UINTN SecondBus;\r
1253 UINT16 Register;\r
1254 PCI_IO_DEVICE *PciDevice;\r
1255 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1256\r
1257 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1258 SecondBus = 0;\r
1259 Register = 0;\r
1260\r
1261 ResetAllPpbBusReg (Bridge, StartBusNumber);\r
1262\r
1263 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1264 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1265\r
1266 //\r
1267 // Check to see whether a pci device is present\r
1268 //\r
1269 Status = PciDevicePresent (\r
1270 PciRootBridgeIo,\r
1271 &Pci,\r
1272 StartBusNumber,\r
1273 Device,\r
1274 Func\r
1275 );\r
1276\r
1277 if (!EFI_ERROR (Status) &&\r
1278 (IS_PCI_BRIDGE (&Pci) ||\r
1279 IS_CARDBUS_BRIDGE (&Pci))) {\r
1280\r
1281 //\r
1282 // Get the bridge information\r
1283 //\r
1284 Status = PciSearchDevice (\r
1285 Bridge,\r
1286 &Pci,\r
1287 StartBusNumber,\r
1288 Device,\r
1289 Func,\r
1290 &PciDevice\r
1291 );\r
1292\r
1293 if (EFI_ERROR (Status)) {\r
1294 return Status;\r
1295 }\r
1296\r
1297 (*SubBusNumber)++;\r
1298\r
1299 SecondBus = (*SubBusNumber);\r
1300\r
1301 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1302\r
1303 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1304\r
1305 Status = PciRootBridgeIoWrite (\r
1306 PciRootBridgeIo,\r
1307 &Pci,\r
1308 EfiPciWidthUint16,\r
1309 Address,\r
1310 1,\r
1311 &Register\r
1312 );\r
1313\r
1314 //\r
1315 // Initialize SubBusNumber to SecondBus\r
1316 //\r
1317 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1318 Status = PciRootBridgeIoWrite (\r
1319 PciRootBridgeIo,\r
1320 &Pci,\r
1321 EfiPciWidthUint8,\r
1322 Address,\r
1323 1,\r
1324 SubBusNumber\r
1325 );\r
1326 //\r
1327 // If it is PPB, resursively search down this bridge\r
1328 //\r
1329 if (IS_PCI_BRIDGE (&Pci)) {\r
1330 //\r
1331 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1332 // PCI configuration transaction to go through any PPB\r
1333 //\r
1334 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1335 Register = 0xFF;\r
1336 Status = PciRootBridgeIoWrite (\r
1337 PciRootBridgeIo,\r
1338 &Pci,\r
1339 EfiPciWidthUint8,\r
1340 Address,\r
1341 1,\r
1342 &Register\r
1343 );\r
1344\r
1345 PreprocessController (\r
1346 PciDevice,\r
1347 PciDevice->BusNumber,\r
1348 PciDevice->DeviceNumber,\r
1349 PciDevice->FunctionNumber,\r
1350 EfiPciBeforeChildBusEnumeration\r
1351 );\r
1352\r
1353 Status = PciScanBus (\r
1354 PciDevice,\r
1355 (UINT8) (SecondBus),\r
1356 SubBusNumber,\r
1357 PaddedBusRange\r
1358 );\r
1359\r
1360 if (EFI_ERROR (Status)) {\r
1361 return EFI_DEVICE_ERROR;\r
1362 }\r
1363 }\r
1364\r
1365 //\r
1366 // Set the current maximum bus number under the PPB\r
1367 //\r
1368\r
1369 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1370\r
1371 Status = PciRootBridgeIoWrite (\r
1372 PciRootBridgeIo,\r
1373 &Pci,\r
1374 EfiPciWidthUint8,\r
1375 Address,\r
1376 1,\r
1377 SubBusNumber\r
1378 );\r
1379\r
1380 }\r
1381\r
1382 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1383\r
1384 //\r
1385 // Skip sub functions, this is not a multi function device\r
1386 //\r
1387\r
1388 Func = PCI_MAX_FUNC;\r
1389 }\r
1390 }\r
1391 }\r
1392\r
1393 return EFI_SUCCESS;\r
1394}\r
1395\r
1396EFI_STATUS\r
1397PciScanBus_WithHotPlugDeviceSupport (\r
1398 IN PCI_IO_DEVICE *Bridge,\r
1399 IN UINT8 StartBusNumber,\r
1400 OUT UINT8 *SubBusNumber,\r
1401 OUT UINT8 *PaddedBusRange\r
1402 )\r
1403/*++\r
1404\r
1405Routine Description:\r
1406\r
1407 This routine is used to assign bus number to the given PCI bus system\r
1408\r
1409Arguments:\r
1410\r
1411 Bridge - A pointer to the PCI_IO_DEVICE structure.\r
1412 StartBusNumber - The start bus number.\r
1413 SubBusNumber - A pointer to the sub bus number.\r
1414 PaddedBusRange - A pointer to the padded bus range.\r
1415\r
1416Returns:\r
1417\r
1418 None\r
1419\r
1420--*/\r
1421// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1422// TODO: EFI_SUCCESS - add return value to function comment\r
1423{\r
1424 EFI_STATUS Status;\r
1425 PCI_TYPE00 Pci;\r
1426 UINT8 Device;\r
1427 UINT8 Func;\r
1428 UINT64 Address;\r
1429 UINTN SecondBus;\r
1430 UINT16 Register;\r
1431 UINTN HpIndex;\r
1432 PCI_IO_DEVICE *PciDevice;\r
1433 EFI_EVENT Event;\r
1434 EFI_HPC_STATE State;\r
1435 UINT64 PciAddress;\r
1436 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
1437 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1438 UINT16 BusRange;\r
1439 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1440 BOOLEAN BusPadding;\r
1441\r
1442 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1443 SecondBus = 0;\r
1444 Register = 0;\r
1445 State = 0;\r
1446 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
1447 BusRange = 0;\r
1448\r
1449 ResetAllPpbBusReg (Bridge, StartBusNumber);\r
1450\r
1451 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1452 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1453\r
1454 //\r
1455 // Check to see whether a pci device is present\r
1456 //\r
1457 Status = PciDevicePresent (\r
1458 PciRootBridgeIo,\r
1459 &Pci,\r
1460 StartBusNumber,\r
1461 Device,\r
1462 Func\r
1463 );\r
1464\r
1465 if (EFI_ERROR (Status)) {\r
1466 if (Func == 0) {\r
1467 //\r
1468 // Skip sub functions, this is not a multi function device\r
1469 //\r
1470 Func = PCI_MAX_FUNC;\r
1471 }\r
1472\r
1473 continue;\r
1474 }\r
1475\r
1476 //\r
1477 // Get the PCI device information\r
1478 //\r
1479 Status = PciSearchDevice (\r
1480 Bridge,\r
1481 &Pci,\r
1482 StartBusNumber,\r
1483 Device,\r
1484 Func,\r
1485 &PciDevice\r
1486 );\r
1487\r
1488 ASSERT (!EFI_ERROR (Status));\r
1489\r
1490 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
1491\r
1492 if (!IS_PCI_BRIDGE (&Pci)) {\r
1493 //\r
1494 // PCI bridges will be called later\r
1495 // Here just need for PCI device or PCI to cardbus controller\r
1496 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1497 //\r
1498 PreprocessController (\r
1499 PciDevice,\r
1500 PciDevice->BusNumber,\r
1501 PciDevice->DeviceNumber,\r
1502 PciDevice->FunctionNumber,\r
1503 EfiPciBeforeChildBusEnumeration\r
1504 );\r
1505 }\r
1506\r
1507 //\r
1508 // For Pci Hotplug controller devcie only\r
1509 //\r
1510 if (gPciHotPlugInit != NULL) {\r
1511 //\r
1512 // Check if it is a Hotplug PCI controller\r
1513 //\r
1514 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
1515\r
1516 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1517\r
1518 Status = CreateEventForHpc (HpIndex, &Event);\r
1519\r
1520 ASSERT (!EFI_ERROR (Status));\r
1521\r
1522 Status = gPciHotPlugInit->InitializeRootHpc (\r
1523 gPciHotPlugInit,\r
1524 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1525 PciAddress,\r
1526 Event,\r
1527 &State\r
1528 );\r
1529\r
1530 PreprocessController (\r
1531 PciDevice,\r
1532 PciDevice->BusNumber,\r
1533 PciDevice->DeviceNumber,\r
1534 PciDevice->FunctionNumber,\r
1535 EfiPciBeforeChildBusEnumeration\r
1536 );\r
1537 continue;\r
1538 }\r
1539 }\r
1540 }\r
1541\r
1542 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1543 //\r
1544 // For PPB\r
1545 // Get the bridge information\r
1546 //\r
1547 BusPadding = FALSE;\r
1548 if (gPciHotPlugInit != NULL) {\r
1549\r
1550 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1551\r
1552 //\r
1553 // If it is initialized, get the padded bus range\r
1554 //\r
1555 Status = gPciHotPlugInit->GetResourcePadding (\r
1556 gPciHotPlugInit,\r
1557 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1558 PciAddress,\r
1559 &State,\r
1560 (VOID **) &Descriptors,\r
1561 &Attributes\r
1562 );\r
1563\r
1564 if (EFI_ERROR (Status)) {\r
1565 return Status;\r
1566 }\r
1567\r
1568 BusRange = 0;\r
1569 Status = PciGetBusRange (\r
1570 &Descriptors,\r
1571 NULL,\r
1572 NULL,\r
1573 &BusRange\r
1574 );\r
1575\r
1576 gBS->FreePool (Descriptors);\r
1577\r
1578 if (EFI_ERROR (Status)) {\r
1579 return Status;\r
1580 }\r
1581\r
1582 BusPadding = TRUE;\r
1583 }\r
1584 }\r
1585\r
1586 (*SubBusNumber)++;\r
1587 SecondBus = *SubBusNumber;\r
1588\r
1589 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1590 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1591\r
1592 Status = PciRootBridgeIoWrite (\r
1593 PciRootBridgeIo,\r
1594 &Pci,\r
1595 EfiPciWidthUint16,\r
1596 Address,\r
1597 1,\r
1598 &Register\r
1599 );\r
1600\r
1601\r
1602 //\r
1603 // If it is PPB, resursively search down this bridge\r
1604 //\r
1605 if (IS_PCI_BRIDGE (&Pci)) {\r
1606\r
1607 //\r
1608 // Initialize SubBusNumber to Maximum bus number\r
1609 //\r
1610 Register = 0xFF;\r
1611 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1612 Status = PciRootBridgeIoWrite (\r
1613 PciRootBridgeIo,\r
1614 &Pci,\r
1615 EfiPciWidthUint8,\r
1616 Address,\r
1617 1,\r
1618 &Register\r
1619 );\r
1620\r
1621 //\r
1622 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1623 //\r
1624 PreprocessController (\r
1625 PciDevice,\r
1626 PciDevice->BusNumber,\r
1627 PciDevice->DeviceNumber,\r
1628 PciDevice->FunctionNumber,\r
1629 EfiPciBeforeChildBusEnumeration\r
1630 );\r
1631\r
1632 Status = PciScanBus (\r
1633 PciDevice,\r
1634 (UINT8) (SecondBus),\r
1635 SubBusNumber,\r
1636 PaddedBusRange\r
1637 );\r
1638\r
1639 if (EFI_ERROR (Status)) {\r
1640 return EFI_DEVICE_ERROR;\r
1641 }\r
1642 }\r
1643\r
1644 if (BusPadding) {\r
1645 //\r
1646 // Ensure the device is enabled and initialized\r
1647 //\r
1648 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1649 (State & EFI_HPC_STATE_ENABLED) &&\r
1650 (State & EFI_HPC_STATE_INITIALIZED) ) {\r
1651 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1652 } else {\r
1653 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1654 }\r
1655 }\r
1656\r
1657 //\r
1658 // Set the current maximum bus number under the PPB\r
1659 //\r
1660 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1661\r
1662 Status = PciRootBridgeIoWrite (\r
1663 PciRootBridgeIo,\r
1664 &Pci,\r
1665 EfiPciWidthUint8,\r
1666 Address,\r
1667 1,\r
1668 SubBusNumber\r
1669 );\r
1670 }\r
1671\r
1672 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1673\r
1674 //\r
1675 // Skip sub functions, this is not a multi function device\r
1676 //\r
1677 Func = PCI_MAX_FUNC;\r
1678 }\r
1679\r
1680 }\r
1681 }\r
1682\r
1683 return EFI_SUCCESS;\r
1684}\r
1685\r
1686EFI_STATUS\r
1687PciRootBridgeP2CProcess (\r
1688 IN PCI_IO_DEVICE *Bridge\r
1689 )\r
1690/*++\r
1691\r
1692Routine Description:\r
1693\r
1694 Process Option Rom on this host bridge\r
1695\r
1696Arguments:\r
1697\r
1698Returns:\r
1699\r
1700 None\r
1701\r
1702--*/\r
1703// TODO: Bridge - add argument and description to function comment\r
1704// TODO: EFI_SUCCESS - add return value to function comment\r
1705{\r
1706 LIST_ENTRY *CurrentLink;\r
1707 PCI_IO_DEVICE *Temp;\r
1708 EFI_HPC_STATE State;\r
1709 UINT64 PciAddress;\r
1710 EFI_STATUS Status;\r
1711\r
1712 CurrentLink = Bridge->ChildList.ForwardLink;\r
1713\r
1714 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
1715\r
1716 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1717\r
1718 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1719\r
1720 if (gPciHotPlugInit && Temp->Allocated) {\r
1721\r
1722 //\r
1723 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1724 //\r
1725 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1726 EFI_PROGRESS_CODE,\r
1727 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
1728 Temp->DevicePath\r
1729 );\r
1730\r
1731 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1732 Status = gPciHotPlugInit->InitializeRootHpc (\r
1733 gPciHotPlugInit,\r
1734 Temp->DevicePath,\r
1735 PciAddress,\r
1736 NULL,\r
1737 &State\r
1738 );\r
1739\r
1740 if (!EFI_ERROR (Status)) {\r
1741 Status = PciBridgeEnumerator (Temp);\r
1742\r
1743 if (EFI_ERROR (Status)) {\r
1744 return Status;\r
1745 }\r
1746 }\r
1747\r
1748 CurrentLink = CurrentLink->ForwardLink;\r
1749 continue;\r
1750\r
1751 }\r
1752 }\r
1753\r
1754 if (!IsListEmpty (&Temp->ChildList)) {\r
1755 Status = PciRootBridgeP2CProcess (Temp);\r
1756 }\r
1757\r
1758 CurrentLink = CurrentLink->ForwardLink;\r
1759 }\r
1760\r
1761 return EFI_SUCCESS;\r
1762}\r
1763\r
1764EFI_STATUS\r
1765PciHostBridgeP2CProcess (\r
1766 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1767 )\r
1768/*++\r
1769\r
1770Routine Description:\r
1771\r
1772Arguments:\r
1773\r
1774Returns:\r
1775\r
1776 None\r
1777\r
1778--*/\r
1779// TODO: PciResAlloc - add argument and description to function comment\r
1780// TODO: EFI_NOT_FOUND - add return value to function comment\r
1781// TODO: EFI_SUCCESS - add return value to function comment\r
1782{\r
1783 EFI_HANDLE RootBridgeHandle;\r
1784 PCI_IO_DEVICE *RootBridgeDev;\r
1785 EFI_STATUS Status;\r
1786\r
1787 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1788 return EFI_SUCCESS;\r
1789 }\r
1790\r
1791 RootBridgeHandle = NULL;\r
1792\r
1793 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1794\r
1795 //\r
1796 // Get RootBridg Device by handle\r
1797 //\r
1798 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1799\r
1800 if (RootBridgeDev == NULL) {\r
1801 return EFI_NOT_FOUND;\r
1802 }\r
1803\r
1804 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1805\r
1806 if (EFI_ERROR (Status)) {\r
1807 return Status;\r
1808 }\r
1809\r
1810 }\r
1811\r
1812 return EFI_SUCCESS;\r
1813}\r
1814\r
1815EFI_STATUS\r
1816PciHostBridgeEnumerator (\r
1817 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1818 )\r
1819/*++\r
1820\r
1821Routine Description:\r
1822\r
1823 This function is used to enumerate the entire host bridge\r
1824 in a given platform\r
1825\r
1826Arguments:\r
1827\r
1828 PciResAlloc - A pointer to the resource allocate protocol.\r
1829\r
1830Returns:\r
1831\r
1832 None\r
1833\r
1834--*/\r
1835// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1836// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1837// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1838// TODO: EFI_SUCCESS - add return value to function comment\r
1839{\r
1840 EFI_HANDLE RootBridgeHandle;\r
1841 PCI_IO_DEVICE *RootBridgeDev;\r
1842 EFI_STATUS Status;\r
1843 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1844 UINT16 MinBus;\r
1845 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1846\r
1847 InitializeHotPlugSupport ();\r
1848\r
1849 //\r
1850 // Notify the bus allocation phase is about to start\r
1851 //\r
1852 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1853\r
1854 RootBridgeHandle = NULL;\r
1855 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1856\r
1857 //\r
1858 // if a root bridge instance is found, create root bridge device for it\r
1859 //\r
1860\r
1861 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1862\r
1863 if (RootBridgeDev == NULL) {\r
1864 return EFI_OUT_OF_RESOURCES;\r
1865 }\r
1866\r
1867 //\r
1868 // Enumerate all the buses under this root bridge\r
1869 //\r
1870\r
1871 Status = PciRootBridgeEnumerator (\r
1872 PciResAlloc,\r
1873 RootBridgeDev\r
1874 );\r
1875\r
1876 DestroyRootBridge (RootBridgeDev);\r
1877 if (EFI_ERROR (Status)) {\r
1878 return Status;\r
1879 }\r
1880 }\r
1881\r
1882 //\r
1883 // Notify the bus allocation phase is finished for the first time\r
1884 //\r
1885 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1886\r
1887 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1888\r
1889 if (gPciHotPlugInit != NULL) {\r
1890 //\r
1891 // Wait for all HPC initialized\r
1892 //\r
1893 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1894\r
1895 if (EFI_ERROR (Status)) {\r
1896 return Status;\r
1897 }\r
1898\r
1899 //\r
1900 // Notify the bus allocation phase is about to start for the 2nd time\r
1901 //\r
1902 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1903\r
1904 RootBridgeHandle = NULL;\r
1905 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1906\r
1907 //\r
1908 // if a root bridge instance is found, create root bridge device for it\r
1909 //\r
1910\r
1911 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1912\r
1913 if (RootBridgeDev == NULL) {\r
1914 return EFI_OUT_OF_RESOURCES;\r
1915 }\r
1916\r
1917 //\r
1918 // Enumerate all the buses under this root bridge\r
1919 //\r
1920\r
1921 Status = PciRootBridgeEnumerator (\r
1922 PciResAlloc,\r
1923 RootBridgeDev\r
1924 );\r
1925\r
1926 DestroyRootBridge (RootBridgeDev);\r
1927 if (EFI_ERROR (Status)) {\r
1928 return Status;\r
1929 }\r
1930 }\r
1931\r
1932 //\r
1933 // Notify the bus allocation phase is to end for the 2nd time\r
1934 //\r
1935 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1936 }\r
1937 }\r
1938\r
1939 //\r
1940 // Notify the resource allocation phase is to start\r
1941 //\r
1942 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1943\r
1944 RootBridgeHandle = NULL;\r
1945 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1946\r
1947 //\r
1948 // if a root bridge instance is found, create root bridge device for it\r
1949 //\r
1950\r
1951 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1952\r
1953 if (RootBridgeDev == NULL) {\r
1954 return EFI_OUT_OF_RESOURCES;\r
1955 }\r
1956\r
1957 Status = StartManagingRootBridge (RootBridgeDev);\r
1958\r
1959 if (EFI_ERROR (Status)) {\r
1960 return Status;\r
1961 }\r
1962\r
1963 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1964 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1965\r
1966 if (EFI_ERROR (Status)) {\r
1967 return Status;\r
1968 }\r
1969\r
1970 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1971\r
1972 if (EFI_ERROR (Status)) {\r
1973 return Status;\r
1974 }\r
1975\r
1976 //\r
1977 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1978 // protocol\r
1979 //\r
1980 DetermineRootBridgeAttributes (\r
1981 PciResAlloc,\r
1982 RootBridgeDev\r
1983 );\r
1984\r
1985 //\r
1986 // Collect all the resource information under this root bridge\r
1987 // A database that records all the information about pci device subject to this\r
1988 // root bridge will then be created\r
1989 //\r
1990 Status = PciPciDeviceInfoCollector (\r
1991 RootBridgeDev,\r
1992 (UINT8) MinBus\r
1993 );\r
1994\r
1995 if (EFI_ERROR (Status)) {\r
1996 return Status;\r
1997 }\r
1998\r
1999 InsertRootBridge (RootBridgeDev);\r
2000\r
2001 //\r
2002 // Record the hostbridge handle\r
2003 //\r
2004 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
2005 }\r
2006\r
2007 return EFI_SUCCESS;\r
2008}\r
2009\r
2010/**\r
2011 Read PCI device configuration register by specified address.\r
2012\r
2013 This function check the incompatiblilites on PCI device. Return the register\r
2014 value.\r
2015\r
2016 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2017 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2018 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2019 @param Width Signifies the width of the memory operations.\r
2020 @Param Address The address within the PCI configuration space for the PCI controller.\r
2021 @param Buffer For read operations, the destination buffer to store the results. For\r
2022 write operations, the source buffer to write data from.\r
2023\r
2024 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2025 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2026 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2027 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2028\r
2029**/\r
2030STATIC\r
2031EFI_STATUS\r
2032ReadConfigData (\r
2033 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2034 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2035 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2036 IN UINT64 Width,\r
2037 IN UINT64 Address,\r
2038 IN OUT VOID *Buffer\r
2039 )\r
2040{\r
2041 EFI_STATUS Status;\r
2042 UINT64 AccessWidth;\r
2043 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2044 UINT64 AccessAddress;\r
2045 UINTN Stride;\r
2046 UINT64 TempBuffer;\r
2047 UINT8 *Pointer;\r
2048\r
2049 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2050\r
2051 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2052 //\r
2053 // check access compatibility at first time\r
2054 //\r
2055 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);\r
2056\r
2057 if (Status == EFI_SUCCESS) {\r
2058 //\r
2059 // there exist incompatibility on this operation\r
2060 //\r
2061 AccessWidth = Width;\r
2062\r
2063 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2064 AccessWidth = PciRegisterAccessData->Width;\r
2065 }\r
2066\r
2067 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2068\r
2069 TempBuffer = 0;\r
2070 Stride = 0;\r
2071 Pointer = (UINT8 *) &TempBuffer;\r
2072\r
2073 while (1) {\r
2074\r
2075 if (PciRootBridgeIo != NULL) {\r
2076 Status = PciRootBridgeIo->Pci.Read (\r
2077 PciRootBridgeIo,\r
2078 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2079 AccessAddress,\r
2080 1,\r
2081 Pointer\r
2082 );\r
2083 } else if (PciIo != NULL) {\r
2084 Status = PciIo->Pci.Read (\r
2085 PciIo,\r
2086 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2087 (UINT32) AccessAddress,\r
2088 1,\r
2089 Pointer\r
2090 );\r
2091 }\r
2092\r
2093 if (Status != EFI_SUCCESS) {\r
2094 return Status;\r
2095 }\r
2096\r
2097 Stride = 1 << AccessWidth;\r
2098 AccessAddress += Stride;\r
2099 if (AccessAddress >= (Address + (1 << Width))) {\r
2100 //\r
2101 // if all datas have been read, exist\r
2102 //\r
2103 break;\r
2104 }\r
2105\r
2106 Pointer += Stride;\r
2107\r
2108 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2109 //\r
2110 // if current offset doesn't reach the end\r
2111 //\r
2112 continue;\r
2113 }\r
2114\r
2115 FreePool (PciRegisterAccessData);\r
2116\r
2117 //\r
2118 // continue checking access incompatibility\r
2119 //\r
2120 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2121 if (Status == EFI_SUCCESS) {\r
2122 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2123 AccessWidth = PciRegisterAccessData->Width;\r
2124 }\r
2125 }\r
2126 }\r
2127\r
2128 FreePool (PciRegisterAccessData);\r
2129\r
2130 switch (Width) {\r
2131 case EfiPciWidthUint8:\r
2132 * (UINT8 *) Buffer = (UINT8) TempBuffer;\r
2133 break;\r
2134 case EfiPciWidthUint16:\r
2135 * (UINT16 *) Buffer = (UINT16) TempBuffer;\r
2136 break;\r
2137 case EfiPciWidthUint32:\r
2138 * (UINT32 *) Buffer = (UINT32) TempBuffer;\r
2139 break;\r
2140 default:\r
2141 return EFI_UNSUPPORTED;\r
2142 }\r
2143\r
2144 return Status;\r
2145 }\r
2146 }\r
2147 //\r
2148 // AccessWidth incompatible check not supportted\r
2149 // or, there doesn't exist incompatibility on this operation\r
2150 //\r
2151 if (PciRootBridgeIo != NULL) {\r
2152 Status = PciRootBridgeIo->Pci.Read (\r
2153 PciRootBridgeIo,\r
2154 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2155 Address,\r
2156 1,\r
2157 Buffer\r
2158 );\r
2159\r
2160 } else {\r
2161 Status = PciIo->Pci.Read (\r
2162 PciIo,\r
2163 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2164 (UINT32) Address,\r
2165 1,\r
2166 Buffer\r
2167 );\r
2168 }\r
2169\r
2170 return Status;\r
2171}\r
2172\r
2173/**\r
2174 Update register value by checking PCI device incompatibility.\r
2175\r
2176 This function check register value incompatibilites on PCI device. Return the register\r
2177 value.\r
2178\r
2179 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2180 @param AccessType Access type, READ or WRITE.\r
2181 @Param Address The address within the PCI configuration space.\r
2182 @param Buffer Store the register data.\r
2183\r
2184 @retval EFI_SUCCESS The data has been updated.\r
2185\r
2186**/\r
2187STATIC\r
2188EFI_STATUS\r
2189UpdateConfigData (\r
2190 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2191 IN UINT64 AccessType,\r
2192 IN UINT64 Width,\r
2193 IN UINT64 Address,\r
2194 IN OUT VOID *Buffer\r
2195)\r
2196{\r
2197 EFI_STATUS Status;\r
2198 EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;\r
2199 UINT32 AndValue;\r
2200 UINT32 OrValue;\r
2201 UINT32 TempValue;\r
2202\r
2203 //\r
2204 // check register value incompatibility\r
2205 //\r
2206 Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);\r
2207\r
2208 if (Status == EFI_SUCCESS) {\r
2209\r
2210 AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);\r
2211 OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);\r
2212\r
2213 TempValue = * (UINT32 *) Buffer;\r
2214 if (PciRegisterData->AndValue != VALUE_NOCARE) {\r
2215 TempValue &= AndValue;\r
2216 }\r
2217 if (PciRegisterData->OrValue != VALUE_NOCARE) {\r
2218 TempValue |= OrValue;\r
2219 }\r
2220\r
2221 switch (Width) {\r
2222 case EfiPciWidthUint8:\r
2223 *(UINT8 *)Buffer = (UINT8) TempValue;\r
2224 break;\r
2225\r
2226 case EfiPciWidthUint16:\r
2227 *(UINT16 *)Buffer = (UINT16) TempValue;\r
2228 break;\r
2229 case EfiPciWidthUint32:\r
2230 *(UINT32 *)Buffer = TempValue;\r
2231 break;\r
2232\r
2233 default:\r
2234 return EFI_UNSUPPORTED;\r
2235 }\r
2236\r
2237 FreePool (PciRegisterData);\r
2238 }\r
2239\r
2240 return Status;\r
2241}\r
2242\r
2243/**\r
2244 Write PCI device configuration register by specified address.\r
2245\r
2246 This function check the incompatiblilites on PCI device, and write date\r
2247 into register.\r
2248\r
2249 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2250 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2251 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2252 @param Width Signifies the width of the memory operations.\r
2253 @Param Address The address within the PCI configuration space for the PCI controller.\r
2254 @param Buffer For read operations, the destination buffer to store the results. For\r
2255 write operations, the source buffer to write data from.\r
2256\r
2257 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2258 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2259 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2260 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2261\r
2262**/\r
2263STATIC\r
2264EFI_STATUS\r
2265WriteConfigData (\r
2266 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2267 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2268 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2269 IN UINT64 Width,\r
2270 IN UINT64 Address,\r
2271 IN VOID *Buffer\r
2272 )\r
2273{\r
2274 EFI_STATUS Status;\r
2275 UINT64 AccessWidth;\r
2276 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2277 UINT64 AccessAddress;\r
2278 UINTN Stride;\r
2279 UINT8 *Pointer;\r
2280 UINT64 Data;\r
2281 UINTN Shift;\r
2282\r
2283 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2284\r
2285 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2286 //\r
2287 // check access compatibility at first time\r
2288 //\r
2289 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);\r
2290\r
2291 if (Status == EFI_SUCCESS) {\r
2292 //\r
2293 // there exist incompatibility on this operation\r
2294 //\r
2295 AccessWidth = Width;\r
2296\r
2297 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2298 AccessWidth = PciRegisterAccessData->Width;\r
2299 }\r
2300\r
2301 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2302\r
2303 Stride = 0;\r
2304 Pointer = (UINT8 *) &Buffer;\r
2305 Data = * (UINT64 *) Buffer;\r
2306\r
2307 while (1) {\r
2308\r
2309 if (AccessWidth > Width) {\r
2310 //\r
2311 // if actual access width is larger than orignal one, additional data need to be read back firstly\r
2312 //\r
2313 Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);\r
2314 if (Status != EFI_SUCCESS) {\r
2315 return Status;\r
2316 }\r
2317\r
2318 //\r
2319 // check data read incompatibility\r
2320 //\r
2321 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);\r
2322\r
307e7596 2323 Shift = (UINTN)(Address - AccessAddress) * 8;\r
ead42efc 2324 switch (Width) {\r
2325 case EfiPciWidthUint8:\r
2326 Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));\r
2327 break;\r
2328\r
2329 case EfiPciWidthUint16:\r
2330 Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));\r
2331 break;\r
2332 }\r
2333\r
2334 //\r
2335 // check data write incompatibility\r
2336 //\r
307e7596 2337 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, MultU64x32 (AccessAddress, 0xff), &Data);\r
ead42efc 2338 }\r
2339\r
2340 if (PciRootBridgeIo != NULL) {\r
2341 Status = PciRootBridgeIo->Pci.Write (\r
2342 PciRootBridgeIo,\r
2343 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2344 AccessAddress,\r
2345 1,\r
2346 &Data\r
2347 );\r
2348 } else {\r
2349 Status = PciIo->Pci.Write (\r
2350 PciIo,\r
2351 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2352 (UINT32) AccessAddress,\r
2353 1,\r
2354 &Data\r
2355 );\r
2356 }\r
2357\r
2358 if (Status != EFI_SUCCESS) {\r
2359 return Status;\r
2360 }\r
2361\r
2362 Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));\r
2363\r
2364 Stride = 1 << AccessWidth;\r
2365 AccessAddress += Stride;\r
2366 if (AccessAddress >= (Address + (1 << Width))) {\r
2367 //\r
2368 // if all datas have been written, exist\r
2369 //\r
2370 break;\r
2371 }\r
2372\r
2373 Pointer += Stride;\r
2374\r
2375 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2376 //\r
2377 // if current offset doesn't reach the end\r
2378 //\r
2379 continue;\r
2380 }\r
2381\r
2382 FreePool (PciRegisterAccessData);\r
2383\r
2384 //\r
2385 // continue checking access incompatibility\r
2386 //\r
2387 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2388 if (Status == EFI_SUCCESS) {\r
2389 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2390 AccessWidth = PciRegisterAccessData->Width;\r
2391 }\r
2392 }\r
2393 };\r
2394\r
2395 FreePool (PciRegisterAccessData);\r
2396\r
2397 return Status;\r
2398 }\r
2399\r
2400 }\r
2401 //\r
2402 // AccessWidth incompatible check not supportted\r
2403 // or, there doesn't exist incompatibility on this operation\r
2404 //\r
2405 if (PciRootBridgeIo != NULL) {\r
2406 Status = PciRootBridgeIo->Pci.Write (\r
2407 PciRootBridgeIo,\r
2408 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2409 Address,\r
2410 1,\r
2411 Buffer\r
2412 );\r
2413 } else {\r
2414 Status = PciIo->Pci.Write (\r
2415 PciIo,\r
2416 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2417 (UINT32) Address,\r
2418 1,\r
2419 Buffer\r
2420 );\r
2421 }\r
2422\r
2423 return Status;\r
2424}\r
2425\r
2426/**\r
2427 Abstract PCI device device information.\r
2428\r
2429 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2430 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2431 @param Pci A pointer to PCI_TYPE00.\r
2432 @Param Address The address within the PCI configuration space for the PCI controller.\r
2433 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2434\r
2435 @retval EFI_SUCCESS Pci device device information has been abstracted.\r
2436\r
2437**/\r
2438STATIC\r
2439EFI_STATUS\r
2440GetPciDeviceDeviceInfo (\r
2441 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2442 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2443 IN PCI_TYPE00 *Pci, OPTIONAL\r
2444 IN UINT64 Address, OPTIONAL\r
2445 OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo\r
2446)\r
2447{\r
2448 EFI_STATUS Status;\r
2449 UINT64 PciAddress;\r
2450 UINT32 PciConfigData;\r
2451 PCI_IO_DEVICE *PciIoDevice;\r
2452\r
2453 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2454\r
2455 if (PciIo != NULL) {\r
2456 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2457\r
2458 //\r
2459 // get pointer to PCI_TYPE00 from PciIoDevice\r
2460 //\r
2461 Pci = &PciIoDevice->Pci;\r
2462 }\r
2463\r
2464 if (Pci == NULL) {\r
2465 //\r
2466 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly\r
2467 //\r
2468 PciAddress = Address & 0xffffffffffffff00ULL;\r
2469 Status = PciRootBridgeIo->Pci.Read (\r
2470 PciRootBridgeIo,\r
2471 EfiPciWidthUint32,\r
2472 PciAddress,\r
2473 1,\r
2474 &PciConfigData\r
2475 );\r
2476\r
2477 if (EFI_ERROR (Status)) {\r
2478 return Status;\r
2479 }\r
2480\r
2481 if ((PciConfigData & 0xffff) == 0xffff) {\r
2482 return EFI_NOT_FOUND;\r
2483 }\r
2484\r
2485 PciDeviceInfo->VendorID = PciConfigData & 0xffff;\r
2486 PciDeviceInfo->DeviceID = PciConfigData >> 16;\r
2487\r
2488 Status = PciRootBridgeIo->Pci.Read (\r
2489 PciRootBridgeIo,\r
2490 EfiPciWidthUint32,\r
2491 PciAddress + 8,\r
2492 1,\r
2493 &PciConfigData\r
2494 );\r
2495 if (EFI_ERROR (Status)) {\r
2496 return Status;\r
2497 }\r
2498\r
2499 PciDeviceInfo->RevisionID = PciConfigData & 0xf;\r
2500\r
2501 Status = PciRootBridgeIo->Pci.Read (\r
2502 PciRootBridgeIo,\r
2503 EfiPciWidthUint32,\r
2504 PciAddress + 0x2c,\r
2505 1,\r
2506 &PciConfigData\r
2507 );\r
2508\r
2509 if (EFI_ERROR (Status)) {\r
2510 return Status;\r
2511 }\r
2512\r
2513 PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;\r
2514 PciDeviceInfo->SubsystemID = PciConfigData >> 16;\r
2515\r
2516 } else {\r
2517 PciDeviceInfo->VendorID = Pci->Hdr.VendorId;\r
2518 PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;\r
2519 PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;\r
2520 PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;\r
2521 PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;\r
2522 }\r
2523\r
2524 return EFI_SUCCESS;\r
2525}\r
2526\r
2527/**\r
2528 Read PCI configuration space with incompatibility check.\r
2529\r
2530 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2531 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2532 @param Pci A pointer to PCI_TYPE00.\r
2533 @param Width Signifies the width of the memory operations.\r
2534 @Param Address The address within the PCI configuration space for the PCI controller.\r
2535 @param Buffer For read operations, the destination buffer to store the results. For\r
2536 write operations, the source buffer to write data from.\r
2537\r
2538 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2539 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2540 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2541 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2542\r
2543**/\r
2544STATIC\r
2545EFI_STATUS\r
2546PciIncompatibilityCheckRead (\r
2547 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2548 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2549 IN PCI_TYPE00 *Pci, OPTIONAL\r
2550 IN UINTN Width,\r
2551 IN UINT64 Address,\r
2552 IN UINTN Count,\r
2553 IN OUT VOID *Buffer\r
2554)\r
2555{\r
2556 EFI_STATUS Status;\r
2557 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2558 UINT32 Stride;\r
2559\r
2560 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2561\r
2562 //\r
2563 // get PCI device device information\r
2564 //\r
2565 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2566 if (Status != EFI_SUCCESS) {\r
2567 return Status;\r
2568 }\r
2569\r
2570 Stride = 1 << Width;\r
2571\r
2572 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {\r
2573\r
2574 //\r
2575 // read configuration register\r
2576 //\r
2577 Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);\r
2578\r
2579 if (Status != EFI_SUCCESS) {\r
2580 return Status;\r
2581 }\r
2582\r
2583 //\r
2584 // update the data read from configuration register\r
2585 //\r
2586 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2587 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);\r
2588 }\r
2589 }\r
2590\r
2591 return EFI_SUCCESS;\r
2592}\r
2593\r
2594/**\r
2595 Write PCI configuration space with incompatibility check.\r
2596\r
2597 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2598 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2599 @param Pci A pointer to PCI_TYPE00.\r
2600 @param Width Signifies the width of the memory operations.\r
2601 @Param Address The address within the PCI configuration space for the PCI controller.\r
2602 @param Buffer For read operations, the destination buffer to store the results. For\r
2603 write operations, the source buffer to write data from.\r
2604\r
2605 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2606 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2607 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2608 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2609\r
2610**/\r
2611STATIC\r
2612EFI_STATUS\r
2613PciIncompatibilityCheckWrite (\r
2614 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2615 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2616 IN PCI_TYPE00 *Pci, OPTIONAL\r
2617 IN UINTN Width,\r
2618 IN UINT64 Address,\r
2619 IN UINTN Count,\r
2620 IN OUT VOID *Buffer\r
2621)\r
2622{\r
2623 EFI_STATUS Status;\r
2624 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2625 UINT32 Stride;\r
2626 UINT64 Data;\r
2627\r
2628 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2629\r
2630 //\r
2631 // get PCI device device information\r
2632 //\r
2633 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2634 if (Status != EFI_SUCCESS) {\r
2635 return Status;\r
2636 }\r
2637\r
2638 Stride = 1 << Width;\r
2639\r
2640 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {\r
2641\r
2642 Data = 0;\r
2643\r
2644 switch (Width) {\r
2645 case EfiPciWidthUint8:\r
2646 Data = * (UINT8 *) Buffer;\r
2647 break;\r
2648 case EfiPciWidthUint16:\r
2649 Data = * (UINT16 *) Buffer;\r
2650 break;\r
2651\r
2652 case EfiPciWidthUint32:\r
2653 Data = * (UINT32 *) Buffer;\r
2654 break;\r
2655\r
2656 default:\r
2657 return EFI_UNSUPPORTED;\r
2658 }\r
2659\r
2660 //\r
2661 // update the data writen into configuration register\r
2662 //\r
2663 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2664 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);\r
2665 }\r
2666\r
2667 //\r
2668 // write configuration register\r
2669 //\r
2670 Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);\r
2671\r
2672 if (Status != EFI_SUCCESS) {\r
2673 return Status;\r
2674 }\r
2675 }\r
2676\r
2677 return EFI_SUCCESS;\r
2678}\r
2679\r
2680/**\r
2681 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2682\r
2683 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2684 @param Pci A pointer to PCI_TYPE00.\r
2685 @param Width Signifies the width of the memory operations.\r
2686 @Param Address The address within the PCI configuration space for the PCI controller.\r
2687 @param Buffer For read operations, the destination buffer to store the results. For\r
2688 write operations, the source buffer to write data from.\r
2689\r
2690 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2691 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2692 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2693 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2694\r
2695**/\r
2696EFI_STATUS\r
2697PciRootBridgeIoRead (\r
2698 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2699 IN PCI_TYPE00 *Pci, OPTIONAL\r
2700 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2701 IN UINT64 Address,\r
2702 IN UINTN Count,\r
2703 IN OUT VOID *Buffer\r
2704 )\r
2705{\r
2706 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2707 //\r
2708 // if PCI incompatibility check enabled\r
2709 //\r
2710 return PciIncompatibilityCheckRead (\r
2711 PciRootBridgeIo,\r
2712 NULL,\r
2713 Pci,\r
2714 (UINTN) Width,\r
2715 Address,\r
2716 Count,\r
2717 Buffer\r
2718 );\r
2719 } else {\r
2720 return PciRootBridgeIo->Pci.Read (\r
2721 PciRootBridgeIo,\r
2722 Width,\r
2723 Address,\r
2724 Count,\r
2725 Buffer\r
2726 );\r
2727 }\r
2728}\r
2729\r
2730/**\r
2731 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2732\r
2733 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2734 @param Pci A pointer to PCI_TYPE00.\r
2735 @param Width Signifies the width of the memory operations.\r
2736 @Param Address The address within the PCI configuration space for the PCI controller.\r
2737 @param Buffer For read operations, the destination buffer to store the results. For\r
2738 write operations, the source buffer to write data from.\r
2739\r
2740 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2741 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2742 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2743 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2744\r
2745**/\r
2746EFI_STATUS\r
2747PciRootBridgeIoWrite (\r
2748 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2749 IN PCI_TYPE00 *Pci,\r
2750 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2751 IN UINT64 Address,\r
2752 IN UINTN Count,\r
2753 IN OUT VOID *Buffer\r
2754 )\r
2755{\r
2756 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2757 //\r
2758 // if PCI incompatibility check enabled\r
2759 //\r
2760 return PciIncompatibilityCheckWrite (\r
2761 PciRootBridgeIo,\r
2762 NULL,\r
2763 Pci,\r
2764 Width,\r
2765 Address,\r
2766 Count,\r
2767 Buffer\r
2768 );\r
2769\r
2770 } else {\r
2771 return PciRootBridgeIo->Pci.Write (\r
2772 PciRootBridgeIo,\r
2773 Width,\r
2774 Address,\r
2775 Count,\r
2776 Buffer\r
2777 );\r
2778 }\r
2779}\r
2780\r
2781/**\r
2782 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2783\r
2784 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2785 @param Width Signifies the width of the memory operations.\r
2786 @Param Address The address within the PCI configuration space for the PCI controller.\r
2787 @param Buffer For read operations, the destination buffer to store the results. For\r
2788 write operations, the source buffer to write data from.\r
2789\r
2790 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2791 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2792 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2793 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2794\r
2795**/\r
2796EFI_STATUS\r
2797PciIoRead (\r
2798 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2799 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2800 IN UINT32 Address,\r
2801 IN UINTN Count,\r
2802 IN OUT VOID *Buffer\r
2803 )\r
2804{\r
2805 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2806 //\r
2807 // if PCI incompatibility check enabled\r
2808 //\r
2809 return PciIncompatibilityCheckRead (\r
2810 NULL,\r
2811 PciIo,\r
2812 NULL,\r
2813 (UINTN) Width,\r
2814 Address,\r
2815 Count,\r
2816 Buffer\r
2817 );\r
2818 } else {\r
2819 return PciIo->Pci.Read (\r
2820 PciIo,\r
2821 Width,\r
2822 Address,\r
2823 Count,\r
2824 Buffer\r
2825 );\r
2826 }\r
2827}\r
2828\r
2829/**\r
2830 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2831\r
2832 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2833 @param Width Signifies the width of the memory operations.\r
2834 @Param Address The address within the PCI configuration space for the PCI controller.\r
2835 @param Buffer For read operations, the destination buffer to store the results. For\r
2836 write operations, the source buffer to write data from.\r
2837\r
2838 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2839 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2840 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2841 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2842\r
2843**/\r
2844EFI_STATUS\r
2845PciIoWrite (\r
2846 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2847 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2848 IN UINT32 Address,\r
2849 IN UINTN Count,\r
2850 IN OUT VOID *Buffer\r
2851 )\r
2852{\r
2853 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2854\r
2855 //\r
2856 // if PCI incompatibility check enabled\r
2857 //\r
2858 return PciIncompatibilityCheckWrite (\r
2859 NULL,\r
2860 PciIo,\r
2861 NULL,\r
2862 Width,\r
2863 Address,\r
2864 Count,\r
2865 Buffer\r
2866 );\r
2867\r
2868 } else {\r
2869 return PciIo->Pci.Write (\r
2870 PciIo,\r
2871 Width,\r
2872 Address,\r
2873 Count,\r
2874 Buffer\r
2875 );\r
2876 }\r
2877}\r