be316effdc8bc52e19fe5a9d8d6eece3f14b47ba
[people/mcb30/edk2.git] / edk2 / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
1 /**@file\r
2 \r
3 Copyright (c) 2006, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 **/\r
13 \r
14 \r
15 #include "pcibus.h"\r
16 #include "PciEnumeratorSupport.h"\r
17 #include "PciCommand.h"\r
18 #include "PciIo.h"\r
19 \r
20 EFI_STATUS\r
21 PciDevicePresent (\r
22   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
23   PCI_TYPE00                          *Pci,\r
24   UINT8                               Bus,\r
25   UINT8                               Device,\r
26   UINT8                               Func\r
27   )\r
28 /*++\r
29 \r
30 Routine Description:\r
31 \r
32   This routine is used to check whether the pci device is present\r
33 \r
34 Arguments:\r
35 \r
36 Returns:\r
37 \r
38   None\r
39 \r
40 --*/\r
41 // TODO:    PciRootBridgeIo - add argument and description to function comment\r
42 // TODO:    Pci - add argument and description to function comment\r
43 // TODO:    Bus - add argument and description to function comment\r
44 // TODO:    Device - add argument and description to function comment\r
45 // TODO:    Func - add argument and description to function comment\r
46 // TODO:    EFI_SUCCESS - add return value to function comment\r
47 // TODO:    EFI_NOT_FOUND - add return value to function comment\r
48 {\r
49   UINT64      Address;\r
50   EFI_STATUS  Status;\r
51 \r
52   //\r
53   // Create PCI address map in terms of Bus, Device and Func\r
54   //\r
55   Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
56 \r
57   //\r
58   // Read the Vendor Id register\r
59   //\r
60   Status = PciRootBridgeIoRead (\r
61                                   PciRootBridgeIo,\r
62                                   NULL,\r
63                                   EfiPciWidthUint32,\r
64                                   Address,\r
65                                   1,\r
66                                   Pci\r
67                                   );\r
68 \r
69   if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
70 \r
71     //\r
72     // Read the entire config header for the device\r
73     //\r
74 \r
75     Status = PciRootBridgeIoRead (\r
76                                     PciRootBridgeIo,\r
77                                     NULL,\r
78                                     EfiPciWidthUint32,\r
79                                     Address,\r
80                                     sizeof (PCI_TYPE00) / sizeof (UINT32),\r
81                                     Pci\r
82                                     );\r
83 \r
84     return EFI_SUCCESS;\r
85   }\r
86 \r
87   return EFI_NOT_FOUND;\r
88 }\r
89 \r
90 EFI_STATUS\r
91 PciPciDeviceInfoCollector (\r
92   IN PCI_IO_DEVICE                      *Bridge,\r
93   UINT8                                 StartBusNumber\r
94   )\r
95 /*++\r
96 \r
97 Routine Description:\r
98 \r
99 Arguments:\r
100 \r
101 Returns:\r
102 \r
103   None\r
104 \r
105 --*/\r
106 // TODO:    Bridge - add argument and description to function comment\r
107 // TODO:    StartBusNumber - add argument and description to function comment\r
108 // TODO:    EFI_SUCCESS - add return value to function comment\r
109 {\r
110   EFI_STATUS          Status;\r
111   PCI_TYPE00          Pci;\r
112   UINT8               Device;\r
113   UINT8               Func;\r
114   UINT8               SecBus;\r
115   PCI_IO_DEVICE       *PciIoDevice;\r
116   EFI_PCI_IO_PROTOCOL *PciIo;\r
117 \r
118   Status  = EFI_SUCCESS;\r
119   SecBus  = 0;\r
120 \r
121   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
122 \r
123     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
124 \r
125       //\r
126       // Check to see whether PCI device is present\r
127       //\r
128 \r
129       Status = PciDevicePresent (\r
130                 Bridge->PciRootBridgeIo,\r
131                 &Pci,\r
132                 (UINT8) StartBusNumber,\r
133                 (UINT8) Device,\r
134                 (UINT8) Func\r
135                 );\r
136 \r
137       if (!EFI_ERROR (Status)) {\r
138 \r
139         //\r
140         // Call back to host bridge function\r
141         //\r
142         PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);\r
143 \r
144         //\r
145         // Collect all the information about the PCI device discovered\r
146         //\r
147         Status = PciSearchDevice (\r
148                   Bridge,\r
149                   &Pci,\r
150                   (UINT8) StartBusNumber,\r
151                   Device,\r
152                   Func,\r
153                   &PciIoDevice\r
154                   );\r
155 \r
156         //\r
157         // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
158         //\r
159         //\r
160 \r
161         if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
162 \r
163           //\r
164           // If it is PPB, we need to get the secondary bus to continue the enumeration\r
165           //\r
166           PciIo   = &(PciIoDevice->PciIo);\r
167 \r
168           Status  = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);\r
169 \r
170           if (EFI_ERROR (Status)) {\r
171             return Status;\r
172           }\r
173 \r
174           //\r
175           // Get resource padding for PPB\r
176           //\r
177           GetResourcePaddingPpb (PciIoDevice);\r
178 \r
179           //\r
180           // Deep enumerate the next level bus\r
181           //\r
182           Status = PciPciDeviceInfoCollector (\r
183                     PciIoDevice,\r
184                     (UINT8) (SecBus)\r
185                     );\r
186 \r
187         }\r
188 \r
189         if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
190 \r
191           //\r
192           // Skip sub functions, this is not a multi function device\r
193           //\r
194           Func = PCI_MAX_FUNC;\r
195         }\r
196       }\r
197 \r
198     }\r
199   }\r
200 \r
201   return EFI_SUCCESS;\r
202 }\r
203 \r
204 EFI_STATUS\r
205 PciSearchDevice (\r
206   IN  PCI_IO_DEVICE                         *Bridge,\r
207   IN  PCI_TYPE00                            *Pci,\r
208   IN  UINT8                                 Bus,\r
209   IN  UINT8                                 Device,\r
210   IN  UINT8                                 Func,\r
211   OUT PCI_IO_DEVICE                         **PciDevice\r
212   )\r
213 /*++\r
214 \r
215 Routine Description:\r
216 \r
217   Search required device.\r
218 \r
219 Arguments:\r
220 \r
221   Bridge     - A pointer to the PCI_IO_DEVICE.\r
222   Pci        - A pointer to the PCI_TYPE00.\r
223   Bus        - Bus number.\r
224   Device     - Device number.\r
225   Func       - Function number.\r
226   PciDevice  - The Required pci device.\r
227 \r
228 Returns:\r
229 \r
230   Status code.\r
231 \r
232 --*/\r
233 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
234 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
235 // TODO:    EFI_SUCCESS - add return value to function comment\r
236 {\r
237   PCI_IO_DEVICE *PciIoDevice;\r
238 \r
239   PciIoDevice = NULL;\r
240 \r
241   if (!IS_PCI_BRIDGE (Pci)) {\r
242 \r
243     if (IS_CARDBUS_BRIDGE (Pci)) {\r
244       PciIoDevice = GatherP2CInfo (\r
245                       Bridge,\r
246                       Pci,\r
247                       Bus,\r
248                       Device,\r
249                       Func\r
250                       );\r
251       if ((PciIoDevice != NULL) && gFullEnumeration) {\r
252         InitializeP2C (PciIoDevice);\r
253       }\r
254     } else {\r
255 \r
256       //\r
257       // Create private data for Pci Device\r
258       //\r
259       PciIoDevice = GatherDeviceInfo (\r
260                       Bridge,\r
261                       Pci,\r
262                       Bus,\r
263                       Device,\r
264                       Func\r
265                       );\r
266 \r
267     }\r
268 \r
269   } else {\r
270 \r
271     //\r
272     // Create private data for PPB\r
273     //\r
274     PciIoDevice = GatherPpbInfo (\r
275                     Bridge,\r
276                     Pci,\r
277                     Bus,\r
278                     Device,\r
279                     Func\r
280                     );\r
281 \r
282     //\r
283     // Special initialization for PPB including making the PPB quiet\r
284     //\r
285     if ((PciIoDevice != NULL) && gFullEnumeration) {\r
286       InitializePpb (PciIoDevice);\r
287     }\r
288   }\r
289 \r
290   if (!PciIoDevice) {\r
291     return EFI_OUT_OF_RESOURCES;\r
292   }\r
293 \r
294   //\r
295   // Update the bar information for this PCI device so as to support some specific device\r
296   //\r
297   UpdatePciInfo (PciIoDevice);\r
298 \r
299   if (PciIoDevice->DevicePath == NULL) {\r
300     return EFI_OUT_OF_RESOURCES;\r
301   }\r
302 \r
303   //\r
304   // Detect this function has option rom\r
305   //\r
306   if (gFullEnumeration) {\r
307 \r
308     if (!IS_CARDBUS_BRIDGE (Pci)) {\r
309 \r
310       GetOpRomInfo (PciIoDevice);\r
311 \r
312     }\r
313 \r
314     ResetPowerManagementFeature (PciIoDevice);\r
315 \r
316   }\r
317 \r
318   //\r
319   // Insert it into a global tree for future reference\r
320   //\r
321   InsertPciDevice (Bridge, PciIoDevice);\r
322 \r
323   //\r
324   // Determine PCI device attributes\r
325   //\r
326 \r
327   if (PciDevice != NULL) {\r
328     *PciDevice = PciIoDevice;\r
329   }\r
330 \r
331   return EFI_SUCCESS;\r
332 }\r
333 \r
334 PCI_IO_DEVICE *\r
335 GatherDeviceInfo (\r
336   IN PCI_IO_DEVICE                    *Bridge,\r
337   IN PCI_TYPE00                       *Pci,\r
338   UINT8                               Bus,\r
339   UINT8                               Device,\r
340   UINT8                               Func\r
341   )\r
342 /*++\r
343 \r
344 Routine Description:\r
345 \r
346 Arguments:\r
347 \r
348 Returns:\r
349 \r
350   None\r
351 \r
352 --*/\r
353 // TODO:    Bridge - add argument and description to function comment\r
354 // TODO:    Pci - add argument and description to function comment\r
355 // TODO:    Bus - add argument and description to function comment\r
356 // TODO:    Device - add argument and description to function comment\r
357 // TODO:    Func - add argument and description to function comment\r
358 {\r
359   UINTN                           Offset;\r
360   UINTN                           BarIndex;\r
361   PCI_IO_DEVICE                   *PciIoDevice;\r
362   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
363 \r
364   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
365   PciIoDevice = CreatePciIoDevice (\r
366                   PciRootBridgeIo,\r
367                   Pci,\r
368                   Bus,\r
369                   Device,\r
370                   Func\r
371                   );\r
372 \r
373   if (!PciIoDevice) {\r
374     return NULL;\r
375   }\r
376 \r
377   //\r
378   // Create a device path for this PCI device and store it into its private data\r
379   //\r
380   CreatePciDevicePath (\r
381     Bridge->DevicePath,\r
382     PciIoDevice\r
383     );\r
384 \r
385   //\r
386   // If it is a full enumeration, disconnect the device in advance\r
387   //\r
388   if (gFullEnumeration) {\r
389 \r
390     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
391 \r
392   }\r
393 \r
394   //\r
395   // Start to parse the bars\r
396   //\r
397   for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {\r
398     Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
399   }\r
400 \r
401   return PciIoDevice;\r
402 }\r
403 \r
404 PCI_IO_DEVICE *\r
405 GatherPpbInfo (\r
406   IN PCI_IO_DEVICE                    *Bridge,\r
407   IN PCI_TYPE00                       *Pci,\r
408   UINT8                               Bus,\r
409   UINT8                               Device,\r
410   UINT8                               Func\r
411   )\r
412 /*++\r
413 \r
414 Routine Description:\r
415 \r
416 Arguments:\r
417 \r
418 Returns:\r
419 \r
420   None\r
421 \r
422 --*/\r
423 // TODO:    Bridge - add argument and description to function comment\r
424 // TODO:    Pci - add argument and description to function comment\r
425 // TODO:    Bus - add argument and description to function comment\r
426 // TODO:    Device - add argument and description to function comment\r
427 // TODO:    Func - add argument and description to function comment\r
428 {\r
429   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
430   PCI_IO_DEVICE                   *PciIoDevice;\r
431   EFI_STATUS                      Status;\r
432   UINT32                          Value;\r
433   EFI_PCI_IO_PROTOCOL             *PciIo;\r
434   UINT8                           Temp;\r
435 \r
436   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
437   PciIoDevice = CreatePciIoDevice (\r
438                   PciRootBridgeIo,\r
439                   Pci,\r
440                   Bus,\r
441                   Device,\r
442                   Func\r
443                   );\r
444 \r
445   if (!PciIoDevice) {\r
446     return NULL;\r
447   }\r
448 \r
449   //\r
450   // Create a device path for this PCI device and store it into its private data\r
451   //\r
452   CreatePciDevicePath (\r
453     Bridge->DevicePath,\r
454     PciIoDevice\r
455     );\r
456 \r
457   if (gFullEnumeration) {\r
458     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
459 \r
460     //\r
461     // Initalize the bridge control register\r
462     //\r
463     PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
464 \r
465   }\r
466 \r
467   //\r
468   // PPB can have two BARs\r
469   //\r
470   if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {\r
471     //\r
472     // Not 64-bit bar\r
473     //\r
474     PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);\r
475   }\r
476 \r
477   PciIo = &PciIoDevice->PciIo;\r
478 \r
479   //\r
480   // Test whether it support 32 decode or not\r
481   //\r
482   PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
483   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
484   PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
485   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
486 \r
487   if (Value) {\r
488     if (Value & 0x01) {\r
489       PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
490     } else {\r
491       PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
492     }\r
493   }\r
494 \r
495   Status = BarExisted (\r
496             PciIoDevice,\r
497             0x24,\r
498             NULL,\r
499             NULL\r
500             );\r
501 \r
502   //\r
503   // test if it supports 64 memory or not\r
504   //\r
505   if (!EFI_ERROR (Status)) {\r
506 \r
507     Status = BarExisted (\r
508               PciIoDevice,\r
509               0x28,\r
510               NULL,\r
511               NULL\r
512               );\r
513 \r
514     if (!EFI_ERROR (Status)) {\r
515       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
516       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
517     } else {\r
518       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
519     }\r
520   }\r
521 \r
522   //\r
523   // Memory 32 code is required for ppb\r
524   //\r
525   PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
526 \r
527   GetResourcePaddingPpb (PciIoDevice);\r
528 \r
529   return PciIoDevice;\r
530 }\r
531 \r
532 PCI_IO_DEVICE *\r
533 GatherP2CInfo (\r
534   IN PCI_IO_DEVICE                    *Bridge,\r
535   IN PCI_TYPE00                       *Pci,\r
536   UINT8                               Bus,\r
537   UINT8                               Device,\r
538   UINT8                               Func\r
539   )\r
540 /*++\r
541 \r
542 Routine Description:\r
543 \r
544 Arguments:\r
545 \r
546 Returns:\r
547 \r
548   None\r
549 \r
550 --*/\r
551 // TODO:    Bridge - add argument and description to function comment\r
552 // TODO:    Pci - add argument and description to function comment\r
553 // TODO:    Bus - add argument and description to function comment\r
554 // TODO:    Device - add argument and description to function comment\r
555 // TODO:    Func - add argument and description to function comment\r
556 {\r
557   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
558   PCI_IO_DEVICE                   *PciIoDevice;\r
559 \r
560   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
561   PciIoDevice = CreatePciIoDevice (\r
562                   PciRootBridgeIo,\r
563                   Pci,\r
564                   Bus,\r
565                   Device,\r
566                   Func\r
567                   );\r
568 \r
569   if (!PciIoDevice) {\r
570     return NULL;\r
571   }\r
572 \r
573   //\r
574   // Create a device path for this PCI device and store it into its private data\r
575   //\r
576   CreatePciDevicePath (\r
577     Bridge->DevicePath,\r
578     PciIoDevice\r
579     );\r
580 \r
581   if (gFullEnumeration) {\r
582     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
583 \r
584     //\r
585     // Initalize the bridge control register\r
586     //\r
587     PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
588 \r
589   }\r
590   //\r
591   // P2C only has one bar that is in 0x10\r
592   //\r
593   PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);\r
594 \r
595   //\r
596   // Read PciBar information from the bar register\r
597   //\r
598   GetBackPcCardBar (PciIoDevice);\r
599   PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |\r
600                          EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
601                          EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
602 \r
603   return PciIoDevice;\r
604 }\r
605 \r
606 EFI_DEVICE_PATH_PROTOCOL *\r
607 CreatePciDevicePath (\r
608   IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
609   IN  PCI_IO_DEVICE            *PciIoDevice\r
610   )\r
611 /*++\r
612 \r
613 Routine Description:\r
614 \r
615 Arguments:\r
616 \r
617 Returns:\r
618 \r
619   None\r
620 \r
621 --*/\r
622 // TODO:    ParentDevicePath - add argument and description to function comment\r
623 // TODO:    PciIoDevice - add argument and description to function comment\r
624 {\r
625 \r
626   PCI_DEVICE_PATH PciNode;\r
627 \r
628   //\r
629   // Create PCI device path\r
630   //\r
631   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
632   PciNode.Header.SubType  = HW_PCI_DP;\r
633   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
634 \r
635   PciNode.Device          = PciIoDevice->DeviceNumber;\r
636   PciNode.Function        = PciIoDevice->FunctionNumber;\r
637   PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
638 \r
639   return PciIoDevice->DevicePath;\r
640 }\r
641 \r
642 EFI_STATUS\r
643 BarExisted (\r
644   IN PCI_IO_DEVICE *PciIoDevice,\r
645   IN UINTN         Offset,\r
646   OUT UINT32       *BarLengthValue,\r
647   OUT UINT32       *OriginalBarValue\r
648   )\r
649 /*++\r
650 \r
651 Routine Description:\r
652 \r
653   Check the bar is existed or not.\r
654 \r
655 Arguments:\r
656 \r
657   PciIoDevice       - A pointer to the PCI_IO_DEVICE.\r
658   Offset            - The offset.\r
659   BarLengthValue    - The bar length value.\r
660   OriginalBarValue  - The original bar value.\r
661 \r
662 Returns:\r
663 \r
664   EFI_NOT_FOUND     - The bar don't exist.\r
665   EFI_SUCCESS       - The bar exist.\r
666 \r
667 --*/\r
668 {\r
669   EFI_PCI_IO_PROTOCOL *PciIo;\r
670   UINT32              OriginalValue;\r
671   UINT32              Value;\r
672   EFI_TPL             OldTpl;\r
673 \r
674   PciIo = &PciIoDevice->PciIo;\r
675 \r
676   //\r
677   // Preserve the original value\r
678   //\r
679 \r
680   PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
681 \r
682   //\r
683   // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
684   //\r
685   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
686 \r
687   PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
688   PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
689 \r
690   //\r
691   // Write back the original value\r
692   //\r
693   PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
694 \r
695   //\r
696   // Restore TPL to its original level\r
697   //\r
698   gBS->RestoreTPL (OldTpl);\r
699 \r
700   if (BarLengthValue != NULL) {\r
701     *BarLengthValue = Value;\r
702   }\r
703 \r
704   if (OriginalBarValue != NULL) {\r
705     *OriginalBarValue = OriginalValue;\r
706   }\r
707 \r
708   if (Value == 0) {\r
709     return EFI_NOT_FOUND;\r
710   } else {\r
711     return EFI_SUCCESS;\r
712   }\r
713 }\r
714 \r
715 EFI_STATUS\r
716 PciTestSupportedAttribute (\r
717   IN PCI_IO_DEVICE                      *PciIoDevice,\r
718   IN UINT16                             *Command,\r
719   IN UINT16                             *BridgeControl,\r
720   IN UINT16                             *OldCommand,\r
721   IN UINT16                             *OldBridgeControl\r
722   )\r
723 /*++\r
724 \r
725 Routine Description:\r
726 \r
727 Arguments:\r
728 \r
729 Returns:\r
730 \r
731   None\r
732 \r
733 --*/\r
734 // TODO:    PciIoDevice - add argument and description to function comment\r
735 // TODO:    Command - add argument and description to function comment\r
736 // TODO:    BridgeControl - add argument and description to function comment\r
737 // TODO:    OldCommand - add argument and description to function comment\r
738 // TODO:    OldBridgeControl - add argument and description to function comment\r
739 // TODO:    EFI_SUCCESS - add return value to function comment\r
740 {\r
741   EFI_TPL OldTpl;\r
742 \r
743   //\r
744   // Preserve the original value\r
745   //\r
746   PciReadCommandRegister (PciIoDevice, OldCommand);\r
747 \r
748   //\r
749   // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
750   //\r
751   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
752 \r
753   PciSetCommandRegister (PciIoDevice, *Command);\r
754   PciReadCommandRegister (PciIoDevice, Command);\r
755 \r
756   //\r
757   // Write back the original value\r
758   //\r
759   PciSetCommandRegister (PciIoDevice, *OldCommand);\r
760 \r
761   //\r
762   // Restore TPL to its original level\r
763   //\r
764   gBS->RestoreTPL (OldTpl);\r
765 \r
766   if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
767 \r
768     //\r
769     // Preserve the original value\r
770     //\r
771     PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl);\r
772 \r
773     //\r
774     // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
775     //\r
776     OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
777 \r
778     PciSetBridgeControlRegister (PciIoDevice, *BridgeControl);\r
779     PciReadBridgeControlRegister (PciIoDevice, BridgeControl);\r
780 \r
781     //\r
782     // Write back the original value\r
783     //\r
784     PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl);\r
785 \r
786     //\r
787     // Restore TPL to its original level\r
788     //\r
789     gBS->RestoreTPL (OldTpl);\r
790 \r
791   } else {\r
792     *OldBridgeControl = 0;\r
793     *BridgeControl    = 0;\r
794   }\r
795 \r
796   return EFI_SUCCESS;\r
797 }\r
798 \r
799 EFI_STATUS\r
800 PciSetDeviceAttribute (\r
801   IN PCI_IO_DEVICE                      *PciIoDevice,\r
802   IN UINT16                             Command,\r
803   IN UINT16                             BridgeControl,\r
804   IN UINTN                              Option\r
805   )\r
806 /*++\r
807 \r
808   Routine Description:\r
809     Set the supported or current attributes of a PCI device\r
810 \r
811   Arguments:\r
812     PciIoDevice   - Structure pointer for PCI device.\r
813     Command       - Command register value.\r
814     BridgeControl - Bridge control value for PPB or P2C.\r
815     Option        - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
816 \r
817   Returns:\r
818 \r
819 --*/\r
820 \r
821 /*++\r
822 \r
823 Routine Description:\r
824 \r
825 \r
826 \r
827 Arguments:\r
828 \r
829 \r
830 Returns:\r
831 \r
832   EFI_SUCCESS   Always success\r
833 \r
834 \r
835 --*/\r
836 {\r
837   UINT64  Attributes;\r
838 \r
839   Attributes = 0;\r
840 \r
841   if (Command & EFI_PCI_COMMAND_IO_SPACE) {\r
842     Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
843   }\r
844 \r
845   if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {\r
846     Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
847   }\r
848 \r
849   if (Command & EFI_PCI_COMMAND_BUS_MASTER) {\r
850     Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
851   }\r
852 \r
853   if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
854     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
855   }\r
856 \r
857   if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {\r
858     Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
859   }\r
860 \r
861   if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {\r
862     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
863     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
864     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
865   }\r
866 \r
867   if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) {\r
868     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
869     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;\r
870   }\r
871 \r
872   if (Option == EFI_SET_SUPPORTS) {\r
873 \r
874     Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
875                   EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        |\r
876                   EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       |\r
877                   EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      |\r
878                   EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         |\r
879                   EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
880 \r
881     if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {\r
882       Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
883       Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
884     }\r
885 \r
886     if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
887       //\r
888       // For bridge, it should support IDE attributes\r
889       //\r
890       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
891       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
892     } else {\r
893 \r
894       if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
895         Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
896         Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
897       }\r
898 \r
899       if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
900         Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
901         Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
902       }\r
903     }\r
904 \r
905     PciIoDevice->Supports = Attributes;\r
906     PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \\r
907                                EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
908                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
909 \r
910   } else {\r
911     PciIoDevice->Attributes = Attributes;\r
912   }\r
913 \r
914   return EFI_SUCCESS;\r
915 }\r
916 \r
917 EFI_STATUS\r
918 GetFastBackToBackSupport (\r
919   IN PCI_IO_DEVICE                      *PciIoDevice,\r
920   IN UINT8                              StatusIndex\r
921   )\r
922 /*++\r
923 \r
924 Routine Description:\r
925 \r
926   Determine if the device can support Fast Back to Back attribute\r
927 \r
928 Arguments:\r
929 \r
930 Returns:\r
931 \r
932   None\r
933 \r
934 --*/\r
935 // TODO:    PciIoDevice - add argument and description to function comment\r
936 // TODO:    StatusIndex - add argument and description to function comment\r
937 // TODO:    EFI_UNSUPPORTED - add return value to function comment\r
938 // TODO:    EFI_SUCCESS - add return value to function comment\r
939 // TODO:    EFI_UNSUPPORTED - add return value to function comment\r
940 {\r
941   EFI_PCI_IO_PROTOCOL *PciIo;\r
942   EFI_STATUS          Status;\r
943   UINT32              StatusRegister;\r
944 \r
945   //\r
946   // Read the status register\r
947   //\r
948   PciIo   = &PciIoDevice->PciIo;\r
949   Status  = PciIoRead (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);\r
950   if (EFI_ERROR (Status)) {\r
951     return EFI_UNSUPPORTED;\r
952   }\r
953 \r
954   //\r
955   // Check the Fast B2B bit\r
956   //\r
957   if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) {\r
958     return EFI_SUCCESS;\r
959   } else {\r
960     return EFI_UNSUPPORTED;\r
961   }\r
962 \r
963 }\r
964 \r
965 STATIC\r
966 EFI_STATUS\r
967 ProcessOptionRomLight (\r
968   IN PCI_IO_DEVICE                      *PciIoDevice\r
969   )\r
970 /*++\r
971 \r
972 Routine Description:\r
973 \r
974   Process the option ROM for all the children of the specified parent PCI device.\r
975   It can only be used after the first full Option ROM process.\r
976 \r
977 Arguments:\r
978 \r
979 Returns:\r
980 \r
981   None\r
982 \r
983 --*/\r
984 // TODO:    PciIoDevice - add argument and description to function comment\r
985 // TODO:    EFI_SUCCESS - add return value to function comment\r
986 {\r
987   PCI_IO_DEVICE   *Temp;\r
988   LIST_ENTRY      *CurrentLink;\r
989 \r
990   //\r
991   // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
992   //\r
993   CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
994   while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
995 \r
996     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
997 \r
998     if (!IsListEmpty (&Temp->ChildList)) {\r
999       ProcessOptionRomLight (Temp);\r
1000     }\r
1001 \r
1002     PciRomGetImageMapping (Temp);\r
1003     CurrentLink = CurrentLink->ForwardLink;\r
1004   }\r
1005 \r
1006   return EFI_SUCCESS;\r
1007 }\r
1008 \r
1009 EFI_STATUS\r
1010 DetermineDeviceAttribute (\r
1011   IN PCI_IO_DEVICE                      *PciIoDevice\r
1012   )\r
1013 /*++\r
1014 \r
1015 Routine Description:\r
1016 \r
1017   Determine the related attributes of all devices under a Root Bridge\r
1018 \r
1019 Arguments:\r
1020 \r
1021 Returns:\r
1022 \r
1023   None\r
1024 \r
1025 --*/\r
1026 // TODO:    PciIoDevice - add argument and description to function comment\r
1027 // TODO:    EFI_SUCCESS - add return value to function comment\r
1028 {\r
1029   UINT16          Command;\r
1030   UINT16          BridgeControl;\r
1031   UINT16          OldCommand;\r
1032   UINT16          OldBridgeControl;\r
1033   BOOLEAN         FastB2BSupport;\r
1034 \r
1035   /*\r
1036   UINT8  IdePI;\r
1037   EFI_PCI_IO_PROTOCOL   *PciIo;\r
1038   */\r
1039   PCI_IO_DEVICE   *Temp;\r
1040   LIST_ENTRY      *CurrentLink;\r
1041   EFI_STATUS      Status;\r
1042 \r
1043   //\r
1044   // For Root Bridge, just copy it by RootBridgeIo proctocol\r
1045   // so as to keep consistent with the actual attribute\r
1046   //\r
1047   if (!PciIoDevice->Parent) {\r
1048     Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1049                                             PciIoDevice->PciRootBridgeIo,\r
1050                                             &PciIoDevice->Supports,\r
1051                                             &PciIoDevice->Attributes\r
1052                                             );\r
1053     if (EFI_ERROR (Status)) {\r
1054       return Status;\r
1055     }\r
1056   } else {\r
1057 \r
1058     //\r
1059     // Set the attributes to be checked for common PCI devices and PPB or P2C\r
1060     // Since some devices only support part of them, it is better to set the\r
1061     // attribute according to its command or bridge control register\r
1062     //\r
1063     Command = EFI_PCI_COMMAND_IO_SPACE     |\r
1064               EFI_PCI_COMMAND_MEMORY_SPACE |\r
1065               EFI_PCI_COMMAND_BUS_MASTER   |\r
1066               EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1067 \r
1068     BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1069 \r
1070     //\r
1071     // Test whether the device can support attributes above\r
1072     //\r
1073     PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
1074 \r
1075     //\r
1076     // Set the supported attributes for specified PCI device\r
1077     //\r
1078     PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
1079 \r
1080     //\r
1081     // Set the current attributes for specified PCI device\r
1082     //\r
1083     PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
1084 \r
1085     //\r
1086     // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
1087     //\r
1088     PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
1089 \r
1090     //\r
1091     // Enable IDE native mode\r
1092     //\r
1093     /*\r
1094     if (IS_PCI_IDE(&PciIoDevice->Pci)) {\r
1095 \r
1096       PciIo = &PciIoDevice->PciIo;\r
1097 \r
1098       PciIoRead (\r
1099                               PciIo,\r
1100                               EfiPciIoWidthUint8,\r
1101                               0x09,\r
1102                               1,\r
1103                               &IdePI\r
1104                               );\r
1105 \r
1106       //\r
1107       // Set native mode if it can be supported\r
1108       //\r
1109       IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);\r
1110 \r
1111       PciIoWrite (\r
1112                               PciIo,\r
1113                               EfiPciIoWidthUint8,\r
1114                               0x09,\r
1115                               1,\r
1116                               &IdePI\r
1117                               );\r
1118 \r
1119     }\r
1120     */\r
1121   }\r
1122 \r
1123   FastB2BSupport = TRUE;\r
1124 \r
1125   //\r
1126   // P2C can not support FB2B on the secondary side\r
1127   //\r
1128   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1129     FastB2BSupport = FALSE;\r
1130   }\r
1131 \r
1132   //\r
1133   // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1134   //\r
1135   CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1136   while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1137 \r
1138     Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1139     Status  = DetermineDeviceAttribute (Temp);\r
1140     if (EFI_ERROR (Status)) {\r
1141       return Status;\r
1142     }\r
1143     //\r
1144     // Detect Fast Bact to Bact support for the device under the bridge\r
1145     //\r
1146     Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
1147     if (FastB2BSupport && EFI_ERROR (Status)) {\r
1148       FastB2BSupport = FALSE;\r
1149     }\r
1150 \r
1151     CurrentLink = CurrentLink->ForwardLink;\r
1152   }\r
1153   //\r
1154   // Set or clear Fast Back to Back bit for the whole bridge\r
1155   //\r
1156   if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
1157 \r
1158     if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
1159 \r
1160       Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
1161 \r
1162       if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
1163         FastB2BSupport = FALSE;\r
1164         PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1165       } else {\r
1166         PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1167       }\r
1168     }\r
1169 \r
1170     CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1171     while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1172       Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1173       if (FastB2BSupport) {\r
1174         PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1175       } else {\r
1176         PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1177       }\r
1178 \r
1179       CurrentLink = CurrentLink->ForwardLink;\r
1180     }\r
1181   }\r
1182   //\r
1183   // End for IsListEmpty\r
1184   //\r
1185   return EFI_SUCCESS;\r
1186 }\r
1187 \r
1188 EFI_STATUS\r
1189 UpdatePciInfo (\r
1190   IN PCI_IO_DEVICE  *PciIoDevice\r
1191   )\r
1192 /*++\r
1193 \r
1194 Routine Description:\r
1195 \r
1196   This routine is used to update the bar information for those incompatible PCI device\r
1197 \r
1198 Arguments:\r
1199 \r
1200 Returns:\r
1201 \r
1202   None\r
1203 \r
1204 --*/\r
1205 // TODO:    PciIoDevice - add argument and description to function comment\r
1206 // TODO:    EFI_UNSUPPORTED - add return value to function comment\r
1207 {\r
1208   EFI_STATUS                        Status;\r
1209   UINTN                             BarIndex;\r
1210   UINTN                             BarEndIndex;\r
1211   BOOLEAN                           SetFlag;\r
1212   EFI_PCI_DEVICE_INFO               PciDeviceInfo;\r
1213   VOID                              *Configuration;\r
1214   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1215 \r
1216   Configuration = NULL;\r
1217   Status        = EFI_SUCCESS;\r
1218 \r
1219   if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
1220     //\r
1221     // It can only be supported after the Incompatible PCI Device\r
1222     // Support Protocol has been installed\r
1223     //\r
1224     Status = gBS->LocateProtocol (\r
1225                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
1226                     NULL,\r
1227                     (VOID **) &gEfiIncompatiblePciDeviceSupport\r
1228                     );\r
1229   }\r
1230   if (Status == EFI_SUCCESS) {\r
1231       //\r
1232       // Check whether the device belongs to incompatible devices from protocol or not\r
1233       // If it is , then get its special requirement in the ACPI table\r
1234       //\r
1235       Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
1236                                                   gEfiIncompatiblePciDeviceSupport,\r
1237                                                   PciIoDevice->Pci.Hdr.VendorId,\r
1238                                                   PciIoDevice->Pci.Hdr.DeviceId,\r
1239                                                   PciIoDevice->Pci.Hdr.RevisionID,\r
1240                                                   PciIoDevice->Pci.Device.SubsystemVendorID,\r
1241                                                   PciIoDevice->Pci.Device.SubsystemID,\r
1242                                                   &Configuration\r
1243                                                   );\r
1244 \r
1245   }\r
1246 \r
1247   if (EFI_ERROR (Status)) {\r
1248     //\r
1249     // Check whether the device belongs to incompatible devices from library or not\r
1250     // If it is , then get its special requirement in the ACPI table\r
1251     //\r
1252     if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {\r
1253       PciDeviceInfo.VendorID          = PciIoDevice->Pci.Hdr.VendorId;\r
1254       PciDeviceInfo.DeviceID          = PciIoDevice->Pci.Hdr.DeviceId;\r
1255       PciDeviceInfo.RevisionID        = PciIoDevice->Pci.Hdr.RevisionID;\r
1256       PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;\r
1257       PciDeviceInfo.SubsystemID       = PciIoDevice->Pci.Device.SubsystemID;\r
1258 \r
1259       Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);\r
1260     }\r
1261   }\r
1262 \r
1263   if (EFI_ERROR (Status)) {\r
1264     return EFI_UNSUPPORTED;\r
1265   }\r
1266 \r
1267   //\r
1268   // Update PCI device information from the ACPI table\r
1269   //\r
1270   Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1271 \r
1272   while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1273 \r
1274     if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1275       //\r
1276       // The format is not support\r
1277       //\r
1278       break;\r
1279     }\r
1280 \r
1281     BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
1282     BarEndIndex = BarIndex;\r
1283 \r
1284     //\r
1285     // Update all the bars in the device\r
1286     //\r
1287     if (BarIndex == PCI_BAR_ALL) {\r
1288       BarIndex    = 0;\r
1289       BarEndIndex = PCI_MAX_BAR - 1;\r
1290     }\r
1291 \r
1292     if (BarIndex >= PCI_MAX_BAR) {\r
1293       Ptr++;\r
1294       continue;\r
1295     }\r
1296 \r
1297     for (; BarIndex <= BarEndIndex; BarIndex++) {\r
1298       SetFlag = FALSE;\r
1299       switch (Ptr->ResType) {\r
1300       case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1301 \r
1302         //\r
1303         // Make sure the bar is memory type\r
1304         //\r
1305         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
1306           SetFlag = TRUE;\r
1307         }\r
1308         break;\r
1309 \r
1310       case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1311 \r
1312         //\r
1313         // Make sure the bar is IO type\r
1314         //\r
1315         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
1316           SetFlag = TRUE;\r
1317         }\r
1318         break;\r
1319       }\r
1320 \r
1321       if (SetFlag) {\r
1322 \r
1323         //\r
1324         // Update the new alignment for the device\r
1325         //\r
1326         SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
1327 \r
1328         //\r
1329         // Update the new length for the device\r
1330         //\r
1331         if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
1332           PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
1333         }\r
1334       }\r
1335     }\r
1336 \r
1337     Ptr++;\r
1338   }\r
1339 \r
1340   gBS->FreePool (Configuration);\r
1341   return Status;\r
1342 \r
1343 }\r
1344 \r
1345 VOID\r
1346 SetNewAlign (\r
1347   IN UINT64 *Alignment,\r
1348   IN UINT64 NewAlignment\r
1349   )\r
1350 /*++\r
1351 \r
1352 Routine Description:\r
1353 \r
1354   This routine will update the alignment with the new alignment\r
1355 \r
1356 Arguments:\r
1357 \r
1358 Returns:\r
1359 \r
1360   None\r
1361 \r
1362 --*/\r
1363 // TODO:    Alignment - add argument and description to function comment\r
1364 // TODO:    NewAlignment - add argument and description to function comment\r
1365 {\r
1366   UINT64  OldAlignment;\r
1367   UINTN   ShiftBit;\r
1368 \r
1369   //\r
1370   // The new alignment is the same as the original,\r
1371   // so skip it\r
1372   //\r
1373   if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
1374     return ;\r
1375   }\r
1376   //\r
1377   // Check the validity of the parameter\r
1378   //\r
1379    if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&\r
1380        NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
1381        NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
1382     *Alignment = NewAlignment;\r
1383     return ;\r
1384   }\r
1385 \r
1386   OldAlignment  = (*Alignment) + 1;\r
1387   ShiftBit      = 0;\r
1388 \r
1389   //\r
1390   // Get the first non-zero hex value of the length\r
1391   //\r
1392   while ((OldAlignment & 0x0F) == 0x00) {\r
1393     OldAlignment = RShiftU64 (OldAlignment, 4);\r
1394     ShiftBit += 4;\r
1395   }\r
1396 \r
1397   //\r
1398   // Adjust the alignment to even, quad or double quad boundary\r
1399   //\r
1400   if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
1401     if (OldAlignment & 0x01) {\r
1402       OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
1403     }\r
1404   } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
1405     if (OldAlignment & 0x03) {\r
1406       OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
1407     }\r
1408   } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
1409     if (OldAlignment & 0x07) {\r
1410       OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
1411     }\r
1412   }\r
1413 \r
1414   //\r
1415   // Update the old value\r
1416   //\r
1417   NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
1418   *Alignment    = NewAlignment;\r
1419 \r
1420   return ;\r
1421 }\r
1422 \r
1423 UINTN\r
1424 PciParseBar (\r
1425   IN PCI_IO_DEVICE  *PciIoDevice,\r
1426   IN UINTN          Offset,\r
1427   IN UINTN          BarIndex\r
1428   )\r
1429 /*++\r
1430 \r
1431 Routine Description:\r
1432 \r
1433 Arguments:\r
1434 \r
1435 Returns:\r
1436 \r
1437   None\r
1438 \r
1439 --*/\r
1440 // TODO:    PciIoDevice - add argument and description to function comment\r
1441 // TODO:    Offset - add argument and description to function comment\r
1442 // TODO:    BarIndex - add argument and description to function comment\r
1443 {\r
1444   UINT32      Value;\r
1445   UINT32      OriginalValue;\r
1446   UINT32      Mask;\r
1447   UINT32      Data;\r
1448   UINT8       Index;\r
1449   EFI_STATUS  Status;\r
1450 \r
1451   OriginalValue = 0;\r
1452   Value         = 0;\r
1453 \r
1454   Status = BarExisted (\r
1455             PciIoDevice,\r
1456             Offset,\r
1457             &Value,\r
1458             &OriginalValue\r
1459             );\r
1460 \r
1461   if (EFI_ERROR (Status)) {\r
1462     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1463     PciIoDevice->PciBar[BarIndex].Length      = 0;\r
1464     PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
1465 \r
1466     //\r
1467     // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
1468     //\r
1469     PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1470     return Offset + 4;\r
1471   }\r
1472 \r
1473   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1474   if (Value & 0x01) {\r
1475     //\r
1476     // Device I/Os\r
1477     //\r
1478     Mask = 0xfffffffc;\r
1479 \r
1480     if (Value & 0xFFFF0000) {\r
1481       //\r
1482       // It is a IO32 bar\r
1483       //\r
1484       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;\r
1485       PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);\r
1486       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1487 \r
1488     } else {\r
1489       //\r
1490       // It is a IO16 bar\r
1491       //\r
1492       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;\r
1493       PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
1494       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1495 \r
1496     }\r
1497     //\r
1498     // Workaround. Some platforms inplement IO bar with 0 length\r
1499     // Need to treat it as no-bar\r
1500     //\r
1501     if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1502       PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
1503     }\r
1504 \r
1505     PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
1506     PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
1507 \r
1508   } else {\r
1509 \r
1510     Mask  = 0xfffffff0;\r
1511 \r
1512     PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1513 \r
1514     switch (Value & 0x07) {\r
1515 \r
1516     //\r
1517     //memory space; anywhere in 32 bit address space\r
1518     //\r
1519     case 0x00:\r
1520       if (Value & 0x08) {\r
1521         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
1522       } else {\r
1523         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
1524       }\r
1525 \r
1526       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
1527       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1528 \r
1529       break;\r
1530 \r
1531     //\r
1532     // memory space; anywhere in 64 bit address space\r
1533     //\r
1534     case 0x04:\r
1535       if (Value & 0x08) {\r
1536         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
1537       } else {\r
1538         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
1539       }\r
1540 \r
1541       //\r
1542       // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
1543       // is regarded as an extension for the first bar. As a result\r
1544       // the sizing will be conducted on combined 64 bit value\r
1545       // Here just store the masked first 32bit value for future size\r
1546       // calculation\r
1547       //\r
1548       PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;\r
1549       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1550 \r
1551       //\r
1552       // Increment the offset to point to next DWORD\r
1553       //\r
1554       Offset += 4;\r
1555 \r
1556       Status = BarExisted (\r
1557                 PciIoDevice,\r
1558                 Offset,\r
1559                 &Value,\r
1560                 &OriginalValue\r
1561                 );\r
1562 \r
1563       if (EFI_ERROR (Status)) {\r
1564         return Offset + 4;\r
1565       }\r
1566 \r
1567       //\r
1568       // Fix the length to support some spefic 64 bit BAR\r
1569       //\r
1570       Data  = Value;\r
1571       Index = 0;\r
1572       for (Data = Value; Data != 0; Data >>= 1) {\r
1573         Index ++;\r
1574       }\r
1575       Value |= ((UINT32)(-1) << Index);\r
1576 \r
1577       //\r
1578       // Calculate the size of 64bit bar\r
1579       //\r
1580       PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
1581 \r
1582       PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
1583       PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
1584       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1585 \r
1586       break;\r
1587 \r
1588     //\r
1589     // reserved\r
1590     //\r
1591     default:\r
1592       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
1593       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
1594       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1595 \r
1596       break;\r
1597     }\r
1598   }\r
1599 \r
1600   //\r
1601   // Check the length again so as to keep compatible with some special bars\r
1602   //\r
1603   if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1604     PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
1605     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1606     PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
1607   }\r
1608 \r
1609   //\r
1610   // Increment number of bar\r
1611   //\r
1612   return Offset + 4;\r
1613 }\r
1614 \r
1615 EFI_STATUS\r
1616 InitializePciDevice (\r
1617   IN PCI_IO_DEVICE *PciIoDevice\r
1618   )\r
1619 /*++\r
1620 \r
1621 Routine Description:\r
1622 \r
1623   This routine is used to initialize the bar of a PCI device\r
1624   It can be called typically when a device is going to be rejected\r
1625 \r
1626 Arguments:\r
1627 \r
1628 Returns:\r
1629 \r
1630   None\r
1631 \r
1632 --*/\r
1633 // TODO:    PciIoDevice - add argument and description to function comment\r
1634 // TODO:    EFI_SUCCESS - add return value to function comment\r
1635 {\r
1636   EFI_PCI_IO_PROTOCOL *PciIo;\r
1637   UINT8               Offset;\r
1638 \r
1639   PciIo = &(PciIoDevice->PciIo);\r
1640 \r
1641   //\r
1642   // Put all the resource apertures\r
1643   // Resource base is set to all ones so as to indicate its resource\r
1644   // has not been alloacted\r
1645   //\r
1646   for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
1647     PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
1648   }\r
1649 \r
1650   return EFI_SUCCESS;\r
1651 }\r
1652 \r
1653 EFI_STATUS\r
1654 InitializePpb (\r
1655   IN PCI_IO_DEVICE *PciIoDevice\r
1656   )\r
1657 /*++\r
1658 \r
1659 Routine Description:\r
1660 \r
1661 Arguments:\r
1662 \r
1663 Returns:\r
1664 \r
1665   None\r
1666 \r
1667 --*/\r
1668 // TODO:    PciIoDevice - add argument and description to function comment\r
1669 // TODO:    EFI_SUCCESS - add return value to function comment\r
1670 {\r
1671   EFI_PCI_IO_PROTOCOL *PciIo;\r
1672 \r
1673   PciIo = &(PciIoDevice->PciIo);\r
1674 \r
1675   //\r
1676   // Put all the resource apertures including IO16\r
1677   // Io32, pMem32, pMem64 to quiescent state\r
1678   // Resource base all ones, Resource limit all zeros\r
1679   //\r
1680   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
1681   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
1682 \r
1683   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
1684   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
1685 \r
1686   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
1687   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
1688 \r
1689   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
1690   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
1691 \r
1692   //\r
1693   // don't support use io32 as for now\r
1694   //\r
1695   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
1696   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
1697 \r
1698   //\r
1699   // Force Interrupt line to zero for cards that come up randomly\r
1700   //\r
1701   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1702 \r
1703   return EFI_SUCCESS;\r
1704 }\r
1705 \r
1706 EFI_STATUS\r
1707 InitializeP2C (\r
1708   IN PCI_IO_DEVICE *PciIoDevice\r
1709   )\r
1710 /*++\r
1711 \r
1712 Routine Description:\r
1713 \r
1714 Arguments:\r
1715 \r
1716 Returns:\r
1717 \r
1718   None\r
1719 \r
1720 --*/\r
1721 // TODO:    PciIoDevice - add argument and description to function comment\r
1722 // TODO:    EFI_SUCCESS - add return value to function comment\r
1723 {\r
1724   EFI_PCI_IO_PROTOCOL *PciIo;\r
1725 \r
1726   PciIo = &(PciIoDevice->PciIo);\r
1727 \r
1728   //\r
1729   // Put all the resource apertures including IO16\r
1730   // Io32, pMem32, pMem64 to quiescent state(\r
1731   // Resource base all ones, Resource limit all zeros\r
1732   //\r
1733   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
1734   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
1735 \r
1736   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
1737   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
1738 \r
1739   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
1740   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
1741 \r
1742   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
1743   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
1744 \r
1745   //\r
1746   // Force Interrupt line to zero for cards that come up randomly\r
1747   //\r
1748   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1749   return EFI_SUCCESS;\r
1750 }\r
1751 \r
1752 PCI_IO_DEVICE *\r
1753 CreatePciIoDevice (\r
1754   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
1755   IN PCI_TYPE00                       *Pci,\r
1756   UINT8                               Bus,\r
1757   UINT8                               Device,\r
1758   UINT8                               Func\r
1759   )\r
1760 /*++\r
1761 \r
1762 Routine Description:\r
1763 \r
1764 Arguments:\r
1765 \r
1766 Returns:\r
1767 \r
1768   None\r
1769 \r
1770 --*/\r
1771 // TODO:    PciRootBridgeIo - add argument and description to function comment\r
1772 // TODO:    Pci - add argument and description to function comment\r
1773 // TODO:    Bus - add argument and description to function comment\r
1774 // TODO:    Device - add argument and description to function comment\r
1775 // TODO:    Func - add argument and description to function comment\r
1776 {\r
1777 \r
1778   EFI_STATUS    Status;\r
1779   PCI_IO_DEVICE *PciIoDevice;\r
1780 \r
1781   PciIoDevice = NULL;\r
1782 \r
1783   Status = gBS->AllocatePool (\r
1784                   EfiBootServicesData,\r
1785                   sizeof (PCI_IO_DEVICE),\r
1786                   (VOID **) &PciIoDevice\r
1787                   );\r
1788 \r
1789   if (EFI_ERROR (Status)) {\r
1790     return NULL;\r
1791   }\r
1792 \r
1793   ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
1794 \r
1795   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
1796   PciIoDevice->Handle           = NULL;\r
1797   PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
1798   PciIoDevice->DevicePath       = NULL;\r
1799   PciIoDevice->BusNumber        = Bus;\r
1800   PciIoDevice->DeviceNumber     = Device;\r
1801   PciIoDevice->FunctionNumber   = Func;\r
1802   PciIoDevice->Decodes          = 0;\r
1803   if (gFullEnumeration) {\r
1804     PciIoDevice->Allocated = FALSE;\r
1805   } else {\r
1806     PciIoDevice->Allocated = TRUE;\r
1807   }\r
1808 \r
1809   PciIoDevice->Registered         = FALSE;\r
1810   PciIoDevice->Attributes         = 0;\r
1811   PciIoDevice->Supports           = 0;\r
1812   PciIoDevice->BusOverride        = FALSE;\r
1813   PciIoDevice->AllOpRomProcessed  = FALSE;\r
1814 \r
1815   PciIoDevice->IsPciExp           = FALSE;\r
1816 \r
1817   CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
1818 \r
1819   //\r
1820   // Initialize the PCI I/O instance structure\r
1821   //\r
1822 \r
1823   Status  = InitializePciIoInstance (PciIoDevice);\r
1824   Status  = InitializePciDriverOverrideInstance (PciIoDevice);\r
1825 \r
1826   if (EFI_ERROR (Status)) {\r
1827     gBS->FreePool (PciIoDevice);\r
1828     return NULL;\r
1829   }\r
1830 \r
1831   //\r
1832   // Initialize the reserved resource list\r
1833   //\r
1834   InitializeListHead (&PciIoDevice->ReservedResourceList);\r
1835 \r
1836   //\r
1837   // Initialize the driver list\r
1838   //\r
1839   InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
1840 \r
1841   //\r
1842   // Initialize the child list\r
1843   //\r
1844   InitializeListHead (&PciIoDevice->ChildList);\r
1845 \r
1846   return PciIoDevice;\r
1847 }\r
1848 \r
1849 EFI_STATUS\r
1850 PciEnumeratorLight (\r
1851   IN EFI_HANDLE                    Controller\r
1852   )\r
1853 /*++\r
1854 \r
1855 Routine Description:\r
1856 \r
1857   This routine is used to enumerate entire pci bus system\r
1858   in a given platform\r
1859 \r
1860 Arguments:\r
1861 \r
1862 Returns:\r
1863 \r
1864   None\r
1865 \r
1866 --*/\r
1867 // TODO:    Controller - add argument and description to function comment\r
1868 // TODO:    EFI_SUCCESS - add return value to function comment\r
1869 // TODO:    EFI_SUCCESS - add return value to function comment\r
1870 {\r
1871 \r
1872   EFI_STATUS                        Status;\r
1873   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
1874   PCI_IO_DEVICE                     *RootBridgeDev;\r
1875   UINT16                            MinBus;\r
1876   UINT16                            MaxBus;\r
1877   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1878 \r
1879   MinBus      = 0;\r
1880   MaxBus      = PCI_MAX_BUS;\r
1881   Descriptors = NULL;\r
1882 \r
1883   //\r
1884   // If this host bridge has been already enumerated, then return successfully\r
1885   //\r
1886   if (RootBridgeExisted (Controller)) {\r
1887     return EFI_SUCCESS;\r
1888   }\r
1889 \r
1890   //\r
1891   // Open pci root bridge io protocol\r
1892   //\r
1893   Status = gBS->OpenProtocol (\r
1894                   Controller,\r
1895                   &gEfiPciRootBridgeIoProtocolGuid,\r
1896                   (VOID **) &PciRootBridgeIo,\r
1897                   gPciBusDriverBinding.DriverBindingHandle,\r
1898                   Controller,\r
1899                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
1900                   );\r
1901   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
1902     return Status;\r
1903   }\r
1904 \r
1905   Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1906 \r
1907   if (EFI_ERROR (Status)) {\r
1908     return Status;\r
1909   }\r
1910 \r
1911   while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
1912 \r
1913     //\r
1914     // Create a device node for root bridge device with a NULL host bridge controller handle\r
1915     //\r
1916     RootBridgeDev = CreateRootBridge (Controller);\r
1917 \r
1918     if (!RootBridgeDev) {\r
1919       Descriptors++;\r
1920       continue;\r
1921     }\r
1922 \r
1923     //\r
1924     // Record the root bridge io protocol\r
1925     //\r
1926     RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
1927 \r
1928     Status = PciPciDeviceInfoCollector (\r
1929               RootBridgeDev,\r
1930               (UINT8) MinBus\r
1931               );\r
1932 \r
1933     if (!EFI_ERROR (Status)) {\r
1934 \r
1935       //\r
1936       // Remove those PCI devices which are rejected when full enumeration\r
1937       //\r
1938       RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
1939 \r
1940       //\r
1941       // Process option rom light\r
1942       //\r
1943       ProcessOptionRomLight (RootBridgeDev);\r
1944 \r
1945       //\r
1946       // Determine attributes for all devices under this root bridge\r
1947       //\r
1948       DetermineDeviceAttribute (RootBridgeDev);\r
1949 \r
1950       //\r
1951       // If successfully, insert the node into device pool\r
1952       //\r
1953       InsertRootBridge (RootBridgeDev);\r
1954     } else {\r
1955 \r
1956       //\r
1957       // If unsuccessly, destroy the entire node\r
1958       //\r
1959       DestroyRootBridge (RootBridgeDev);\r
1960     }\r
1961 \r
1962     Descriptors++;\r
1963   }\r
1964 \r
1965   return EFI_SUCCESS;\r
1966 }\r
1967 \r
1968 EFI_STATUS\r
1969 PciGetBusRange (\r
1970   IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,\r
1971   OUT    UINT16                             *MinBus,\r
1972   OUT    UINT16                             *MaxBus,\r
1973   OUT    UINT16                             *BusRange\r
1974   )\r
1975 /*++\r
1976 \r
1977 Routine Description:\r
1978 \r
1979   Get the bus range.\r
1980 \r
1981 Arguments:\r
1982 \r
1983   Descriptors     - A pointer to the address space descriptor.\r
1984   MinBus          - The min bus.\r
1985   MaxBus          - The max bus.\r
1986   BusRange        - The bus range.\r
1987 \r
1988 Returns:\r
1989 \r
1990   Status Code.\r
1991 \r
1992 --*/\r
1993 // TODO:    EFI_SUCCESS - add return value to function comment\r
1994 // TODO:    EFI_NOT_FOUND - add return value to function comment\r
1995 {\r
1996 \r
1997   while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1998     if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
1999       if (MinBus != NULL) {\r
2000         *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
2001       }\r
2002 \r
2003       if (MaxBus != NULL) {\r
2004         *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
2005       }\r
2006 \r
2007       if (BusRange != NULL) {\r
2008         *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
2009       }\r
2010 \r
2011       return EFI_SUCCESS;\r
2012     }\r
2013 \r
2014     (*Descriptors)++;\r
2015   }\r
2016 \r
2017   return EFI_NOT_FOUND;\r
2018 }\r
2019 \r
2020 EFI_STATUS\r
2021 StartManagingRootBridge (\r
2022   IN PCI_IO_DEVICE *RootBridgeDev\r
2023   )\r
2024 /*++\r
2025 \r
2026 Routine Description:\r
2027 \r
2028 \r
2029 Arguments:\r
2030 \r
2031 Returns:\r
2032 \r
2033   None\r
2034 \r
2035 --*/\r
2036 // TODO:    RootBridgeDev - add argument and description to function comment\r
2037 // TODO:    EFI_SUCCESS - add return value to function comment\r
2038 {\r
2039   EFI_HANDLE                      RootBridgeHandle;\r
2040   EFI_STATUS                      Status;\r
2041   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2042 \r
2043   //\r
2044   // Get the root bridge handle\r
2045   //\r
2046   RootBridgeHandle  = RootBridgeDev->Handle;\r
2047   PciRootBridgeIo   = NULL;\r
2048 \r
2049   //\r
2050   // Get the pci root bridge io protocol\r
2051   //\r
2052   Status = gBS->OpenProtocol (\r
2053                   RootBridgeHandle,\r
2054                   &gEfiPciRootBridgeIoProtocolGuid,\r
2055                   (VOID **) &PciRootBridgeIo,\r
2056                   gPciBusDriverBinding.DriverBindingHandle,\r
2057                   RootBridgeHandle,\r
2058                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
2059                   );\r
2060 \r
2061   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
2062     return Status;\r
2063   }\r
2064 \r
2065   //\r
2066   // Store the PciRootBridgeIo protocol into root bridge private data\r
2067   //\r
2068   RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
2069 \r
2070   return EFI_SUCCESS;\r
2071 \r
2072 }\r
2073 \r
2074 BOOLEAN\r
2075 IsPciDeviceRejected (\r
2076   IN PCI_IO_DEVICE *PciIoDevice\r
2077   )\r
2078 /*++\r
2079 \r
2080 Routine Description:\r
2081 \r
2082   This routine can be used to check whether a PCI device should be rejected when light enumeration\r
2083 \r
2084 Arguments:\r
2085 \r
2086 Returns:\r
2087 \r
2088   TRUE      This device should be rejected\r
2089   FALSE     This device shouldn't be rejected\r
2090 \r
2091 --*/\r
2092 // TODO:    PciIoDevice - add argument and description to function comment\r
2093 {\r
2094   EFI_STATUS  Status;\r
2095   UINT32      TestValue;\r
2096   UINT32      OldValue;\r
2097   UINT32      Mask;\r
2098   UINT8       BarOffset;\r
2099 \r
2100   //\r
2101   // PPB should be skip!\r
2102   //\r
2103   if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
2104     return FALSE;\r
2105   }\r
2106 \r
2107   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
2108     //\r
2109     // Only test base registers for P2C\r
2110     //\r
2111     for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
2112 \r
2113       Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
2114       Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2115       if (EFI_ERROR (Status)) {\r
2116         continue;\r
2117       }\r
2118 \r
2119       TestValue = TestValue & Mask;\r
2120       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2121         //\r
2122         // The bar isn't programed, so it should be rejected\r
2123         //\r
2124         return TRUE;\r
2125       }\r
2126     }\r
2127 \r
2128     return FALSE;\r
2129   }\r
2130 \r
2131   for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
2132     //\r
2133     // Test PCI devices\r
2134     //\r
2135     Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2136     if (EFI_ERROR (Status)) {\r
2137       continue;\r
2138     }\r
2139 \r
2140     if (TestValue & 0x01) {\r
2141 \r
2142       //\r
2143       // IO Bar\r
2144       //\r
2145 \r
2146       Mask      = 0xFFFFFFFC;\r
2147       TestValue = TestValue & Mask;\r
2148       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2149         return TRUE;\r
2150       }\r
2151 \r
2152     } else {\r
2153 \r
2154       //\r
2155       // Mem Bar\r
2156       //\r
2157 \r
2158       Mask      = 0xFFFFFFF0;\r
2159       TestValue = TestValue & Mask;\r
2160 \r
2161       if ((TestValue & 0x07) == 0x04) {\r
2162 \r
2163         //\r
2164         // Mem64 or PMem64\r
2165         //\r
2166         BarOffset += sizeof (UINT32);\r
2167         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2168 \r
2169           //\r
2170           // Test its high 32-Bit BAR\r
2171           //\r
2172 \r
2173           Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2174           if (TestValue == OldValue) {\r
2175             return TRUE;\r
2176           }\r
2177         }\r
2178 \r
2179       } else {\r
2180 \r
2181         //\r
2182         // Mem32 or PMem32\r
2183         //\r
2184         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2185           return TRUE;\r
2186         }\r
2187       }\r
2188     }\r
2189   }\r
2190 \r
2191   return FALSE;\r
2192 }\r
2193 \r
2194 EFI_STATUS\r
2195 ResetAllPpbBusNumber (\r
2196   IN PCI_IO_DEVICE                      *Bridge,\r
2197   IN UINT8                              StartBusNumber\r
2198   )\r
2199 /*++\r
2200 \r
2201 Routine Description:\r
2202 \r
2203   TODO: Add function description\r
2204 \r
2205 Arguments:\r
2206 \r
2207   Bridge          - TODO: add argument description\r
2208   StartBusNumber  - TODO: add argument description\r
2209 \r
2210 Returns:\r
2211 \r
2212   EFI_SUCCESS - TODO: Add description for return value\r
2213 \r
2214 --*/\r
2215 {\r
2216   EFI_STATUS                      Status;\r
2217   PCI_TYPE00                      Pci;\r
2218   UINT8                           Device;\r
2219   UINT32                          Register;\r
2220   UINT8                           Func;\r
2221   UINT64                          Address;\r
2222   UINT8                           SecondaryBus;\r
2223   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2224 \r
2225   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
2226 \r
2227   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
2228     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
2229 \r
2230       //\r
2231       // Check to see whether a pci device is present\r
2232       //\r
2233       Status = PciDevicePresent (\r
2234                 PciRootBridgeIo,\r
2235                 &Pci,\r
2236                 StartBusNumber,\r
2237                 Device,\r
2238                 Func\r
2239                 );\r
2240 \r
2241       if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
2242 \r
2243         Register  = 0;\r
2244         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
2245         Status   = PciRootBridgeIoRead (\r
2246                                         PciRootBridgeIo,\r
2247                                         &Pci,\r
2248                                         EfiPciWidthUint32,\r
2249                                         Address,\r
2250                                         1,\r
2251                                         &Register\r
2252                                         );\r
2253         SecondaryBus = (UINT8)(Register >> 8);\r
2254 \r
2255         if (SecondaryBus != 0) {\r
2256           ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
2257         }\r
2258 \r
2259         //\r
2260         // Reset register 18h, 19h, 1Ah on PCI Bridge\r
2261         //\r
2262         Register &= 0xFF000000;\r
2263         Status = PciRootBridgeIoWrite (\r
2264                                         PciRootBridgeIo,\r
2265                                         &Pci,\r
2266                                         EfiPciWidthUint32,\r
2267                                         Address,\r
2268                                         1,\r
2269                                         &Register\r
2270                                         );\r
2271       }\r
2272 \r
2273       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
2274         //\r
2275         // Skip sub functions, this is not a multi function device\r
2276         //\r
2277         Func = PCI_MAX_FUNC;\r
2278       }\r
2279     }\r
2280   }\r
2281 \r
2282   return EFI_SUCCESS;\r
2283 }\r
2284 \r