]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Give the output information in right place.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciLib.c
CommitLineData
3db51098 1/**@file\r
ead42efc 2\r
3 PCI Bus Driver Lib file\r
4 It abstracts some functions that can be different\r
5 between light PCI bus driver and full PCI bus driver\r
6\r
4beb4afe 7Copyright (c) 2006 - 2008, Intel Corporation\r
8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
ead42efc 15\r
3db51098 16**/\r
ead42efc 17\r
18#include "pcibus.h"\r
19\r
20GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {\r
21 PciHotPlugRequestNotify\r
22};\r
23\r
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
2012STATIC\r
2013EFI_STATUS\r
2014ReadConfigData (\r
2015 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2016 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2017 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2018 IN UINT64 Width,\r
2019 IN UINT64 Address,\r
2020 IN OUT VOID *Buffer\r
2021 )\r
2022{\r
2023 EFI_STATUS Status;\r
2024 UINT64 AccessWidth;\r
2025 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2026 UINT64 AccessAddress;\r
2027 UINTN Stride;\r
2028 UINT64 TempBuffer;\r
2029 UINT8 *Pointer;\r
2030\r
2031 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2032\r
2033 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2034 //\r
2035 // check access compatibility at first time\r
2036 //\r
2037 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);\r
2038\r
2039 if (Status == EFI_SUCCESS) {\r
2040 //\r
2041 // there exist incompatibility on this operation\r
2042 //\r
2043 AccessWidth = Width;\r
2044\r
2045 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2046 AccessWidth = PciRegisterAccessData->Width;\r
2047 }\r
2048\r
2049 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2050\r
2051 TempBuffer = 0;\r
2052 Stride = 0;\r
2053 Pointer = (UINT8 *) &TempBuffer;\r
2054\r
2055 while (1) {\r
2056\r
2057 if (PciRootBridgeIo != NULL) {\r
2058 Status = PciRootBridgeIo->Pci.Read (\r
2059 PciRootBridgeIo,\r
2060 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2061 AccessAddress,\r
2062 1,\r
2063 Pointer\r
2064 );\r
2065 } else if (PciIo != NULL) {\r
2066 Status = PciIo->Pci.Read (\r
2067 PciIo,\r
2068 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2069 (UINT32) AccessAddress,\r
2070 1,\r
2071 Pointer\r
2072 );\r
2073 }\r
2074\r
2075 if (Status != EFI_SUCCESS) {\r
2076 return Status;\r
2077 }\r
2078\r
23bd66f4 2079 Stride = (UINTN)1 << AccessWidth;\r
ead42efc 2080 AccessAddress += Stride;\r
6deef763 2081 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {\r
ead42efc 2082 //\r
2083 // if all datas have been read, exist\r
2084 //\r
2085 break;\r
2086 }\r
2087\r
2088 Pointer += Stride;\r
2089\r
2090 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2091 //\r
2092 // if current offset doesn't reach the end\r
2093 //\r
2094 continue;\r
2095 }\r
2096\r
2097 FreePool (PciRegisterAccessData);\r
2098\r
2099 //\r
2100 // continue checking access incompatibility\r
2101 //\r
2102 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2103 if (Status == EFI_SUCCESS) {\r
2104 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2105 AccessWidth = PciRegisterAccessData->Width;\r
2106 }\r
2107 }\r
2108 }\r
2109\r
2110 FreePool (PciRegisterAccessData);\r
2111\r
2112 switch (Width) {\r
2113 case EfiPciWidthUint8:\r
2114 * (UINT8 *) Buffer = (UINT8) TempBuffer;\r
2115 break;\r
2116 case EfiPciWidthUint16:\r
2117 * (UINT16 *) Buffer = (UINT16) TempBuffer;\r
2118 break;\r
2119 case EfiPciWidthUint32:\r
2120 * (UINT32 *) Buffer = (UINT32) TempBuffer;\r
2121 break;\r
2122 default:\r
2123 return EFI_UNSUPPORTED;\r
2124 }\r
2125\r
2126 return Status;\r
2127 }\r
2128 }\r
2129 //\r
2130 // AccessWidth incompatible check not supportted\r
2131 // or, there doesn't exist incompatibility on this operation\r
2132 //\r
2133 if (PciRootBridgeIo != NULL) {\r
2134 Status = PciRootBridgeIo->Pci.Read (\r
2135 PciRootBridgeIo,\r
2136 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2137 Address,\r
2138 1,\r
2139 Buffer\r
2140 );\r
2141\r
2142 } else {\r
2143 Status = PciIo->Pci.Read (\r
2144 PciIo,\r
2145 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2146 (UINT32) Address,\r
2147 1,\r
2148 Buffer\r
2149 );\r
2150 }\r
2151\r
2152 return Status;\r
2153}\r
2154\r
2155/**\r
2156 Update register value by checking PCI device incompatibility.\r
2157\r
2158 This function check register value incompatibilites on PCI device. Return the register\r
2159 value.\r
2160\r
2161 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2162 @param AccessType Access type, READ or WRITE.\r
2163 @Param Address The address within the PCI configuration space.\r
2164 @param Buffer Store the register data.\r
2165\r
2166 @retval EFI_SUCCESS The data has been updated.\r
2167\r
2168**/\r
2169STATIC\r
2170EFI_STATUS\r
2171UpdateConfigData (\r
2172 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2173 IN UINT64 AccessType,\r
2174 IN UINT64 Width,\r
2175 IN UINT64 Address,\r
2176 IN OUT VOID *Buffer\r
2177)\r
2178{\r
2179 EFI_STATUS Status;\r
2180 EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;\r
2181 UINT32 AndValue;\r
2182 UINT32 OrValue;\r
2183 UINT32 TempValue;\r
2184\r
2185 //\r
2186 // check register value incompatibility\r
2187 //\r
2188 Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);\r
2189\r
2190 if (Status == EFI_SUCCESS) {\r
2191\r
2192 AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);\r
2193 OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);\r
2194\r
2195 TempValue = * (UINT32 *) Buffer;\r
2196 if (PciRegisterData->AndValue != VALUE_NOCARE) {\r
2197 TempValue &= AndValue;\r
2198 }\r
2199 if (PciRegisterData->OrValue != VALUE_NOCARE) {\r
2200 TempValue |= OrValue;\r
2201 }\r
2202\r
2203 switch (Width) {\r
2204 case EfiPciWidthUint8:\r
2205 *(UINT8 *)Buffer = (UINT8) TempValue;\r
2206 break;\r
2207\r
2208 case EfiPciWidthUint16:\r
2209 *(UINT16 *)Buffer = (UINT16) TempValue;\r
2210 break;\r
2211 case EfiPciWidthUint32:\r
2212 *(UINT32 *)Buffer = TempValue;\r
2213 break;\r
2214\r
2215 default:\r
2216 return EFI_UNSUPPORTED;\r
2217 }\r
2218\r
2219 FreePool (PciRegisterData);\r
2220 }\r
2221\r
2222 return Status;\r
2223}\r
2224\r
2225/**\r
2226 Write PCI device configuration register by specified address.\r
2227\r
2228 This function check the incompatiblilites on PCI device, and write date\r
2229 into register.\r
2230\r
2231 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2232 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2233 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2234 @param Width Signifies the width of the memory operations.\r
2235 @Param Address The address within the PCI configuration space for the PCI controller.\r
2236 @param Buffer For read operations, the destination buffer to store the results. For\r
2237 write operations, the source buffer to write data from.\r
2238\r
2239 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2240 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2241 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2242 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2243\r
2244**/\r
2245STATIC\r
2246EFI_STATUS\r
2247WriteConfigData (\r
2248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2249 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2250 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
2251 IN UINT64 Width,\r
2252 IN UINT64 Address,\r
2253 IN VOID *Buffer\r
2254 )\r
2255{\r
2256 EFI_STATUS Status;\r
2257 UINT64 AccessWidth;\r
2258 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;\r
2259 UINT64 AccessAddress;\r
2260 UINTN Stride;\r
2261 UINT8 *Pointer;\r
2262 UINT64 Data;\r
2263 UINTN Shift;\r
2264\r
2265 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2266\r
2267 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {\r
2268 //\r
2269 // check access compatibility at first time\r
2270 //\r
2271 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);\r
2272\r
2273 if (Status == EFI_SUCCESS) {\r
2274 //\r
2275 // there exist incompatibility on this operation\r
2276 //\r
2277 AccessWidth = Width;\r
2278\r
2279 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2280 AccessWidth = PciRegisterAccessData->Width;\r
2281 }\r
2282\r
2283 AccessAddress = Address & ~((1 << AccessWidth) - 1);\r
2284\r
2285 Stride = 0;\r
2286 Pointer = (UINT8 *) &Buffer;\r
2287 Data = * (UINT64 *) Buffer;\r
2288\r
2289 while (1) {\r
2290\r
2291 if (AccessWidth > Width) {\r
2292 //\r
2293 // if actual access width is larger than orignal one, additional data need to be read back firstly\r
2294 //\r
2295 Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);\r
2296 if (Status != EFI_SUCCESS) {\r
2297 return Status;\r
2298 }\r
2299\r
2300 //\r
2301 // check data read incompatibility\r
2302 //\r
2303 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);\r
2304\r
307e7596 2305 Shift = (UINTN)(Address - AccessAddress) * 8;\r
ead42efc 2306 switch (Width) {\r
2307 case EfiPciWidthUint8:\r
2308 Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));\r
2309 break;\r
2310\r
2311 case EfiPciWidthUint16:\r
2312 Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));\r
2313 break;\r
2314 }\r
2315\r
2316 //\r
2317 // check data write incompatibility\r
2318 //\r
307e7596 2319 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, MultU64x32 (AccessAddress, 0xff), &Data);\r
ead42efc 2320 }\r
2321\r
2322 if (PciRootBridgeIo != NULL) {\r
2323 Status = PciRootBridgeIo->Pci.Write (\r
2324 PciRootBridgeIo,\r
2325 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,\r
2326 AccessAddress,\r
2327 1,\r
2328 &Data\r
2329 );\r
2330 } else {\r
2331 Status = PciIo->Pci.Write (\r
2332 PciIo,\r
2333 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,\r
2334 (UINT32) AccessAddress,\r
2335 1,\r
2336 &Data\r
2337 );\r
2338 }\r
2339\r
2340 if (Status != EFI_SUCCESS) {\r
2341 return Status;\r
2342 }\r
2343\r
2344 Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));\r
2345\r
23bd66f4 2346 Stride = (UINTN)1 << AccessWidth;\r
ead42efc 2347 AccessAddress += Stride;\r
6deef763 2348 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {\r
ead42efc 2349 //\r
2350 // if all datas have been written, exist\r
2351 //\r
2352 break;\r
2353 }\r
2354\r
2355 Pointer += Stride;\r
2356\r
2357 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {\r
2358 //\r
2359 // if current offset doesn't reach the end\r
2360 //\r
2361 continue;\r
2362 }\r
2363\r
2364 FreePool (PciRegisterAccessData);\r
2365\r
2366 //\r
2367 // continue checking access incompatibility\r
2368 //\r
2369 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);\r
2370 if (Status == EFI_SUCCESS) {\r
2371 if (PciRegisterAccessData->Width != VALUE_NOCARE) {\r
2372 AccessWidth = PciRegisterAccessData->Width;\r
2373 }\r
2374 }\r
2375 };\r
2376\r
2377 FreePool (PciRegisterAccessData);\r
2378\r
2379 return Status;\r
2380 }\r
2381\r
2382 }\r
2383 //\r
2384 // AccessWidth incompatible check not supportted\r
2385 // or, there doesn't exist incompatibility on this operation\r
2386 //\r
2387 if (PciRootBridgeIo != NULL) {\r
2388 Status = PciRootBridgeIo->Pci.Write (\r
2389 PciRootBridgeIo,\r
2390 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
2391 Address,\r
2392 1,\r
2393 Buffer\r
2394 );\r
2395 } else {\r
2396 Status = PciIo->Pci.Write (\r
2397 PciIo,\r
2398 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,\r
2399 (UINT32) Address,\r
2400 1,\r
2401 Buffer\r
2402 );\r
2403 }\r
2404\r
2405 return Status;\r
2406}\r
2407\r
2408/**\r
2409 Abstract PCI device device information.\r
2410\r
2411 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2412 @param PciIo A pointer to EFI_PCI_PROTOCOL.\r
2413 @param Pci A pointer to PCI_TYPE00.\r
2414 @Param Address The address within the PCI configuration space for the PCI controller.\r
2415 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
2416\r
2417 @retval EFI_SUCCESS Pci device device information has been abstracted.\r
2418\r
2419**/\r
2420STATIC\r
2421EFI_STATUS\r
2422GetPciDeviceDeviceInfo (\r
2423 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2424 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2425 IN PCI_TYPE00 *Pci, OPTIONAL\r
2426 IN UINT64 Address, OPTIONAL\r
2427 OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo\r
2428)\r
2429{\r
2430 EFI_STATUS Status;\r
2431 UINT64 PciAddress;\r
2432 UINT32 PciConfigData;\r
2433 PCI_IO_DEVICE *PciIoDevice;\r
2434\r
2435 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2436\r
2437 if (PciIo != NULL) {\r
2438 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2439\r
2440 //\r
2441 // get pointer to PCI_TYPE00 from PciIoDevice\r
2442 //\r
2443 Pci = &PciIoDevice->Pci;\r
2444 }\r
2445\r
2446 if (Pci == NULL) {\r
2447 //\r
2448 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly\r
2449 //\r
2450 PciAddress = Address & 0xffffffffffffff00ULL;\r
2451 Status = PciRootBridgeIo->Pci.Read (\r
2452 PciRootBridgeIo,\r
2453 EfiPciWidthUint32,\r
2454 PciAddress,\r
2455 1,\r
2456 &PciConfigData\r
2457 );\r
2458\r
2459 if (EFI_ERROR (Status)) {\r
2460 return Status;\r
2461 }\r
2462\r
2463 if ((PciConfigData & 0xffff) == 0xffff) {\r
2464 return EFI_NOT_FOUND;\r
2465 }\r
2466\r
2467 PciDeviceInfo->VendorID = PciConfigData & 0xffff;\r
2468 PciDeviceInfo->DeviceID = PciConfigData >> 16;\r
2469\r
2470 Status = PciRootBridgeIo->Pci.Read (\r
2471 PciRootBridgeIo,\r
2472 EfiPciWidthUint32,\r
2473 PciAddress + 8,\r
2474 1,\r
2475 &PciConfigData\r
2476 );\r
2477 if (EFI_ERROR (Status)) {\r
2478 return Status;\r
2479 }\r
2480\r
2481 PciDeviceInfo->RevisionID = PciConfigData & 0xf;\r
2482\r
2483 Status = PciRootBridgeIo->Pci.Read (\r
2484 PciRootBridgeIo,\r
2485 EfiPciWidthUint32,\r
2486 PciAddress + 0x2c,\r
2487 1,\r
2488 &PciConfigData\r
2489 );\r
2490\r
2491 if (EFI_ERROR (Status)) {\r
2492 return Status;\r
2493 }\r
2494\r
2495 PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;\r
2496 PciDeviceInfo->SubsystemID = PciConfigData >> 16;\r
2497\r
2498 } else {\r
2499 PciDeviceInfo->VendorID = Pci->Hdr.VendorId;\r
2500 PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;\r
2501 PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;\r
2502 PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;\r
2503 PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;\r
2504 }\r
2505\r
2506 return EFI_SUCCESS;\r
2507}\r
2508\r
2509/**\r
2510 Read PCI configuration space with incompatibility check.\r
2511\r
2512 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2513 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2514 @param Pci A pointer to PCI_TYPE00.\r
2515 @param Width Signifies the width of the memory operations.\r
2516 @Param Address The address within the PCI configuration space for the PCI controller.\r
2517 @param Buffer For read operations, the destination buffer to store the results. For\r
2518 write operations, the source buffer to write data from.\r
2519\r
2520 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2521 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2522 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2523 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2524\r
2525**/\r
2526STATIC\r
2527EFI_STATUS\r
2528PciIncompatibilityCheckRead (\r
2529 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2530 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2531 IN PCI_TYPE00 *Pci, OPTIONAL\r
2532 IN UINTN Width,\r
2533 IN UINT64 Address,\r
2534 IN UINTN Count,\r
2535 IN OUT VOID *Buffer\r
2536)\r
2537{\r
2538 EFI_STATUS Status;\r
2539 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2540 UINT32 Stride;\r
2541\r
2542 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2543\r
2544 //\r
2545 // get PCI device device information\r
2546 //\r
2547 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2548 if (Status != EFI_SUCCESS) {\r
2549 return Status;\r
2550 }\r
2551\r
2552 Stride = 1 << Width;\r
2553\r
2554 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {\r
2555\r
2556 //\r
2557 // read configuration register\r
2558 //\r
2559 Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);\r
2560\r
2561 if (Status != EFI_SUCCESS) {\r
2562 return Status;\r
2563 }\r
2564\r
2565 //\r
2566 // update the data read from configuration register\r
2567 //\r
2568 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2569 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);\r
2570 }\r
2571 }\r
2572\r
2573 return EFI_SUCCESS;\r
2574}\r
2575\r
2576/**\r
2577 Write PCI configuration space with incompatibility check.\r
2578\r
2579 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2580 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.\r
2581 @param Pci A pointer to PCI_TYPE00.\r
2582 @param Width Signifies the width of the memory operations.\r
2583 @Param Address The address within the PCI configuration space for the PCI controller.\r
2584 @param Buffer For read operations, the destination buffer to store the results. For\r
2585 write operations, the source buffer to write data from.\r
2586\r
2587 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2588 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2589 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2590 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2591\r
2592**/\r
2593STATIC\r
2594EFI_STATUS\r
2595PciIncompatibilityCheckWrite (\r
2596 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL\r
2597 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL\r
2598 IN PCI_TYPE00 *Pci, OPTIONAL\r
2599 IN UINTN Width,\r
2600 IN UINT64 Address,\r
2601 IN UINTN Count,\r
2602 IN OUT VOID *Buffer\r
2603)\r
2604{\r
2605 EFI_STATUS Status;\r
2606 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
2607 UINT32 Stride;\r
2608 UINT64 Data;\r
2609\r
2610 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));\r
2611\r
2612 //\r
2613 // get PCI device device information\r
2614 //\r
2615 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);\r
2616 if (Status != EFI_SUCCESS) {\r
2617 return Status;\r
2618 }\r
2619\r
2620 Stride = 1 << Width;\r
2621\r
2622 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {\r
2623\r
2624 Data = 0;\r
2625\r
2626 switch (Width) {\r
2627 case EfiPciWidthUint8:\r
2628 Data = * (UINT8 *) Buffer;\r
2629 break;\r
2630 case EfiPciWidthUint16:\r
2631 Data = * (UINT16 *) Buffer;\r
2632 break;\r
2633\r
2634 case EfiPciWidthUint32:\r
2635 Data = * (UINT32 *) Buffer;\r
2636 break;\r
2637\r
2638 default:\r
2639 return EFI_UNSUPPORTED;\r
2640 }\r
2641\r
2642 //\r
2643 // update the data writen into configuration register\r
2644 //\r
2645 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {\r
2646 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);\r
2647 }\r
2648\r
2649 //\r
2650 // write configuration register\r
2651 //\r
2652 Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);\r
2653\r
2654 if (Status != EFI_SUCCESS) {\r
2655 return Status;\r
2656 }\r
2657 }\r
2658\r
2659 return EFI_SUCCESS;\r
2660}\r
2661\r
2662/**\r
2663 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2664\r
2665 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2666 @param Pci A pointer to PCI_TYPE00.\r
2667 @param Width Signifies the width of the memory operations.\r
2668 @Param Address The address within the PCI configuration space for the PCI controller.\r
2669 @param Buffer For read operations, the destination buffer to store the results. For\r
2670 write operations, the source buffer to write data from.\r
2671\r
2672 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2673 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2674 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2675 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2676\r
2677**/\r
2678EFI_STATUS\r
2679PciRootBridgeIoRead (\r
2680 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2681 IN PCI_TYPE00 *Pci, OPTIONAL\r
2682 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2683 IN UINT64 Address,\r
2684 IN UINTN Count,\r
2685 IN OUT VOID *Buffer\r
2686 )\r
2687{\r
2688 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2689 //\r
2690 // if PCI incompatibility check enabled\r
2691 //\r
2692 return PciIncompatibilityCheckRead (\r
2693 PciRootBridgeIo,\r
2694 NULL,\r
2695 Pci,\r
2696 (UINTN) Width,\r
2697 Address,\r
2698 Count,\r
2699 Buffer\r
2700 );\r
2701 } else {\r
2702 return PciRootBridgeIo->Pci.Read (\r
2703 PciRootBridgeIo,\r
2704 Width,\r
2705 Address,\r
2706 Count,\r
2707 Buffer\r
2708 );\r
2709 }\r
2710}\r
2711\r
2712/**\r
2713 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2714\r
2715 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
2716 @param Pci A pointer to PCI_TYPE00.\r
2717 @param Width Signifies the width of the memory operations.\r
2718 @Param Address The address within the PCI configuration space for the PCI controller.\r
2719 @param Buffer For read operations, the destination buffer to store the results. For\r
2720 write operations, the source buffer to write data from.\r
2721\r
2722 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2723 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2724 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2725 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2726\r
2727**/\r
2728EFI_STATUS\r
2729PciRootBridgeIoWrite (\r
2730 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
2731 IN PCI_TYPE00 *Pci,\r
2732 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
2733 IN UINT64 Address,\r
2734 IN UINTN Count,\r
2735 IN OUT VOID *Buffer\r
2736 )\r
2737{\r
2738 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2739 //\r
2740 // if PCI incompatibility check enabled\r
2741 //\r
2742 return PciIncompatibilityCheckWrite (\r
2743 PciRootBridgeIo,\r
2744 NULL,\r
2745 Pci,\r
2746 Width,\r
2747 Address,\r
2748 Count,\r
2749 Buffer\r
2750 );\r
2751\r
2752 } else {\r
2753 return PciRootBridgeIo->Pci.Write (\r
2754 PciRootBridgeIo,\r
2755 Width,\r
2756 Address,\r
2757 Count,\r
2758 Buffer\r
2759 );\r
2760 }\r
2761}\r
2762\r
2763/**\r
2764 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2765\r
2766 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2767 @param Width Signifies the width of the memory operations.\r
2768 @Param Address The address within the PCI configuration space for the PCI controller.\r
2769 @param Buffer For read operations, the destination buffer to store the results. For\r
2770 write operations, the source buffer to write data from.\r
2771\r
2772 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2773 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2774 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2775 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2776\r
2777**/\r
2778EFI_STATUS\r
2779PciIoRead (\r
2780 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2781 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2782 IN UINT32 Address,\r
2783 IN UINTN Count,\r
2784 IN OUT VOID *Buffer\r
2785 )\r
2786{\r
2787 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {\r
2788 //\r
2789 // if PCI incompatibility check enabled\r
2790 //\r
2791 return PciIncompatibilityCheckRead (\r
2792 NULL,\r
2793 PciIo,\r
2794 NULL,\r
2795 (UINTN) Width,\r
2796 Address,\r
2797 Count,\r
2798 Buffer\r
2799 );\r
2800 } else {\r
2801 return PciIo->Pci.Read (\r
2802 PciIo,\r
2803 Width,\r
2804 Address,\r
2805 Count,\r
2806 Buffer\r
2807 );\r
2808 }\r
2809}\r
2810\r
2811/**\r
2812 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.\r
2813\r
2814 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.\r
2815 @param Width Signifies the width of the memory operations.\r
2816 @Param Address The address within the PCI configuration space for the PCI controller.\r
2817 @param Buffer For read operations, the destination buffer to store the results. For\r
2818 write operations, the source buffer to write data from.\r
2819\r
2820 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.\r
2821 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
2822 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
2823 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2824\r
2825**/\r
2826EFI_STATUS\r
2827PciIoWrite (\r
2828 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2829 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
2830 IN UINT32 Address,\r
2831 IN UINTN Count,\r
2832 IN OUT VOID *Buffer\r
2833 )\r
2834{\r
2835 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {\r
2836\r
2837 //\r
2838 // if PCI incompatibility check enabled\r
2839 //\r
2840 return PciIncompatibilityCheckWrite (\r
2841 NULL,\r
2842 PciIo,\r
2843 NULL,\r
2844 Width,\r
2845 Address,\r
2846 Count,\r
2847 Buffer\r
2848 );\r
2849\r
2850 } else {\r
2851 return PciIo->Pci.Write (\r
2852 PciIo,\r
2853 Width,\r
2854 Address,\r
2855 Count,\r
2856 Buffer\r
2857 );\r
2858 }\r
2859}\r
57076f45 2860\r