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