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