1 /*++ 2 3 Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 PciDeviceSupport.c 15 16 Abstract: 17 18 This file provides routine to support Pci device node manipulation 19 20 Revision History 21 22 --*/ 23 24 #include "PciBus.h" 25 26 // 27 // This device structure is serviced as a header. 28 // Its Next field points to the first root bridge device node 29 // 30 LIST_ENTRY gPciDevicePool; 31 32 EFI_STATUS 33 InitializePciDevicePool ( 34 VOID 35 ) 36 /*++ 37 38 Routine Description: 39 40 Initialize the gPciDevicePool 41 42 Arguments: 43 44 Returns: 45 46 None 47 48 --*/ 49 { 50 InitializeListHead (&gPciDevicePool); 51 52 return EFI_SUCCESS; 53 } 54 55 EFI_STATUS 56 InsertRootBridge ( 57 IN PCI_IO_DEVICE *RootBridge 58 ) 59 /*++ 60 61 Routine Description: 62 63 Insert a root bridge into PCI device pool 64 65 Arguments: 66 67 RootBridge - A pointer to the PCI_IO_DEVICE. 68 69 Returns: 70 71 None 72 73 --*/ 74 { 75 InsertTailList (&gPciDevicePool, &(RootBridge->Link)); 76 77 return EFI_SUCCESS; 78 } 79 80 EFI_STATUS 81 InsertPciDevice ( 82 PCI_IO_DEVICE *Bridge, 83 PCI_IO_DEVICE *PciDeviceNode 84 ) 85 /*++ 86 87 Routine Description: 88 89 This function is used to insert a PCI device node under 90 a bridge 91 92 Arguments: 93 Bridge - A pointer to the PCI_IO_DEVICE. 94 PciDeviceNode - A pointer to the PCI_IO_DEVICE. 95 96 Returns: 97 98 None 99 100 --*/ 101 102 { 103 104 InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link)); 105 PciDeviceNode->Parent = Bridge; 106 107 return EFI_SUCCESS; 108 } 109 110 EFI_STATUS 111 DestroyRootBridge ( 112 IN PCI_IO_DEVICE *RootBridge 113 ) 114 /*++ 115 116 Routine Description: 117 118 119 Arguments: 120 121 RootBridge - A pointer to the PCI_IO_DEVICE. 122 123 Returns: 124 125 None 126 127 --*/ 128 { 129 DestroyPciDeviceTree (RootBridge); 130 131 gBS->FreePool (RootBridge); 132 133 return EFI_SUCCESS; 134 } 135 136 EFI_STATUS 137 DestroyPciDeviceTree ( 138 IN PCI_IO_DEVICE *Bridge 139 ) 140 /*++ 141 142 Routine Description: 143 144 Destroy all the pci device node under the bridge. 145 Bridge itself is not included. 146 147 Arguments: 148 149 Bridge - A pointer to the PCI_IO_DEVICE. 150 151 Returns: 152 153 None 154 155 --*/ 156 { 157 LIST_ENTRY *CurrentLink; 158 PCI_IO_DEVICE *Temp; 159 160 while (!IsListEmpty (&Bridge->ChildList)) { 161 162 CurrentLink = Bridge->ChildList.ForwardLink; 163 164 // 165 // Remove this node from the linked list 166 // 167 RemoveEntryList (CurrentLink); 168 169 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 170 171 if (IS_PCI_BRIDGE (&(Temp->Pci))) { 172 DestroyPciDeviceTree (Temp); 173 } 174 gBS->FreePool (Temp); 175 } 176 177 return EFI_SUCCESS; 178 } 179 180 EFI_STATUS 181 DestroyRootBridgeByHandle ( 182 EFI_HANDLE Controller 183 ) 184 /*++ 185 186 Routine Description: 187 188 Destroy all device nodes under the root bridge 189 specified by Controller. 190 The root bridge itself is also included. 191 192 Arguments: 193 194 Controller - An efi handle. 195 196 Returns: 197 198 None 199 200 --*/ 201 { 202 203 LIST_ENTRY *CurrentLink; 204 PCI_IO_DEVICE *Temp; 205 206 CurrentLink = gPciDevicePool.ForwardLink; 207 208 while (CurrentLink && CurrentLink != &gPciDevicePool) { 209 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 210 211 if (Temp->Handle == Controller) { 212 213 RemoveEntryList (CurrentLink); 214 215 DestroyPciDeviceTree (Temp); 216 217 gBS->FreePool(Temp); 218 219 return EFI_SUCCESS; 220 } 221 222 CurrentLink = CurrentLink->ForwardLink; 223 } 224 225 return EFI_NOT_FOUND; 226 } 227 228 EFI_STATUS 229 RegisterPciDevice ( 230 IN EFI_HANDLE Controller, 231 IN PCI_IO_DEVICE *PciIoDevice, 232 OUT EFI_HANDLE *Handle OPTIONAL 233 ) 234 /*++ 235 236 Routine Description: 237 238 This function registers the PCI IO device. It creates a handle for this PCI IO device 239 (if the handle does not exist), attaches appropriate protocols onto the handle, does 240 necessary initialization, and sets up parent/child relationship with its bus controller. 241 242 Arguments: 243 244 Controller - An EFI handle for the PCI bus controller. 245 PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered. 246 Handle - A pointer to hold the EFI handle for the PCI IO device. 247 248 Returns: 249 250 EFI_SUCCESS - The PCI device is successfully registered. 251 Others - An error occurred when registering the PCI device. 252 253 --*/ 254 { 255 EFI_STATUS Status; 256 UINT8 PciExpressCapRegOffset; 257 258 // 259 // Install the pciio protocol, device path protocol and 260 // Bus Specific Driver Override Protocol 261 // 262 263 if (PciIoDevice->BusOverride) { 264 Status = gBS->InstallMultipleProtocolInterfaces ( 265 &PciIoDevice->Handle, 266 &gEfiDevicePathProtocolGuid, 267 PciIoDevice->DevicePath, 268 &gEfiPciIoProtocolGuid, 269 &PciIoDevice->PciIo, 270 &gEfiBusSpecificDriverOverrideProtocolGuid, 271 &PciIoDevice->PciDriverOverride, 272 NULL 273 ); 274 } else { 275 Status = gBS->InstallMultipleProtocolInterfaces ( 276 &PciIoDevice->Handle, 277 &gEfiDevicePathProtocolGuid, 278 PciIoDevice->DevicePath, 279 &gEfiPciIoProtocolGuid, 280 &PciIoDevice->PciIo, 281 NULL 282 ); 283 } 284 285 if (EFI_ERROR (Status)) { 286 return Status; 287 } else { 288 Status = gBS->OpenProtocol ( 289 Controller, 290 &gEfiPciRootBridgeIoProtocolGuid, 291 (VOID **)&(PciIoDevice->PciRootBridgeIo), 292 gPciBusDriverBinding.DriverBindingHandle, 293 PciIoDevice->Handle, 294 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 295 ); 296 if (EFI_ERROR (Status)) { 297 return Status; 298 } 299 } 300 301 if (Handle != NULL) { 302 *Handle = PciIoDevice->Handle; 303 } 304 305 // 306 // Detect if PCI Express Device 307 // 308 PciExpressCapRegOffset = 0; 309 Status = LocateCapabilityRegBlock ( 310 PciIoDevice, 311 EFI_PCI_CAPABILITY_ID_PCIEXP, 312 &PciExpressCapRegOffset, 313 NULL 314 ); 315 if (!EFI_ERROR (Status)) { 316 PciIoDevice->IsPciExp = TRUE; 317 DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber)); 318 } 319 320 // 321 // Indicate the pci device is registered 322 // 323 PciIoDevice->Registered = TRUE; 324 325 return EFI_SUCCESS; 326 } 327 328 329 EFI_STATUS 330 DeRegisterPciDevice ( 331 IN EFI_HANDLE Controller, 332 IN EFI_HANDLE Handle 333 ) 334 /*++ 335 336 Routine Description: 337 338 This function is used to de-register the PCI device from the EFI, 339 That includes un-installing PciIo protocol from the specified PCI 340 device handle. 341 342 Arguments: 343 344 Controller - An efi handle. 345 Handle - An efi handle. 346 347 Returns: 348 349 None 350 351 --*/ 352 { 353 EFI_PCI_IO_PROTOCOL *PciIo; 354 EFI_STATUS Status; 355 PCI_IO_DEVICE *PciIoDevice; 356 PCI_IO_DEVICE *Node; 357 LIST_ENTRY *CurrentLink; 358 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 359 360 Status = gBS->OpenProtocol ( 361 Handle, 362 &gEfiPciIoProtocolGuid, 363 (VOID **) &PciIo, 364 gPciBusDriverBinding.DriverBindingHandle, 365 Controller, 366 EFI_OPEN_PROTOCOL_GET_PROTOCOL 367 ); 368 if (!EFI_ERROR (Status)) { 369 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); 370 371 // 372 // If it is already de-registered 373 // 374 if (!PciIoDevice->Registered) { 375 return EFI_SUCCESS; 376 } 377 378 // 379 // If it is PPB, first de-register its children 380 // 381 382 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) { 383 384 CurrentLink = PciIoDevice->ChildList.ForwardLink; 385 386 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { 387 Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 388 Status = DeRegisterPciDevice (Controller, Node->Handle); 389 390 if (EFI_ERROR (Status)) { 391 return Status; 392 } 393 394 CurrentLink = CurrentLink->ForwardLink; 395 } 396 } 397 398 // 399 // First disconnect this device 400 // 401 // PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo), 402 // EfiPciIoAttributeOperationDisable, 403 // EFI_PCI_DEVICE_ENABLE, 404 // NULL 405 // ); 406 407 // 408 // Close the child handle 409 // 410 Status = gBS->CloseProtocol ( 411 Controller, 412 &gEfiPciRootBridgeIoProtocolGuid, 413 gPciBusDriverBinding.DriverBindingHandle, 414 Handle 415 ); 416 417 // 418 // Un-install the device path protocol and pci io protocol 419 // 420 if (PciIoDevice->BusOverride) { 421 Status = gBS->UninstallMultipleProtocolInterfaces ( 422 Handle, 423 &gEfiDevicePathProtocolGuid, 424 PciIoDevice->DevicePath, 425 &gEfiPciIoProtocolGuid, 426 &PciIoDevice->PciIo, 427 &gEfiBusSpecificDriverOverrideProtocolGuid, 428 &PciIoDevice->PciDriverOverride, 429 NULL 430 ); 431 } else { 432 Status = gBS->UninstallMultipleProtocolInterfaces ( 433 Handle, 434 &gEfiDevicePathProtocolGuid, 435 PciIoDevice->DevicePath, 436 &gEfiPciIoProtocolGuid, 437 &PciIoDevice->PciIo, 438 NULL 439 ); 440 } 441 442 if (EFI_ERROR (Status)) { 443 gBS->OpenProtocol ( 444 Controller, 445 &gEfiPciRootBridgeIoProtocolGuid, 446 (VOID **) &PciRootBridgeIo, 447 gPciBusDriverBinding.DriverBindingHandle, 448 Handle, 449 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 450 ); 451 return Status; 452 } 453 454 // 455 // The Device Driver should disable this device after disconnect 456 // so the Pci Bus driver will not touch this device any more. 457 // Restore the register field to the original value 458 // 459 PciIoDevice->Registered = FALSE; 460 PciIoDevice->Handle = NULL; 461 } else { 462 463 // 464 // Handle may be closed before 465 // 466 return EFI_SUCCESS; 467 } 468 469 return EFI_SUCCESS; 470 } 471 472 EFI_STATUS 473 EnableBridgeAttributes ( 474 IN PCI_IO_DEVICE *PciIoDevice 475 ) 476 { 477 PCI_TYPE01 PciData; 478 479 // 480 // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge 481 // directly, because some legacy BIOS will NOT assign 482 // IO or Memory resource for a bridge who has no child 483 // device. So we add check IO or Memory here. 484 // 485 486 PciIoDevice->PciIo.Pci.Read ( 487 &PciIoDevice->PciIo, 488 EfiPciIoWidthUint8, 489 0, 490 sizeof (PciData), 491 &PciData 492 ); 493 494 if ((((PciData.Bridge.IoBase & 0xF) == 0) && 495 (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) || 496 (((PciData.Bridge.IoBase & 0xF) == 1) && 497 ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) { 498 PciIoDevice->PciIo.Attributes( 499 &(PciIoDevice->PciIo), 500 EfiPciIoAttributeOperationEnable, 501 (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), 502 NULL 503 ); 504 } 505 if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) { 506 PciIoDevice->PciIo.Attributes( 507 &(PciIoDevice->PciIo), 508 EfiPciIoAttributeOperationEnable, 509 (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), 510 NULL 511 ); 512 } 513 if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) && 514 (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) || 515 (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) && 516 ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) { 517 PciIoDevice->PciIo.Attributes( 518 &(PciIoDevice->PciIo), 519 EfiPciIoAttributeOperationEnable, 520 (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), 521 NULL 522 ); 523 } 524 525 return EFI_SUCCESS; 526 } 527 528 EFI_STATUS 529 StartPciDevicesOnBridge ( 530 IN EFI_HANDLE Controller, 531 IN PCI_IO_DEVICE *RootBridge, 532 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 533 ) 534 /*++ 535 536 Routine Description: 537 538 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge 539 540 Arguments: 541 542 Controller - An efi handle. 543 RootBridge - A pointer to the PCI_IO_DEVICE. 544 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. 545 NumberOfChildren - Children number. 546 ChildHandleBuffer - A pointer to the child handle buffer. 547 548 Returns: 549 550 None 551 552 --*/ 553 { 554 PCI_IO_DEVICE *Temp; 555 PCI_IO_DEVICE *PciIoDevice; 556 EFI_DEV_PATH_PTR Node; 557 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; 558 EFI_STATUS Status; 559 LIST_ENTRY *CurrentLink; 560 561 CurrentLink = RootBridge->ChildList.ForwardLink; 562 563 while (CurrentLink && CurrentLink != &RootBridge->ChildList) { 564 565 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 566 if (RemainingDevicePath != NULL) { 567 568 Node.DevPath = RemainingDevicePath; 569 570 if (Node.Pci->Device != Temp->DeviceNumber || 571 Node.Pci->Function != Temp->FunctionNumber) { 572 CurrentLink = CurrentLink->ForwardLink; 573 continue; 574 } 575 576 // 577 // Check if the device has been assigned with required resource 578 // 579 if (!Temp->Allocated) { 580 return EFI_NOT_READY; 581 } 582 583 // 584 // Check if the current node has been registered before 585 // If it is not, register it 586 // 587 if (!Temp->Registered) { 588 PciIoDevice = Temp; 589 590 Status = RegisterPciDevice ( 591 Controller, 592 PciIoDevice, 593 NULL 594 ); 595 596 } 597 598 // 599 // Get the next device path 600 // 601 CurrentDevicePath = NextDevicePathNode (RemainingDevicePath); 602 if (IsDevicePathEnd (CurrentDevicePath)) { 603 return EFI_SUCCESS; 604 } 605 606 // 607 // If it is a PPB 608 // 609 if (IS_PCI_BRIDGE (&(Temp->Pci))) { 610 Status = StartPciDevicesOnBridge ( 611 Controller, 612 Temp, 613 CurrentDevicePath 614 ); 615 EnableBridgeAttributes (Temp); 616 617 return Status; 618 } else { 619 620 // 621 // Currently, the PCI bus driver only support PCI-PCI bridge 622 // 623 return EFI_UNSUPPORTED; 624 } 625 626 } else { 627 628 // 629 // If remaining device path is NULL, 630 // try to enable all the pci devices under this bridge 631 // 632 633 if (!Temp->Registered && Temp->Allocated) { 634 635 PciIoDevice = Temp; 636 637 Status = RegisterPciDevice ( 638 Controller, 639 PciIoDevice, 640 NULL 641 ); 642 643 } 644 645 if (IS_PCI_BRIDGE (&(Temp->Pci))) { 646 Status = StartPciDevicesOnBridge ( 647 Controller, 648 Temp, 649 RemainingDevicePath 650 ); 651 EnableBridgeAttributes (Temp); 652 } 653 654 CurrentLink = CurrentLink->ForwardLink; 655 continue; 656 } 657 } 658 659 return EFI_NOT_FOUND; 660 } 661 662 EFI_STATUS 663 StartPciDevices ( 664 IN EFI_HANDLE Controller, 665 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 666 ) 667 /*++ 668 669 Routine Description: 670 671 Start to manage the PCI device according to RemainingDevicePath 672 If RemainingDevicePath == NULL, the PCI bus driver will start 673 to manage all the PCI devices it found previously 674 675 Arguments: 676 Controller - An efi handle. 677 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. 678 679 Returns: 680 681 None 682 683 --*/ 684 { 685 EFI_DEV_PATH_PTR Node; 686 PCI_IO_DEVICE *RootBridge; 687 LIST_ENTRY *CurrentLink; 688 689 if (RemainingDevicePath != NULL) { 690 691 // 692 // Check if the RemainingDevicePath is valid 693 // 694 Node.DevPath = RemainingDevicePath; 695 if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || 696 Node.DevPath->SubType != HW_PCI_DP || 697 DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH) 698 ) { 699 return EFI_UNSUPPORTED; 700 } 701 } 702 703 CurrentLink = gPciDevicePool.ForwardLink; 704 705 while (CurrentLink && CurrentLink != &gPciDevicePool) { 706 707 RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 708 // 709 // Locate the right root bridge to start 710 // 711 if (RootBridge->Handle == Controller) { 712 StartPciDevicesOnBridge ( 713 Controller, 714 RootBridge, 715 RemainingDevicePath 716 ); 717 } 718 719 CurrentLink = CurrentLink->ForwardLink; 720 } 721 722 return EFI_SUCCESS; 723 } 724 725 PCI_IO_DEVICE * 726 CreateRootBridge ( 727 IN EFI_HANDLE RootBridgeHandle 728 ) 729 /*++ 730 731 Routine Description: 732 733 734 Arguments: 735 RootBridgeHandle - An efi handle. 736 737 Returns: 738 739 None 740 741 --*/ 742 { 743 744 EFI_STATUS Status; 745 PCI_IO_DEVICE *Dev; 746 747 Dev = NULL; 748 Status = gBS->AllocatePool ( 749 EfiBootServicesData, 750 sizeof (PCI_IO_DEVICE), 751 (VOID **) &Dev 752 ); 753 754 if (EFI_ERROR (Status)) { 755 return NULL; 756 } 757 758 ZeroMem (Dev, sizeof (PCI_IO_DEVICE)); 759 Dev->Signature = PCI_IO_DEVICE_SIGNATURE; 760 Dev->Handle = RootBridgeHandle; 761 InitializeListHead (&Dev->ChildList); 762 763 return Dev; 764 } 765 766 PCI_IO_DEVICE * 767 GetRootBridgeByHandle ( 768 EFI_HANDLE RootBridgeHandle 769 ) 770 /*++ 771 772 Routine Description: 773 774 775 Arguments: 776 777 RootBridgeHandle - An efi handle. 778 779 Returns: 780 781 None 782 783 --*/ 784 { 785 PCI_IO_DEVICE *RootBridgeDev; 786 LIST_ENTRY *CurrentLink; 787 788 CurrentLink = gPciDevicePool.ForwardLink; 789 790 while (CurrentLink && CurrentLink != &gPciDevicePool) { 791 792 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 793 if (RootBridgeDev->Handle == RootBridgeHandle) { 794 return RootBridgeDev; 795 } 796 797 CurrentLink = CurrentLink->ForwardLink; 798 } 799 800 return NULL; 801 } 802 803 BOOLEAN 804 RootBridgeExisted ( 805 IN EFI_HANDLE RootBridgeHandle 806 ) 807 /*++ 808 809 Routine Description: 810 811 This function searches if RootBridgeHandle has already existed 812 in current device pool. 813 814 If so, it means the given root bridge has been already enumerated. 815 816 Arguments: 817 818 RootBridgeHandle - An efi handle. 819 820 Returns: 821 822 None 823 824 --*/ 825 { 826 PCI_IO_DEVICE *Bridge; 827 828 Bridge = GetRootBridgeByHandle (RootBridgeHandle); 829 830 if (Bridge != NULL) { 831 return TRUE; 832 } 833 834 return FALSE; 835 } 836 837 BOOLEAN 838 PciDeviceExisted ( 839 IN PCI_IO_DEVICE *Bridge, 840 IN PCI_IO_DEVICE *PciIoDevice 841 ) 842 /*++ 843 844 Routine Description: 845 846 Arguments: 847 848 Bridge - A pointer to the PCI_IO_DEVICE. 849 PciIoDevice - A pointer to the PCI_IO_DEVICE. 850 851 Returns: 852 853 None 854 855 --*/ 856 { 857 858 PCI_IO_DEVICE *Temp; 859 LIST_ENTRY *CurrentLink; 860 861 CurrentLink = Bridge->ChildList.ForwardLink; 862 863 while (CurrentLink && CurrentLink != &Bridge->ChildList) { 864 865 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 866 867 if (Temp == PciIoDevice) { 868 return TRUE; 869 } 870 871 if (!IsListEmpty (&Temp->ChildList)) { 872 if (PciDeviceExisted (Temp, PciIoDevice)) { 873 return TRUE; 874 } 875 } 876 877 CurrentLink = CurrentLink->ForwardLink; 878 } 879 880 return FALSE; 881 } 882 883 PCI_IO_DEVICE * 884 ActiveVGADeviceOnTheSameSegment ( 885 IN PCI_IO_DEVICE *VgaDevice 886 ) 887 /*++ 888 889 Routine Description: 890 891 Arguments: 892 893 VgaDevice - A pointer to the PCI_IO_DEVICE. 894 895 Returns: 896 897 None 898 899 --*/ 900 { 901 LIST_ENTRY *CurrentLink; 902 PCI_IO_DEVICE *Temp; 903 904 CurrentLink = gPciDevicePool.ForwardLink; 905 906 while (CurrentLink && CurrentLink != &gPciDevicePool) { 907 908 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 909 910 if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) { 911 912 Temp = ActiveVGADeviceOnTheRootBridge (Temp); 913 914 if (Temp != NULL) { 915 return Temp; 916 } 917 } 918 919 CurrentLink = CurrentLink->ForwardLink; 920 } 921 922 return NULL; 923 } 924 925 PCI_IO_DEVICE * 926 ActiveVGADeviceOnTheRootBridge ( 927 IN PCI_IO_DEVICE *RootBridge 928 ) 929 /*++ 930 931 Routine Description: 932 933 Arguments: 934 935 RootBridge - A pointer to the PCI_IO_DEVICE. 936 937 Returns: 938 939 None 940 941 --*/ 942 { 943 LIST_ENTRY *CurrentLink; 944 PCI_IO_DEVICE *Temp; 945 946 CurrentLink = RootBridge->ChildList.ForwardLink; 947 948 while (CurrentLink && CurrentLink != &RootBridge->ChildList) { 949 950 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 951 952 if (IS_PCI_VGA(&Temp->Pci) && 953 (Temp->Attributes & 954 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | 955 EFI_PCI_IO_ATTRIBUTE_VGA_IO | 956 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) { 957 return Temp; 958 } 959 960 if (IS_PCI_BRIDGE (&Temp->Pci)) { 961 962 Temp = ActiveVGADeviceOnTheRootBridge (Temp); 963 964 if (Temp != NULL) { 965 return Temp; 966 } 967 } 968 969 CurrentLink = CurrentLink->ForwardLink; 970 } 971 972 return NULL; 973 } 974