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