Produce all the PciIo & Dpath protocol for all the pci devices under the current...
[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 \r
1004     //\r
1005     // The OpRom has already been processed in the first round\r
1006     //\r
1007     Temp->AllOpRomProcessed = TRUE;\r
1008 \r
1009     CurrentLink = CurrentLink->ForwardLink;\r
1010   }\r
1011 \r
1012   return EFI_SUCCESS;\r
1013 }\r
1014 \r
1015 EFI_STATUS\r
1016 DetermineDeviceAttribute (\r
1017   IN PCI_IO_DEVICE                      *PciIoDevice\r
1018   )\r
1019 /*++\r
1020 \r
1021 Routine Description:\r
1022 \r
1023   Determine the related attributes of all devices under a Root Bridge\r
1024 \r
1025 Arguments:\r
1026 \r
1027 Returns:\r
1028 \r
1029   None\r
1030 \r
1031 --*/\r
1032 // TODO:    PciIoDevice - add argument and description to function comment\r
1033 // TODO:    EFI_SUCCESS - add return value to function comment\r
1034 {\r
1035   UINT16          Command;\r
1036   UINT16          BridgeControl;\r
1037   UINT16          OldCommand;\r
1038   UINT16          OldBridgeControl;\r
1039   BOOLEAN         FastB2BSupport;\r
1040 \r
1041   /*\r
1042   UINT8  IdePI;\r
1043   EFI_PCI_IO_PROTOCOL   *PciIo;\r
1044   */\r
1045   PCI_IO_DEVICE   *Temp;\r
1046   LIST_ENTRY      *CurrentLink;\r
1047   EFI_STATUS      Status;\r
1048 \r
1049   //\r
1050   // For Root Bridge, just copy it by RootBridgeIo proctocol\r
1051   // so as to keep consistent with the actual attribute\r
1052   //\r
1053   if (!PciIoDevice->Parent) {\r
1054     Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1055                                             PciIoDevice->PciRootBridgeIo,\r
1056                                             &PciIoDevice->Supports,\r
1057                                             &PciIoDevice->Attributes\r
1058                                             );\r
1059     if (EFI_ERROR (Status)) {\r
1060       return Status;\r
1061     }\r
1062   } else {\r
1063 \r
1064     //\r
1065     // Set the attributes to be checked for common PCI devices and PPB or P2C\r
1066     // Since some devices only support part of them, it is better to set the\r
1067     // attribute according to its command or bridge control register\r
1068     //\r
1069     Command = EFI_PCI_COMMAND_IO_SPACE     |\r
1070               EFI_PCI_COMMAND_MEMORY_SPACE |\r
1071               EFI_PCI_COMMAND_BUS_MASTER   |\r
1072               EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1073 \r
1074     BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1075 \r
1076     //\r
1077     // Test whether the device can support attributes above\r
1078     //\r
1079     PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
1080 \r
1081     //\r
1082     // Set the supported attributes for specified PCI device\r
1083     //\r
1084     PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
1085 \r
1086     //\r
1087     // Set the current attributes for specified PCI device\r
1088     //\r
1089     PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
1090 \r
1091     //\r
1092     // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
1093     //\r
1094     PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
1095 \r
1096     //\r
1097     // Enable IDE native mode\r
1098     //\r
1099     /*\r
1100     if (IS_PCI_IDE(&PciIoDevice->Pci)) {\r
1101 \r
1102       PciIo = &PciIoDevice->PciIo;\r
1103 \r
1104       PciIoRead (\r
1105                               PciIo,\r
1106                               EfiPciIoWidthUint8,\r
1107                               0x09,\r
1108                               1,\r
1109                               &IdePI\r
1110                               );\r
1111 \r
1112       //\r
1113       // Set native mode if it can be supported\r
1114       //\r
1115       IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);\r
1116 \r
1117       PciIoWrite (\r
1118                               PciIo,\r
1119                               EfiPciIoWidthUint8,\r
1120                               0x09,\r
1121                               1,\r
1122                               &IdePI\r
1123                               );\r
1124 \r
1125     }\r
1126     */\r
1127   }\r
1128 \r
1129   FastB2BSupport = TRUE;\r
1130 \r
1131   //\r
1132   // P2C can not support FB2B on the secondary side\r
1133   //\r
1134   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1135     FastB2BSupport = FALSE;\r
1136   }\r
1137 \r
1138   //\r
1139   // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1140   //\r
1141   CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1142   while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1143 \r
1144     Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1145     Status  = DetermineDeviceAttribute (Temp);\r
1146     if (EFI_ERROR (Status)) {\r
1147       return Status;\r
1148     }\r
1149     //\r
1150     // Detect Fast Bact to Bact support for the device under the bridge\r
1151     //\r
1152     Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
1153     if (FastB2BSupport && EFI_ERROR (Status)) {\r
1154       FastB2BSupport = FALSE;\r
1155     }\r
1156 \r
1157     CurrentLink = CurrentLink->ForwardLink;\r
1158   }\r
1159   //\r
1160   // Set or clear Fast Back to Back bit for the whole bridge\r
1161   //\r
1162   if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
1163 \r
1164     if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
1165 \r
1166       Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
1167 \r
1168       if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
1169         FastB2BSupport = FALSE;\r
1170         PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1171       } else {\r
1172         PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1173       }\r
1174     }\r
1175 \r
1176     CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1177     while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1178       Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1179       if (FastB2BSupport) {\r
1180         PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1181       } else {\r
1182         PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1183       }\r
1184 \r
1185       CurrentLink = CurrentLink->ForwardLink;\r
1186     }\r
1187   }\r
1188   //\r
1189   // End for IsListEmpty\r
1190   //\r
1191   return EFI_SUCCESS;\r
1192 }\r
1193 \r
1194 EFI_STATUS\r
1195 UpdatePciInfo (\r
1196   IN PCI_IO_DEVICE  *PciIoDevice\r
1197   )\r
1198 /*++\r
1199 \r
1200 Routine Description:\r
1201 \r
1202   This routine is used to update the bar information for those incompatible PCI device\r
1203 \r
1204 Arguments:\r
1205 \r
1206 Returns:\r
1207 \r
1208   None\r
1209 \r
1210 --*/\r
1211 // TODO:    PciIoDevice - add argument and description to function comment\r
1212 // TODO:    EFI_UNSUPPORTED - add return value to function comment\r
1213 {\r
1214   EFI_STATUS                        Status;\r
1215   UINTN                             BarIndex;\r
1216   UINTN                             BarEndIndex;\r
1217   BOOLEAN                           SetFlag;\r
1218   EFI_PCI_DEVICE_INFO               PciDeviceInfo;\r
1219   VOID                              *Configuration;\r
1220   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1221 \r
1222   Configuration = NULL;\r
1223   Status        = EFI_SUCCESS;\r
1224 \r
1225   if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
1226     //\r
1227     // It can only be supported after the Incompatible PCI Device\r
1228     // Support Protocol has been installed\r
1229     //\r
1230     Status = gBS->LocateProtocol (\r
1231                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
1232                     NULL,\r
1233                     (VOID **) &gEfiIncompatiblePciDeviceSupport\r
1234                     );\r
1235   }\r
1236   if (Status == EFI_SUCCESS) {\r
1237       //\r
1238       // Check whether the device belongs to incompatible devices from protocol or not\r
1239       // If it is , then get its special requirement in the ACPI table\r
1240       //\r
1241       Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
1242                                                   gEfiIncompatiblePciDeviceSupport,\r
1243                                                   PciIoDevice->Pci.Hdr.VendorId,\r
1244                                                   PciIoDevice->Pci.Hdr.DeviceId,\r
1245                                                   PciIoDevice->Pci.Hdr.RevisionID,\r
1246                                                   PciIoDevice->Pci.Device.SubsystemVendorID,\r
1247                                                   PciIoDevice->Pci.Device.SubsystemID,\r
1248                                                   &Configuration\r
1249                                                   );\r
1250 \r
1251   }\r
1252 \r
1253   if (EFI_ERROR (Status)) {\r
1254     //\r
1255     // Check whether the device belongs to incompatible devices from library or not\r
1256     // If it is , then get its special requirement in the ACPI table\r
1257     //\r
1258     if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {\r
1259       PciDeviceInfo.VendorID          = PciIoDevice->Pci.Hdr.VendorId;\r
1260       PciDeviceInfo.DeviceID          = PciIoDevice->Pci.Hdr.DeviceId;\r
1261       PciDeviceInfo.RevisionID        = PciIoDevice->Pci.Hdr.RevisionID;\r
1262       PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;\r
1263       PciDeviceInfo.SubsystemID       = PciIoDevice->Pci.Device.SubsystemID;\r
1264 \r
1265       Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);\r
1266     }\r
1267   }\r
1268 \r
1269   if (EFI_ERROR (Status)) {\r
1270     return EFI_UNSUPPORTED;\r
1271   }\r
1272 \r
1273   //\r
1274   // Update PCI device information from the ACPI table\r
1275   //\r
1276   Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1277 \r
1278   while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1279 \r
1280     if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1281       //\r
1282       // The format is not support\r
1283       //\r
1284       break;\r
1285     }\r
1286 \r
1287     BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
1288     BarEndIndex = BarIndex;\r
1289 \r
1290     //\r
1291     // Update all the bars in the device\r
1292     //\r
1293     if (BarIndex == PCI_BAR_ALL) {\r
1294       BarIndex    = 0;\r
1295       BarEndIndex = PCI_MAX_BAR - 1;\r
1296     }\r
1297 \r
1298     if (BarIndex >= PCI_MAX_BAR) {\r
1299       Ptr++;\r
1300       continue;\r
1301     }\r
1302 \r
1303     for (; BarIndex <= BarEndIndex; BarIndex++) {\r
1304       SetFlag = FALSE;\r
1305       switch (Ptr->ResType) {\r
1306       case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1307 \r
1308         //\r
1309         // Make sure the bar is memory type\r
1310         //\r
1311         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
1312           SetFlag = TRUE;\r
1313         }\r
1314         break;\r
1315 \r
1316       case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1317 \r
1318         //\r
1319         // Make sure the bar is IO type\r
1320         //\r
1321         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
1322           SetFlag = TRUE;\r
1323         }\r
1324         break;\r
1325       }\r
1326 \r
1327       if (SetFlag) {\r
1328 \r
1329         //\r
1330         // Update the new alignment for the device\r
1331         //\r
1332         SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
1333 \r
1334         //\r
1335         // Update the new length for the device\r
1336         //\r
1337         if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
1338           PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
1339         }\r
1340       }\r
1341     }\r
1342 \r
1343     Ptr++;\r
1344   }\r
1345 \r
1346   gBS->FreePool (Configuration);\r
1347   return Status;\r
1348 \r
1349 }\r
1350 \r
1351 VOID\r
1352 SetNewAlign (\r
1353   IN UINT64 *Alignment,\r
1354   IN UINT64 NewAlignment\r
1355   )\r
1356 /*++\r
1357 \r
1358 Routine Description:\r
1359 \r
1360   This routine will update the alignment with the new alignment\r
1361 \r
1362 Arguments:\r
1363 \r
1364 Returns:\r
1365 \r
1366   None\r
1367 \r
1368 --*/\r
1369 // TODO:    Alignment - add argument and description to function comment\r
1370 // TODO:    NewAlignment - add argument and description to function comment\r
1371 {\r
1372   UINT64  OldAlignment;\r
1373   UINTN   ShiftBit;\r
1374 \r
1375   //\r
1376   // The new alignment is the same as the original,\r
1377   // so skip it\r
1378   //\r
1379   if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
1380     return ;\r
1381   }\r
1382   //\r
1383   // Check the validity of the parameter\r
1384   //\r
1385    if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&\r
1386        NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
1387        NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
1388     *Alignment = NewAlignment;\r
1389     return ;\r
1390   }\r
1391 \r
1392   OldAlignment  = (*Alignment) + 1;\r
1393   ShiftBit      = 0;\r
1394 \r
1395   //\r
1396   // Get the first non-zero hex value of the length\r
1397   //\r
1398   while ((OldAlignment & 0x0F) == 0x00) {\r
1399     OldAlignment = RShiftU64 (OldAlignment, 4);\r
1400     ShiftBit += 4;\r
1401   }\r
1402 \r
1403   //\r
1404   // Adjust the alignment to even, quad or double quad boundary\r
1405   //\r
1406   if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
1407     if (OldAlignment & 0x01) {\r
1408       OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
1409     }\r
1410   } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
1411     if (OldAlignment & 0x03) {\r
1412       OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
1413     }\r
1414   } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
1415     if (OldAlignment & 0x07) {\r
1416       OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
1417     }\r
1418   }\r
1419 \r
1420   //\r
1421   // Update the old value\r
1422   //\r
1423   NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
1424   *Alignment    = NewAlignment;\r
1425 \r
1426   return ;\r
1427 }\r
1428 \r
1429 UINTN\r
1430 PciParseBar (\r
1431   IN PCI_IO_DEVICE  *PciIoDevice,\r
1432   IN UINTN          Offset,\r
1433   IN UINTN          BarIndex\r
1434   )\r
1435 /*++\r
1436 \r
1437 Routine Description:\r
1438 \r
1439 Arguments:\r
1440 \r
1441 Returns:\r
1442 \r
1443   None\r
1444 \r
1445 --*/\r
1446 // TODO:    PciIoDevice - add argument and description to function comment\r
1447 // TODO:    Offset - add argument and description to function comment\r
1448 // TODO:    BarIndex - add argument and description to function comment\r
1449 {\r
1450   UINT32      Value;\r
1451   UINT32      OriginalValue;\r
1452   UINT32      Mask;\r
1453   UINT32      Data;\r
1454   UINT8       Index;\r
1455   EFI_STATUS  Status;\r
1456 \r
1457   OriginalValue = 0;\r
1458   Value         = 0;\r
1459 \r
1460   Status = BarExisted (\r
1461             PciIoDevice,\r
1462             Offset,\r
1463             &Value,\r
1464             &OriginalValue\r
1465             );\r
1466 \r
1467   if (EFI_ERROR (Status)) {\r
1468     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1469     PciIoDevice->PciBar[BarIndex].Length      = 0;\r
1470     PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
1471 \r
1472     //\r
1473     // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
1474     //\r
1475     PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1476     return Offset + 4;\r
1477   }\r
1478 \r
1479   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1480   if (Value & 0x01) {\r
1481     //\r
1482     // Device I/Os\r
1483     //\r
1484     Mask = 0xfffffffc;\r
1485 \r
1486     if (Value & 0xFFFF0000) {\r
1487       //\r
1488       // It is a IO32 bar\r
1489       //\r
1490       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;\r
1491       PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);\r
1492       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1493 \r
1494     } else {\r
1495       //\r
1496       // It is a IO16 bar\r
1497       //\r
1498       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;\r
1499       PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
1500       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1501 \r
1502     }\r
1503     //\r
1504     // Workaround. Some platforms inplement IO bar with 0 length\r
1505     // Need to treat it as no-bar\r
1506     //\r
1507     if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1508       PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
1509     }\r
1510 \r
1511     PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
1512     PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
1513 \r
1514   } else {\r
1515 \r
1516     Mask  = 0xfffffff0;\r
1517 \r
1518     PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1519 \r
1520     switch (Value & 0x07) {\r
1521 \r
1522     //\r
1523     //memory space; anywhere in 32 bit address space\r
1524     //\r
1525     case 0x00:\r
1526       if (Value & 0x08) {\r
1527         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
1528       } else {\r
1529         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
1530       }\r
1531 \r
1532       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
1533       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1534 \r
1535       break;\r
1536 \r
1537     //\r
1538     // memory space; anywhere in 64 bit address space\r
1539     //\r
1540     case 0x04:\r
1541       if (Value & 0x08) {\r
1542         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
1543       } else {\r
1544         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
1545       }\r
1546 \r
1547       //\r
1548       // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
1549       // is regarded as an extension for the first bar. As a result\r
1550       // the sizing will be conducted on combined 64 bit value\r
1551       // Here just store the masked first 32bit value for future size\r
1552       // calculation\r
1553       //\r
1554       PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;\r
1555       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1556 \r
1557       //\r
1558       // Increment the offset to point to next DWORD\r
1559       //\r
1560       Offset += 4;\r
1561 \r
1562       Status = BarExisted (\r
1563                 PciIoDevice,\r
1564                 Offset,\r
1565                 &Value,\r
1566                 &OriginalValue\r
1567                 );\r
1568 \r
1569       if (EFI_ERROR (Status)) {\r
1570         return Offset + 4;\r
1571       }\r
1572 \r
1573       //\r
1574       // Fix the length to support some spefic 64 bit BAR\r
1575       //\r
1576       Data  = Value;\r
1577       Index = 0;\r
1578       for (Data = Value; Data != 0; Data >>= 1) {\r
1579         Index ++;\r
1580       }\r
1581       Value |= ((UINT32)(-1) << Index);\r
1582 \r
1583       //\r
1584       // Calculate the size of 64bit bar\r
1585       //\r
1586       PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
1587 \r
1588       PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
1589       PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
1590       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1591 \r
1592       break;\r
1593 \r
1594     //\r
1595     // reserved\r
1596     //\r
1597     default:\r
1598       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
1599       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
1600       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1601 \r
1602       break;\r
1603     }\r
1604   }\r
1605 \r
1606   //\r
1607   // Check the length again so as to keep compatible with some special bars\r
1608   //\r
1609   if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1610     PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
1611     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1612     PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
1613   }\r
1614 \r
1615   //\r
1616   // Increment number of bar\r
1617   //\r
1618   return Offset + 4;\r
1619 }\r
1620 \r
1621 EFI_STATUS\r
1622 InitializePciDevice (\r
1623   IN PCI_IO_DEVICE *PciIoDevice\r
1624   )\r
1625 /*++\r
1626 \r
1627 Routine Description:\r
1628 \r
1629   This routine is used to initialize the bar of a PCI device\r
1630   It can be called typically when a device is going to be rejected\r
1631 \r
1632 Arguments:\r
1633 \r
1634 Returns:\r
1635 \r
1636   None\r
1637 \r
1638 --*/\r
1639 // TODO:    PciIoDevice - add argument and description to function comment\r
1640 // TODO:    EFI_SUCCESS - add return value to function comment\r
1641 {\r
1642   EFI_PCI_IO_PROTOCOL *PciIo;\r
1643   UINT8               Offset;\r
1644 \r
1645   PciIo = &(PciIoDevice->PciIo);\r
1646 \r
1647   //\r
1648   // Put all the resource apertures\r
1649   // Resource base is set to all ones so as to indicate its resource\r
1650   // has not been alloacted\r
1651   //\r
1652   for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
1653     PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
1654   }\r
1655 \r
1656   return EFI_SUCCESS;\r
1657 }\r
1658 \r
1659 EFI_STATUS\r
1660 InitializePpb (\r
1661   IN PCI_IO_DEVICE *PciIoDevice\r
1662   )\r
1663 /*++\r
1664 \r
1665 Routine Description:\r
1666 \r
1667 Arguments:\r
1668 \r
1669 Returns:\r
1670 \r
1671   None\r
1672 \r
1673 --*/\r
1674 // TODO:    PciIoDevice - add argument and description to function comment\r
1675 // TODO:    EFI_SUCCESS - add return value to function comment\r
1676 {\r
1677   EFI_PCI_IO_PROTOCOL *PciIo;\r
1678 \r
1679   PciIo = &(PciIoDevice->PciIo);\r
1680 \r
1681   //\r
1682   // Put all the resource apertures including IO16\r
1683   // Io32, pMem32, pMem64 to quiescent state\r
1684   // Resource base all ones, Resource limit all zeros\r
1685   //\r
1686   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
1687   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
1688 \r
1689   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
1690   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
1691 \r
1692   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
1693   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
1694 \r
1695   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
1696   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
1697 \r
1698   //\r
1699   // don't support use io32 as for now\r
1700   //\r
1701   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
1702   PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
1703 \r
1704   //\r
1705   // Force Interrupt line to zero for cards that come up randomly\r
1706   //\r
1707   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1708 \r
1709   return EFI_SUCCESS;\r
1710 }\r
1711 \r
1712 EFI_STATUS\r
1713 InitializeP2C (\r
1714   IN PCI_IO_DEVICE *PciIoDevice\r
1715   )\r
1716 /*++\r
1717 \r
1718 Routine Description:\r
1719 \r
1720 Arguments:\r
1721 \r
1722 Returns:\r
1723 \r
1724   None\r
1725 \r
1726 --*/\r
1727 // TODO:    PciIoDevice - add argument and description to function comment\r
1728 // TODO:    EFI_SUCCESS - add return value to function comment\r
1729 {\r
1730   EFI_PCI_IO_PROTOCOL *PciIo;\r
1731 \r
1732   PciIo = &(PciIoDevice->PciIo);\r
1733 \r
1734   //\r
1735   // Put all the resource apertures including IO16\r
1736   // Io32, pMem32, pMem64 to quiescent state(\r
1737   // Resource base all ones, Resource limit all zeros\r
1738   //\r
1739   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
1740   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
1741 \r
1742   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
1743   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
1744 \r
1745   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
1746   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
1747 \r
1748   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
1749   PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
1750 \r
1751   //\r
1752   // Force Interrupt line to zero for cards that come up randomly\r
1753   //\r
1754   PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1755   return EFI_SUCCESS;\r
1756 }\r
1757 \r
1758 PCI_IO_DEVICE *\r
1759 CreatePciIoDevice (\r
1760   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
1761   IN PCI_TYPE00                       *Pci,\r
1762   UINT8                               Bus,\r
1763   UINT8                               Device,\r
1764   UINT8                               Func\r
1765   )\r
1766 /*++\r
1767 \r
1768 Routine Description:\r
1769 \r
1770 Arguments:\r
1771 \r
1772 Returns:\r
1773 \r
1774   None\r
1775 \r
1776 --*/\r
1777 // TODO:    PciRootBridgeIo - add argument and description to function comment\r
1778 // TODO:    Pci - add argument and description to function comment\r
1779 // TODO:    Bus - add argument and description to function comment\r
1780 // TODO:    Device - add argument and description to function comment\r
1781 // TODO:    Func - add argument and description to function comment\r
1782 {\r
1783 \r
1784   EFI_STATUS    Status;\r
1785   PCI_IO_DEVICE *PciIoDevice;\r
1786 \r
1787   PciIoDevice = NULL;\r
1788 \r
1789   Status = gBS->AllocatePool (\r
1790                   EfiBootServicesData,\r
1791                   sizeof (PCI_IO_DEVICE),\r
1792                   (VOID **) &PciIoDevice\r
1793                   );\r
1794 \r
1795   if (EFI_ERROR (Status)) {\r
1796     return NULL;\r
1797   }\r
1798 \r
1799   ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
1800 \r
1801   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
1802   PciIoDevice->Handle           = NULL;\r
1803   PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
1804   PciIoDevice->DevicePath       = NULL;\r
1805   PciIoDevice->BusNumber        = Bus;\r
1806   PciIoDevice->DeviceNumber     = Device;\r
1807   PciIoDevice->FunctionNumber   = Func;\r
1808   PciIoDevice->Decodes          = 0;\r
1809   if (gFullEnumeration) {\r
1810     PciIoDevice->Allocated = FALSE;\r
1811   } else {\r
1812     PciIoDevice->Allocated = TRUE;\r
1813   }\r
1814 \r
1815   PciIoDevice->Registered         = FALSE;\r
1816   PciIoDevice->Attributes         = 0;\r
1817   PciIoDevice->Supports           = 0;\r
1818   PciIoDevice->BusOverride        = FALSE;\r
1819   PciIoDevice->AllOpRomProcessed  = FALSE;\r
1820 \r
1821   PciIoDevice->IsPciExp           = FALSE;\r
1822 \r
1823   CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
1824 \r
1825   //\r
1826   // Initialize the PCI I/O instance structure\r
1827   //\r
1828 \r
1829   Status  = InitializePciIoInstance (PciIoDevice);\r
1830   Status  = InitializePciDriverOverrideInstance (PciIoDevice);\r
1831 \r
1832   if (EFI_ERROR (Status)) {\r
1833     gBS->FreePool (PciIoDevice);\r
1834     return NULL;\r
1835   }\r
1836 \r
1837   //\r
1838   // Initialize the reserved resource list\r
1839   //\r
1840   InitializeListHead (&PciIoDevice->ReservedResourceList);\r
1841 \r
1842   //\r
1843   // Initialize the driver list\r
1844   //\r
1845   InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
1846 \r
1847   //\r
1848   // Initialize the child list\r
1849   //\r
1850   InitializeListHead (&PciIoDevice->ChildList);\r
1851 \r
1852   return PciIoDevice;\r
1853 }\r
1854 \r
1855 EFI_STATUS\r
1856 PciEnumeratorLight (\r
1857   IN EFI_HANDLE                    Controller\r
1858   )\r
1859 /*++\r
1860 \r
1861 Routine Description:\r
1862 \r
1863   This routine is used to enumerate entire pci bus system\r
1864   in a given platform\r
1865   It is only called on the second start on the same Root Bridge.\r
1866 \r
1867 Arguments:\r
1868 \r
1869 Returns:\r
1870 \r
1871   None\r
1872 \r
1873 --*/\r
1874 // TODO:    Controller - add argument and description to function comment\r
1875 // TODO:    EFI_SUCCESS - add return value to function comment\r
1876 // TODO:    EFI_SUCCESS - add return value to function comment\r
1877 {\r
1878 \r
1879   EFI_STATUS                        Status;\r
1880   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
1881   PCI_IO_DEVICE                     *RootBridgeDev;\r
1882   UINT16                            MinBus;\r
1883   UINT16                            MaxBus;\r
1884   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1885 \r
1886   MinBus      = 0;\r
1887   MaxBus      = PCI_MAX_BUS;\r
1888   Descriptors = NULL;\r
1889 \r
1890   //\r
1891   // If this root bridge has been already enumerated, then return successfully\r
1892   //\r
1893   if (GetRootBridgeByHandle (Controller) != NULL) {\r
1894     return EFI_SUCCESS;\r
1895   }\r
1896 \r
1897   //\r
1898   // Open pci root bridge io protocol\r
1899   //\r
1900   Status = gBS->OpenProtocol (\r
1901                   Controller,\r
1902                   &gEfiPciRootBridgeIoProtocolGuid,\r
1903                   (VOID **) &PciRootBridgeIo,\r
1904                   gPciBusDriverBinding.DriverBindingHandle,\r
1905                   Controller,\r
1906                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
1907                   );\r
1908   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
1909     return Status;\r
1910   }\r
1911 \r
1912   Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1913 \r
1914   if (EFI_ERROR (Status)) {\r
1915     return Status;\r
1916   }\r
1917 \r
1918   while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
1919 \r
1920     //\r
1921     // Create a device node for root bridge device with a NULL host bridge controller handle\r
1922     //\r
1923     RootBridgeDev = CreateRootBridge (Controller);\r
1924 \r
1925     if (!RootBridgeDev) {\r
1926       Descriptors++;\r
1927       continue;\r
1928     }\r
1929 \r
1930     //\r
1931     // Record the root bridge io protocol\r
1932     //\r
1933     RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
1934 \r
1935     Status = PciPciDeviceInfoCollector (\r
1936               RootBridgeDev,\r
1937               (UINT8) MinBus\r
1938               );\r
1939 \r
1940     if (!EFI_ERROR (Status)) {\r
1941 \r
1942       //\r
1943       // Remove those PCI devices which are rejected when full enumeration\r
1944       //\r
1945       RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
1946 \r
1947       //\r
1948       // Process option rom light\r
1949       //\r
1950       ProcessOptionRomLight (RootBridgeDev);\r
1951 \r
1952       //\r
1953       // Determine attributes for all devices under this root bridge\r
1954       //\r
1955       DetermineDeviceAttribute (RootBridgeDev);\r
1956 \r
1957       //\r
1958       // If successfully, insert the node into device pool\r
1959       //\r
1960       InsertRootBridge (RootBridgeDev);\r
1961     } else {\r
1962 \r
1963       //\r
1964       // If unsuccessly, destroy the entire node\r
1965       //\r
1966       DestroyRootBridge (RootBridgeDev);\r
1967     }\r
1968 \r
1969     Descriptors++;\r
1970   }\r
1971 \r
1972   return EFI_SUCCESS;\r
1973 }\r
1974 \r
1975 EFI_STATUS\r
1976 PciGetBusRange (\r
1977   IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,\r
1978   OUT    UINT16                             *MinBus,\r
1979   OUT    UINT16                             *MaxBus,\r
1980   OUT    UINT16                             *BusRange\r
1981   )\r
1982 /*++\r
1983 \r
1984 Routine Description:\r
1985 \r
1986   Get the bus range.\r
1987 \r
1988 Arguments:\r
1989 \r
1990   Descriptors     - A pointer to the address space descriptor.\r
1991   MinBus          - The min bus.\r
1992   MaxBus          - The max bus.\r
1993   BusRange        - The bus range.\r
1994 \r
1995 Returns:\r
1996 \r
1997   Status Code.\r
1998 \r
1999 --*/\r
2000 // TODO:    EFI_SUCCESS - add return value to function comment\r
2001 // TODO:    EFI_NOT_FOUND - add return value to function comment\r
2002 {\r
2003 \r
2004   while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2005     if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
2006       if (MinBus != NULL) {\r
2007         *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
2008       }\r
2009 \r
2010       if (MaxBus != NULL) {\r
2011         *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
2012       }\r
2013 \r
2014       if (BusRange != NULL) {\r
2015         *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
2016       }\r
2017 \r
2018       return EFI_SUCCESS;\r
2019     }\r
2020 \r
2021     (*Descriptors)++;\r
2022   }\r
2023 \r
2024   return EFI_NOT_FOUND;\r
2025 }\r
2026 \r
2027 EFI_STATUS\r
2028 StartManagingRootBridge (\r
2029   IN PCI_IO_DEVICE *RootBridgeDev\r
2030   )\r
2031 /*++\r
2032 \r
2033 Routine Description:\r
2034 \r
2035 \r
2036 Arguments:\r
2037 \r
2038 Returns:\r
2039 \r
2040   None\r
2041 \r
2042 --*/\r
2043 // TODO:    RootBridgeDev - add argument and description to function comment\r
2044 // TODO:    EFI_SUCCESS - add return value to function comment\r
2045 {\r
2046   EFI_HANDLE                      RootBridgeHandle;\r
2047   EFI_STATUS                      Status;\r
2048   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2049 \r
2050   //\r
2051   // Get the root bridge handle\r
2052   //\r
2053   RootBridgeHandle  = RootBridgeDev->Handle;\r
2054   PciRootBridgeIo   = NULL;\r
2055 \r
2056   //\r
2057   // Get the pci root bridge io protocol\r
2058   //\r
2059   Status = gBS->OpenProtocol (\r
2060                   RootBridgeHandle,\r
2061                   &gEfiPciRootBridgeIoProtocolGuid,\r
2062                   (VOID **) &PciRootBridgeIo,\r
2063                   gPciBusDriverBinding.DriverBindingHandle,\r
2064                   RootBridgeHandle,\r
2065                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
2066                   );\r
2067 \r
2068   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
2069     return Status;\r
2070   }\r
2071 \r
2072   //\r
2073   // Store the PciRootBridgeIo protocol into root bridge private data\r
2074   //\r
2075   RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
2076 \r
2077   return EFI_SUCCESS;\r
2078 \r
2079 }\r
2080 \r
2081 BOOLEAN\r
2082 IsPciDeviceRejected (\r
2083   IN PCI_IO_DEVICE *PciIoDevice\r
2084   )\r
2085 /*++\r
2086 \r
2087 Routine Description:\r
2088 \r
2089   This routine can be used to check whether a PCI device should be rejected when light enumeration\r
2090 \r
2091 Arguments:\r
2092 \r
2093 Returns:\r
2094 \r
2095   TRUE      This device should be rejected\r
2096   FALSE     This device shouldn't be rejected\r
2097 \r
2098 --*/\r
2099 // TODO:    PciIoDevice - add argument and description to function comment\r
2100 {\r
2101   EFI_STATUS  Status;\r
2102   UINT32      TestValue;\r
2103   UINT32      OldValue;\r
2104   UINT32      Mask;\r
2105   UINT8       BarOffset;\r
2106 \r
2107   //\r
2108   // PPB should be skip!\r
2109   //\r
2110   if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
2111     return FALSE;\r
2112   }\r
2113 \r
2114   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
2115     //\r
2116     // Only test base registers for P2C\r
2117     //\r
2118     for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
2119 \r
2120       Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
2121       Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2122       if (EFI_ERROR (Status)) {\r
2123         continue;\r
2124       }\r
2125 \r
2126       TestValue = TestValue & Mask;\r
2127       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2128         //\r
2129         // The bar isn't programed, so it should be rejected\r
2130         //\r
2131         return TRUE;\r
2132       }\r
2133     }\r
2134 \r
2135     return FALSE;\r
2136   }\r
2137 \r
2138   for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
2139     //\r
2140     // Test PCI devices\r
2141     //\r
2142     Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2143     if (EFI_ERROR (Status)) {\r
2144       continue;\r
2145     }\r
2146 \r
2147     if (TestValue & 0x01) {\r
2148 \r
2149       //\r
2150       // IO Bar\r
2151       //\r
2152 \r
2153       Mask      = 0xFFFFFFFC;\r
2154       TestValue = TestValue & Mask;\r
2155       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2156         return TRUE;\r
2157       }\r
2158 \r
2159     } else {\r
2160 \r
2161       //\r
2162       // Mem Bar\r
2163       //\r
2164 \r
2165       Mask      = 0xFFFFFFF0;\r
2166       TestValue = TestValue & Mask;\r
2167 \r
2168       if ((TestValue & 0x07) == 0x04) {\r
2169 \r
2170         //\r
2171         // Mem64 or PMem64\r
2172         //\r
2173         BarOffset += sizeof (UINT32);\r
2174         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2175 \r
2176           //\r
2177           // Test its high 32-Bit BAR\r
2178           //\r
2179 \r
2180           Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2181           if (TestValue == OldValue) {\r
2182             return TRUE;\r
2183           }\r
2184         }\r
2185 \r
2186       } else {\r
2187 \r
2188         //\r
2189         // Mem32 or PMem32\r
2190         //\r
2191         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2192           return TRUE;\r
2193         }\r
2194       }\r
2195     }\r
2196   }\r
2197 \r
2198   return FALSE;\r
2199 }\r
2200 \r
2201 EFI_STATUS\r
2202 ResetAllPpbBusNumber (\r
2203   IN PCI_IO_DEVICE                      *Bridge,\r
2204   IN UINT8                              StartBusNumber\r
2205   )\r
2206 /*++\r
2207 \r
2208 Routine Description:\r
2209 \r
2210   TODO: Add function description\r
2211 \r
2212 Arguments:\r
2213 \r
2214   Bridge          - TODO: add argument description\r
2215   StartBusNumber  - TODO: add argument description\r
2216 \r
2217 Returns:\r
2218 \r
2219   EFI_SUCCESS - TODO: Add description for return value\r
2220 \r
2221 --*/\r
2222 {\r
2223   EFI_STATUS                      Status;\r
2224   PCI_TYPE00                      Pci;\r
2225   UINT8                           Device;\r
2226   UINT32                          Register;\r
2227   UINT8                           Func;\r
2228   UINT64                          Address;\r
2229   UINT8                           SecondaryBus;\r
2230   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2231 \r
2232   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
2233 \r
2234   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
2235     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
2236 \r
2237       //\r
2238       // Check to see whether a pci device is present\r
2239       //\r
2240       Status = PciDevicePresent (\r
2241                 PciRootBridgeIo,\r
2242                 &Pci,\r
2243                 StartBusNumber,\r
2244                 Device,\r
2245                 Func\r
2246                 );\r
2247 \r
2248       if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
2249 \r
2250         Register  = 0;\r
2251         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
2252         Status   = PciRootBridgeIoRead (\r
2253                                         PciRootBridgeIo,\r
2254                                         &Pci,\r
2255                                         EfiPciWidthUint32,\r
2256                                         Address,\r
2257                                         1,\r
2258                                         &Register\r
2259                                         );\r
2260         SecondaryBus = (UINT8)(Register >> 8);\r
2261 \r
2262         if (SecondaryBus != 0) {\r
2263           ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
2264         }\r
2265 \r
2266         //\r
2267         // Reset register 18h, 19h, 1Ah on PCI Bridge\r
2268         //\r
2269         Register &= 0xFF000000;\r
2270         Status = PciRootBridgeIoWrite (\r
2271                                         PciRootBridgeIo,\r
2272                                         &Pci,\r
2273                                         EfiPciWidthUint32,\r
2274                                         Address,\r
2275                                         1,\r
2276                                         &Register\r
2277                                         );\r
2278       }\r
2279 \r
2280       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
2281         //\r
2282         // Skip sub functions, this is not a multi function device\r
2283         //\r
2284         Func = PCI_MAX_FUNC;\r
2285       }\r
2286     }\r
2287   }\r
2288 \r
2289   return EFI_SUCCESS;\r
2290 }\r
2291 \r