ec733ccbf33a74d2803acb6fb49fdb1afbb1604c
[people/mcb30/edk2.git] / edk2 / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / Pcibus.c
1 /**@file\r
2    Driver Binding functions for PCI bus module.\r
3    \r
4 Copyright (c) 2006, Intel Corporation                                                         \r
5 All rights reserved. This program and the accompanying materials                          \r
6 are licensed and made available under the terms and conditions of the BSD License         \r
7 which accompanies this distribution.  The full text of the license may be found at        \r
8 http://opensource.org/licenses/bsd-license.php                                            \r
9                                                                                           \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
12 \r
13 **/\r
14 \r
15 \r
16 #include "Pcibus.h"\r
17 \r
18 //\r
19 // PCI Bus Driver Global Variables\r
20 //\r
21 \r
22 EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {\r
23   PciBusDriverBindingSupported,\r
24   PciBusDriverBindingStart,\r
25   PciBusDriverBindingStop,\r
26   0xa,\r
27   NULL,\r
28   NULL\r
29 };\r
30 \r
31 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gEfiIncompatiblePciDeviceSupport = NULL;\r
32 EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];\r
33 UINTN                                         gPciHostBridgeNumber;\r
34 BOOLEAN                                       gFullEnumeration;\r
35 UINT64                                        gAllOne   = 0xFFFFFFFFFFFFFFFFULL;\r
36 UINT64                                        gAllZero  = 0;\r
37 \r
38 EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;\r
39 \r
40 //\r
41 // PCI Bus Driver Support Functions\r
42 //\r
43 /**\r
44   Initialize the global variables\r
45   publish the driver binding protocol\r
46 \r
47   @param[IN] ImageHandle,\r
48   @param[IN] *SystemTable\r
49 \r
50   @retval status of installing driver binding component name protocol.\r
51 \r
52 **/\r
53 EFI_STATUS\r
54 EFIAPI\r
55 PciBusEntryPoint (\r
56   IN EFI_HANDLE         ImageHandle,\r
57   IN EFI_SYSTEM_TABLE   *SystemTable\r
58   )\r
59 {\r
60   EFI_STATUS  Status;\r
61 \r
62   InitializePciDevicePool ();\r
63 \r
64   gFullEnumeration      = TRUE;\r
65 \r
66   gPciHostBridgeNumber  = 0;\r
67   \r
68   //\r
69   // Install driver model protocol(s).\r
70   //\r
71   Status = EfiLibInstallDriverBindingComponentName2 (\r
72              ImageHandle,\r
73              SystemTable,\r
74              &gPciBusDriverBinding,\r
75              ImageHandle,\r
76              &gPciBusComponentName,\r
77              &gPciBusComponentName2\r
78              );\r
79   ASSERT_EFI_ERROR (Status);\r
80 \r
81   InstallHotPlugRequestProtocol (&Status);\r
82   \r
83   return Status;\r
84 }\r
85 \r
86 /**\r
87   Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
88   than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.\r
89 \r
90   @param  This                Protocol instance pointer.\r
91   @param  ControllerHandle    Handle of device to test\r
92   @param  RemainingDevicePath Optional parameter use to pick a specific child\r
93                               device to start.\r
94 \r
95   @retval EFI_SUCCESS         This driver supports this device\r
96   @retval EFI_ALREADY_STARTED This driver is already running on this device\r
97   @retval other               This driver does not support this device\r
98 \r
99 **/\r
100 EFI_STATUS\r
101 EFIAPI\r
102 PciBusDriverBindingSupported (\r
103   IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
104   IN EFI_HANDLE                     Controller,\r
105   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
106   )\r
107 {\r
108   EFI_STATUS                      Status;\r
109   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
110   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
111   EFI_DEV_PATH_PTR                Node;\r
112 \r
113   if (RemainingDevicePath != NULL) {\r
114     Node.DevPath = RemainingDevicePath;\r
115     if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
116         Node.DevPath->SubType != HW_PCI_DP         ||\r
117         DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {\r
118       return EFI_UNSUPPORTED;\r
119     }\r
120   }\r
121   //\r
122   // Open the IO Abstraction(s) needed to perform the supported test\r
123   //\r
124   Status = gBS->OpenProtocol (\r
125                   Controller,\r
126                   &gEfiDevicePathProtocolGuid,\r
127                   (VOID **) &ParentDevicePath,\r
128                   This->DriverBindingHandle,\r
129                   Controller,\r
130                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
131                   );\r
132   if (Status == EFI_ALREADY_STARTED) {\r
133     return EFI_SUCCESS;\r
134   }\r
135 \r
136   if (EFI_ERROR (Status)) {\r
137     return Status;\r
138   }\r
139 \r
140   gBS->CloseProtocol (\r
141         Controller,\r
142         &gEfiDevicePathProtocolGuid,\r
143         This->DriverBindingHandle,\r
144         Controller\r
145         );\r
146 \r
147   Status = gBS->OpenProtocol (\r
148                   Controller,\r
149                   &gEfiPciRootBridgeIoProtocolGuid,\r
150                   (VOID **) &PciRootBridgeIo,\r
151                   This->DriverBindingHandle,\r
152                   Controller,\r
153                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
154                   );\r
155   if (Status == EFI_ALREADY_STARTED) {\r
156     return EFI_SUCCESS;\r
157   }\r
158 \r
159   if (EFI_ERROR (Status)) {\r
160     return Status;\r
161   }\r
162 \r
163   gBS->CloseProtocol (\r
164         Controller,\r
165         &gEfiPciRootBridgeIoProtocolGuid,\r
166         This->DriverBindingHandle,\r
167         Controller\r
168         );\r
169 \r
170   return EFI_SUCCESS;\r
171 }\r
172 \r
173 /**\r
174   Start this driver on ControllerHandle and enumerate Pci bus and start\r
175   all device under PCI bus.\r
176 \r
177   @param  This                 Protocol instance pointer.\r
178   @param  ControllerHandle     Handle of device to bind driver to\r
179   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
180                                device to start.\r
181 \r
182   @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
183   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
184   @retval other                This driver does not support this device\r
185 \r
186 **/\r
187 EFI_STATUS\r
188 EFIAPI\r
189 PciBusDriverBindingStart (\r
190   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
191   IN EFI_HANDLE                   Controller,\r
192   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
193   )\r
194 {\r
195   EFI_STATUS  Status;\r
196 \r
197   Status = gBS->LocateProtocol (\r
198                   &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
199                   NULL,\r
200                   (VOID **) &gEfiIncompatiblePciDeviceSupport\r
201                   );\r
202 \r
203   //\r
204   // If PCI Platform protocol is available, get it now.\r
205   // If the platform implements this, it must be installed before BDS phase\r
206   //\r
207   gPciPlatformProtocol = NULL;\r
208   gBS->LocateProtocol (\r
209         &gEfiPciPlatformProtocolGuid,\r
210         NULL,\r
211         (VOID **) &gPciPlatformProtocol\r
212         );\r
213 \r
214   gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));\r
215 \r
216   //\r
217   // Enumerate the entire host bridge\r
218   // After enumeration, a database that records all the device information will be created\r
219   //\r
220   //\r
221   Status = PciEnumerator (Controller);\r
222 \r
223   if (EFI_ERROR (Status)) {\r
224     return Status;\r
225   }\r
226   \r
227   //\r
228   // Start all the devices under the entire host bridge.\r
229   //\r
230   StartPciDevices (Controller);\r
231 \r
232   return EFI_SUCCESS;\r
233 }\r
234 \r
235 /**\r
236   Stop this driver on ControllerHandle. Support stoping any child handles\r
237   created by this driver.\r
238 \r
239   @param  This              Protocol instance pointer.\r
240   @param  ControllerHandle  Handle of device to stop driver on\r
241   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
242                             children is zero stop the entire bus driver.\r
243   @param  ChildHandleBuffer List of Child Handles to Stop.\r
244 \r
245   @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
246   @retval other             This driver was not removed from this device\r
247 \r
248 **/\r
249 EFI_STATUS\r
250 EFIAPI\r
251 PciBusDriverBindingStop (\r
252   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
253   IN  EFI_HANDLE                    Controller,\r
254   IN  UINTN                         NumberOfChildren,\r
255   IN  EFI_HANDLE                    *ChildHandleBuffer\r
256   )\r
257 {\r
258   EFI_STATUS  Status;\r
259   UINTN       Index;\r
260   BOOLEAN     AllChildrenStopped;\r
261 \r
262   if (NumberOfChildren == 0) {\r
263     //\r
264     // Close the bus driver\r
265     //\r
266     gBS->CloseProtocol (\r
267           Controller,\r
268           &gEfiDevicePathProtocolGuid,\r
269           This->DriverBindingHandle,\r
270           Controller\r
271           );\r
272     gBS->CloseProtocol (\r
273           Controller,\r
274           &gEfiPciRootBridgeIoProtocolGuid,\r
275           This->DriverBindingHandle,\r
276           Controller\r
277           );\r
278 \r
279     DestroyRootBridgeByHandle (\r
280       Controller\r
281       );\r
282 \r
283     return EFI_SUCCESS;\r
284   }\r
285 \r
286   //\r
287   // Stop all the children\r
288   //\r
289 \r
290   AllChildrenStopped = TRUE;\r
291 \r
292   for (Index = 0; Index < NumberOfChildren; Index++) {\r
293 \r
294     //\r
295     // De register all the pci device\r
296     //\r
297     Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);\r
298 \r
299     if (EFI_ERROR (Status)) {\r
300       AllChildrenStopped = FALSE;\r
301     }\r
302   }\r
303 \r
304   if (!AllChildrenStopped) {\r
305     return EFI_DEVICE_ERROR;\r
306   }\r
307 \r
308   return EFI_SUCCESS;\r
309 }\r
310 \r