]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
Produce all the PciIo & Dpath protocol for all the pci devices under the current...
[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
eb9a9a5e 1003\r
1004 //\r
1005 // The OpRom has already been processed in the first round\r
1006 //\r
1007 Temp->AllOpRomProcessed = TRUE;\r
1008\r
ead42efc 1009 CurrentLink = CurrentLink->ForwardLink;\r
1010 }\r
1011\r
1012 return EFI_SUCCESS;\r
1013}\r
1014\r
1015EFI_STATUS\r
1016DetermineDeviceAttribute (\r
1017 IN PCI_IO_DEVICE *PciIoDevice\r
1018 )\r
1019/*++\r
1020\r
1021Routine Description:\r
1022\r
1023 Determine the related attributes of all devices under a Root Bridge\r
1024\r
1025Arguments:\r
1026\r
1027Returns:\r
1028\r
1029 None\r
1030\r
1031--*/\r
1032// TODO: PciIoDevice - add argument and description to function comment\r
1033// TODO: EFI_SUCCESS - add return value to function comment\r
1034{\r
1035 UINT16 Command;\r
1036 UINT16 BridgeControl;\r
1037 UINT16 OldCommand;\r
1038 UINT16 OldBridgeControl;\r
1039 BOOLEAN FastB2BSupport;\r
1040\r
1041 /*\r
1042 UINT8 IdePI;\r
1043 EFI_PCI_IO_PROTOCOL *PciIo;\r
1044 */\r
1045 PCI_IO_DEVICE *Temp;\r
1046 LIST_ENTRY *CurrentLink;\r
1047 EFI_STATUS Status;\r
1048\r
1049 //\r
1050 // For Root Bridge, just copy it by RootBridgeIo proctocol\r
1051 // so as to keep consistent with the actual attribute\r
1052 //\r
1053 if (!PciIoDevice->Parent) {\r
1054 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1055 PciIoDevice->PciRootBridgeIo,\r
1056 &PciIoDevice->Supports,\r
1057 &PciIoDevice->Attributes\r
1058 );\r
1059 if (EFI_ERROR (Status)) {\r
1060 return Status;\r
1061 }\r
1062 } else {\r
1063\r
1064 //\r
1065 // Set the attributes to be checked for common PCI devices and PPB or P2C\r
1066 // Since some devices only support part of them, it is better to set the\r
1067 // attribute according to its command or bridge control register\r
1068 //\r
1069 Command = EFI_PCI_COMMAND_IO_SPACE |\r
1070 EFI_PCI_COMMAND_MEMORY_SPACE |\r
1071 EFI_PCI_COMMAND_BUS_MASTER |\r
1072 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1073\r
1074 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1075\r
1076 //\r
1077 // Test whether the device can support attributes above\r
1078 //\r
1079 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
1080\r
1081 //\r
1082 // Set the supported attributes for specified PCI device\r
1083 //\r
1084 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
1085\r
1086 //\r
1087 // Set the current attributes for specified PCI device\r
1088 //\r
1089 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
1090\r
1091 //\r
1092 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
1093 //\r
1094 PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
1095\r
1096 //\r
1097 // Enable IDE native mode\r
1098 //\r
1099 /*\r
1100 if (IS_PCI_IDE(&PciIoDevice->Pci)) {\r
1101\r
1102 PciIo = &PciIoDevice->PciIo;\r
1103\r
1104 PciIoRead (\r
1105 PciIo,\r
1106 EfiPciIoWidthUint8,\r
1107 0x09,\r
1108 1,\r
1109 &IdePI\r
1110 );\r
1111\r
1112 //\r
1113 // Set native mode if it can be supported\r
1114 //\r
1115 IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);\r
1116\r
1117 PciIoWrite (\r
1118 PciIo,\r
1119 EfiPciIoWidthUint8,\r
1120 0x09,\r
1121 1,\r
1122 &IdePI\r
1123 );\r
1124\r
1125 }\r
1126 */\r
1127 }\r
1128\r
1129 FastB2BSupport = TRUE;\r
1130\r
1131 //\r
1132 // P2C can not support FB2B on the secondary side\r
1133 //\r
1134 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1135 FastB2BSupport = FALSE;\r
1136 }\r
1137\r
1138 //\r
1139 // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1140 //\r
1141 CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1142 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1143\r
1144 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1145 Status = DetermineDeviceAttribute (Temp);\r
1146 if (EFI_ERROR (Status)) {\r
1147 return Status;\r
1148 }\r
1149 //\r
1150 // Detect Fast Bact to Bact support for the device under the bridge\r
1151 //\r
1152 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
1153 if (FastB2BSupport && EFI_ERROR (Status)) {\r
1154 FastB2BSupport = FALSE;\r
1155 }\r
1156\r
1157 CurrentLink = CurrentLink->ForwardLink;\r
1158 }\r
1159 //\r
1160 // Set or clear Fast Back to Back bit for the whole bridge\r
1161 //\r
1162 if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
1163\r
1164 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
1165\r
1166 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
1167\r
1168 if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
1169 FastB2BSupport = FALSE;\r
1170 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1171 } else {\r
1172 PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1173 }\r
1174 }\r
1175\r
1176 CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1177 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
1178 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1179 if (FastB2BSupport) {\r
1180 PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1181 } else {\r
1182 PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1183 }\r
1184\r
1185 CurrentLink = CurrentLink->ForwardLink;\r
1186 }\r
1187 }\r
1188 //\r
1189 // End for IsListEmpty\r
1190 //\r
1191 return EFI_SUCCESS;\r
1192}\r
1193\r
1194EFI_STATUS\r
1195UpdatePciInfo (\r
1196 IN PCI_IO_DEVICE *PciIoDevice\r
1197 )\r
1198/*++\r
1199\r
1200Routine Description:\r
1201\r
1202 This routine is used to update the bar information for those incompatible PCI device\r
1203\r
1204Arguments:\r
1205\r
1206Returns:\r
1207\r
1208 None\r
1209\r
1210--*/\r
1211// TODO: PciIoDevice - add argument and description to function comment\r
1212// TODO: EFI_UNSUPPORTED - add return value to function comment\r
1213{\r
1214 EFI_STATUS Status;\r
1215 UINTN BarIndex;\r
1216 UINTN BarEndIndex;\r
1217 BOOLEAN SetFlag;\r
1218 EFI_PCI_DEVICE_INFO PciDeviceInfo;\r
1219 VOID *Configuration;\r
1220 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1221\r
1222 Configuration = NULL;\r
ea5632e5 1223 Status = EFI_SUCCESS;\r
ead42efc 1224\r
ea5632e5 1225 if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
1226 //\r
1227 // It can only be supported after the Incompatible PCI Device\r
1228 // Support Protocol has been installed\r
1229 //\r
1230 Status = gBS->LocateProtocol (\r
1231 &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
1232 NULL,\r
1233 (VOID **) &gEfiIncompatiblePciDeviceSupport\r
1234 );\r
1235 }\r
1236 if (Status == EFI_SUCCESS) {\r
1237 //\r
1238 // Check whether the device belongs to incompatible devices from protocol or not\r
1239 // If it is , then get its special requirement in the ACPI table\r
1240 //\r
1241 Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
1242 gEfiIncompatiblePciDeviceSupport,\r
1243 PciIoDevice->Pci.Hdr.VendorId,\r
1244 PciIoDevice->Pci.Hdr.DeviceId,\r
1245 PciIoDevice->Pci.Hdr.RevisionID,\r
1246 PciIoDevice->Pci.Device.SubsystemVendorID,\r
1247 PciIoDevice->Pci.Device.SubsystemID,\r
1248 &Configuration\r
1249 );\r
ead42efc 1250\r
ea5632e5 1251 }\r
ead42efc 1252\r
1253 if (EFI_ERROR (Status)) {\r
ea5632e5 1254 //\r
1255 // Check whether the device belongs to incompatible devices from library or not\r
1256 // If it is , then get its special requirement in the ACPI table\r
1257 //\r
1258 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {\r
1259 PciDeviceInfo.VendorID = PciIoDevice->Pci.Hdr.VendorId;\r
1260 PciDeviceInfo.DeviceID = PciIoDevice->Pci.Hdr.DeviceId;\r
1261 PciDeviceInfo.RevisionID = PciIoDevice->Pci.Hdr.RevisionID;\r
1262 PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;\r
1263 PciDeviceInfo.SubsystemID = PciIoDevice->Pci.Device.SubsystemID;\r
1264\r
1265 Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);\r
1266 }\r
1267 }\r
1268\r
1269 if (EFI_ERROR (Status)) {\r
1270 return EFI_UNSUPPORTED;\r
ead42efc 1271 }\r
1272\r
1273 //\r
1274 // Update PCI device information from the ACPI table\r
1275 //\r
1276 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1277\r
1278 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1279\r
1280 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1281 //\r
1282 // The format is not support\r
1283 //\r
1284 break;\r
1285 }\r
1286\r
1287 BarIndex = (UINTN) Ptr->AddrTranslationOffset;\r
1288 BarEndIndex = BarIndex;\r
1289\r
1290 //\r
1291 // Update all the bars in the device\r
1292 //\r
1293 if (BarIndex == PCI_BAR_ALL) {\r
1294 BarIndex = 0;\r
1295 BarEndIndex = PCI_MAX_BAR - 1;\r
1296 }\r
1297\r
1298 if (BarIndex >= PCI_MAX_BAR) {\r
1299 Ptr++;\r
1300 continue;\r
1301 }\r
1302\r
1303 for (; BarIndex <= BarEndIndex; BarIndex++) {\r
1304 SetFlag = FALSE;\r
1305 switch (Ptr->ResType) {\r
1306 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1307\r
1308 //\r
1309 // Make sure the bar is memory type\r
1310 //\r
1311 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
1312 SetFlag = TRUE;\r
1313 }\r
1314 break;\r
1315\r
1316 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1317\r
1318 //\r
1319 // Make sure the bar is IO type\r
1320 //\r
1321 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
1322 SetFlag = TRUE;\r
1323 }\r
1324 break;\r
1325 }\r
1326\r
1327 if (SetFlag) {\r
1328\r
1329 //\r
1330 // Update the new alignment for the device\r
1331 //\r
1332 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
1333\r
1334 //\r
1335 // Update the new length for the device\r
1336 //\r
1337 if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
1338 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
1339 }\r
1340 }\r
1341 }\r
1342\r
1343 Ptr++;\r
1344 }\r
1345\r
1346 gBS->FreePool (Configuration);\r
1347 return Status;\r
1348\r
1349}\r
1350\r
1351VOID\r
1352SetNewAlign (\r
1353 IN UINT64 *Alignment,\r
1354 IN UINT64 NewAlignment\r
1355 )\r
1356/*++\r
1357\r
1358Routine Description:\r
1359\r
1360 This routine will update the alignment with the new alignment\r
1361\r
1362Arguments:\r
1363\r
1364Returns:\r
1365\r
1366 None\r
1367\r
1368--*/\r
1369// TODO: Alignment - add argument and description to function comment\r
1370// TODO: NewAlignment - add argument and description to function comment\r
1371{\r
1372 UINT64 OldAlignment;\r
1373 UINTN ShiftBit;\r
1374\r
1375 //\r
1376 // The new alignment is the same as the original,\r
1377 // so skip it\r
1378 //\r
1379 if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
1380 return ;\r
1381 }\r
1382 //\r
1383 // Check the validity of the parameter\r
1384 //\r
1385 if (NewAlignment != PCI_BAR_EVEN_ALIGN &&\r
1386 NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
1387 NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
1388 *Alignment = NewAlignment;\r
1389 return ;\r
1390 }\r
1391\r
1392 OldAlignment = (*Alignment) + 1;\r
1393 ShiftBit = 0;\r
1394\r
1395 //\r
1396 // Get the first non-zero hex value of the length\r
1397 //\r
1398 while ((OldAlignment & 0x0F) == 0x00) {\r
1399 OldAlignment = RShiftU64 (OldAlignment, 4);\r
1400 ShiftBit += 4;\r
1401 }\r
1402\r
1403 //\r
1404 // Adjust the alignment to even, quad or double quad boundary\r
1405 //\r
1406 if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
1407 if (OldAlignment & 0x01) {\r
1408 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
1409 }\r
1410 } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
1411 if (OldAlignment & 0x03) {\r
1412 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
1413 }\r
1414 } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
1415 if (OldAlignment & 0x07) {\r
1416 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
1417 }\r
1418 }\r
1419\r
1420 //\r
1421 // Update the old value\r
1422 //\r
1423 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
1424 *Alignment = NewAlignment;\r
1425\r
1426 return ;\r
1427}\r
1428\r
1429UINTN\r
1430PciParseBar (\r
1431 IN PCI_IO_DEVICE *PciIoDevice,\r
1432 IN UINTN Offset,\r
1433 IN UINTN BarIndex\r
1434 )\r
1435/*++\r
1436\r
1437Routine Description:\r
1438\r
1439Arguments:\r
1440\r
1441Returns:\r
1442\r
1443 None\r
1444\r
1445--*/\r
1446// TODO: PciIoDevice - add argument and description to function comment\r
1447// TODO: Offset - add argument and description to function comment\r
1448// TODO: BarIndex - add argument and description to function comment\r
1449{\r
1450 UINT32 Value;\r
1451 UINT32 OriginalValue;\r
1452 UINT32 Mask;\r
1453 UINT32 Data;\r
1454 UINT8 Index;\r
1455 EFI_STATUS Status;\r
1456\r
1457 OriginalValue = 0;\r
1458 Value = 0;\r
1459\r
1460 Status = BarExisted (\r
1461 PciIoDevice,\r
1462 Offset,\r
1463 &Value,\r
1464 &OriginalValue\r
1465 );\r
1466\r
1467 if (EFI_ERROR (Status)) {\r
1468 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1469 PciIoDevice->PciBar[BarIndex].Length = 0;\r
1470 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
1471\r
1472 //\r
1473 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
1474 //\r
1475 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1476 return Offset + 4;\r
1477 }\r
1478\r
1479 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1480 if (Value & 0x01) {\r
1481 //\r
1482 // Device I/Os\r
1483 //\r
1484 Mask = 0xfffffffc;\r
1485\r
1486 if (Value & 0xFFFF0000) {\r
1487 //\r
1488 // It is a IO32 bar\r
1489 //\r
1490 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;\r
1491 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);\r
1492 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1493\r
1494 } else {\r
1495 //\r
1496 // It is a IO16 bar\r
1497 //\r
1498 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;\r
1499 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
1500 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1501\r
1502 }\r
1503 //\r
1504 // Workaround. Some platforms inplement IO bar with 0 length\r
1505 // Need to treat it as no-bar\r
1506 //\r
1507 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1508 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
1509 }\r
1510\r
1511 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;\r
1512 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1513\r
1514 } else {\r
1515\r
1516 Mask = 0xfffffff0;\r
1517\r
1518 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1519\r
1520 switch (Value & 0x07) {\r
1521\r
1522 //\r
1523 //memory space; anywhere in 32 bit address space\r
1524 //\r
1525 case 0x00:\r
1526 if (Value & 0x08) {\r
1527 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
1528 } else {\r
1529 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
1530 }\r
1531\r
1532 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1533 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1534\r
1535 break;\r
1536\r
1537 //\r
1538 // memory space; anywhere in 64 bit address space\r
1539 //\r
1540 case 0x04:\r
1541 if (Value & 0x08) {\r
1542 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
1543 } else {\r
1544 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
1545 }\r
1546\r
1547 //\r
1548 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
1549 // is regarded as an extension for the first bar. As a result\r
1550 // the sizing will be conducted on combined 64 bit value\r
1551 // Here just store the masked first 32bit value for future size\r
1552 // calculation\r
1553 //\r
1554 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;\r
1555 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1556\r
1557 //\r
1558 // Increment the offset to point to next DWORD\r
1559 //\r
1560 Offset += 4;\r
1561\r
1562 Status = BarExisted (\r
1563 PciIoDevice,\r
1564 Offset,\r
1565 &Value,\r
1566 &OriginalValue\r
1567 );\r
1568\r
1569 if (EFI_ERROR (Status)) {\r
1570 return Offset + 4;\r
1571 }\r
1572\r
1573 //\r
1574 // Fix the length to support some spefic 64 bit BAR\r
1575 //\r
1576 Data = Value;\r
1577 Index = 0;\r
1578 for (Data = Value; Data != 0; Data >>= 1) {\r
1579 Index ++;\r
1580 }\r
1581 Value |= ((UINT32)(-1) << Index);\r
1582\r
1583 //\r
1584 // Calculate the size of 64bit bar\r
1585 //\r
1586 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
1587\r
1588 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
1589 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
1590 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1591\r
1592 break;\r
1593\r
1594 //\r
1595 // reserved\r
1596 //\r
1597 default:\r
1598 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1599 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1600 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1601\r
1602 break;\r
1603 }\r
1604 }\r
1605\r
1606 //\r
1607 // Check the length again so as to keep compatible with some special bars\r
1608 //\r
1609 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1610 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1611 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1612 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
1613 }\r
1614\r
1615 //\r
1616 // Increment number of bar\r
1617 //\r
1618 return Offset + 4;\r
1619}\r
1620\r
1621EFI_STATUS\r
1622InitializePciDevice (\r
1623 IN PCI_IO_DEVICE *PciIoDevice\r
1624 )\r
1625/*++\r
1626\r
1627Routine Description:\r
1628\r
1629 This routine is used to initialize the bar of a PCI device\r
1630 It can be called typically when a device is going to be rejected\r
1631\r
1632Arguments:\r
1633\r
1634Returns:\r
1635\r
1636 None\r
1637\r
1638--*/\r
1639// TODO: PciIoDevice - add argument and description to function comment\r
1640// TODO: EFI_SUCCESS - add return value to function comment\r
1641{\r
1642 EFI_PCI_IO_PROTOCOL *PciIo;\r
1643 UINT8 Offset;\r
1644\r
1645 PciIo = &(PciIoDevice->PciIo);\r
1646\r
1647 //\r
1648 // Put all the resource apertures\r
1649 // Resource base is set to all ones so as to indicate its resource\r
1650 // has not been alloacted\r
1651 //\r
1652 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
1653 PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
1654 }\r
1655\r
1656 return EFI_SUCCESS;\r
1657}\r
1658\r
1659EFI_STATUS\r
1660InitializePpb (\r
1661 IN PCI_IO_DEVICE *PciIoDevice\r
1662 )\r
1663/*++\r
1664\r
1665Routine Description:\r
1666\r
1667Arguments:\r
1668\r
1669Returns:\r
1670\r
1671 None\r
1672\r
1673--*/\r
1674// TODO: PciIoDevice - add argument and description to function comment\r
1675// TODO: EFI_SUCCESS - add return value to function comment\r
1676{\r
1677 EFI_PCI_IO_PROTOCOL *PciIo;\r
1678\r
1679 PciIo = &(PciIoDevice->PciIo);\r
1680\r
1681 //\r
1682 // Put all the resource apertures including IO16\r
1683 // Io32, pMem32, pMem64 to quiescent state\r
1684 // Resource base all ones, Resource limit all zeros\r
1685 //\r
1686 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
1687 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
1688\r
1689 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
1690 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
1691\r
1692 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
1693 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
1694\r
1695 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
1696 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
1697\r
1698 //\r
1699 // don't support use io32 as for now\r
1700 //\r
1701 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
1702 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
1703\r
1704 //\r
1705 // Force Interrupt line to zero for cards that come up randomly\r
1706 //\r
1707 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1708\r
1709 return EFI_SUCCESS;\r
1710}\r
1711\r
1712EFI_STATUS\r
1713InitializeP2C (\r
1714 IN PCI_IO_DEVICE *PciIoDevice\r
1715 )\r
1716/*++\r
1717\r
1718Routine Description:\r
1719\r
1720Arguments:\r
1721\r
1722Returns:\r
1723\r
1724 None\r
1725\r
1726--*/\r
1727// TODO: PciIoDevice - add argument and description to function comment\r
1728// TODO: EFI_SUCCESS - add return value to function comment\r
1729{\r
1730 EFI_PCI_IO_PROTOCOL *PciIo;\r
1731\r
1732 PciIo = &(PciIoDevice->PciIo);\r
1733\r
1734 //\r
1735 // Put all the resource apertures including IO16\r
1736 // Io32, pMem32, pMem64 to quiescent state(\r
1737 // Resource base all ones, Resource limit all zeros\r
1738 //\r
1739 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
1740 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
1741\r
1742 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
1743 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
1744\r
1745 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
1746 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
1747\r
1748 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
1749 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
1750\r
1751 //\r
1752 // Force Interrupt line to zero for cards that come up randomly\r
1753 //\r
1754 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1755 return EFI_SUCCESS;\r
1756}\r
1757\r
1758PCI_IO_DEVICE *\r
1759CreatePciIoDevice (\r
1760 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
1761 IN PCI_TYPE00 *Pci,\r
1762 UINT8 Bus,\r
1763 UINT8 Device,\r
1764 UINT8 Func\r
1765 )\r
1766/*++\r
1767\r
1768Routine Description:\r
1769\r
1770Arguments:\r
1771\r
1772Returns:\r
1773\r
1774 None\r
1775\r
1776--*/\r
1777// TODO: PciRootBridgeIo - add argument and description to function comment\r
1778// TODO: Pci - add argument and description to function comment\r
1779// TODO: Bus - add argument and description to function comment\r
1780// TODO: Device - add argument and description to function comment\r
1781// TODO: Func - add argument and description to function comment\r
1782{\r
1783\r
1784 EFI_STATUS Status;\r
1785 PCI_IO_DEVICE *PciIoDevice;\r
1786\r
1787 PciIoDevice = NULL;\r
1788\r
1789 Status = gBS->AllocatePool (\r
1790 EfiBootServicesData,\r
1791 sizeof (PCI_IO_DEVICE),\r
1792 (VOID **) &PciIoDevice\r
1793 );\r
1794\r
1795 if (EFI_ERROR (Status)) {\r
1796 return NULL;\r
1797 }\r
1798\r
1799 ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
1800\r
1801 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;\r
1802 PciIoDevice->Handle = NULL;\r
1803 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;\r
1804 PciIoDevice->DevicePath = NULL;\r
1805 PciIoDevice->BusNumber = Bus;\r
1806 PciIoDevice->DeviceNumber = Device;\r
1807 PciIoDevice->FunctionNumber = Func;\r
1808 PciIoDevice->Decodes = 0;\r
1809 if (gFullEnumeration) {\r
1810 PciIoDevice->Allocated = FALSE;\r
1811 } else {\r
1812 PciIoDevice->Allocated = TRUE;\r
1813 }\r
1814\r
1815 PciIoDevice->Registered = FALSE;\r
1816 PciIoDevice->Attributes = 0;\r
1817 PciIoDevice->Supports = 0;\r
1818 PciIoDevice->BusOverride = FALSE;\r
1819 PciIoDevice->AllOpRomProcessed = FALSE;\r
1820\r
1821 PciIoDevice->IsPciExp = FALSE;\r
1822\r
1823 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
1824\r
1825 //\r
1826 // Initialize the PCI I/O instance structure\r
1827 //\r
1828\r
1829 Status = InitializePciIoInstance (PciIoDevice);\r
1830 Status = InitializePciDriverOverrideInstance (PciIoDevice);\r
1831\r
1832 if (EFI_ERROR (Status)) {\r
1833 gBS->FreePool (PciIoDevice);\r
1834 return NULL;\r
1835 }\r
1836\r
1837 //\r
1838 // Initialize the reserved resource list\r
1839 //\r
1840 InitializeListHead (&PciIoDevice->ReservedResourceList);\r
1841\r
1842 //\r
1843 // Initialize the driver list\r
1844 //\r
1845 InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
1846\r
1847 //\r
1848 // Initialize the child list\r
1849 //\r
1850 InitializeListHead (&PciIoDevice->ChildList);\r
1851\r
1852 return PciIoDevice;\r
1853}\r
1854\r
1855EFI_STATUS\r
1856PciEnumeratorLight (\r
1857 IN EFI_HANDLE Controller\r
1858 )\r
1859/*++\r
1860\r
1861Routine Description:\r
1862\r
1863 This routine is used to enumerate entire pci bus system\r
1864 in a given platform\r
eb9a9a5e 1865 It is only called on the second start on the same Root Bridge.\r
ead42efc 1866\r
1867Arguments:\r
1868\r
1869Returns:\r
1870\r
1871 None\r
1872\r
1873--*/\r
1874// TODO: Controller - add argument and description to function comment\r
1875// TODO: EFI_SUCCESS - add return value to function comment\r
1876// TODO: EFI_SUCCESS - add return value to function comment\r
1877{\r
1878\r
1879 EFI_STATUS Status;\r
1880 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1881 PCI_IO_DEVICE *RootBridgeDev;\r
1882 UINT16 MinBus;\r
1883 UINT16 MaxBus;\r
1884 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1885\r
1886 MinBus = 0;\r
1887 MaxBus = PCI_MAX_BUS;\r
1888 Descriptors = NULL;\r
1889\r
1890 //\r
eb9a9a5e 1891 // If this root bridge has been already enumerated, then return successfully\r
ead42efc 1892 //\r
eb9a9a5e 1893 if (GetRootBridgeByHandle (Controller) != NULL) {\r
ead42efc 1894 return EFI_SUCCESS;\r
1895 }\r
1896\r
1897 //\r
1898 // Open pci root bridge io protocol\r
1899 //\r
1900 Status = gBS->OpenProtocol (\r
1901 Controller,\r
1902 &gEfiPciRootBridgeIoProtocolGuid,\r
1903 (VOID **) &PciRootBridgeIo,\r
1904 gPciBusDriverBinding.DriverBindingHandle,\r
1905 Controller,\r
1906 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1907 );\r
1908 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
1909 return Status;\r
1910 }\r
1911\r
1912 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1913\r
1914 if (EFI_ERROR (Status)) {\r
1915 return Status;\r
1916 }\r
1917\r
1918 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
1919\r
1920 //\r
1921 // Create a device node for root bridge device with a NULL host bridge controller handle\r
1922 //\r
1923 RootBridgeDev = CreateRootBridge (Controller);\r
1924\r
1925 if (!RootBridgeDev) {\r
1926 Descriptors++;\r
1927 continue;\r
1928 }\r
1929\r
1930 //\r
1931 // Record the root bridge io protocol\r
1932 //\r
1933 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
1934\r
1935 Status = PciPciDeviceInfoCollector (\r
1936 RootBridgeDev,\r
1937 (UINT8) MinBus\r
1938 );\r
1939\r
1940 if (!EFI_ERROR (Status)) {\r
1941\r
1942 //\r
1943 // Remove those PCI devices which are rejected when full enumeration\r
1944 //\r
1945 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
1946\r
1947 //\r
1948 // Process option rom light\r
1949 //\r
1950 ProcessOptionRomLight (RootBridgeDev);\r
1951\r
1952 //\r
1953 // Determine attributes for all devices under this root bridge\r
1954 //\r
1955 DetermineDeviceAttribute (RootBridgeDev);\r
1956\r
1957 //\r
1958 // If successfully, insert the node into device pool\r
1959 //\r
1960 InsertRootBridge (RootBridgeDev);\r
1961 } else {\r
1962\r
1963 //\r
1964 // If unsuccessly, destroy the entire node\r
1965 //\r
1966 DestroyRootBridge (RootBridgeDev);\r
1967 }\r
1968\r
1969 Descriptors++;\r
1970 }\r
1971\r
1972 return EFI_SUCCESS;\r
1973}\r
1974\r
1975EFI_STATUS\r
1976PciGetBusRange (\r
1977 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,\r
1978 OUT UINT16 *MinBus,\r
1979 OUT UINT16 *MaxBus,\r
1980 OUT UINT16 *BusRange\r
1981 )\r
1982/*++\r
1983\r
1984Routine Description:\r
1985\r
1986 Get the bus range.\r
1987\r
1988Arguments:\r
1989\r
1990 Descriptors - A pointer to the address space descriptor.\r
1991 MinBus - The min bus.\r
1992 MaxBus - The max bus.\r
1993 BusRange - The bus range.\r
1994\r
1995Returns:\r
1996\r
1997 Status Code.\r
1998\r
1999--*/\r
2000// TODO: EFI_SUCCESS - add return value to function comment\r
2001// TODO: EFI_NOT_FOUND - add return value to function comment\r
2002{\r
2003\r
2004 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2005 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
2006 if (MinBus != NULL) {\r
2007 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
2008 }\r
2009\r
2010 if (MaxBus != NULL) {\r
2011 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
2012 }\r
2013\r
2014 if (BusRange != NULL) {\r
2015 *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
2016 }\r
2017\r
2018 return EFI_SUCCESS;\r
2019 }\r
2020\r
2021 (*Descriptors)++;\r
2022 }\r
2023\r
2024 return EFI_NOT_FOUND;\r
2025}\r
2026\r
2027EFI_STATUS\r
2028StartManagingRootBridge (\r
2029 IN PCI_IO_DEVICE *RootBridgeDev\r
2030 )\r
2031/*++\r
2032\r
2033Routine Description:\r
2034\r
2035\r
2036Arguments:\r
2037\r
2038Returns:\r
2039\r
2040 None\r
2041\r
2042--*/\r
2043// TODO: RootBridgeDev - add argument and description to function comment\r
2044// TODO: EFI_SUCCESS - add return value to function comment\r
2045{\r
2046 EFI_HANDLE RootBridgeHandle;\r
2047 EFI_STATUS Status;\r
2048 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2049\r
2050 //\r
2051 // Get the root bridge handle\r
2052 //\r
2053 RootBridgeHandle = RootBridgeDev->Handle;\r
2054 PciRootBridgeIo = NULL;\r
2055\r
2056 //\r
2057 // Get the pci root bridge io protocol\r
2058 //\r
2059 Status = gBS->OpenProtocol (\r
2060 RootBridgeHandle,\r
2061 &gEfiPciRootBridgeIoProtocolGuid,\r
2062 (VOID **) &PciRootBridgeIo,\r
2063 gPciBusDriverBinding.DriverBindingHandle,\r
2064 RootBridgeHandle,\r
2065 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2066 );\r
2067\r
2068 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
2069 return Status;\r
2070 }\r
2071\r
2072 //\r
2073 // Store the PciRootBridgeIo protocol into root bridge private data\r
2074 //\r
2075 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
2076\r
2077 return EFI_SUCCESS;\r
2078\r
2079}\r
2080\r
2081BOOLEAN\r
2082IsPciDeviceRejected (\r
2083 IN PCI_IO_DEVICE *PciIoDevice\r
2084 )\r
2085/*++\r
2086\r
2087Routine Description:\r
2088\r
2089 This routine can be used to check whether a PCI device should be rejected when light enumeration\r
2090\r
2091Arguments:\r
2092\r
2093Returns:\r
2094\r
2095 TRUE This device should be rejected\r
2096 FALSE This device shouldn't be rejected\r
2097\r
2098--*/\r
2099// TODO: PciIoDevice - add argument and description to function comment\r
2100{\r
2101 EFI_STATUS Status;\r
2102 UINT32 TestValue;\r
2103 UINT32 OldValue;\r
2104 UINT32 Mask;\r
2105 UINT8 BarOffset;\r
2106\r
2107 //\r
2108 // PPB should be skip!\r
2109 //\r
2110 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
2111 return FALSE;\r
2112 }\r
2113\r
2114 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
2115 //\r
2116 // Only test base registers for P2C\r
2117 //\r
2118 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
2119\r
2120 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
2121 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2122 if (EFI_ERROR (Status)) {\r
2123 continue;\r
2124 }\r
2125\r
2126 TestValue = TestValue & Mask;\r
2127 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2128 //\r
2129 // The bar isn't programed, so it should be rejected\r
2130 //\r
2131 return TRUE;\r
2132 }\r
2133 }\r
2134\r
2135 return FALSE;\r
2136 }\r
2137\r
2138 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
2139 //\r
2140 // Test PCI devices\r
2141 //\r
2142 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2143 if (EFI_ERROR (Status)) {\r
2144 continue;\r
2145 }\r
2146\r
2147 if (TestValue & 0x01) {\r
2148\r
2149 //\r
2150 // IO Bar\r
2151 //\r
2152\r
2153 Mask = 0xFFFFFFFC;\r
2154 TestValue = TestValue & Mask;\r
2155 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2156 return TRUE;\r
2157 }\r
2158\r
2159 } else {\r
2160\r
2161 //\r
2162 // Mem Bar\r
2163 //\r
2164\r
2165 Mask = 0xFFFFFFF0;\r
2166 TestValue = TestValue & Mask;\r
2167\r
2168 if ((TestValue & 0x07) == 0x04) {\r
2169\r
2170 //\r
2171 // Mem64 or PMem64\r
2172 //\r
2173 BarOffset += sizeof (UINT32);\r
2174 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2175\r
2176 //\r
2177 // Test its high 32-Bit BAR\r
2178 //\r
2179\r
2180 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2181 if (TestValue == OldValue) {\r
2182 return TRUE;\r
2183 }\r
2184 }\r
2185\r
2186 } else {\r
2187\r
2188 //\r
2189 // Mem32 or PMem32\r
2190 //\r
2191 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2192 return TRUE;\r
2193 }\r
2194 }\r
2195 }\r
2196 }\r
2197\r
2198 return FALSE;\r
2199}\r
2200\r
2201EFI_STATUS\r
ff62de37 2202ResetAllPpbBusNumber (\r
ead42efc 2203 IN PCI_IO_DEVICE *Bridge,\r
2204 IN UINT8 StartBusNumber\r
2205 )\r
2206/*++\r
2207\r
2208Routine Description:\r
2209\r
2210 TODO: Add function description\r
2211\r
2212Arguments:\r
2213\r
2214 Bridge - TODO: add argument description\r
2215 StartBusNumber - TODO: add argument description\r
2216\r
2217Returns:\r
2218\r
2219 EFI_SUCCESS - TODO: Add description for return value\r
2220\r
2221--*/\r
2222{\r
2223 EFI_STATUS Status;\r
2224 PCI_TYPE00 Pci;\r
2225 UINT8 Device;\r
2226 UINT32 Register;\r
2227 UINT8 Func;\r
2228 UINT64 Address;\r
ff62de37 2229 UINT8 SecondaryBus;\r
ead42efc 2230 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2231\r
2232 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
2233\r
2234 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
2235 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
2236\r
2237 //\r
2238 // Check to see whether a pci device is present\r
2239 //\r
2240 Status = PciDevicePresent (\r
2241 PciRootBridgeIo,\r
2242 &Pci,\r
2243 StartBusNumber,\r
2244 Device,\r
2245 Func\r
2246 );\r
2247\r
2248 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
ff62de37 2249\r
ead42efc 2250 Register = 0;\r
2251 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
2252 Status = PciRootBridgeIoRead (\r
2253 PciRootBridgeIo,\r
2254 &Pci,\r
2255 EfiPciWidthUint32,\r
2256 Address,\r
2257 1,\r
2258 &Register\r
2259 );\r
ff62de37 2260 SecondaryBus = (UINT8)(Register >> 8);\r
2261\r
2262 if (SecondaryBus != 0) {\r
2263 ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
2264 }\r
2265\r
ead42efc 2266 //\r
2267 // Reset register 18h, 19h, 1Ah on PCI Bridge\r
2268 //\r
2269 Register &= 0xFF000000;\r
2270 Status = PciRootBridgeIoWrite (\r
2271 PciRootBridgeIo,\r
2272 &Pci,\r
2273 EfiPciWidthUint32,\r
2274 Address,\r
2275 1,\r
2276 &Register\r
2277 );\r
2278 }\r
2279\r
2280 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
2281 //\r
2282 // Skip sub functions, this is not a multi function device\r
2283 //\r
2284 Func = PCI_MAX_FUNC;\r
2285 }\r
2286 }\r
2287 }\r
2288\r
2289 return EFI_SUCCESS;\r
2290}\r
2291\r