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