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
InitializePciDevicePool(VOID)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
InsertRootBridge(IN PCI_IO_DEVICE * RootBridge)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
InsertPciDevice(PCI_IO_DEVICE * Bridge,PCI_IO_DEVICE * PciDeviceNode)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
DestroyRootBridge(IN PCI_IO_DEVICE * RootBridge)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
DestroyPciDeviceTree(IN PCI_IO_DEVICE * Bridge)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
DestroyRootBridgeByHandle(EFI_HANDLE Controller)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
RegisterPciDevice(IN EFI_HANDLE Controller,IN PCI_IO_DEVICE * PciIoDevice,OUT EFI_HANDLE * Handle OPTIONAL)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
DeRegisterPciDevice(IN EFI_HANDLE Controller,IN EFI_HANDLE Handle)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
EnableBridgeAttributes(IN PCI_IO_DEVICE * PciIoDevice)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
StartPciDevicesOnBridge(IN EFI_HANDLE Controller,IN PCI_IO_DEVICE * RootBridge,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
StartPciDevices(IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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 *
CreateRootBridge(IN EFI_HANDLE RootBridgeHandle)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 *
GetRootBridgeByHandle(EFI_HANDLE RootBridgeHandle)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
RootBridgeExisted(IN EFI_HANDLE RootBridgeHandle)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
PciDeviceExisted(IN PCI_IO_DEVICE * Bridge,IN PCI_IO_DEVICE * PciIoDevice)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 *
ActiveVGADeviceOnTheSameSegment(IN PCI_IO_DEVICE * VgaDevice)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 *
ActiveVGADeviceOnTheRootBridge(IN PCI_IO_DEVICE * RootBridge)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