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