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