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