]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
MdeModulePkg: exit pci function loops early if device is not multi-function
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciEnumeratorSupport.c
CommitLineData
10590588 1/*++\r
2\r
5ce5ea60 3Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
b1f700a8 4This program and the accompanying materials \r
10590588 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PciEnumeratorSupport.c\r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
d8bee43c 24#include "PciBus.h"\r
10590588 25\r
26EFI_STATUS \r
27InitializePPB (\r
28 IN PCI_IO_DEVICE *PciIoDevice \r
29);\r
30\r
31EFI_STATUS \r
32InitializeP2C (\r
33 IN PCI_IO_DEVICE *PciIoDevice \r
34);\r
35\r
36PCI_IO_DEVICE* \r
37CreatePciIoDevice (\r
38 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
39 IN PCI_TYPE00 *Pci,\r
40 UINT8 Bus,\r
41 UINT8 Device,\r
42 UINT8 Func\r
43);\r
44\r
45\r
46PCI_IO_DEVICE*\r
47GatherP2CInfo (\r
48 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
49 IN PCI_TYPE00 *Pci,\r
50 UINT8 Bus,\r
51 UINT8 Device,\r
52 UINT8 Func\r
53);\r
54\r
55UINTN\r
56PciParseBar (\r
57 IN PCI_IO_DEVICE *PciIoDevice,\r
58 IN UINTN Offset,\r
59 IN UINTN BarIndex\r
60);\r
61\r
62\r
63EFI_STATUS\r
64PciSearchDevice (\r
65 IN PCI_IO_DEVICE *Bridge,\r
66 PCI_TYPE00 *Pci,\r
67 UINT8 Bus,\r
68 UINT8 Device,\r
69 UINT8 Func,\r
70 PCI_IO_DEVICE **PciDevice\r
71);\r
72\r
73\r
74EFI_STATUS \r
75DetermineDeviceAttribute (\r
76 IN PCI_IO_DEVICE *PciIoDevice\r
77);\r
78\r
79EFI_STATUS \r
80BarExisted (\r
81 IN PCI_IO_DEVICE *PciIoDevice,\r
82 IN UINTN Offset,\r
83 OUT UINT32 *BarLengthValue,\r
84 OUT UINT32 *OriginalBarValue\r
85 );\r
86\r
87\r
88\r
89EFI_DEVICE_PATH_PROTOCOL*\r
90CreatePciDevicePath(\r
91 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
92 IN PCI_IO_DEVICE *PciIoDevice \r
93);\r
94\r
95PCI_IO_DEVICE* \r
96GatherDeviceInfo (\r
97 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
98 IN PCI_TYPE00 *Pci,\r
99 UINT8 Bus,\r
100 UINT8 Device,\r
101 UINT8 Func\r
102);\r
103\r
104PCI_IO_DEVICE* \r
105GatherPPBInfo (\r
106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
107 IN PCI_TYPE00 *Pci,\r
108 UINT8 Bus,\r
109 UINT8 Device,\r
110 UINT8 Func\r
111);\r
112\r
113EFI_STATUS\r
114PciDevicePresent (\r
115 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
116 PCI_TYPE00 *Pci,\r
117 UINT8 Bus,\r
118 UINT8 Device,\r
119 UINT8 Func\r
120 )\r
121/*++\r
122\r
123Routine Description:\r
124\r
125 This routine is used to check whether the pci device is present\r
126\r
127Arguments:\r
128\r
129Returns:\r
130\r
131 None\r
132\r
133--*/\r
134{\r
135 UINT64 Address;\r
136 EFI_STATUS Status;\r
137\r
138 //\r
139 // Create PCI address map in terms of Bus, Device and Func\r
140 //\r
141 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
142\r
143 //\r
144 // Read the Vendor Id register\r
145 //\r
146 Status = PciRootBridgeIo->Pci.Read (\r
147 PciRootBridgeIo,\r
148 EfiPciWidthUint32,\r
149 Address,\r
150 1,\r
151 Pci\r
152 );\r
153\r
154 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
155\r
156 //\r
157 // Read the entire config header for the device\r
158 //\r
159\r
160 Status = PciRootBridgeIo->Pci.Read (\r
161 PciRootBridgeIo,\r
162 EfiPciWidthUint32,\r
163 Address,\r
164 sizeof (PCI_TYPE00) / sizeof (UINT32),\r
165 Pci\r
166 );\r
167\r
168 return EFI_SUCCESS;\r
169 }\r
170\r
171 return EFI_NOT_FOUND;\r
172}\r
173\r
174EFI_STATUS\r
175PciPciDeviceInfoCollector (\r
176 IN PCI_IO_DEVICE *Bridge,\r
177 UINT8 StartBusNumber\r
178 )\r
179/*++\r
180\r
181Routine Description:\r
182\r
183Arguments:\r
184\r
185Returns:\r
186\r
187 None\r
188\r
189--*/\r
190{\r
191 EFI_STATUS Status;\r
192 PCI_TYPE00 Pci;\r
193 UINT8 Device;\r
194 UINT8 Func;\r
195 UINT8 SecBus;\r
196 PCI_IO_DEVICE *PciIoDevice;\r
197 EFI_PCI_IO_PROTOCOL *PciIo;\r
198\r
5ce5ea60
RN
199 Status = EFI_SUCCESS;\r
200 SecBus = 0;\r
201 PciIoDevice = NULL;\r
10590588 202\r
203 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
204\r
205 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
206\r
207 //\r
208 // Check to see whether PCI device is present\r
209 //\r
210\r
211 Status = PciDevicePresent (\r
212 Bridge->PciRootBridgeIo,\r
213 &Pci,\r
214 (UINT8) StartBusNumber,\r
215 (UINT8) Device,\r
216 (UINT8) Func\r
217 );\r
218\r
219 if (!EFI_ERROR (Status)) {\r
220\r
221 //\r
222 // Collect all the information about the PCI device discovered\r
223 //\r
224 Status = PciSearchDevice (\r
225 Bridge,\r
226 &Pci,\r
227 (UINT8) StartBusNumber,\r
228 Device,\r
229 Func,\r
230 &PciIoDevice\r
231 );\r
232\r
233 //\r
234 // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
235 //\r
236 //\r
237\r
238 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
239\r
240 //\r
241 // If it is PPB, we need to get the secondary bus to continue the enumeration\r
242 //\r
243 PciIo = &(PciIoDevice->PciIo);\r
244\r
245 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);\r
246\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
250 \r
251 //\r
252 // Deep enumerate the next level bus\r
253 //\r
254 Status = PciPciDeviceInfoCollector (\r
255 PciIoDevice,\r
256 (UINT8) (SecBus)\r
257 );\r
258\r
259 }\r
260\r
261 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
262\r
263 //\r
264 // Skip sub functions, this is not a multi function device\r
265 //\r
266 Func = PCI_MAX_FUNC;\r
267 }\r
268 }\r
269\r
270 }\r
271 }\r
272\r
273 return EFI_SUCCESS;\r
274}\r
275\r
276EFI_STATUS\r
277PciSearchDevice (\r
278 IN PCI_IO_DEVICE *Bridge,\r
279 IN PCI_TYPE00 *Pci,\r
280 IN UINT8 Bus,\r
281 IN UINT8 Device,\r
282 IN UINT8 Func,\r
283 OUT PCI_IO_DEVICE **PciDevice\r
284 )\r
285/*++\r
286\r
287Routine Description:\r
288\r
289 Search required device.\r
290\r
291Arguments:\r
292\r
293 Bridge - A pointer to the PCI_IO_DEVICE.\r
294 Pci - A pointer to the PCI_TYPE00.\r
295 Bus - Bus number.\r
296 Device - Device number.\r
297 Func - Function number.\r
298 PciDevice - The Required pci device.\r
299\r
300Returns:\r
301\r
302 Status code.\r
303\r
304--*/\r
305{\r
306 PCI_IO_DEVICE *PciIoDevice;\r
307\r
308 PciIoDevice = NULL;\r
309\r
310 if (!IS_PCI_BRIDGE (Pci)) {\r
311\r
312 if (IS_CARDBUS_BRIDGE (Pci)) {\r
313 PciIoDevice = GatherP2CInfo (\r
314 Bridge->PciRootBridgeIo,\r
315 Pci,\r
316 Bus,\r
317 Device,\r
318 Func\r
319 );\r
320 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {\r
321 InitializeP2C (PciIoDevice);\r
322 }\r
323 } else {\r
324\r
325 //\r
326 // Create private data for Pci Device\r
327 //\r
328 PciIoDevice = GatherDeviceInfo (\r
329 Bridge->PciRootBridgeIo,\r
330 Pci,\r
331 Bus,\r
332 Device,\r
333 Func\r
334 );\r
335\r
336 }\r
337\r
338 } else {\r
339\r
340 //\r
341 // Create private data for PPB\r
342 //\r
343 PciIoDevice = GatherPPBInfo (\r
344 Bridge->PciRootBridgeIo,\r
345 Pci,\r
346 Bus,\r
347 Device,\r
348 Func\r
349 );\r
350\r
351 //\r
352 // Special initialization for PPB including making the PPB quiet\r
353 //\r
354 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {\r
355 InitializePPB (PciIoDevice);\r
356 }\r
357 }\r
358\r
359 if (!PciIoDevice) {\r
360 return EFI_OUT_OF_RESOURCES;\r
361 }\r
362 \r
363 //\r
364 // Create a device path for this PCI device and store it into its private data\r
365 //\r
366 CreatePciDevicePath(\r
367 Bridge->DevicePath,\r
368 PciIoDevice \r
369 );\r
370 \r
371 //\r
372 // Detect this function has option rom\r
373 //\r
374 if (gFullEnumeration) {\r
375\r
376 if (!IS_CARDBUS_BRIDGE (Pci)) {\r
377\r
378 GetOpRomInfo (PciIoDevice);\r
379\r
380 }\r
381\r
382 ResetPowerManagementFeature (PciIoDevice);\r
383 \r
384 } \r
385 else {\r
386 PciRomGetRomResourceFromPciOptionRomTable (\r
387 &gPciBusDriverBinding,\r
388 PciIoDevice->PciRootBridgeIo,\r
389 PciIoDevice\r
390 );\r
391 }\r
392\r
393 \r
394 //\r
395 // Insert it into a global tree for future reference\r
396 //\r
397 InsertPciDevice (Bridge, PciIoDevice);\r
398\r
399 //\r
400 // Determine PCI device attributes\r
401 //\r
402 DetermineDeviceAttribute (PciIoDevice);\r
403\r
404 if (PciDevice != NULL) {\r
405 *PciDevice = PciIoDevice;\r
406 }\r
407\r
408 return EFI_SUCCESS;\r
409}\r
410\r
411PCI_IO_DEVICE *\r
412GatherDeviceInfo (\r
413 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
414 IN PCI_TYPE00 *Pci,\r
415 UINT8 Bus,\r
416 UINT8 Device,\r
417 UINT8 Func\r
418 )\r
419/*++\r
420\r
421Routine Description:\r
422\r
423Arguments:\r
424\r
425Returns:\r
426\r
427 None\r
428\r
429--*/\r
430{\r
431 UINTN Offset;\r
432 UINTN BarIndex;\r
433 PCI_IO_DEVICE *PciIoDevice;\r
434\r
435 PciIoDevice = CreatePciIoDevice (\r
436 PciRootBridgeIo,\r
437 Pci,\r
438 Bus,\r
439 Device,\r
440 Func\r
441 );\r
442\r
443 if (!PciIoDevice) {\r
444 return NULL;\r
445 }\r
446\r
447 //\r
448 // If it is a full enumeration, disconnect the device in advance\r
449 //\r
450 if (gFullEnumeration) {\r
451\r
452 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
453\r
454 }\r
455\r
456 //\r
457 // Start to parse the bars\r
458 //\r
459 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {\r
460 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
461 }\r
462\r
463 return PciIoDevice;\r
464}\r
465\r
466PCI_IO_DEVICE *\r
467GatherPPBInfo (\r
468 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
469 IN PCI_TYPE00 *Pci,\r
470 UINT8 Bus,\r
471 UINT8 Device,\r
472 UINT8 Func\r
473 )\r
474/*++\r
475\r
476Routine Description:\r
477\r
478Arguments:\r
479\r
480Returns:\r
481\r
482 None\r
483\r
484--*/\r
485{\r
486 PCI_IO_DEVICE *PciIoDevice;\r
487 EFI_STATUS Status;\r
7e7e7fec 488 UINT8 Value;\r
10590588 489 EFI_PCI_IO_PROTOCOL *PciIo;\r
490 UINT8 Temp;\r
491\r
492 PciIoDevice = CreatePciIoDevice (\r
493 PciRootBridgeIo,\r
494 Pci,\r
495 Bus,\r
496 Device,\r
497 Func\r
498 );\r
499\r
500 if (!PciIoDevice) {\r
501 return NULL;\r
502 }\r
503 \r
504 if (gFullEnumeration) {\r
505 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
506\r
507 //\r
508 // Initalize the bridge control register\r
509 //\r
510 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
511 }\r
512\r
513 PciIo = &PciIoDevice->PciIo;\r
514\r
515 //\r
516 // Test whether it support 32 decode or not\r
517 //\r
518 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
519 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
520 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
521 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
522\r
523 if (Value) {\r
524 if (Value & 0x01) {\r
525 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
526 } else {\r
527 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
528 }\r
529 }\r
530\r
531 Status = BarExisted (\r
532 PciIoDevice,\r
533 0x24,\r
534 NULL,\r
535 NULL\r
536 );\r
537\r
538 //\r
539 // test if it supports 64 memory or not\r
540 //\r
541 if (!EFI_ERROR (Status)) {\r
542\r
543 Status = BarExisted (\r
544 PciIoDevice,\r
545 0x28,\r
546 NULL,\r
547 NULL\r
548 );\r
549\r
550 if (!EFI_ERROR (Status)) {\r
551 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
552 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
553 } else {\r
554 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
555 }\r
556 }\r
557\r
558 //\r
559 // Memory 32 code is required for ppb\r
560 //\r
561 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
562\r
563 return PciIoDevice;\r
564}\r
565\r
566PCI_IO_DEVICE *\r
567GatherP2CInfo (\r
568 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
569 IN PCI_TYPE00 *Pci,\r
570 UINT8 Bus,\r
571 UINT8 Device,\r
572 UINT8 Func\r
573 )\r
574/*++\r
575\r
576Routine Description:\r
577\r
578Arguments:\r
579\r
580Returns:\r
581\r
582 None\r
583\r
584--*/\r
585{\r
586 PCI_IO_DEVICE *PciIoDevice;\r
587 \r
588 PciIoDevice = CreatePciIoDevice (\r
589 PciRootBridgeIo,\r
590 Pci,\r
591 Bus,\r
592 Device,\r
593 Func\r
594 );\r
595\r
596 if (!PciIoDevice) {\r
597 return NULL;\r
598 }\r
599\r
600 if (gFullEnumeration) {\r
601 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
602\r
603 //\r
604 // Initalize the bridge control register\r
605 //\r
606 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
607\r
608 }\r
609 //\r
610 // P2C only has one bar that is in 0x10\r
611 //\r
612 PciParseBar(PciIoDevice, 0x10, 0);\r
613 \r
614 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |\r
615 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
616 EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
617\r
618 return PciIoDevice;\r
619}\r
620\r
621EFI_DEVICE_PATH_PROTOCOL *\r
622CreatePciDevicePath (\r
623 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
624 IN PCI_IO_DEVICE *PciIoDevice\r
625 )\r
626/*++\r
627\r
628Routine Description:\r
629\r
630Arguments:\r
631\r
632Returns:\r
633\r
634 None\r
635\r
636--*/\r
637{\r
638\r
639 PCI_DEVICE_PATH PciNode;\r
640\r
641 //\r
642 // Create PCI device path\r
643 //\r
644 PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
645 PciNode.Header.SubType = HW_PCI_DP;\r
646 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
647\r
648 PciNode.Device = PciIoDevice->DeviceNumber;\r
649 PciNode.Function = PciIoDevice->FunctionNumber;\r
650 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
651\r
652 return PciIoDevice->DevicePath;\r
653}\r
654\r
655EFI_STATUS\r
656BarExisted (\r
657 IN PCI_IO_DEVICE *PciIoDevice,\r
658 IN UINTN Offset,\r
659 OUT UINT32 *BarLengthValue,\r
660 OUT UINT32 *OriginalBarValue\r
661 )\r
662/*++\r
663\r
664Routine Description:\r
665\r
666 Check the bar is existed or not.\r
667\r
668Arguments:\r
669\r
670 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
671 Offset - The offset.\r
672 BarLengthValue - The bar length value.\r
673 OriginalBarValue - The original bar value.\r
674\r
675Returns:\r
676\r
677 EFI_NOT_FOUND - The bar don't exist.\r
678 EFI_SUCCESS - The bar exist.\r
679\r
680--*/\r
681{\r
682 EFI_PCI_IO_PROTOCOL *PciIo;\r
683 UINT32 OriginalValue;\r
684 UINT32 Value;\r
685 EFI_TPL OldTpl;\r
686\r
687 PciIo = &PciIoDevice->PciIo;\r
688\r
689 //\r
690 // Preserve the original value\r
691 //\r
692\r
693 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
694\r
695 //\r
696 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
697 //\r
698 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
699\r
700 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
701 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
702\r
703 //\r
704 // Write back the original value\r
705 //\r
706 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
707\r
708 //\r
709 // Restore TPL to its original level\r
710 //\r
711 gBS->RestoreTPL (OldTpl);\r
712\r
713 if (BarLengthValue != NULL) {\r
714 *BarLengthValue = Value;\r
715 }\r
716\r
717 if (OriginalBarValue != NULL) {\r
718 *OriginalBarValue = OriginalValue;\r
719 }\r
720\r
721 if (Value == 0) {\r
722 return EFI_NOT_FOUND;\r
723 } else {\r
724 return EFI_SUCCESS;\r
725 }\r
726}\r
727\r
728\r
729EFI_STATUS\r
730DetermineDeviceAttribute (\r
731 IN PCI_IO_DEVICE *PciIoDevice\r
732 )\r
733/*++\r
734\r
735Routine Description:\r
736 \r
737 Determine the related attributes of all devices under a Root Bridge\r
738\r
739Arguments:\r
740\r
741Returns:\r
742\r
743 None\r
744\r
745--*/\r
746{\r
747 UINT16 Command;\r
748 UINT16 BridgeControl;\r
749\r
750 Command = 0;\r
751\r
752 PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;\r
753 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
754\r
755 if (IS_PCI_VGA (&(PciIoDevice->Pci))){\r
756\r
757 //\r
758 // If the device is VGA, VGA related Attributes are supported\r
759 //\r
760 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;\r
761 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ;\r
762 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ;\r
763 }\r
764\r
765 if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {\r
766 //\r
767 // If the devie is a ISA Bridge, set the two attributes\r
768 //\r
769 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
770 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
771 }\r
772\r
773 if (IS_PCI_GFX (&(PciIoDevice->Pci))) {\r
774\r
775 //\r
776 // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO\r
777 // attribute\r
778 //\r
779 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;\r
780 }\r
781\r
782\r
783 //\r
784 // If the device is IDE, IDE related attributes are supported\r
785 //\r
786 if (IS_PCI_IDE (&(PciIoDevice->Pci))) {\r
787 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ;\r
788 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ;\r
789 }\r
790\r
791 PciReadCommandRegister(PciIoDevice, &Command);\r
792\r
793 \r
794 if (Command & EFI_PCI_COMMAND_IO_SPACE) {\r
795 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
796 }\r
797\r
798 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {\r
799 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
800 }\r
801\r
802 if (Command & EFI_PCI_COMMAND_BUS_MASTER) {\r
803 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
804 }\r
805\r
806 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || \r
807 IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){\r
808\r
809 //\r
810 // If it is a PPB, read the Bridge Control Register to determine\r
811 // the relevant attributes\r
812 //\r
813 BridgeControl = 0;\r
814 PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);\r
815\r
816 //\r
817 // Determine whether the ISA bit is set\r
818 // If ISA Enable on Bridge is set, the PPB\r
819 // will block forwarding 0x100-0x3ff for each 1KB in the \r
820 // first 64KB I/O range.\r
821 //\r
1c8bea11 822 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {\r
10590588 823 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
824 } \r
825\r
826 //\r
827 // Determine whether the VGA bit is set\r
828 // If it is set, the bridge is set to decode VGA memory range\r
829 // and palette register range\r
830 //\r
831 if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {\r
832 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
833 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
834 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
835 }\r
836\r
837 //\r
838 // if the palette snoop bit is set, then the brige is set to \r
839 // decode palette IO write\r
840 //\r
841 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
842 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
843 }\r
844 } \r
845\r
846 return EFI_SUCCESS;\r
847}\r
848\r
849UINTN\r
850PciParseBar (\r
851 IN PCI_IO_DEVICE *PciIoDevice,\r
852 IN UINTN Offset,\r
853 IN UINTN BarIndex\r
854 )\r
855/*++\r
856\r
857Routine Description:\r
858\r
859Arguments:\r
860\r
861Returns:\r
862\r
863 None\r
864\r
865--*/\r
866{\r
867 UINT32 Value;\r
10590588 868 UINT32 OriginalValue;\r
869 UINT32 Mask;\r
10590588 870 EFI_STATUS Status;\r
871\r
872 OriginalValue = 0;\r
873 Value = 0;\r
10590588 874\r
875 Status = BarExisted (\r
876 PciIoDevice,\r
877 Offset,\r
878 &Value,\r
879 &OriginalValue\r
880 );\r
881\r
882 if (EFI_ERROR (Status)) {\r
883 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
884 PciIoDevice->PciBar[BarIndex].Length = 0;\r
885 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
886\r
887 //\r
888 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
889 //\r
890 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
891 return Offset + 4;\r
892 }\r
893\r
894 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
895 if (Value & 0x01) {\r
896 //\r
897 // Device I/Os\r
898 //\r
899 Mask = 0xfffffffc;\r
900\r
901 if (Value & 0xFFFF0000) {\r
902 //\r
903 // It is a IO32 bar\r
904 //\r
905 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;\r
906 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);\r
907 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
908\r
909 } else {\r
910 //\r
911 // It is a IO16 bar\r
912 //\r
913 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;\r
914 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
915 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
916\r
917 }\r
918 //\r
919 // Workaround. Some platforms inplement IO bar with 0 length\r
920 // Need to treat it as no-bar\r
921 //\r
922 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
9c83c97a 923 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
10590588 924 }\r
925\r
926 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;\r
927 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
928\r
929 } else {\r
930\r
931 Mask = 0xfffffff0;\r
932\r
933 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
934\r
935 switch (Value & 0x07) {\r
936\r
937 //\r
938 //memory space; anywhere in 32 bit address space\r
939 //\r
940 case 0x00:\r
941 if (Value & 0x08) {\r
942 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
943 } else {\r
944 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
945 }\r
946\r
947 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
948 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
949\r
950 break;\r
951\r
952 //\r
953 // memory space; anywhere in 64 bit address space\r
954 //\r
955 case 0x04:\r
956 if (Value & 0x08) {\r
957 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
958 } else {\r
959 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
960 }\r
961\r
962 //\r
963 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
964 // is regarded as an extension for the first bar. As a result\r
965 // the sizing will be conducted on combined 64 bit value\r
966 // Here just store the masked first 32bit value for future size\r
967 // calculation\r
968 //\r
969 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;\r
970 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
971\r
972 //\r
973 // Increment the offset to point to next DWORD\r
974 //\r
975 Offset += 4;\r
976\r
977 Status = BarExisted (\r
978 PciIoDevice,\r
979 Offset,\r
980 &Value,\r
981 &OriginalValue\r
982 );\r
983\r
984 if (EFI_ERROR (Status)) {\r
985 return Offset + 4;\r
986 }\r
987\r
988 //\r
989 // Fix the length to support some spefic 64 bit BAR\r
990 //\r
ae837d36 991 Value |= ((UINT32)(-1) << HighBitSet32 (Value)); \r
10590588 992\r
993 //\r
994 // Calculate the size of 64bit bar\r
995 //\r
996 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
997\r
998 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
999 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
1000 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1001\r
1002 break;\r
1003\r
1004 //\r
1005 // reserved\r
1006 //\r
1007 default:\r
1008 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1009 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1010 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1011\r
1012 break;\r
1013 }\r
1014 }\r
1015 \r
1016 //\r
1017 // Check the length again so as to keep compatible with some special bars\r
1018 //\r
1019 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1020 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1021 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1022 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
1023 }\r
1024 \r
1025 //\r
1026 // Increment number of bar\r
1027 //\r
1028 return Offset + 4;\r
1029}\r
1030\r
1031EFI_STATUS\r
1032InitializePPB (\r
1033 IN PCI_IO_DEVICE *PciIoDevice\r
1034 )\r
1035/*++\r
1036\r
1037Routine Description:\r
1038\r
1039Arguments:\r
1040\r
1041Returns:\r
1042\r
1043 None\r
1044\r
1045--*/\r
1046{\r
1047 EFI_PCI_IO_PROTOCOL *PciIo;\r
1048\r
1049 PciIo = &(PciIoDevice->PciIo);\r
1050\r
1051 //\r
1052 // Put all the resource apertures including IO16\r
1053 // Io32, pMem32, pMem64 to quiescent state\r
1054 // Resource base all ones, Resource limit all zeros\r
1055 //\r
1056 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
1057 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
1058\r
1059 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
1060 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
1061\r
1062 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
1063 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
1064\r
1065 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
1066 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
1067\r
1068 //\r
1069 // don't support use io32 as for now\r
1070 //\r
1071 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
1072 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
1073\r
1074 return EFI_SUCCESS;\r
1075}\r
1076\r
1077EFI_STATUS\r
1078InitializeP2C (\r
1079 IN PCI_IO_DEVICE *PciIoDevice\r
1080 )\r
1081/*++\r
1082\r
1083Routine Description:\r
1084\r
1085Arguments:\r
1086\r
1087Returns:\r
1088\r
1089 None\r
1090\r
1091--*/\r
1092{\r
1093 EFI_PCI_IO_PROTOCOL *PciIo;\r
1094\r
1095 PciIo = &(PciIoDevice->PciIo);\r
1096\r
1097 //\r
1098 // Put all the resource apertures including IO16\r
1099 // Io32, pMem32, pMem64 to quiescent state(\r
1100 // Resource base all ones, Resource limit all zeros\r
1101 //\r
1102 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
1103 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
1104\r
1105 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
1106 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
1107\r
1108 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
1109 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
1110\r
1111 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
1112 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
1113\r
1114 return EFI_SUCCESS;\r
1115}\r
1116\r
1117PCI_IO_DEVICE *\r
1118CreatePciIoDevice (\r
1119 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
1120 IN PCI_TYPE00 *Pci,\r
1121 UINT8 Bus,\r
1122 UINT8 Device,\r
1123 UINT8 Func\r
1124 )\r
1125/*++\r
1126\r
1127Routine Description:\r
1128\r
1129Arguments:\r
1130\r
1131Returns:\r
1132\r
1133 None\r
1134\r
1135--*/\r
1136{\r
1137\r
1138 EFI_STATUS Status;\r
1139 PCI_IO_DEVICE *PciIoDevice;\r
1140\r
1141 PciIoDevice = NULL;\r
1142\r
1143 Status = gBS->AllocatePool (\r
1144 EfiBootServicesData,\r
1145 sizeof (PCI_IO_DEVICE),\r
1146 (VOID **) &PciIoDevice\r
1147 );\r
1148\r
1149 if (EFI_ERROR (Status)) {\r
1150 return NULL;\r
1151 }\r
1152\r
1153 ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
1154\r
1155 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;\r
1156 PciIoDevice->Handle = NULL;\r
1157 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;\r
1158 PciIoDevice->DevicePath = NULL;\r
1159 PciIoDevice->BusNumber = Bus;\r
1160 PciIoDevice->DeviceNumber = Device;\r
1161 PciIoDevice->FunctionNumber = Func;\r
1162 PciIoDevice->Decodes = 0;\r
1163 if (gFullEnumeration) {\r
1164 PciIoDevice->Allocated = FALSE;\r
1165 } else {\r
1166 PciIoDevice->Allocated = TRUE;\r
1167 }\r
1168\r
1169 PciIoDevice->Attributes = 0;\r
1170 PciIoDevice->Supports = 0;\r
1171 PciIoDevice->BusOverride = FALSE;\r
1172 PciIoDevice->IsPciExp = FALSE;\r
1173\r
1174 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
1175\r
1176 //\r
1177 // Initialize the PCI I/O instance structure\r
1178 //\r
1179\r
1180 Status = InitializePciIoInstance (PciIoDevice);\r
1181 Status = InitializePciDriverOverrideInstance (PciIoDevice);\r
1182\r
1183 if (EFI_ERROR (Status)) {\r
1184 gBS->FreePool (PciIoDevice);\r
1185 return NULL;\r
1186 }\r
1187\r
1188 //\r
1189 // Initialize the reserved resource list\r
1190 //\r
1191 InitializeListHead (&PciIoDevice->ReservedResourceList);\r
1192\r
1193 //\r
1194 // Initialize the driver list\r
1195 //\r
1196 InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
1197\r
1198 //\r
1199 // Initialize the child list\r
1200 //\r
1201 InitializeListHead (&PciIoDevice->ChildList);\r
1202\r
1203 return PciIoDevice;\r
1204}\r
1205\r
1206EFI_STATUS\r
1207PciEnumeratorLight (\r
1208 IN EFI_HANDLE Controller\r
1209 )\r
1210/*++\r
1211\r
1212Routine Description:\r
1213\r
1214 This routine is used to enumerate entire pci bus system \r
1215 in a given platform\r
1216\r
1217Arguments:\r
1218\r
1219Returns:\r
1220\r
1221 None\r
1222\r
1223--*/\r
1224{\r
1225\r
1226 EFI_STATUS Status;\r
1227 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1228 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1229 PCI_IO_DEVICE *RootBridgeDev;\r
1230 UINT16 MinBus;\r
1231 UINT16 MaxBus;\r
1232 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1233\r
1234 MinBus = 0;\r
1235 MaxBus = PCI_MAX_BUS;\r
1236 Descriptors = NULL;\r
1237\r
1238 //\r
1239 // If this host bridge has been already enumerated, then return successfully\r
1240 //\r
1241 if (RootBridgeExisted (Controller)) {\r
1242 return EFI_SUCCESS;\r
1243 }\r
1244\r
1245 //\r
1246 // Open the IO Abstraction(s) needed to perform the supported test\r
1247 //\r
1248 Status = gBS->OpenProtocol (\r
1249 Controller , \r
1250 &gEfiDevicePathProtocolGuid, \r
1251 (VOID **)&ParentDevicePath,\r
1252 gPciBusDriverBinding.DriverBindingHandle, \r
1253 Controller, \r
1254 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1255 );\r
1256 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
1257 return Status;\r
1258 }\r
1259\r
1260 //\r
1261 // Open pci root bridge io protocol\r
1262 //\r
1263 Status = gBS->OpenProtocol (\r
1264 Controller,\r
1265 &gEfiPciRootBridgeIoProtocolGuid,\r
1266 (VOID **) &PciRootBridgeIo,\r
1267 gPciBusDriverBinding.DriverBindingHandle,\r
1268 Controller,\r
1269 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1270 );\r
1271 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
1272 return Status;\r
1273 }\r
1274\r
1275 //\r
1276 // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge \r
1277 //\r
1278 Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);\r
1279\r
1280 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1281\r
1282 if (EFI_ERROR (Status)) {\r
1283 return Status;\r
1284 }\r
1285\r
a5f2a205 1286 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
10590588 1287\r
1288 //\r
1289 // Create a device node for root bridge device with a NULL host bridge controller handle\r
1290 //\r
1291 RootBridgeDev = CreateRootBridge (Controller);\r
1292\r
1293 //\r
1294 // Record the root bridge device path\r
1295 //\r
1296 RootBridgeDev->DevicePath = ParentDevicePath;\r
1297\r
1298 //\r
1299 // Record the root bridge io protocol\r
1300 //\r
1301 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
1302\r
1303 Status = PciPciDeviceInfoCollector (\r
1304 RootBridgeDev,\r
1305 (UINT8) MinBus\r
1306 );\r
1307\r
1308 if (!EFI_ERROR (Status)) {\r
1309\r
1310 //\r
1311 // If successfully, insert the node into device pool\r
1312 //\r
1313 InsertRootBridge (RootBridgeDev);\r
1314 } else {\r
1315\r
1316 //\r
1317 // If unsuccessly, destroy the entire node\r
1318 //\r
1319 DestroyRootBridge (RootBridgeDev);\r
1320 }\r
1321\r
1322 Descriptors++;\r
1323 }\r
1324\r
1325 return EFI_SUCCESS;\r
1326}\r
1327\r
1328EFI_STATUS\r
1329PciGetBusRange (\r
a5f2a205 1330 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,\r
10590588 1331 OUT UINT16 *MinBus,\r
1332 OUT UINT16 *MaxBus,\r
1333 OUT UINT16 *BusRange\r
1334 )\r
1335/*++\r
1336\r
1337Routine Description:\r
1338\r
1339 Get the bus range.\r
1340\r
1341Arguments:\r
1342\r
1343 Descriptors - A pointer to the address space descriptor.\r
1344 MinBus - The min bus.\r
1345 MaxBus - The max bus.\r
1346 BusRange - The bus range.\r
1347 \r
1348Returns:\r
1349 \r
1350 Status Code.\r
1351\r
1352--*/\r
1353{\r
1354\r
a5f2a205 1355 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1356 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
10590588 1357 if (MinBus != NULL) {\r
a5f2a205 1358 *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;\r
10590588 1359 }\r
1360\r
1361 if (MaxBus != NULL) {\r
a5f2a205 1362 *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;\r
10590588 1363 }\r
1364\r
1365 if (BusRange != NULL) {\r
a5f2a205 1366 *BusRange = (UINT16)(*Descriptors)->AddrLen;\r
10590588 1367 }\r
1368 return EFI_SUCCESS;\r
1369 }\r
1370\r
a5f2a205 1371 (*Descriptors)++;\r
10590588 1372 }\r
1373\r
1374 return EFI_NOT_FOUND;\r
1375}\r
1376\r