2 The SioBusDxe driver is used to create child devices on the ISA bus and
3 installs the Super I/O protocols on them.
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "SioBusDxe.h"
14 // SioBus Driver Binding Protocol
16 EFI_DRIVER_BINDING_PROTOCOL gSioBusDriverBinding
= {
17 SioBusDriverBindingSupported
,
18 SioBusDriverBindingStart
,
19 SioBusDriverBindingStop
,
26 Tests to see if this driver supports a given controller. If a child device is
27 provided, it further tests to see if this driver supports creating a handle
28 for the specified child device.
30 This function checks to see if the driver specified by This supports the
31 device specified by ControllerHandle. Drivers will typically use the device
32 path attached to ControllerHandle and/or the services from the bus I/O
33 abstraction attached to ControllerHandle to determine if the driver supports
34 ControllerHandle. This function may be called many times during platform
35 initialization. In order to reduce boot times, the tests performed by this
36 function must be very small, and take as little time as possible to execute.
37 This function must not change the state of any hardware devices, and this
38 function must be aware that the device specified by ControllerHandle may
39 already be managed by the same driver or a different driver. This function
40 must match its calls to AllocatePages() with FreePages(), AllocatePool() with
41 FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle
42 may have been previously started by the same driver, if a protocol is already
43 in the opened state, then it must not be closed with CloseProtocol(). This is
44 required to guarantee the state of ControllerHandle is not modified by this
47 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
49 @param[in] ControllerHandle The handle of the controller to test. This
50 handle must support a protocol interface
51 that supplies an I/O abstraction to the
53 @param[in] RemainingDevicePath A pointer to the remaining portion of a
54 device path. This parameter is ignored by
55 device drivers, and is optional for bus
56 drivers. For bus drivers, if this parameter
57 is not NULL, then the bus driver must
58 determine if the bus controller specified by
59 ControllerHandle and the child controller
60 specified by RemainingDevicePath are both
61 supported by this bus driver.
63 @retval EFI_SUCCESS The device specified by ControllerHandle and
64 RemainingDevicePath is supported by the
65 driver specified by This.
66 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
67 RemainingDevicePath is already being managed
68 by the driver specified by This.
69 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
70 RemainingDevicePath is already being managed
71 by a different driver or an application that
72 requires exclusive access.
73 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
74 RemainingDevicePath is not supported by the
75 driver specified by This.
80 SioBusDriverBindingSupported (
81 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
82 IN EFI_HANDLE Controller
,
83 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
87 EFI_PCI_IO_PROTOCOL
*PciIo
;
95 // Get PciIo protocol instance
97 Status
= gBS
->OpenProtocol (
99 &gEfiPciIoProtocolGuid
,
101 This
->DriverBindingHandle
,
103 EFI_OPEN_PROTOCOL_BY_DRIVER
105 if (EFI_ERROR (Status
)) {
109 Status
= PciIo
->Pci
.Read (
113 sizeof (Pci
) / sizeof (UINT32
),
117 if (!EFI_ERROR (Status
)) {
118 Status
= EFI_UNSUPPORTED
;
119 if ((Pci
.Hdr
.Command
& 0x03) == 0x03) {
120 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_BRIDGE
) {
122 // See if this is a standard PCI to ISA Bridge from the Base Code and
125 if (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA
) {
126 Status
= EFI_SUCCESS
;
130 // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
132 if ((Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA_PDECODE
) &&
133 (Pci
.Hdr
.VendorId
== 0x8086))
136 // See if this is on Function #0 to avoid false positives on
137 // PCI_CLASS_BRIDGE_OTHER that has the same value as
138 // PCI_CLASS_BRIDGE_ISA_PDECODE
140 Status
= PciIo
->GetLocation (
147 if (!EFI_ERROR (Status
) && (FunctionNumber
== 0)) {
148 Status
= EFI_SUCCESS
;
150 Status
= EFI_UNSUPPORTED
;
159 &gEfiPciIoProtocolGuid
,
160 This
->DriverBindingHandle
,
168 Starts a device controller or a bus controller.
170 The Start() function is designed to be invoked from the EFI boot service
171 ConnectController(). As a result, much of the error checking on the
172 parameters to Start() has been moved into this common boot service. It is
173 legal to call Start() from other locations, but the following calling
174 restrictions must be followed or the system behavior will not be
176 1. ControllerHandle must be a valid EFI_HANDLE.
177 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
178 naturally aligned EFI_DEVICE_PATH_PROTOCOL.
179 3. Prior to calling Start(), the Supported() function for the driver
180 specified by This must have been called with the same calling parameters,
181 and Supported() must have returned EFI_SUCCESS.
183 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
185 @param[in] ControllerHandle The handle of the controller to start. This
186 handle must support a protocol interface
187 that supplies an I/O abstraction to the
189 @param[in] RemainingDevicePath A pointer to the remaining portion of a
190 device path. This parameter is ignored by
191 device drivers, and is optional for bus
192 drivers. For a bus driver, if this parameter
193 is NULL, then handles for all the children
194 of Controller are created by this driver. If
195 this parameter is not NULL and the first
196 Device Path Node is not the End of Device
197 Path Node, then only the handle for the
198 child device specified by the first Device
199 Path Node of RemainingDevicePath is created
200 by this driver. If the first Device Path
201 Node of RemainingDevicePath is the End of
202 Device Path Node, no child handle is created
205 @retval EFI_SUCCESS The device was started.
206 @retval EFI_DEVICE_ERROR The device could not be started due to a
208 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
210 @retval Others The driver failded to start the device.
215 SioBusDriverBindingStart (
216 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
217 IN EFI_HANDLE Controller
,
218 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
222 EFI_PCI_IO_PROTOCOL
*PciIo
;
223 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
225 UINT64 OriginalAttributes
;
228 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
229 UINT32 ChildDeviceNumber
;
233 OriginalAttributes
= 0;
237 // Open the PCI I/O Protocol Interface
240 Status
= gBS
->OpenProtocol (
242 &gEfiPciIoProtocolGuid
,
244 This
->DriverBindingHandle
,
246 EFI_OPEN_PROTOCOL_BY_DRIVER
248 if (EFI_ERROR (Status
)) {
253 // Open Device Path Protocol
255 Status
= gBS
->OpenProtocol (
257 &gEfiDevicePathProtocolGuid
,
258 (VOID
**)&ParentDevicePath
,
259 This
->DriverBindingHandle
,
261 EFI_OPEN_PROTOCOL_BY_DRIVER
263 if (EFI_ERROR (Status
)) {
266 &gEfiPciIoProtocolGuid
,
267 This
->DriverBindingHandle
,
274 // Get supported PCI attributes
276 Status
= PciIo
->Attributes (
278 EfiPciIoAttributeOperationSupported
,
282 if (EFI_ERROR (Status
)) {
286 Supports
&= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
287 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
288 if ((Supports
== 0) ||
289 (Supports
== (EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
290 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
)))
292 Status
= EFI_UNSUPPORTED
;
296 Status
= PciIo
->Attributes (
298 EfiPciIoAttributeOperationGet
,
302 if (EFI_ERROR (Status
)) {
306 Attributes
= EFI_PCI_DEVICE_ENABLE
|
308 EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
309 Status
= PciIo
->Attributes (
311 EfiPciIoAttributeOperationEnable
,
315 if (EFI_ERROR (Status
)) {
322 // Store the OriginalAttributes for the restore in BindingStop()
324 Private
= AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA
));
325 if (Private
== NULL
) {
326 Status
= EFI_OUT_OF_RESOURCES
;
330 Private
->PciIo
= PciIo
;
331 Private
->OriginalAttributes
= OriginalAttributes
;
333 Status
= gBS
->InstallProtocolInterface (
336 EFI_NATIVE_INTERFACE
,
339 if (EFI_ERROR (Status
)) {
344 // Report status code for the start of general controller initialization
346 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
348 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
353 // Report status code for the start of enabling devices on the bus
355 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
357 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
362 // Create all the children upon the first entrance
364 ChildDeviceNumber
= SioCreateAllChildDevices (
370 if (ChildDeviceNumber
== 0) {
371 Status
= EFI_DEVICE_ERROR
;
375 if (EFI_ERROR (Status
)) {
376 if ((PciIo
!= NULL
) && Enabled
) {
379 EfiPciIoAttributeOperationSet
,
387 &gEfiDevicePathProtocolGuid
,
388 This
->DriverBindingHandle
,
394 &gEfiPciIoProtocolGuid
,
395 This
->DriverBindingHandle
,
399 if (Private
!= NULL
) {
400 gBS
->UninstallMultipleProtocolInterfaces (
416 Stops a device controller or a bus controller.
418 The Stop() function is designed to be invoked from the EFI boot service
419 DisconnectController(). As a result, much of the error checking on the
420 parameters to Stop() has been moved into this common boot service. It is
421 legal to call Stop() from other locations, but the following calling
422 restrictions must be followed or the system behavior will not be
424 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
425 call to this same driver's Start() function.
426 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
427 valid EFI_HANDLE. In addition, all of these handles must have been created
428 in this driver's Start() function, and the Start() function must have
429 called OpenProtocol() on ControllerHandle with an Attribute of
430 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
432 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
434 @param[in] ControllerHandle A handle to the device being stopped. The
435 handle must support a bus specific I/O
436 protocol for the driver to use to stop the
438 @param[in] NumberOfChildren The number of child device handles in
440 @param[in] ChildHandleBuffer An array of child handles to be freed. May be
441 NULL if NumberOfChildren is 0.
443 @retval EFI_SUCCESS The device was stopped.
444 @retval EFI_DEVICE_ERROR The device could not be stopped due to a
450 SioBusDriverBindingStop (
451 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
452 IN EFI_HANDLE Controller
,
453 IN UINTN NumberOfChildren
,
454 IN EFI_HANDLE
*ChildHandleBuffer
458 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
460 BOOLEAN AllChildrenStopped
;
461 EFI_SIO_PROTOCOL
*Sio
;
463 EFI_PCI_IO_PROTOCOL
*PciIo
;
465 if (NumberOfChildren
== 0) {
467 // Restore PCI attributes
469 Status
= gBS
->OpenProtocol (
473 This
->DriverBindingHandle
,
475 EFI_OPEN_PROTOCOL_GET_PROTOCOL
477 if (EFI_ERROR (Status
)) {
481 Status
= Private
->PciIo
->Attributes (
483 EfiPciIoAttributeOperationSet
,
484 Private
->OriginalAttributes
,
487 if (EFI_ERROR (Status
)) {
491 gBS
->UninstallProtocolInterface (
499 // Close the bus driver
501 Status
= gBS
->CloseProtocol (
503 &gEfiDevicePathProtocolGuid
,
504 This
->DriverBindingHandle
,
507 if (EFI_ERROR (Status
)) {
511 Status
= gBS
->CloseProtocol (
513 &gEfiPciIoProtocolGuid
,
514 This
->DriverBindingHandle
,
517 if (EFI_ERROR (Status
)) {
525 // Stop all the children
527 AllChildrenStopped
= TRUE
;
529 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
530 Status
= gBS
->OpenProtocol (
531 ChildHandleBuffer
[Index
],
532 &gEfiSioProtocolGuid
,
534 This
->DriverBindingHandle
,
536 EFI_OPEN_PROTOCOL_GET_PROTOCOL
538 if (!EFI_ERROR (Status
)) {
539 SioDevice
= SIO_DEV_FROM_SIO (Sio
);
542 // Close the child handle
544 Status
= gBS
->CloseProtocol (
546 &gEfiPciIoProtocolGuid
,
547 This
->DriverBindingHandle
,
548 ChildHandleBuffer
[Index
]
550 Status
= gBS
->UninstallMultipleProtocolInterfaces (
551 ChildHandleBuffer
[Index
],
552 &gEfiDevicePathProtocolGuid
,
553 SioDevice
->DevicePath
,
554 &gEfiSioProtocolGuid
,
559 if (!EFI_ERROR (Status
)) {
560 FreePool (SioDevice
->DevicePath
);
561 FreePool (SioDevice
);
564 // Re-open PCI IO Protocol on behalf of the child device
565 // because of failure of destroying the child device handle
569 &gEfiPciIoProtocolGuid
,
571 This
->DriverBindingHandle
,
572 ChildHandleBuffer
[Index
],
573 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
578 if (EFI_ERROR (Status
)) {
579 AllChildrenStopped
= FALSE
;
583 if (!AllChildrenStopped
) {
584 return EFI_DEVICE_ERROR
;
591 The entry point for the SioBusDxe driver.
593 @param[in] ImageHandle The firmware allocated handle for the EFI image.
594 @param[in] SystemTable A pointer to the EFI System Table.
596 @retval EFI_SUCCESS The entry point is executed successfully.
597 @retval other Some error occurs when executing this entry point.
602 SioBusDxeDriverEntryPoint (
603 IN EFI_HANDLE ImageHandle
,
604 IN EFI_SYSTEM_TABLE
*SystemTable
608 // Install driver model protocol(s).
610 return EfiLibInstallDriverBindingComponentName2 (
613 &gSioBusDriverBinding
,
615 &gSioBusComponentName
,
616 &gSioBusComponentName2