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