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
,
27 Tests to see if this driver supports a given controller. If a child device is
28 provided, it further tests to see if this driver supports creating a handle
29 for the specified child device.
31 This function checks to see if the driver specified by This supports the
32 device specified by ControllerHandle. Drivers will typically use the device
33 path attached to ControllerHandle and/or the services from the bus I/O
34 abstraction attached to ControllerHandle to determine if the driver supports
35 ControllerHandle. This function may be called many times during platform
36 initialization. In order to reduce boot times, the tests performed by this
37 function must be very small, and take as little time as possible to execute.
38 This function must not change the state of any hardware devices, and this
39 function must be aware that the device specified by ControllerHandle may
40 already be managed by the same driver or a different driver. This function
41 must match its calls to AllocatePages() with FreePages(), AllocatePool() with
42 FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle
43 may have been previously started by the same driver, if a protocol is already
44 in the opened state, then it must not be closed with CloseProtocol(). This is
45 required to guarantee the state of ControllerHandle is not modified by this
48 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
50 @param[in] ControllerHandle The handle of the controller to test. This
51 handle must support a protocol interface
52 that supplies an I/O abstraction to the
54 @param[in] RemainingDevicePath A pointer to the remaining portion of a
55 device path. This parameter is ignored by
56 device drivers, and is optional for bus
57 drivers. For bus drivers, if this parameter
58 is not NULL, then the bus driver must
59 determine if the bus controller specified by
60 ControllerHandle and the child controller
61 specified by RemainingDevicePath are both
62 supported by this bus driver.
64 @retval EFI_SUCCESS The device specified by ControllerHandle and
65 RemainingDevicePath is supported by the
66 driver specified by This.
67 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
68 RemainingDevicePath is already being managed
69 by the driver specified by This.
70 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
71 RemainingDevicePath is already being managed
72 by a different driver or an application that
73 requires exclusive access.
74 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
75 RemainingDevicePath is not supported by the
76 driver specified by This.
81 SioBusDriverBindingSupported (
82 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
83 IN EFI_HANDLE Controller
,
84 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
88 EFI_PCI_IO_PROTOCOL
*PciIo
;
96 // Get PciIo protocol instance
98 Status
= gBS
->OpenProtocol (
100 &gEfiPciIoProtocolGuid
,
102 This
->DriverBindingHandle
,
104 EFI_OPEN_PROTOCOL_BY_DRIVER
106 if (EFI_ERROR(Status
)) {
110 Status
= PciIo
->Pci
.Read (
114 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) {
135 // See if this is on Function #0 to avoid false positives on
136 // PCI_CLASS_BRIDGE_OTHER that has the same value as
137 // PCI_CLASS_BRIDGE_ISA_PDECODE
139 Status
= PciIo
->GetLocation (
146 if (!EFI_ERROR (Status
) && FunctionNumber
== 0) {
147 Status
= EFI_SUCCESS
;
149 Status
= EFI_UNSUPPORTED
;
158 &gEfiPciIoProtocolGuid
,
159 This
->DriverBindingHandle
,
167 Starts a device controller or a bus controller.
169 The Start() function is designed to be invoked from the EFI boot service
170 ConnectController(). As a result, much of the error checking on the
171 parameters to Start() has been moved into this common boot service. It is
172 legal to call Start() from other locations, but the following calling
173 restrictions must be followed or the system behavior will not be
175 1. ControllerHandle must be a valid EFI_HANDLE.
176 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
177 naturally aligned EFI_DEVICE_PATH_PROTOCOL.
178 3. Prior to calling Start(), the Supported() function for the driver
179 specified by This must have been called with the same calling parameters,
180 and Supported() must have returned EFI_SUCCESS.
182 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
184 @param[in] ControllerHandle The handle of the controller to start. This
185 handle must support a protocol interface
186 that supplies an I/O abstraction to the
188 @param[in] RemainingDevicePath A pointer to the remaining portion of a
189 device path. This parameter is ignored by
190 device drivers, and is optional for bus
191 drivers. For a bus driver, if this parameter
192 is NULL, then handles for all the children
193 of Controller are created by this driver. If
194 this parameter is not NULL and the first
195 Device Path Node is not the End of Device
196 Path Node, then only the handle for the
197 child device specified by the first Device
198 Path Node of RemainingDevicePath is created
199 by this driver. If the first Device Path
200 Node of RemainingDevicePath is the End of
201 Device Path Node, no child handle is created
204 @retval EFI_SUCCESS The device was started.
205 @retval EFI_DEVICE_ERROR The device could not be started due to a
207 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
209 @retval Others The driver failded to start the device.
214 SioBusDriverBindingStart (
215 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
216 IN EFI_HANDLE Controller
,
217 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
221 EFI_PCI_IO_PROTOCOL
*PciIo
;
222 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
224 UINT64 OriginalAttributes
;
227 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
228 UINT32 ChildDeviceNumber
;
232 OriginalAttributes
= 0;
236 // Open the PCI I/O Protocol Interface
239 Status
= gBS
->OpenProtocol (
241 &gEfiPciIoProtocolGuid
,
243 This
->DriverBindingHandle
,
245 EFI_OPEN_PROTOCOL_BY_DRIVER
247 if (EFI_ERROR (Status
)) {
252 // Open Device Path Protocol
254 Status
= gBS
->OpenProtocol (
256 &gEfiDevicePathProtocolGuid
,
257 (VOID
**) &ParentDevicePath
,
258 This
->DriverBindingHandle
,
260 EFI_OPEN_PROTOCOL_BY_DRIVER
262 if (EFI_ERROR (Status
)) {
265 &gEfiPciIoProtocolGuid
,
266 This
->DriverBindingHandle
,
273 // Get supported PCI attributes
275 Status
= PciIo
->Attributes (
277 EfiPciIoAttributeOperationSupported
,
281 if (EFI_ERROR (Status
)) {
285 Supports
&= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
286 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
288 Supports
== (EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
289 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
)) {
290 Status
= EFI_UNSUPPORTED
;
294 Status
= PciIo
->Attributes (
296 EfiPciIoAttributeOperationGet
,
300 if (EFI_ERROR (Status
)) {
304 Attributes
= EFI_PCI_DEVICE_ENABLE
|
306 EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
307 Status
= PciIo
->Attributes (
309 EfiPciIoAttributeOperationEnable
,
313 if (EFI_ERROR (Status
)) {
320 // Store the OriginalAttributes for the restore in BindingStop()
322 Private
= AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA
));
323 if (Private
== NULL
) {
324 Status
= EFI_OUT_OF_RESOURCES
;
327 Private
->PciIo
= PciIo
;
328 Private
->OriginalAttributes
= OriginalAttributes
;
330 Status
= gBS
->InstallProtocolInterface (
333 EFI_NATIVE_INTERFACE
,
336 if (EFI_ERROR (Status
)) {
341 // Report status code for the start of general controller initialization
343 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
345 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
350 // Report status code for the start of enabling devices on the bus
352 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
354 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
359 // Create all the children upon the first entrance
361 ChildDeviceNumber
= SioCreateAllChildDevices (
367 if (ChildDeviceNumber
== 0) {
368 Status
= EFI_DEVICE_ERROR
;
372 if (EFI_ERROR (Status
)) {
373 if (PciIo
!= NULL
&& Enabled
) {
376 EfiPciIoAttributeOperationSet
,
384 &gEfiDevicePathProtocolGuid
,
385 This
->DriverBindingHandle
,
391 &gEfiPciIoProtocolGuid
,
392 This
->DriverBindingHandle
,
396 if (Private
!= NULL
) {
397 gBS
->UninstallMultipleProtocolInterfaces (
413 Stops a device controller or a bus controller.
415 The Stop() function is designed to be invoked from the EFI boot service
416 DisconnectController(). As a result, much of the error checking on the
417 parameters to Stop() has been moved into this common boot service. It is
418 legal to call Stop() from other locations, but the following calling
419 restrictions must be followed or the system behavior will not be
421 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
422 call to this same driver's Start() function.
423 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
424 valid EFI_HANDLE. In addition, all of these handles must have been created
425 in this driver's Start() function, and the Start() function must have
426 called OpenProtocol() on ControllerHandle with an Attribute of
427 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
429 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
431 @param[in] ControllerHandle A handle to the device being stopped. The
432 handle must support a bus specific I/O
433 protocol for the driver to use to stop the
435 @param[in] NumberOfChildren The number of child device handles in
437 @param[in] ChildHandleBuffer An array of child handles to be freed. May be
438 NULL if NumberOfChildren is 0.
440 @retval EFI_SUCCESS The device was stopped.
441 @retval EFI_DEVICE_ERROR The device could not be stopped due to a
447 SioBusDriverBindingStop (
448 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
449 IN EFI_HANDLE Controller
,
450 IN UINTN NumberOfChildren
,
451 IN EFI_HANDLE
*ChildHandleBuffer
455 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
457 BOOLEAN AllChildrenStopped
;
458 EFI_SIO_PROTOCOL
*Sio
;
460 EFI_PCI_IO_PROTOCOL
*PciIo
;
462 if (NumberOfChildren
== 0) {
464 // Restore PCI attributes
466 Status
= gBS
->OpenProtocol (
470 This
->DriverBindingHandle
,
472 EFI_OPEN_PROTOCOL_GET_PROTOCOL
474 if (EFI_ERROR (Status
)) {
478 Status
= Private
->PciIo
->Attributes (
480 EfiPciIoAttributeOperationSet
,
481 Private
->OriginalAttributes
,
484 if (EFI_ERROR (Status
)) {
488 gBS
->UninstallProtocolInterface (
496 // Close the bus driver
498 Status
= gBS
->CloseProtocol (
500 &gEfiDevicePathProtocolGuid
,
501 This
->DriverBindingHandle
,
504 if (EFI_ERROR (Status
)) {
508 Status
= gBS
->CloseProtocol (
510 &gEfiPciIoProtocolGuid
,
511 This
->DriverBindingHandle
,
514 if (EFI_ERROR (Status
)) {
522 // Stop all the children
524 AllChildrenStopped
= TRUE
;
526 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
527 Status
= gBS
->OpenProtocol (
528 ChildHandleBuffer
[Index
],
529 &gEfiSioProtocolGuid
,
531 This
->DriverBindingHandle
,
533 EFI_OPEN_PROTOCOL_GET_PROTOCOL
535 if (!EFI_ERROR (Status
)) {
536 SioDevice
= SIO_DEV_FROM_SIO (Sio
);
539 // Close the child handle
541 Status
= gBS
->CloseProtocol (
543 &gEfiPciIoProtocolGuid
,
544 This
->DriverBindingHandle
,
545 ChildHandleBuffer
[Index
]
547 Status
= gBS
->UninstallMultipleProtocolInterfaces (
548 ChildHandleBuffer
[Index
],
549 &gEfiDevicePathProtocolGuid
,
550 SioDevice
->DevicePath
,
551 &gEfiSioProtocolGuid
,
556 if (!EFI_ERROR (Status
)) {
557 FreePool (SioDevice
->DevicePath
);
558 FreePool (SioDevice
);
561 // Re-open PCI IO Protocol on behalf of the child device
562 // because of failure of destroying the child device handle
566 &gEfiPciIoProtocolGuid
,
568 This
->DriverBindingHandle
,
569 ChildHandleBuffer
[Index
],
570 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
575 if (EFI_ERROR (Status
)) {
576 AllChildrenStopped
= FALSE
;
580 if (!AllChildrenStopped
) {
581 return EFI_DEVICE_ERROR
;
588 The entry point for the SioBusDxe driver.
590 @param[in] ImageHandle The firmware allocated handle for the EFI image.
591 @param[in] SystemTable A pointer to the EFI System Table.
593 @retval EFI_SUCCESS The entry point is executed successfully.
594 @retval other Some error occurs when executing this entry point.
599 SioBusDxeDriverEntryPoint (
600 IN EFI_HANDLE ImageHandle
,
601 IN EFI_SYSTEM_TABLE
*SystemTable
605 // Install driver model protocol(s).
607 return EfiLibInstallDriverBindingComponentName2 (
610 &gSioBusDriverBinding
,
612 &gSioBusComponentName
,
613 &gSioBusComponentName2