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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "SioBusDxe.h"
21 // SioBus Driver Binding Protocol
23 EFI_DRIVER_BINDING_PROTOCOL gSioBusDriverBinding
= {
24 SioBusDriverBindingSupported
,
25 SioBusDriverBindingStart
,
26 SioBusDriverBindingStop
,
34 Tests to see if this driver supports a given controller. If a child device is
35 provided, it further tests to see if this driver supports creating a handle
36 for the specified child device.
38 This function checks to see if the driver specified by This supports the
39 device specified by ControllerHandle. Drivers will typically use the device
40 path attached to ControllerHandle and/or the services from the bus I/O
41 abstraction attached to ControllerHandle to determine if the driver supports
42 ControllerHandle. This function may be called many times during platform
43 initialization. In order to reduce boot times, the tests performed by this
44 function must be very small, and take as little time as possible to execute.
45 This function must not change the state of any hardware devices, and this
46 function must be aware that the device specified by ControllerHandle may
47 already be managed by the same driver or a different driver. This function
48 must match its calls to AllocatePages() with FreePages(), AllocatePool() with
49 FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle
50 may have been previously started by the same driver, if a protocol is already
51 in the opened state, then it must not be closed with CloseProtocol(). This is
52 required to guarantee the state of ControllerHandle is not modified by this
55 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
57 @param[in] ControllerHandle The handle of the controller to test. This
58 handle must support a protocol interface
59 that supplies an I/O abstraction to the
61 @param[in] RemainingDevicePath A pointer to the remaining portion of a
62 device path. This parameter is ignored by
63 device drivers, and is optional for bus
64 drivers. For bus drivers, if this parameter
65 is not NULL, then the bus driver must
66 determine if the bus controller specified by
67 ControllerHandle and the child controller
68 specified by RemainingDevicePath are both
69 supported by this bus driver.
71 @retval EFI_SUCCESS The device specified by ControllerHandle and
72 RemainingDevicePath is supported by the
73 driver specified by This.
74 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
75 RemainingDevicePath is already being managed
76 by the driver specified by This.
77 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
78 RemainingDevicePath is already being managed
79 by a different driver or an application that
80 requires exclusive access.
81 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
82 RemainingDevicePath is not supported by the
83 driver specified by This.
88 SioBusDriverBindingSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
90 IN EFI_HANDLE Controller
,
91 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
95 EFI_PCI_IO_PROTOCOL
*PciIo
;
100 UINTN FunctionNumber
;
103 // Get PciIo protocol instance
105 Status
= gBS
->OpenProtocol (
107 &gEfiPciIoProtocolGuid
,
109 This
->DriverBindingHandle
,
111 EFI_OPEN_PROTOCOL_BY_DRIVER
113 if (EFI_ERROR(Status
)) {
117 Status
= PciIo
->Pci
.Read (
121 sizeof(Pci
) / sizeof(UINT32
),
124 if (!EFI_ERROR (Status
)) {
125 Status
= EFI_UNSUPPORTED
;
126 if ((Pci
.Hdr
.Command
& 0x03) == 0x03) {
127 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_BRIDGE
) {
129 // See if this is a standard PCI to ISA Bridge from the Base Code and
132 if (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA
) {
133 Status
= EFI_SUCCESS
;
137 // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
139 if (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA_PDECODE
&&
140 Pci
.Hdr
.VendorId
== 0x8086) {
142 // See if this is on Function #0 to avoid false positives on
143 // PCI_CLASS_BRIDGE_OTHER that has the same value as
144 // PCI_CLASS_BRIDGE_ISA_PDECODE
146 Status
= PciIo
->GetLocation (
153 if (!EFI_ERROR (Status
) && FunctionNumber
== 0) {
154 Status
= EFI_SUCCESS
;
156 Status
= EFI_UNSUPPORTED
;
165 &gEfiPciIoProtocolGuid
,
166 This
->DriverBindingHandle
,
174 Starts a device controller or a bus controller.
176 The Start() function is designed to be invoked from the EFI boot service
177 ConnectController(). As a result, much of the error checking on the
178 parameters to Start() has been moved into this common boot service. It is
179 legal to call Start() from other locations, but the following calling
180 restrictions must be followed or the system behavior will not be
182 1. ControllerHandle must be a valid EFI_HANDLE.
183 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
184 naturally aligned EFI_DEVICE_PATH_PROTOCOL.
185 3. Prior to calling Start(), the Supported() function for the driver
186 specified by This must have been called with the same calling parameters,
187 and Supported() must have returned EFI_SUCCESS.
189 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
191 @param[in] ControllerHandle The handle of the controller to start. This
192 handle must support a protocol interface
193 that supplies an I/O abstraction to the
195 @param[in] RemainingDevicePath A pointer to the remaining portion of a
196 device path. This parameter is ignored by
197 device drivers, and is optional for bus
198 drivers. For a bus driver, if this parameter
199 is NULL, then handles for all the children
200 of Controller are created by this driver. If
201 this parameter is not NULL and the first
202 Device Path Node is not the End of Device
203 Path Node, then only the handle for the
204 child device specified by the first Device
205 Path Node of RemainingDevicePath is created
206 by this driver. If the first Device Path
207 Node of RemainingDevicePath is the End of
208 Device Path Node, no child handle is created
211 @retval EFI_SUCCESS The device was started.
212 @retval EFI_DEVICE_ERROR The device could not be started due to a
214 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
216 @retval Others The driver failded to start the device.
221 SioBusDriverBindingStart (
222 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
223 IN EFI_HANDLE Controller
,
224 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
228 EFI_PCI_IO_PROTOCOL
*PciIo
;
229 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
231 UINT64 OriginalAttributes
;
234 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
235 UINT32 ChildDeviceNumber
;
239 OriginalAttributes
= 0;
243 // Open the PCI I/O Protocol Interface
246 Status
= gBS
->OpenProtocol (
248 &gEfiPciIoProtocolGuid
,
250 This
->DriverBindingHandle
,
252 EFI_OPEN_PROTOCOL_BY_DRIVER
254 if (EFI_ERROR (Status
)) {
259 // Open Device Path Protocol
261 Status
= gBS
->OpenProtocol (
263 &gEfiDevicePathProtocolGuid
,
264 (VOID
**) &ParentDevicePath
,
265 This
->DriverBindingHandle
,
267 EFI_OPEN_PROTOCOL_BY_DRIVER
269 if (EFI_ERROR (Status
)) {
272 &gEfiPciIoProtocolGuid
,
273 This
->DriverBindingHandle
,
280 // Get supported PCI attributes
282 Status
= PciIo
->Attributes (
284 EfiPciIoAttributeOperationSupported
,
288 if (EFI_ERROR (Status
)) {
292 Supports
&= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
293 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
295 Supports
== (EFI_PCI_IO_ATTRIBUTE_ISA_IO
|
296 EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
)) {
297 Status
= EFI_UNSUPPORTED
;
301 Status
= PciIo
->Attributes (
303 EfiPciIoAttributeOperationGet
,
307 if (EFI_ERROR (Status
)) {
311 Attributes
= EFI_PCI_DEVICE_ENABLE
|
313 EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
314 Status
= PciIo
->Attributes (
316 EfiPciIoAttributeOperationEnable
,
320 if (EFI_ERROR (Status
)) {
327 // Store the OriginalAttributes for the restore in BindingStop()
329 Private
= AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA
));
330 if (Private
== NULL
) {
331 Status
= EFI_OUT_OF_RESOURCES
;
334 Private
->PciIo
= PciIo
;
335 Private
->OriginalAttributes
= OriginalAttributes
;
337 Status
= gBS
->InstallProtocolInterface (
340 EFI_NATIVE_INTERFACE
,
343 if (EFI_ERROR (Status
)) {
348 // Report status code for the start of general controller initialization
350 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
352 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
357 // Report status code for the start of enabling devices on the bus
359 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
361 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
366 // Create all the children upon the first entrance
368 ChildDeviceNumber
= SioCreateAllChildDevices (
374 if (ChildDeviceNumber
== 0) {
375 Status
= EFI_DEVICE_ERROR
;
379 if (EFI_ERROR (Status
)) {
380 if (PciIo
!= NULL
&& Enabled
) {
383 EfiPciIoAttributeOperationSet
,
391 &gEfiDevicePathProtocolGuid
,
392 This
->DriverBindingHandle
,
398 &gEfiPciIoProtocolGuid
,
399 This
->DriverBindingHandle
,
403 if (Private
!= NULL
) {
404 gBS
->UninstallMultipleProtocolInterfaces (
420 Stops a device controller or a bus controller.
422 The Stop() function is designed to be invoked from the EFI boot service
423 DisconnectController(). As a result, much of the error checking on the
424 parameters to Stop() has been moved into this common boot service. It is
425 legal to call Stop() from other locations, but the following calling
426 restrictions must be followed or the system behavior will not be
428 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
429 call to this same driver's Start() function.
430 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
431 valid EFI_HANDLE. In addition, all of these handles must have been created
432 in this driver's Start() function, and the Start() function must have
433 called OpenProtocol() on ControllerHandle with an Attribute of
434 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
436 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
438 @param[in] ControllerHandle A handle to the device being stopped. The
439 handle must support a bus specific I/O
440 protocol for the driver to use to stop the
442 @param[in] NumberOfChildren The number of child device handles in
444 @param[in] ChildHandleBuffer An array of child handles to be freed. May be
445 NULL if NumberOfChildren is 0.
447 @retval EFI_SUCCESS The device was stopped.
448 @retval EFI_DEVICE_ERROR The device could not be stopped due to a
454 SioBusDriverBindingStop (
455 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
456 IN EFI_HANDLE Controller
,
457 IN UINTN NumberOfChildren
,
458 IN EFI_HANDLE
*ChildHandleBuffer
462 SIO_BUS_DRIVER_PRIVATE_DATA
*Private
;
464 BOOLEAN AllChildrenStopped
;
465 EFI_SIO_PROTOCOL
*Sio
;
467 EFI_PCI_IO_PROTOCOL
*PciIo
;
469 if (NumberOfChildren
== 0) {
471 // Restore PCI attributes
473 Status
= gBS
->OpenProtocol (
477 This
->DriverBindingHandle
,
479 EFI_OPEN_PROTOCOL_GET_PROTOCOL
481 if (EFI_ERROR (Status
)) {
485 Status
= Private
->PciIo
->Attributes (
487 EfiPciIoAttributeOperationSet
,
488 Private
->OriginalAttributes
,
491 if (EFI_ERROR (Status
)) {
495 gBS
->UninstallProtocolInterface (
503 // Close the bus driver
505 Status
= gBS
->CloseProtocol (
507 &gEfiDevicePathProtocolGuid
,
508 This
->DriverBindingHandle
,
511 if (EFI_ERROR (Status
)) {
515 Status
= gBS
->CloseProtocol (
517 &gEfiPciIoProtocolGuid
,
518 This
->DriverBindingHandle
,
521 if (EFI_ERROR (Status
)) {
529 // Stop all the children
531 AllChildrenStopped
= TRUE
;
533 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
534 Status
= gBS
->OpenProtocol (
535 ChildHandleBuffer
[Index
],
536 &gEfiSioProtocolGuid
,
538 This
->DriverBindingHandle
,
540 EFI_OPEN_PROTOCOL_GET_PROTOCOL
542 if (!EFI_ERROR (Status
)) {
543 SioDevice
= SIO_DEV_FROM_SIO (Sio
);
546 // Close the child handle
548 Status
= gBS
->CloseProtocol (
550 &gEfiPciIoProtocolGuid
,
551 This
->DriverBindingHandle
,
552 ChildHandleBuffer
[Index
]
554 Status
= gBS
->UninstallMultipleProtocolInterfaces (
555 ChildHandleBuffer
[Index
],
556 &gEfiDevicePathProtocolGuid
,
557 SioDevice
->DevicePath
,
558 &gEfiSioProtocolGuid
,
563 if (!EFI_ERROR (Status
)) {
564 FreePool (SioDevice
->DevicePath
);
565 FreePool (SioDevice
);
568 // Re-open PCI IO Protocol on behalf of the child device
569 // because of failure of destroying the child device handle
573 &gEfiPciIoProtocolGuid
,
575 This
->DriverBindingHandle
,
576 ChildHandleBuffer
[Index
],
577 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
582 if (EFI_ERROR (Status
)) {
583 AllChildrenStopped
= FALSE
;
587 if (!AllChildrenStopped
) {
588 return EFI_DEVICE_ERROR
;
595 The entry point for the SioBusDxe driver.
597 @param[in] ImageHandle The firmware allocated handle for the EFI image.
598 @param[in] SystemTable A pointer to the EFI System Table.
600 @retval EFI_SUCCESS The entry point is executed successfully.
601 @retval other Some error occurs when executing this entry point.
606 SioBusDxeDriverEntryPoint (
607 IN EFI_HANDLE ImageHandle
,
608 IN EFI_SYSTEM_TABLE
*SystemTable
612 // Install driver model protocol(s).
614 return EfiLibInstallDriverBindingComponentName2 (
617 &gSioBusDriverBinding
,
619 &gSioBusComponentName
,
620 &gSioBusComponentName2