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   PciBus.c
15 
16 Abstract:
17 
18   PCI Bus Driver
19 
20 Revision History
21 
22 --*/
23 
24 #include "PciBus.h"
25 
26 //
27 // PCI Bus Support Function Prototypes
28 //
29 
30 EFI_STATUS
31 EFIAPI
32 PciBusEntryPoint (
33   IN EFI_HANDLE         ImageHandle,
34   IN EFI_SYSTEM_TABLE   *SystemTable
35   );
36 
37 EFI_STATUS
38 EFIAPI
39 PciBusDriverBindingSupported (
40   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
41   IN EFI_HANDLE                     Controller,
42   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
43   );
44 
45 EFI_STATUS
46 EFIAPI
47 PciBusDriverBindingStart (
48   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
49   IN EFI_HANDLE                     Controller,
50   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
51   );
52 
53 EFI_STATUS
54 EFIAPI
55 PciBusDriverBindingStop (
56   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
57   IN  EFI_HANDLE                    Controller,
58   IN  UINTN                         NumberOfChildren,
59   IN  EFI_HANDLE                    *ChildHandleBuffer
60   );
61 
62 
63 //
64 // PCI Bus Driver Global Variables
65 //
66 
67 EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
68   PciBusDriverBindingSupported,
69   PciBusDriverBindingStart,
70   PciBusDriverBindingStop,
71   0xa,
72   NULL,
73   NULL
74 };
75 
76 BOOLEAN gFullEnumeration;
77 
78 UINT64 gAllOne    = 0xFFFFFFFFFFFFFFFFULL;
79 UINT64 gAllZero   = 0;
80 
81 //
82 // PCI Bus Driver Support Functions
83 //
84 EFI_STATUS
85 EFIAPI
PciBusEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)86 PciBusEntryPoint (
87   IN EFI_HANDLE         ImageHandle,
88   IN EFI_SYSTEM_TABLE   *SystemTable
89   )
90 /*++
91 
92 Routine Description:
93 
94   Initialize the global variables
95   publish the driver binding protocol
96 
97 Arguments:
98 
99   IN EFI_HANDLE     ImageHandle,
100   IN EFI_SYSTEM_TABLE   *SystemTable
101 
102 Returns:
103 
104   EFI_SUCCESS
105   EFI_DEVICE_ERROR
106 
107 --*/
108 {
109   EFI_STATUS         Status;
110 
111   //
112   // Initialize the EFI Driver Library
113   //
114   Status = EfiLibInstallDriverBindingComponentName2 (
115              ImageHandle,
116              SystemTable,
117              &gPciBusDriverBinding,
118              ImageHandle,
119              &gPciBusComponentName,
120              &gPciBusComponentName2
121              );
122   ASSERT_EFI_ERROR (Status);
123 
124   InitializePciDevicePool ();
125 
126   gFullEnumeration = TRUE;
127 
128   return Status;
129 }
130 
131 EFI_STATUS
132 EFIAPI
PciBusDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)133 PciBusDriverBindingSupported (
134   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
135   IN EFI_HANDLE                     Controller,
136   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
137   )
138 /*++
139 
140 Routine Description:
141 
142   Check to see if pci bus driver supports the given controller
143 
144 Arguments:
145 
146   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
147   IN EFI_HANDLE                     Controller,
148   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
149 
150 Returns:
151 
152   EFI_SUCCESS
153 
154 --*/
155 {
156   EFI_STATUS                      Status;
157   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
158   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
159   EFI_DEV_PATH_PTR                Node;
160 
161   if (RemainingDevicePath != NULL) {
162     Node.DevPath = RemainingDevicePath;
163     if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
164         Node.DevPath->SubType != HW_PCI_DP         ||
165         DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
166       return EFI_UNSUPPORTED;
167     }
168   }
169   //
170   // Open the IO Abstraction(s) needed to perform the supported test
171   //
172   Status = gBS->OpenProtocol (
173                   Controller,
174                   &gEfiDevicePathProtocolGuid,
175                   (VOID **) &ParentDevicePath,
176                   This->DriverBindingHandle,
177                   Controller,
178                   EFI_OPEN_PROTOCOL_BY_DRIVER
179                   );
180   if (Status == EFI_ALREADY_STARTED) {
181     return EFI_SUCCESS;
182   }
183 
184   if (EFI_ERROR (Status)) {
185     return Status;
186   }
187 
188   gBS->CloseProtocol (
189         Controller,
190         &gEfiDevicePathProtocolGuid,
191         This->DriverBindingHandle,
192         Controller
193         );
194 
195   Status = gBS->OpenProtocol (
196                   Controller,
197                   &gEfiPciRootBridgeIoProtocolGuid,
198                   (VOID **) &PciRootBridgeIo,
199                   This->DriverBindingHandle,
200                   Controller,
201                   EFI_OPEN_PROTOCOL_BY_DRIVER
202                   );
203   if (Status == EFI_ALREADY_STARTED) {
204     return EFI_SUCCESS;
205   }
206 
207   if (EFI_ERROR (Status)) {
208     return Status;
209   }
210 
211   gBS->CloseProtocol (
212          Controller,
213          &gEfiPciRootBridgeIoProtocolGuid,
214          This->DriverBindingHandle,
215          Controller
216          );
217 
218   return EFI_SUCCESS;
219 }
220 
221 EFI_STATUS
222 EFIAPI
PciBusDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)223 PciBusDriverBindingStart (
224   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
225   IN EFI_HANDLE                   Controller,
226   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
227   )
228 /*++
229 
230 Routine Description:
231 
232   Start to management the controller passed in
233 
234 Arguments:
235 
236   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
237   IN EFI_HANDLE                   Controller,
238   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
239 
240 Returns:
241 
242 
243 --*/
244 {
245   EFI_STATUS                          Status;
246 
247   //
248   // Enumerate the entire host bridge
249   // After enumeration, a database that records all the device information will be created
250   //
251   //
252   Status = PciEnumerator (Controller);
253 
254   if (EFI_ERROR (Status)) {
255     return Status;
256   }
257 
258   //
259   // Enable PCI device specified by remaining device path. BDS or other driver can call the
260   // start more than once.
261   //
262 
263   StartPciDevices (Controller, RemainingDevicePath);
264 
265   return EFI_SUCCESS;
266 }
267 
268 EFI_STATUS
269 EFIAPI
PciBusDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)270 PciBusDriverBindingStop (
271   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
272   IN  EFI_HANDLE                    Controller,
273   IN  UINTN                         NumberOfChildren,
274   IN  EFI_HANDLE                    *ChildHandleBuffer
275   )
276 /*++
277 
278 Routine Description:
279 
280   Stop one or more children created at start of pci bus driver
281   if all the the children get closed, close the protocol
282 
283 Arguments:
284 
285   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
286   IN  EFI_HANDLE                    Controller,
287   IN  UINTN                         NumberOfChildren,
288   IN  EFI_HANDLE                    *ChildHandleBuffer
289 
290 Returns:
291 
292 
293 --*/
294 {
295   EFI_STATUS  Status;
296   UINTN       Index;
297   BOOLEAN     AllChildrenStopped;
298 
299   if (NumberOfChildren == 0) {
300     //
301     // Close the bus driver
302     //
303     gBS->CloseProtocol (
304            Controller,
305            &gEfiDevicePathProtocolGuid,
306            This->DriverBindingHandle,
307            Controller
308            );
309     gBS->CloseProtocol (
310            Controller,
311            &gEfiPciRootBridgeIoProtocolGuid,
312            This->DriverBindingHandle,
313            Controller
314            );
315 
316     DestroyRootBridgeByHandle (
317       Controller
318       );
319 
320     return EFI_SUCCESS;
321   }
322 
323   //
324   // Stop all the children
325   //
326 
327   AllChildrenStopped = TRUE;
328 
329   for (Index = 0; Index < NumberOfChildren; Index++) {
330 
331     //
332     // De register all the pci device
333     //
334     Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
335 
336     if (EFI_ERROR (Status)) {
337       AllChildrenStopped = FALSE;
338     }
339   }
340 
341   if (!AllChildrenStopped) {
342     return EFI_DEVICE_ERROR;
343   }
344 
345   return EFI_SUCCESS;
346 }
347