1/*++
2
3Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution.  The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14  PciBus.c
15
16Abstract:
17
18  PCI Bus Driver
19
20Revision History
21
22--*/
23
24#include "PciBus.h"
25
26//
27// PCI Bus Support Function Prototypes
28//
29
30EFI_STATUS
31EFIAPI
32PciBusEntryPoint (
33  IN EFI_HANDLE         ImageHandle,
34  IN EFI_SYSTEM_TABLE   *SystemTable
35  );
36
37EFI_STATUS
38EFIAPI
39PciBusDriverBindingSupported (
40  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
41  IN EFI_HANDLE                     Controller,
42  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
43  );
44
45EFI_STATUS
46EFIAPI
47PciBusDriverBindingStart (
48  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
49  IN EFI_HANDLE                     Controller,
50  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
51  );
52
53EFI_STATUS
54EFIAPI
55PciBusDriverBindingStop (
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
67EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
68  PciBusDriverBindingSupported,
69  PciBusDriverBindingStart,
70  PciBusDriverBindingStop,
71  0xa,
72  NULL,
73  NULL
74};
75
76BOOLEAN gFullEnumeration;
77
78UINT64 gAllOne    = 0xFFFFFFFFFFFFFFFFULL;
79UINT64 gAllZero   = 0;
80
81//
82// PCI Bus Driver Support Functions
83//
84EFI_STATUS
85EFIAPI
86PciBusEntryPoint (
87  IN EFI_HANDLE         ImageHandle,
88  IN EFI_SYSTEM_TABLE   *SystemTable
89  )
90/*++
91
92Routine Description:
93
94  Initialize the global variables
95  publish the driver binding protocol
96
97Arguments:
98
99  IN EFI_HANDLE     ImageHandle,
100  IN EFI_SYSTEM_TABLE   *SystemTable
101
102Returns:
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
131EFI_STATUS
132EFIAPI
133PciBusDriverBindingSupported (
134  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
135  IN EFI_HANDLE                     Controller,
136  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
137  )
138/*++
139
140Routine Description:
141
142  Check to see if pci bus driver supports the given controller
143
144Arguments:
145
146  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
147  IN EFI_HANDLE                     Controller,
148  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
149
150Returns:
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
221EFI_STATUS
222EFIAPI
223PciBusDriverBindingStart (
224  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
225  IN EFI_HANDLE                   Controller,
226  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
227  )
228/*++
229
230Routine Description:
231
232  Start to management the controller passed in
233
234Arguments:
235
236  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
237  IN EFI_HANDLE                   Controller,
238  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
239
240Returns:
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
268EFI_STATUS
269EFIAPI
270PciBusDriverBindingStop (
271  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
272  IN  EFI_HANDLE                    Controller,
273  IN  UINTN                         NumberOfChildren,
274  IN  EFI_HANDLE                    *ChildHandleBuffer
275  )
276/*++
277
278Routine 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
283Arguments:
284
285  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
286  IN  EFI_HANDLE                    Controller,
287  IN  UINTN                         NumberOfChildren,
288  IN  EFI_HANDLE                    *ChildHandleBuffer
289
290Returns:
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