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