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