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