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