]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Coding style modification.
[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
4beb4afe 7Copyright (c) 2006 - 2008, 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
bcd70414 29/**\r
ead42efc 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
bcd70414 40**/\r
ead42efc 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
bcd70414 61/**\r
ead42efc 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
bcd70414 73**/\r
ead42efc 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
bcd70414 97/**\r
ead42efc 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
bcd70414 109**/\r
ead42efc 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
bcd70414 143/**\r
ead42efc 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
bcd70414 156**/\r
ead42efc 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
bcd70414 230/**\r
ead42efc 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
bcd70414 244**/\r
ead42efc 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
bcd70414 319/**\r
ead42efc 320\r
321Routine Description:\r
322\r
323Arguments:\r
324\r
325Returns:\r
326\r
327 None\r
328\r
bcd70414 329**/\r
ead42efc 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
bcd70414 692/**\r
ead42efc 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
bcd70414 706**/\r
ead42efc 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
bcd70414 1227/**\r
ead42efc 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
bcd70414 1239**/\r
ead42efc 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
ead42efc 1261 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1262 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1263\r
1264 //\r
1265 // Check to see whether a pci device is present\r
1266 //\r
1267 Status = PciDevicePresent (\r
1268 PciRootBridgeIo,\r
1269 &Pci,\r
1270 StartBusNumber,\r
1271 Device,\r
1272 Func\r
1273 );\r
1274\r
1275 if (!EFI_ERROR (Status) &&\r
1276 (IS_PCI_BRIDGE (&Pci) ||\r
1277 IS_CARDBUS_BRIDGE (&Pci))) {\r
1278\r
ff62de37 1279 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
1280\r
ead42efc 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
ff62de37 1297 //\r
1298 // Add feature to support customized secondary bus number\r
1299 //\r
4beb4afe 1300 if (*SubBusNumber == 0) {\r
ff62de37 1301 *SubBusNumber = *PaddedBusRange;\r
1302 *PaddedBusRange = 0;\r
1303 }\r
1304\r
ead42efc 1305 (*SubBusNumber)++;\r
1306\r
1307 SecondBus = (*SubBusNumber);\r
1308\r
1309 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1310\r
1311 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1312\r
1313 Status = PciRootBridgeIoWrite (\r
1314 PciRootBridgeIo,\r
1315 &Pci,\r
1316 EfiPciWidthUint16,\r
1317 Address,\r
1318 1,\r
1319 &Register\r
1320 );\r
1321\r
1322 //\r
1323 // Initialize SubBusNumber to SecondBus\r
1324 //\r
1325 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1326 Status = PciRootBridgeIoWrite (\r
1327 PciRootBridgeIo,\r
1328 &Pci,\r
1329 EfiPciWidthUint8,\r
1330 Address,\r
1331 1,\r
1332 SubBusNumber\r
1333 );\r
1334 //\r
1335 // If it is PPB, resursively search down this bridge\r
1336 //\r
1337 if (IS_PCI_BRIDGE (&Pci)) {\r
1338 //\r
1339 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1340 // PCI configuration transaction to go through any PPB\r
1341 //\r
1342 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1343 Register = 0xFF;\r
1344 Status = PciRootBridgeIoWrite (\r
1345 PciRootBridgeIo,\r
1346 &Pci,\r
1347 EfiPciWidthUint8,\r
1348 Address,\r
1349 1,\r
1350 &Register\r
1351 );\r
1352\r
1353 PreprocessController (\r
1354 PciDevice,\r
1355 PciDevice->BusNumber,\r
1356 PciDevice->DeviceNumber,\r
1357 PciDevice->FunctionNumber,\r
1358 EfiPciBeforeChildBusEnumeration\r
1359 );\r
1360\r
ff62de37 1361 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));\r
ead42efc 1362 Status = PciScanBus (\r
1363 PciDevice,\r
1364 (UINT8) (SecondBus),\r
1365 SubBusNumber,\r
1366 PaddedBusRange\r
1367 );\r
1368\r
1369 if (EFI_ERROR (Status)) {\r
1370 return EFI_DEVICE_ERROR;\r
1371 }\r
1372 }\r
1373\r
1374 //\r
1375 // Set the current maximum bus number under the PPB\r
1376 //\r
1377\r
1378 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1379\r
1380 Status = PciRootBridgeIoWrite (\r
1381 PciRootBridgeIo,\r
1382 &Pci,\r
1383 EfiPciWidthUint8,\r
1384 Address,\r
1385 1,\r
1386 SubBusNumber\r
1387 );\r
1388\r
1389 }\r
1390\r
1391 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1392\r
1393 //\r
1394 // Skip sub functions, this is not a multi function device\r
1395 //\r
1396\r
1397 Func = PCI_MAX_FUNC;\r
1398 }\r
1399 }\r
1400 }\r
1401\r
1402 return EFI_SUCCESS;\r
1403}\r
1404\r
1405EFI_STATUS\r
1406PciScanBus_WithHotPlugDeviceSupport (\r
1407 IN PCI_IO_DEVICE *Bridge,\r
1408 IN UINT8 StartBusNumber,\r
1409 OUT UINT8 *SubBusNumber,\r
1410 OUT UINT8 *PaddedBusRange\r
1411 )\r
bcd70414 1412/**\r
ead42efc 1413\r
1414Routine Description:\r
1415\r
1416 This routine is used to assign bus number to the given PCI bus system\r
1417\r
1418Arguments:\r
1419\r
1420 Bridge - A pointer to the PCI_IO_DEVICE structure.\r
1421 StartBusNumber - The start bus number.\r
1422 SubBusNumber - A pointer to the sub bus number.\r
1423 PaddedBusRange - A pointer to the padded bus range.\r
1424\r
1425Returns:\r
1426\r
1427 None\r
1428\r
bcd70414 1429**/\r
ead42efc 1430// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1431// TODO: EFI_SUCCESS - add return value to function comment\r
1432{\r
1433 EFI_STATUS Status;\r
1434 PCI_TYPE00 Pci;\r
1435 UINT8 Device;\r
1436 UINT8 Func;\r
1437 UINT64 Address;\r
1438 UINTN SecondBus;\r
1439 UINT16 Register;\r
1440 UINTN HpIndex;\r
1441 PCI_IO_DEVICE *PciDevice;\r
1442 EFI_EVENT Event;\r
1443 EFI_HPC_STATE State;\r
1444 UINT64 PciAddress;\r
1445 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
1446 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1447 UINT16 BusRange;\r
1448 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1449 BOOLEAN BusPadding;\r
1450\r
1451 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1452 SecondBus = 0;\r
1453 Register = 0;\r
1454 State = 0;\r
1455 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
1456 BusRange = 0;\r
1457\r
ead42efc 1458 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1459 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1460\r
1461 //\r
1462 // Check to see whether a pci device is present\r
1463 //\r
1464 Status = PciDevicePresent (\r
1465 PciRootBridgeIo,\r
1466 &Pci,\r
1467 StartBusNumber,\r
1468 Device,\r
1469 Func\r
1470 );\r
1471\r
1472 if (EFI_ERROR (Status)) {\r
1473 if (Func == 0) {\r
1474 //\r
1475 // Skip sub functions, this is not a multi function device\r
1476 //\r
1477 Func = PCI_MAX_FUNC;\r
1478 }\r
1479\r
1480 continue;\r
1481 }\r
1482\r
ff62de37 1483 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
4beb4afe 1484\r
ead42efc 1485 //\r
1486 // Get the PCI device information\r
1487 //\r
1488 Status = PciSearchDevice (\r
1489 Bridge,\r
1490 &Pci,\r
1491 StartBusNumber,\r
1492 Device,\r
1493 Func,\r
1494 &PciDevice\r
1495 );\r
1496\r
1497 ASSERT (!EFI_ERROR (Status));\r
1498\r
1499 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
1500\r
1501 if (!IS_PCI_BRIDGE (&Pci)) {\r
1502 //\r
1503 // PCI bridges will be called later\r
1504 // Here just need for PCI device or PCI to cardbus controller\r
1505 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1506 //\r
1507 PreprocessController (\r
1508 PciDevice,\r
1509 PciDevice->BusNumber,\r
1510 PciDevice->DeviceNumber,\r
1511 PciDevice->FunctionNumber,\r
1512 EfiPciBeforeChildBusEnumeration\r
1513 );\r
1514 }\r
1515\r
1516 //\r
1517 // For Pci Hotplug controller devcie only\r
1518 //\r
1519 if (gPciHotPlugInit != NULL) {\r
1520 //\r
1521 // Check if it is a Hotplug PCI controller\r
1522 //\r
1523 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
1524\r
1525 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1526\r
1527 Status = CreateEventForHpc (HpIndex, &Event);\r
1528\r
1529 ASSERT (!EFI_ERROR (Status));\r
1530\r
1531 Status = gPciHotPlugInit->InitializeRootHpc (\r
1532 gPciHotPlugInit,\r
1533 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1534 PciAddress,\r
1535 Event,\r
1536 &State\r
1537 );\r
1538\r
1539 PreprocessController (\r
1540 PciDevice,\r
1541 PciDevice->BusNumber,\r
1542 PciDevice->DeviceNumber,\r
1543 PciDevice->FunctionNumber,\r
1544 EfiPciBeforeChildBusEnumeration\r
1545 );\r
ead42efc 1546 }\r
1547 }\r
1548 }\r
1549\r
1550 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1551 //\r
1552 // For PPB\r
1553 // Get the bridge information\r
1554 //\r
1555 BusPadding = FALSE;\r
1556 if (gPciHotPlugInit != NULL) {\r
1557\r
1558 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1559\r
1560 //\r
1561 // If it is initialized, get the padded bus range\r
1562 //\r
1563 Status = gPciHotPlugInit->GetResourcePadding (\r
1564 gPciHotPlugInit,\r
1565 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1566 PciAddress,\r
1567 &State,\r
1568 (VOID **) &Descriptors,\r
1569 &Attributes\r
1570 );\r
1571\r
1572 if (EFI_ERROR (Status)) {\r
1573 return Status;\r
1574 }\r
1575\r
1576 BusRange = 0;\r
1577 Status = PciGetBusRange (\r
1578 &Descriptors,\r
1579 NULL,\r
1580 NULL,\r
1581 &BusRange\r
1582 );\r
1583\r
1584 gBS->FreePool (Descriptors);\r
1585\r
1586 if (EFI_ERROR (Status)) {\r
1587 return Status;\r
1588 }\r
1589\r
1590 BusPadding = TRUE;\r
1591 }\r
1592 }\r
1593\r
ff62de37 1594 //\r
1595 // Add feature to support customized secondary bus number\r
1596 //\r
4beb4afe 1597 if (*SubBusNumber == 0) {\r
ff62de37 1598 *SubBusNumber = *PaddedBusRange;\r
1599 *PaddedBusRange = 0;\r
1600 }\r
1601\r
ead42efc 1602 (*SubBusNumber)++;\r
1603 SecondBus = *SubBusNumber;\r
1604\r
1605 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1606 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1607\r
1608 Status = PciRootBridgeIoWrite (\r
1609 PciRootBridgeIo,\r
1610 &Pci,\r
1611 EfiPciWidthUint16,\r
1612 Address,\r
1613 1,\r
1614 &Register\r
1615 );\r
1616\r
1617\r
1618 //\r
1619 // If it is PPB, resursively search down this bridge\r
1620 //\r
1621 if (IS_PCI_BRIDGE (&Pci)) {\r
1622\r
1623 //\r
1624 // Initialize SubBusNumber to Maximum bus number\r
1625 //\r
1626 Register = 0xFF;\r
1627 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1628 Status = PciRootBridgeIoWrite (\r
1629 PciRootBridgeIo,\r
1630 &Pci,\r
1631 EfiPciWidthUint8,\r
1632 Address,\r
1633 1,\r
1634 &Register\r
1635 );\r
1636\r
1637 //\r
1638 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1639 //\r
1640 PreprocessController (\r
1641 PciDevice,\r
1642 PciDevice->BusNumber,\r
1643 PciDevice->DeviceNumber,\r
1644 PciDevice->FunctionNumber,\r
1645 EfiPciBeforeChildBusEnumeration\r
1646 );\r
1647\r
ff62de37 1648 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));\r
ead42efc 1649 Status = PciScanBus (\r
1650 PciDevice,\r
1651 (UINT8) (SecondBus),\r
1652 SubBusNumber,\r
1653 PaddedBusRange\r
1654 );\r
1655\r
1656 if (EFI_ERROR (Status)) {\r
1657 return EFI_DEVICE_ERROR;\r
1658 }\r
1659 }\r
1660\r
1661 if (BusPadding) {\r
1662 //\r
1663 // Ensure the device is enabled and initialized\r
1664 //\r
1665 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1666 (State & EFI_HPC_STATE_ENABLED) &&\r
1667 (State & EFI_HPC_STATE_INITIALIZED) ) {\r
1668 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1669 } else {\r
1670 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1671 }\r
1672 }\r
1673\r
1674 //\r
1675 // Set the current maximum bus number under the PPB\r
1676 //\r
1677 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1678\r
1679 Status = PciRootBridgeIoWrite (\r
1680 PciRootBridgeIo,\r
1681 &Pci,\r
1682 EfiPciWidthUint8,\r
1683 Address,\r
1684 1,\r
1685 SubBusNumber\r
1686 );\r
1687 }\r
1688\r
1689 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1690\r
1691 //\r
1692 // Skip sub functions, this is not a multi function device\r
1693 //\r
1694 Func = PCI_MAX_FUNC;\r
1695 }\r
1696\r
1697 }\r
1698 }\r
1699\r
1700 return EFI_SUCCESS;\r
1701}\r
1702\r
1703EFI_STATUS\r
1704PciRootBridgeP2CProcess (\r
1705 IN PCI_IO_DEVICE *Bridge\r
1706 )\r
bcd70414 1707/**\r
ead42efc 1708\r
1709Routine Description:\r
1710\r
1711 Process Option Rom on this host bridge\r
1712\r
1713Arguments:\r
1714\r
1715Returns:\r
1716\r
1717 None\r
1718\r
bcd70414 1719**/\r
ead42efc 1720// TODO: Bridge - add argument and description to function comment\r
1721// TODO: EFI_SUCCESS - add return value to function comment\r
1722{\r
1723 LIST_ENTRY *CurrentLink;\r
1724 PCI_IO_DEVICE *Temp;\r
1725 EFI_HPC_STATE State;\r
1726 UINT64 PciAddress;\r
1727 EFI_STATUS Status;\r
1728\r
1729 CurrentLink = Bridge->ChildList.ForwardLink;\r
1730\r
1731 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
1732\r
1733 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1734\r
1735 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1736\r
1737 if (gPciHotPlugInit && Temp->Allocated) {\r
1738\r
1739 //\r
1740 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1741 //\r
1742 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1743 EFI_PROGRESS_CODE,\r
1744 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
1745 Temp->DevicePath\r
1746 );\r
1747\r
1748 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1749 Status = gPciHotPlugInit->InitializeRootHpc (\r
1750 gPciHotPlugInit,\r
1751 Temp->DevicePath,\r
1752 PciAddress,\r
1753 NULL,\r
1754 &State\r
1755 );\r
1756\r
1757 if (!EFI_ERROR (Status)) {\r
1758 Status = PciBridgeEnumerator (Temp);\r
1759\r
1760 if (EFI_ERROR (Status)) {\r
1761 return Status;\r
1762 }\r
1763 }\r
1764\r
1765 CurrentLink = CurrentLink->ForwardLink;\r
1766 continue;\r
1767\r
1768 }\r
1769 }\r
1770\r
1771 if (!IsListEmpty (&Temp->ChildList)) {\r
1772 Status = PciRootBridgeP2CProcess (Temp);\r
1773 }\r
1774\r
1775 CurrentLink = CurrentLink->ForwardLink;\r
1776 }\r
1777\r
1778 return EFI_SUCCESS;\r
1779}\r
1780\r
1781EFI_STATUS\r
1782PciHostBridgeP2CProcess (\r
1783 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1784 )\r
bcd70414 1785/**\r
ead42efc 1786\r
1787Routine Description:\r
1788\r
1789Arguments:\r
1790\r
1791Returns:\r
1792\r
1793 None\r
1794\r
bcd70414 1795**/\r
ead42efc 1796// TODO: PciResAlloc - add argument and description to function comment\r
1797// TODO: EFI_NOT_FOUND - add return value to function comment\r
1798// TODO: EFI_SUCCESS - add return value to function comment\r
1799{\r
1800 EFI_HANDLE RootBridgeHandle;\r
1801 PCI_IO_DEVICE *RootBridgeDev;\r
1802 EFI_STATUS Status;\r
1803\r
1804 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1805 return EFI_SUCCESS;\r
1806 }\r
1807\r
1808 RootBridgeHandle = NULL;\r
1809\r
1810 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1811\r
1812 //\r
1813 // Get RootBridg Device by handle\r
1814 //\r
1815 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1816\r
1817 if (RootBridgeDev == NULL) {\r
1818 return EFI_NOT_FOUND;\r
1819 }\r
1820\r
1821 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1822\r
1823 if (EFI_ERROR (Status)) {\r
1824 return Status;\r
1825 }\r
1826\r
1827 }\r
1828\r
1829 return EFI_SUCCESS;\r
1830}\r
1831\r
1832EFI_STATUS\r
1833PciHostBridgeEnumerator (\r
1834 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1835 )\r
bcd70414 1836/**\r
ead42efc 1837\r
1838Routine Description:\r
1839\r
1840 This function is used to enumerate the entire host bridge\r
1841 in a given platform\r
1842\r
1843Arguments:\r
1844\r
1845 PciResAlloc - A pointer to the resource allocate protocol.\r
1846\r
1847Returns:\r
1848\r
1849 None\r
1850\r
bcd70414 1851**/\r
ead42efc 1852// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1853// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1854// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1855// TODO: EFI_SUCCESS - add return value to function comment\r
1856{\r
1857 EFI_HANDLE RootBridgeHandle;\r
1858 PCI_IO_DEVICE *RootBridgeDev;\r
1859 EFI_STATUS Status;\r
1860 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1861 UINT16 MinBus;\r
1862 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
4beb4afe 1863 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;\r
1864 UINT8 StartBusNumber;\r
1865 LIST_ENTRY RootBridgeList;\r
1866 LIST_ENTRY *Link;\r
ead42efc 1867\r
1868 InitializeHotPlugSupport ();\r
1869\r
4beb4afe 1870 InitializeListHead (&RootBridgeList);\r
1871\r
ead42efc 1872 //\r
1873 // Notify the bus allocation phase is about to start\r
1874 //\r
1875 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1876\r
ff62de37 1877 DEBUG((EFI_D_ERROR, "PCI Bus First Scanning\n"));\r
ead42efc 1878 RootBridgeHandle = NULL;\r
1879 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1880\r
1881 //\r
1882 // if a root bridge instance is found, create root bridge device for it\r
1883 //\r
1884\r
1885 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1886\r
1887 if (RootBridgeDev == NULL) {\r
1888 return EFI_OUT_OF_RESOURCES;\r
1889 }\r
1890\r
1891 //\r
1892 // Enumerate all the buses under this root bridge\r
1893 //\r
1894\r
1895 Status = PciRootBridgeEnumerator (\r
1896 PciResAlloc,\r
1897 RootBridgeDev\r
1898 );\r
1899\r
4beb4afe 1900 if (gPciHotPlugInit != NULL) {\r
1901 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1902 } else {\r
1903 DestroyRootBridge (RootBridgeDev);\r
1904 }\r
ead42efc 1905 if (EFI_ERROR (Status)) {\r
1906 return Status;\r
1907 }\r
1908 }\r
1909\r
1910 //\r
1911 // Notify the bus allocation phase is finished for the first time\r
1912 //\r
1913 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1914\r
1915 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1916\r
1917 if (gPciHotPlugInit != NULL) {\r
1918 //\r
4beb4afe 1919 // Reset all assigned PCI bus number in all PPB\r
ead42efc 1920 //\r
4beb4afe 1921 RootBridgeHandle = NULL;\r
1922 Link = GetFirstNode (&RootBridgeList);\r
1923 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1924 (!IsNull (&RootBridgeList, Link))) {\r
1925 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1926 //\r
1927 // Get the Bus information\r
1928 //\r
1929 Status = PciResAlloc->StartBusEnumeration (\r
1930 PciResAlloc,\r
1931 RootBridgeHandle,\r
1932 (VOID **) &pConfiguration\r
1933 );\r
1934 if (EFI_ERROR (Status)) {\r
1935 return Status;\r
1936 }\r
1937\r
1938 //\r
1939 // Get the bus number to start with\r
1940 //\r
1941 StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);\r
1942\r
1943 ResetAllPpbBusNumber (\r
1944 RootBridgeDev,\r
1945 StartBusNumber\r
1946 );\r
1947\r
1948 gBS->FreePool (pConfiguration);\r
1949 Link = GetNextNode (&RootBridgeList, Link);\r
1950 DestroyRootBridge (RootBridgeDev);\r
1951 }\r
1952\r
1953 //\r
1954 // Wait for all HPC initialized\r
1955 //\r
ead42efc 1956 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1957\r
1958 if (EFI_ERROR (Status)) {\r
1959 return Status;\r
1960 }\r
1961\r
1962 //\r
1963 // Notify the bus allocation phase is about to start for the 2nd time\r
1964 //\r
1965 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1966\r
4beb4afe 1967 DEBUG((EFI_D_ERROR, "PCI Bus Second Scanning\n"));\r
ead42efc 1968 RootBridgeHandle = NULL;\r
1969 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1970\r
1971 //\r
1972 // if a root bridge instance is found, create root bridge device for it\r
1973 //\r
1974\r
1975 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1976\r
1977 if (RootBridgeDev == NULL) {\r
1978 return EFI_OUT_OF_RESOURCES;\r
1979 }\r
1980\r
1981 //\r
1982 // Enumerate all the buses under this root bridge\r
1983 //\r
1984\r
1985 Status = PciRootBridgeEnumerator (\r
1986 PciResAlloc,\r
1987 RootBridgeDev\r
1988 );\r
1989\r
1990 DestroyRootBridge (RootBridgeDev);\r
1991 if (EFI_ERROR (Status)) {\r
1992 return Status;\r
1993 }\r
1994 }\r
1995\r
1996 //\r
1997 // Notify the bus allocation phase is to end for the 2nd time\r
1998 //\r
1999 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
2000 }\r
2001 }\r
2002\r
2003 //\r
2004 // Notify the resource allocation phase is to start\r
2005 //\r
2006 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
2007\r
2008 RootBridgeHandle = NULL;\r
2009 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
2010\r
2011 //\r
2012 // if a root bridge instance is found, create root bridge device for it\r
2013 //\r
2014\r
2015 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
2016\r
2017 if (RootBridgeDev == NULL) {\r
2018 return EFI_OUT_OF_RESOURCES;\r
2019 }\r
2020\r
2021 Status = StartManagingRootBridge (RootBridgeDev);\r
2022\r
2023 if (EFI_ERROR (Status)) {\r
2024 return Status;\r
2025 }\r
2026\r
2027 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
2028 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
2029\r
2030 if (EFI_ERROR (Status)) {\r
2031 return Status;\r
2032 }\r
2033\r
2034 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
2035\r
2036 if (EFI_ERROR (Status)) {\r
2037 return Status;\r
2038 }\r
2039\r
2040 //\r
2041 // Determine root bridge attribute by calling interface of Pcihostbridge\r
2042 // protocol\r
2043 //\r
2044 DetermineRootBridgeAttributes (\r
2045 PciResAlloc,\r
2046 RootBridgeDev\r
2047 );\r
2048\r
2049 //\r
2050 // Collect all the resource information under this root bridge\r
2051 // A database that records all the information about pci device subject to this\r
2052 // root bridge will then be created\r
2053 //\r
2054 Status = PciPciDeviceInfoCollector (\r
2055 RootBridgeDev,\r
2056 (UINT8) MinBus\r
2057 );\r
2058\r
2059 if (EFI_ERROR (Status)) {\r
2060 return Status;\r
2061 }\r
2062\r
2063 InsertRootBridge (RootBridgeDev);\r
2064\r
2065 //\r
2066 // Record the hostbridge handle\r
2067 //\r
2068 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
2069 }\r
2070\r
2071 return EFI_SUCCESS;\r
2072}\r
2073\r
2074/**\r
2075 Read PCI device configuration register by specified address.\r
2076\r
2077 This function check the incompatiblilites on PCI device. Return the register\r
2078 value.\r
2079\r
2080 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2081 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2082 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2083 @param Width Signifies the width of the memory operations.\r
2084 @Param Address The address within the PCI configuration space for the PCI controller.\r
2085 @param Buffer For read operations, the destination buffer to store the results. For\r
2086 write operations, the source buffer to write data from.\r
2087\r
2088 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2089 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2090 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2091 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2092\r
2093**/\r
2094STATIC\r
2095EFI_STATUS\r
2096ReadConfigData (\r
2097 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2098 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2099 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2100 IN UINT64 Width,\r
2101 IN UINT64 Address,\r
2102 IN OUT VOID *Buffer\r
2103 )\r
2104{\r
2105 EFI_STATUS Status;\r
2106 UINT64 AccessWidth;\r
2107 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2108 UINT64 AccessAddress;\r
2109 UINTN Stride;\r
2110 UINT64 TempBuffer;\r
2111 UINT8 *Pointer;\r
2112\r
2113 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2114\r
2115 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2116 //\r
2117 // check access compatibility at first time\r
2118 //\r
2119 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);\r
2120\r
2121 if (Status == EFI_SUCCESS) {\r
2122 //\r
2123 // there exist incompatibility on this operation\r
2124 //\r
2125 AccessWidth = Width;\r
2126\r
2127 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2128 AccessWidth = PciRegisterAccessData->Width;\r
2129 }\r
2130\r
2131 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2132\r
2133 TempBuffer = 0;\r
2134 Stride = 0;\r
2135 Pointer = (UINT8 *) &TempBuffer;\r
2136\r
2137 while (1) {\r
2138\r
2139 if (PciRootBridgeIo != NULL) {\r
2140 Status = PciRootBridgeIo->Pci.Read (\r
2141 PciRootBridgeIo,\r
2142 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2143 AccessAddress,\r
2144 1,\r
2145 Pointer\r
2146 );\r
2147 } else if (PciIo != NULL) {\r
2148 Status = PciIo->Pci.Read (\r
2149 PciIo,\r
2150 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2151 (UINT32) AccessAddress,\r
2152 1,\r
2153 Pointer\r
2154 );\r
2155 }\r
2156\r
2157 if (Status != EFI_SUCCESS) {\r
2158 return Status;\r
2159 }\r
2160\r
23bd66f4 2161 Stride = (UINTN)1 << AccessWidth;\r
ead42efc 2162 AccessAddress += Stride;\r
6deef763 2163 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {\r
ead42efc 2164 //\r
2165 // if all datas have been read, exist\r
2166 //\r
2167 break;\r
2168 }\r
2169\r
2170 Pointer += Stride;\r
2171\r
2172 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2173 //\r
2174 // if current offset doesn't reach the end\r
2175 //\r
2176 continue;\r
2177 }\r
2178\r
2179 FreePool (PciRegisterAccessData);\r
2180\r
2181 //\r
2182 // continue checking access incompatibility\r
2183 //\r
2184 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2185 if (Status == EFI_SUCCESS) {\r
2186 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2187 AccessWidth = PciRegisterAccessData->Width;\r
2188 }\r
2189 }\r
2190 }\r
2191\r
2192 FreePool (PciRegisterAccessData);\r
2193\r
2194 switch (Width) {\r
2195 case EfiPciWidthUint8:\r
2196 * (UINT8 *) Buffer = (UINT8) TempBuffer;\r
2197 break;\r
2198 case EfiPciWidthUint16:\r
2199 * (UINT16 *) Buffer = (UINT16) TempBuffer;\r
2200 break;\r
2201 case EfiPciWidthUint32:\r
2202 * (UINT32 *) Buffer = (UINT32) TempBuffer;\r
2203 break;\r
2204 default:\r
2205 return EFI_UNSUPPORTED;\r
2206 }\r
2207\r
2208 return Status;\r
2209 }\r
2210 }\r
2211 //\r
2212 // AccessWidth incompatible check not supportted\r
2213 // or, there doesn't exist incompatibility on this operation\r
2214 //\r
2215 if (PciRootBridgeIo != NULL) {\r
2216 Status = PciRootBridgeIo->Pci.Read (\r
2217 PciRootBridgeIo,\r
2218 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2219 Address,\r
2220 1,\r
2221 Buffer\r
2222 );\r
2223\r
2224 } else {\r
2225 Status = PciIo->Pci.Read (\r
2226 PciIo,\r
2227 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2228 (UINT32) Address,\r
2229 1,\r
2230 Buffer\r
2231 );\r
2232 }\r
2233\r
2234 return Status;\r
2235}\r
2236\r
2237/**\r
2238 Update register value by checking PCI device incompatibility.\r
2239\r
2240 This function check register value incompatibilites on PCI device. Return the register\r
2241 value.\r
2242\r
2243 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2244 @param AccessType Access type, READ or WRITE.\r
2245 @Param Address The address within the PCI configuration space.\r
2246 @param Buffer Store the register data.\r
2247\r
2248 @retval EFI_SUCCESS The data has been updated.\r
2249\r
2250**/\r
2251STATIC\r
2252EFI_STATUS\r
2253UpdateConfigData (\r
2254 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2255 IN UINT64 AccessType,\r
2256 IN UINT64 Width,\r
2257 IN UINT64 Address,\r
2258 IN OUT VOID *Buffer\r
2259)\r
2260{\r
2261 EFI_STATUS Status;\r
2262 EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;\r
2263 UINT32 AndValue;\r
2264 UINT32 OrValue;\r
2265 UINT32 TempValue;\r
2266\r
2267 //\r
2268 // check register value incompatibility\r
2269 //\r
2270 Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);\r
2271\r
2272 if (Status == EFI_SUCCESS) {\r
2273\r
2274 AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);\r
2275 OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);\r
2276\r
2277 TempValue = * (UINT32 *) Buffer;\r
2278 if (PciRegisterData->AndValue != VALUE_NOCARE) {\r
2279 TempValue &= AndValue;\r
2280 }\r
2281 if (PciRegisterData->OrValue != VALUE_NOCARE) {\r
2282 TempValue |= OrValue;\r
2283 }\r
2284\r
2285 switch (Width) {\r
2286 case EfiPciWidthUint8:\r
2287 *(UINT8 *)Buffer = (UINT8) TempValue;\r
2288 break;\r
2289\r
2290 case EfiPciWidthUint16:\r
2291 *(UINT16 *)Buffer = (UINT16) TempValue;\r
2292 break;\r
2293 case EfiPciWidthUint32:\r
2294 *(UINT32 *)Buffer = TempValue;\r
2295 break;\r
2296\r
2297 default:\r
2298 return EFI_UNSUPPORTED;\r
2299 }\r
2300\r
2301 FreePool (PciRegisterData);\r
2302 }\r
2303\r
2304 return Status;\r
2305}\r
2306\r
2307/**\r
2308 Write PCI device configuration register by specified address.\r
2309\r
2310 This function check the incompatiblilites on PCI device, and write date\r
2311 into register.\r
2312\r
2313 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2314 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2315 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2316 @param Width Signifies the width of the memory operations.\r
2317 @Param Address The address within the PCI configuration space for the PCI controller.\r
2318 @param Buffer For read operations, the destination buffer to store the results. For\r
2319 write operations, the source buffer to write data from.\r
2320\r
2321 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2322 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2323 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2324 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2325\r
2326**/\r
2327STATIC\r
2328EFI_STATUS\r
2329WriteConfigData (\r
2330 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2331 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2332 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2333 IN UINT64 Width,\r
2334 IN UINT64 Address,\r
2335 IN VOID *Buffer\r
2336 )\r
2337{\r
2338 EFI_STATUS Status;\r
2339 UINT64 AccessWidth;\r
2340 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2341 UINT64 AccessAddress;\r
2342 UINTN Stride;\r
2343 UINT8 *Pointer;\r
2344 UINT64 Data;\r
2345 UINTN Shift;\r
2346\r
2347 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2348\r
2349 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2350 //\r
2351 // check access compatibility at first time\r
2352 //\r
2353 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);\r
2354\r
2355 if (Status == EFI_SUCCESS) {\r
2356 //\r
2357 // there exist incompatibility on this operation\r
2358 //\r
2359 AccessWidth = Width;\r
2360\r
2361 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2362 AccessWidth = PciRegisterAccessData->Width;\r
2363 }\r
2364\r
2365 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2366\r
2367 Stride = 0;\r
2368 Pointer = (UINT8 *) &Buffer;\r
2369 Data = * (UINT64 *) Buffer;\r
2370\r
2371 while (1) {\r
2372\r
2373 if (AccessWidth > Width) {\r
2374 //\r
2375 // if actual access width is larger than orignal one, additional data need to be read back firstly\r
2376 //\r
2377 Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);\r
2378 if (Status != EFI_SUCCESS) {\r
2379 return Status;\r
2380 }\r
2381\r
2382 //\r
2383 // check data read incompatibility\r
2384 //\r
2385 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);\r
2386\r
307e7596 2387 Shift = (UINTN)(Address - AccessAddress) * 8;\r
ead42efc 2388 switch (Width) {\r
2389 case EfiPciWidthUint8:\r
2390 Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));\r
2391 break;\r
2392\r
2393 case EfiPciWidthUint16:\r
2394 Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));\r
2395 break;\r
2396 }\r
2397\r
2398 //\r
2399 // check data write incompatibility\r
2400 //\r
307e7596 2401 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, MultU64x32 (AccessAddress, 0xff), &Data);\r
ead42efc 2402 }\r
2403\r
2404 if (PciRootBridgeIo != NULL) {\r
2405 Status = PciRootBridgeIo->Pci.Write (\r
2406 PciRootBridgeIo,\r
2407 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2408 AccessAddress,\r
2409 1,\r
2410 &Data\r
2411 );\r
2412 } else {\r
2413 Status = PciIo->Pci.Write (\r
2414 PciIo,\r
2415 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2416 (UINT32) AccessAddress,\r
2417 1,\r
2418 &Data\r
2419 );\r
2420 }\r
2421\r
2422 if (Status != EFI_SUCCESS) {\r
2423 return Status;\r
2424 }\r
2425\r
2426 Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));\r
2427\r
23bd66f4 2428 Stride = (UINTN)1 << AccessWidth;\r
ead42efc 2429 AccessAddress += Stride;\r
6deef763 2430 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {\r
ead42efc 2431 //\r
2432 // if all datas have been written, exist\r
2433 //\r
2434 break;\r
2435 }\r
2436\r
2437 Pointer += Stride;\r
2438\r
2439 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2440 //\r
2441 // if current offset doesn't reach the end\r
2442 //\r
2443 continue;\r
2444 }\r
2445\r
2446 FreePool (PciRegisterAccessData);\r
2447\r
2448 //\r
2449 // continue checking access incompatibility\r
2450 //\r
2451 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2452 if (Status == EFI_SUCCESS) {\r
2453 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2454 AccessWidth = PciRegisterAccessData->Width;\r
2455 }\r
2456 }\r
2457 };\r
2458\r
2459 FreePool (PciRegisterAccessData);\r
2460\r
2461 return Status;\r
2462 }\r
2463\r
2464 }\r
2465 //\r
2466 // AccessWidth incompatible check not supportted\r
2467 // or, there doesn't exist incompatibility on this operation\r
2468 //\r
2469 if (PciRootBridgeIo != NULL) {\r
2470 Status = PciRootBridgeIo->Pci.Write (\r
2471 PciRootBridgeIo,\r
2472 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2473 Address,\r
2474 1,\r
2475 Buffer\r
2476 );\r
2477 } else {\r
2478 Status = PciIo->Pci.Write (\r
2479 PciIo,\r
2480 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2481 (UINT32) Address,\r
2482 1,\r
2483 Buffer\r
2484 );\r
2485 }\r
2486\r
2487 return Status;\r
2488}\r
2489\r
2490/**\r
2491 Abstract PCI device device information.\r
2492\r
2493 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2494 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2495 @param Pci A pointer to PCI_TYPE00.\r
2496 @Param Address The address within the PCI configuration space for the PCI controller.\r
2497 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2498\r
2499 @retval EFI_SUCCESS Pci device device information has been abstracted.\r
2500\r
2501**/\r
2502STATIC\r
2503EFI_STATUS\r
2504GetPciDeviceDeviceInfo (\r
2505 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2506 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2507 IN PCI_TYPE00 *Pci, OPTIONAL\r
2508 IN UINT64 Address, OPTIONAL\r
2509 OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo\r
2510)\r
2511{\r
2512 EFI_STATUS Status;\r
2513 UINT64 PciAddress;\r
2514 UINT32 PciConfigData;\r
2515 PCI_IO_DEVICE *PciIoDevice;\r
2516\r
2517 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2518\r
2519 if (PciIo != NULL) {\r
2520 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2521\r
2522 //\r
2523 // get pointer to PCI_TYPE00 from PciIoDevice\r
2524 //\r
2525 Pci = &PciIoDevice->Pci;\r
2526 }\r
2527\r
2528 if (Pci == NULL) {\r
2529 //\r
2530 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly\r
2531 //\r
2532 PciAddress = Address & 0xffffffffffffff00ULL;\r
2533 Status = PciRootBridgeIo->Pci.Read (\r
2534 PciRootBridgeIo,\r
2535 EfiPciWidthUint32,\r
2536 PciAddress,\r
2537 1,\r
2538 &PciConfigData\r
2539 );\r
2540\r
2541 if (EFI_ERROR (Status)) {\r
2542 return Status;\r
2543 }\r
2544\r
2545 if ((PciConfigData & 0xffff) == 0xffff) {\r
2546 return EFI_NOT_FOUND;\r
2547 }\r
2548\r
2549 PciDeviceInfo->VendorID = PciConfigData & 0xffff;\r
2550 PciDeviceInfo->DeviceID = PciConfigData >> 16;\r
2551\r
2552 Status = PciRootBridgeIo->Pci.Read (\r
2553 PciRootBridgeIo,\r
2554 EfiPciWidthUint32,\r
2555 PciAddress + 8,\r
2556 1,\r
2557 &PciConfigData\r
2558 );\r
2559 if (EFI_ERROR (Status)) {\r
2560 return Status;\r
2561 }\r
2562\r
2563 PciDeviceInfo->RevisionID = PciConfigData & 0xf;\r
2564\r
2565 Status = PciRootBridgeIo->Pci.Read (\r
2566 PciRootBridgeIo,\r
2567 EfiPciWidthUint32,\r
2568 PciAddress + 0x2c,\r
2569 1,\r
2570 &PciConfigData\r
2571 );\r
2572\r
2573 if (EFI_ERROR (Status)) {\r
2574 return Status;\r
2575 }\r
2576\r
2577 PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;\r
2578 PciDeviceInfo->SubsystemID = PciConfigData >> 16;\r
2579\r
2580 } else {\r
2581 PciDeviceInfo->VendorID = Pci->Hdr.VendorId;\r
2582 PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;\r
2583 PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;\r
2584 PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;\r
2585 PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;\r
2586 }\r
2587\r
2588 return EFI_SUCCESS;\r
2589}\r
2590\r
2591/**\r
2592 Read PCI configuration space with incompatibility check.\r
2593\r
2594 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2595 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2596 @param Pci A pointer to PCI_TYPE00.\r
2597 @param Width Signifies the width of the memory operations.\r
2598 @Param Address The address within the PCI configuration space for the PCI controller.\r
2599 @param Buffer For read operations, the destination buffer to store the results. For\r
2600 write operations, the source buffer to write data from.\r
2601\r
2602 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2603 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2604 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2605 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2606\r
2607**/\r
2608STATIC\r
2609EFI_STATUS\r
2610PciIncompatibilityCheckRead (\r
2611 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2612 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2613 IN PCI_TYPE00 *Pci, OPTIONAL\r
2614 IN UINTN Width,\r
2615 IN UINT64 Address,\r
2616 IN UINTN Count,\r
2617 IN OUT VOID *Buffer\r
2618)\r
2619{\r
2620 EFI_STATUS Status;\r
2621 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2622 UINT32 Stride;\r
2623\r
2624 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2625\r
2626 //\r
2627 // get PCI device device information\r
2628 //\r
2629 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2630 if (Status != EFI_SUCCESS) {\r
2631 return Status;\r
2632 }\r
2633\r
2634 Stride = 1 << Width;\r
2635\r
2636 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {\r
2637\r
2638 //\r
2639 // read configuration register\r
2640 //\r
2641 Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);\r
2642\r
2643 if (Status != EFI_SUCCESS) {\r
2644 return Status;\r
2645 }\r
2646\r
2647 //\r
2648 // update the data read from configuration register\r
2649 //\r
2650 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2651 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);\r
2652 }\r
2653 }\r
2654\r
2655 return EFI_SUCCESS;\r
2656}\r
2657\r
2658/**\r
2659 Write PCI configuration space with incompatibility check.\r
2660\r
2661 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2662 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2663 @param Pci A pointer to PCI_TYPE00.\r
2664 @param Width Signifies the width of the memory operations.\r
2665 @Param Address The address within the PCI configuration space for the PCI controller.\r
2666 @param Buffer For read operations, the destination buffer to store the results. For\r
2667 write operations, the source buffer to write data from.\r
2668\r
2669 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2670 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2671 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2672 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2673\r
2674**/\r
2675STATIC\r
2676EFI_STATUS\r
2677PciIncompatibilityCheckWrite (\r
2678 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2679 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2680 IN PCI_TYPE00 *Pci, OPTIONAL\r
2681 IN UINTN Width,\r
2682 IN UINT64 Address,\r
2683 IN UINTN Count,\r
2684 IN OUT VOID *Buffer\r
2685)\r
2686{\r
2687 EFI_STATUS Status;\r
2688 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2689 UINT32 Stride;\r
2690 UINT64 Data;\r
2691\r
2692 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2693\r
2694 //\r
2695 // get PCI device device information\r
2696 //\r
2697 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2698 if (Status != EFI_SUCCESS) {\r
2699 return Status;\r
2700 }\r
2701\r
2702 Stride = 1 << Width;\r
2703\r
2704 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {\r
2705\r
2706 Data = 0;\r
2707\r
2708 switch (Width) {\r
2709 case EfiPciWidthUint8:\r
2710 Data = * (UINT8 *) Buffer;\r
2711 break;\r
2712 case EfiPciWidthUint16:\r
2713 Data = * (UINT16 *) Buffer;\r
2714 break;\r
2715\r
2716 case EfiPciWidthUint32:\r
2717 Data = * (UINT32 *) Buffer;\r
2718 break;\r
2719\r
2720 default:\r
2721 return EFI_UNSUPPORTED;\r
2722 }\r
2723\r
2724 //\r
2725 // update the data writen into configuration register\r
2726 //\r
2727 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2728 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);\r
2729 }\r
2730\r
2731 //\r
2732 // write configuration register\r
2733 //\r
2734 Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);\r
2735\r
2736 if (Status != EFI_SUCCESS) {\r
2737 return Status;\r
2738 }\r
2739 }\r
2740\r
2741 return EFI_SUCCESS;\r
2742}\r
2743\r
2744/**\r
2745 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2746\r
2747 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2748 @param Pci A pointer to PCI_TYPE00.\r
2749 @param Width Signifies the width of the memory operations.\r
2750 @Param Address The address within the PCI configuration space for the PCI controller.\r
2751 @param Buffer For read operations, the destination buffer to store the results. For\r
2752 write operations, the source buffer to write data from.\r
2753\r
2754 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2755 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2756 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2757 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2758\r
2759**/\r
2760EFI_STATUS\r
2761PciRootBridgeIoRead (\r
2762 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2763 IN PCI_TYPE00 *Pci, OPTIONAL\r
2764 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2765 IN UINT64 Address,\r
2766 IN UINTN Count,\r
2767 IN OUT VOID *Buffer\r
2768 )\r
2769{\r
2770 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2771 //\r
2772 // if PCI incompatibility check enabled\r
2773 //\r
2774 return PciIncompatibilityCheckRead (\r
2775 PciRootBridgeIo,\r
2776 NULL,\r
2777 Pci,\r
2778 (UINTN) Width,\r
2779 Address,\r
2780 Count,\r
2781 Buffer\r
2782 );\r
2783 } else {\r
2784 return PciRootBridgeIo->Pci.Read (\r
2785 PciRootBridgeIo,\r
2786 Width,\r
2787 Address,\r
2788 Count,\r
2789 Buffer\r
2790 );\r
2791 }\r
2792}\r
2793\r
2794/**\r
2795 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2796\r
2797 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2798 @param Pci A pointer to PCI_TYPE00.\r
2799 @param Width Signifies the width of the memory operations.\r
2800 @Param Address The address within the PCI configuration space for the PCI controller.\r
2801 @param Buffer For read operations, the destination buffer to store the results. For\r
2802 write operations, the source buffer to write data from.\r
2803\r
2804 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2805 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2806 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2807 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2808\r
2809**/\r
2810EFI_STATUS\r
2811PciRootBridgeIoWrite (\r
2812 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2813 IN PCI_TYPE00 *Pci,\r
2814 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2815 IN UINT64 Address,\r
2816 IN UINTN Count,\r
2817 IN OUT VOID *Buffer\r
2818 )\r
2819{\r
2820 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2821 //\r
2822 // if PCI incompatibility check enabled\r
2823 //\r
2824 return PciIncompatibilityCheckWrite (\r
2825 PciRootBridgeIo,\r
2826 NULL,\r
2827 Pci,\r
2828 Width,\r
2829 Address,\r
2830 Count,\r
2831 Buffer\r
2832 );\r
2833\r
2834 } else {\r
2835 return PciRootBridgeIo->Pci.Write (\r
2836 PciRootBridgeIo,\r
2837 Width,\r
2838 Address,\r
2839 Count,\r
2840 Buffer\r
2841 );\r
2842 }\r
2843}\r
2844\r
2845/**\r
2846 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2847\r
2848 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2849 @param Width Signifies the width of the memory operations.\r
2850 @Param Address The address within the PCI configuration space for the PCI controller.\r
2851 @param Buffer For read operations, the destination buffer to store the results. For\r
2852 write operations, the source buffer to write data from.\r
2853\r
2854 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2855 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2856 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2857 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2858\r
2859**/\r
2860EFI_STATUS\r
2861PciIoRead (\r
2862 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2863 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2864 IN UINT32 Address,\r
2865 IN UINTN Count,\r
2866 IN OUT VOID *Buffer\r
2867 )\r
2868{\r
2869 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2870 //\r
2871 // if PCI incompatibility check enabled\r
2872 //\r
2873 return PciIncompatibilityCheckRead (\r
2874 NULL,\r
2875 PciIo,\r
2876 NULL,\r
2877 (UINTN) Width,\r
2878 Address,\r
2879 Count,\r
2880 Buffer\r
2881 );\r
2882 } else {\r
2883 return PciIo->Pci.Read (\r
2884 PciIo,\r
2885 Width,\r
2886 Address,\r
2887 Count,\r
2888 Buffer\r
2889 );\r
2890 }\r
2891}\r
2892\r
2893/**\r
2894 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2895\r
2896 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2897 @param Width Signifies the width of the memory operations.\r
2898 @Param Address The address within the PCI configuration space for the PCI controller.\r
2899 @param Buffer For read operations, the destination buffer to store the results. For\r
2900 write operations, the source buffer to write data from.\r
2901\r
2902 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2903 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2904 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2905 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2906\r
2907**/\r
2908EFI_STATUS\r
2909PciIoWrite (\r
2910 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2911 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2912 IN UINT32 Address,\r
2913 IN UINTN Count,\r
2914 IN OUT VOID *Buffer\r
2915 )\r
2916{\r
2917 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2918\r
2919 //\r
2920 // if PCI incompatibility check enabled\r
2921 //\r
2922 return PciIncompatibilityCheckWrite (\r
2923 NULL,\r
2924 PciIo,\r
2925 NULL,\r
2926 Width,\r
2927 Address,\r
2928 Count,\r
2929 Buffer\r
2930 );\r
2931\r
2932 } else {\r
2933 return PciIo->Pci.Write (\r
2934 PciIo,\r
2935 Width,\r
2936 Address,\r
2937 Count,\r
2938 Buffer\r
2939 );\r
2940 }\r
2941}\r