4 Discovers all the ISA Controllers and their resources by using the ISA ACPI
5 Protocol, produces an instance of the ISA I/O Protocol for every ISA
6 Controller found. This driver is designed to manage a PCI-to-ISA bridge Device
9 Copyright (c) 2006 - 2009, Intel Corporation.<BR>
10 All rights reserved. This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "InternalIsaBus.h"
23 // ISA Bus Driver Global Variables
25 EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver
= {
26 IsaBusControllerDriverSupported
,
27 IsaBusControllerDriverStart
,
28 IsaBusControllerDriverStop
,
35 The main entry point for the ISA Bus driver.
37 @param[in] ImageHandle The firmware allocated handle for the EFI image.
38 @param[in] SystemTable A pointer to the EFI System Table.
40 @retval EFI_SUCCESS The entry point is executed successfully.
41 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
46 IN EFI_HANDLE ImageHandle
,
47 IN EFI_SYSTEM_TABLE
*SystemTable
53 // Install driver model protocol(s).
55 Status
= EfiLibInstallDriverBindingComponentName2 (
58 &gIsaBusControllerDriver
,
60 &gIsaBusComponentName
,
61 &gIsaBusComponentName2
63 ASSERT_EFI_ERROR (Status
);
69 Tests to see if a controller can be managed by the ISA Bus Driver. If a child device is provided,
70 it further tests to see if this driver supports creating a handle for the specified child device.
72 Note that the ISA Bus driver always creates all of its child handles on the first call to Start().
73 How the Start() function of a driver is implemented can affect how the Supported() function is implemented.
75 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
76 @param[in] Controller The handle of the controller to test.
77 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
79 @retval EFI_SUCCESS The device is supported by this driver.
80 @retval EFI_ALREADY_STARTED The device is already being managed by this driver.
81 @retval EFI_ACCESS_DENIED The device is already being managed by a different driver
82 or an application that requires exclusive access.
83 @retval EFI_UNSUPPORTED The device is is not supported by this driver.
88 IsaBusControllerDriverSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
90 IN EFI_HANDLE Controller
,
91 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
95 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
96 EFI_PCI_IO_PROTOCOL
*PciIo
;
97 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
100 // If RemainingDevicePath is not NULL, it should verify that the first device
101 // path node in RemainingDevicePath is an ACPI Device path node which is a
102 // legal Device Path Node for this bus driver's children.
104 if (RemainingDevicePath
!= NULL
) {
105 if (RemainingDevicePath
->Type
!= ACPI_DEVICE_PATH
) {
106 return EFI_UNSUPPORTED
;
107 } else if (RemainingDevicePath
->SubType
== ACPI_DP
) {
108 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_HID_DEVICE_PATH
)) {
109 return EFI_UNSUPPORTED
;
111 } else if (RemainingDevicePath
->SubType
== ACPI_EXTENDED_DP
) {
112 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH
)) {
113 return EFI_UNSUPPORTED
;
116 return EFI_UNSUPPORTED
;
120 // Try to open EFI DEVICE PATH protocol on the controller
122 Status
= gBS
->OpenProtocol (
124 &gEfiDevicePathProtocolGuid
,
125 (VOID
**) &ParentDevicePath
,
126 This
->DriverBindingHandle
,
128 EFI_OPEN_PROTOCOL_BY_DRIVER
130 if (EFI_ERROR (Status
)) {
136 &gEfiDevicePathProtocolGuid
,
137 This
->DriverBindingHandle
,
142 // Try to get Pci IO Protocol because it is assumed
143 // to have been opened by ISA ACPI driver
145 Status
= gBS
->OpenProtocol (
147 &gEfiPciIoProtocolGuid
,
149 This
->DriverBindingHandle
,
151 EFI_OPEN_PROTOCOL_GET_PROTOCOL
153 if (EFI_ERROR (Status
)) {
158 // Try to open the Isa Acpi protocol on the controller
160 Status
= gBS
->OpenProtocol (
162 &gEfiIsaAcpiProtocolGuid
,
164 This
->DriverBindingHandle
,
166 EFI_OPEN_PROTOCOL_BY_DRIVER
168 if (EFI_ERROR (Status
)) {
173 // Add more check to see if the child device is valid by calling IsaAcpi->DeviceEnumerate?
178 &gEfiIsaAcpiProtocolGuid
,
179 This
->DriverBindingHandle
,
187 Start this driver on ControllerHandle.
189 Note that the ISA Bus driver always creates all of its child handles on the first call to Start().
190 The Start() function is designed to be invoked from the EFI boot service ConnectController().
191 As a result, much of the error checking on the parameters to Start() has been moved into this
192 common boot service. It is legal to call Start() from other locations, but the following calling
193 restrictions must be followed or the system behavior will not be deterministic.
194 1. ControllerHandle must be a valid EFI_HANDLE.
195 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
196 EFI_DEVICE_PATH_PROTOCOL.
197 3. Prior to calling Start(), the Supported() function for the driver specified by This must
198 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
200 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
201 @param[in] ControllerHandle The handle of the controller to start. This handle
202 must support a protocol interface that supplies
203 an I/O abstraction to the driver.
204 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
205 This parameter is ignored by device drivers, and is optional for bus drivers.
207 @retval EFI_SUCCESS The device was started.
208 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
209 Currently not implemented.
210 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
211 @retval Others The driver failded to start the device.
215 IsaBusControllerDriverStart (
216 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
217 IN EFI_HANDLE Controller
,
218 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
222 EFI_PCI_IO_PROTOCOL
*PciIo
;
223 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
224 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
225 EFI_ISA_ACPI_DEVICE_ID
*IsaDevice
;
226 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
227 EFI_GENERIC_MEMORY_TEST_PROTOCOL
*GenMemoryTest
;
230 // Local variables declaration for StatusCode reporting
232 EFI_DEVICE_PATH_PROTOCOL
*DevicePathData
;
235 // Get Pci IO Protocol
237 Status
= gBS
->OpenProtocol (
239 &gEfiPciIoProtocolGuid
,
241 This
->DriverBindingHandle
,
243 EFI_OPEN_PROTOCOL_GET_PROTOCOL
245 if (EFI_ERROR (Status
)) {
250 // Open Device Path Protocol
252 Status
= gBS
->OpenProtocol (
254 &gEfiDevicePathProtocolGuid
,
255 (VOID
**) &ParentDevicePath
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_BY_DRIVER
260 if (EFI_ERROR (Status
)) {
265 // Open ISA Acpi Protocol
267 Status
= gBS
->OpenProtocol (
269 &gEfiIsaAcpiProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
275 if (EFI_ERROR (Status
)) {
277 // Close opened protocol
281 &gEfiDevicePathProtocolGuid
,
282 This
->DriverBindingHandle
,
288 // The IsaBus driver will use memory below 16M, which is not tested yet,
289 // so call CompatibleRangeTest to test them. Since memory below 1M should
290 // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M
293 Status
= gBS
->LocateProtocol (
294 &gEfiGenericMemTestProtocolGuid
,
296 (VOID
**) &GenMemoryTest
299 if (!EFI_ERROR (Status
)) {
300 Status
= GenMemoryTest
->CompatibleRangeTest (
307 // Report Status Code here since we will initialize the host controller
309 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
311 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
316 // first init ISA interface
318 IsaAcpi
->InterfaceInit (IsaAcpi
);
321 // Report Status Code here since we will enable the host controller
323 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
325 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
330 // Create each ISA device handle in this ISA bus
334 Status
= IsaAcpi
->DeviceEnumerate (IsaAcpi
, &IsaDevice
);
335 if (EFI_ERROR (Status
)) {
339 // Get current resource of this ISA device
342 Status
= IsaAcpi
->GetCurResource (IsaAcpi
, IsaDevice
, &ResourceList
);
343 if (EFI_ERROR (Status
)) {
348 // Create handle for this ISA device
350 Status
= IsaCreateDevice (
359 if (EFI_ERROR (Status
)) {
363 // Initialize ISA device
365 IsaAcpi
->InitDevice (IsaAcpi
, IsaDevice
);
368 // Set resources for this ISA device
370 Status
= IsaAcpi
->SetResource (IsaAcpi
, IsaDevice
, ResourceList
);
373 // Report Status Code here when failed to resource conflicts
375 if (EFI_ERROR (Status
) && (Status
!= EFI_UNSUPPORTED
)) {
377 // It's hard to tell which resource conflicts
379 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
381 (EFI_IO_BUS_LPC
| EFI_IOB_EC_RESOURCE_CONFLICT
),
387 // Set power for this ISA device
389 IsaAcpi
->SetPower (IsaAcpi
, IsaDevice
, TRUE
);
392 // Enable this ISA device
394 IsaAcpi
->EnableDevice (IsaAcpi
, IsaDevice
, TRUE
);
402 Stop this driver on ControllerHandle.
404 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
405 As a result, much of the error checking on the parameters to Stop() has been moved
406 into this common boot service. It is legal to call Stop() from other locations,
407 but the following calling restrictions must be followed or the system behavior will not be deterministic.
408 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
409 same driver's Start() function.
410 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
411 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
412 Start() function, and the Start() function must have called OpenProtocol() on
413 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
415 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
416 @param[in] ControllerHandle A handle to the device being stopped. The handle must
417 support a bus specific I/O protocol for the driver
418 to use to stop the device.
419 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
420 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
421 if NumberOfChildren is 0.
423 @retval EFI_SUCCESS The device was stopped.
424 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
428 IsaBusControllerDriverStop (
429 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
430 IN EFI_HANDLE Controller
,
431 IN UINTN NumberOfChildren
,
432 IN EFI_HANDLE
* ChildHandleBuffer OPTIONAL
437 BOOLEAN AllChildrenStopped
;
438 ISA_IO_DEVICE
*IsaIoDevice
;
439 EFI_ISA_IO_PROTOCOL
*IsaIo
;
441 if (NumberOfChildren
== 0) {
443 // Close the bus driver
445 Status
= gBS
->CloseProtocol (
447 &gEfiDevicePathProtocolGuid
,
448 This
->DriverBindingHandle
,
451 if (EFI_ERROR (Status
)) {
455 Status
= gBS
->CloseProtocol (
457 &gEfiIsaAcpiProtocolGuid
,
458 This
->DriverBindingHandle
,
461 if (EFI_ERROR (Status
)) {
468 // Complete all outstanding transactions to Controller.
469 // Don't allow any new transaction to Controller to be started.
472 // Stop all the children
473 // Find all the ISA devices that were discovered on this PCI to ISA Bridge
474 // with the Start() function.
476 AllChildrenStopped
= TRUE
;
478 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
480 Status
= gBS
->OpenProtocol (
481 ChildHandleBuffer
[Index
],
482 &gEfiIsaIoProtocolGuid
,
484 This
->DriverBindingHandle
,
486 EFI_OPEN_PROTOCOL_GET_PROTOCOL
488 if (!EFI_ERROR (Status
)) {
490 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo
);
492 Status
= gBS
->UninstallMultipleProtocolInterfaces (
493 ChildHandleBuffer
[Index
],
494 &gEfiDevicePathProtocolGuid
,
495 IsaIoDevice
->DevicePath
,
496 &gEfiIsaIoProtocolGuid
,
501 if (!EFI_ERROR (Status
)) {
503 // Close the child handle
505 Status
= gBS
->CloseProtocol (
507 &gEfiPciIoProtocolGuid
,
508 This
->DriverBindingHandle
,
509 ChildHandleBuffer
[Index
]
512 gBS
->FreePool (IsaIoDevice
->DevicePath
);
513 gBS
->FreePool (IsaIoDevice
);
517 if (EFI_ERROR (Status
)) {
518 AllChildrenStopped
= FALSE
;
522 if (!AllChildrenStopped
) {
523 return EFI_DEVICE_ERROR
;
534 Create EFI Handle for a ISA device found via ISA ACPI Protocol
536 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance.
537 @param[in] Controller The handle of ISA bus controller(PCI to ISA bridge)
538 @param[in] PciIo The Pointer to the PCI protocol
539 @param[in] ParentDevicePath Device path of the ISA bus controller
540 @param[in] IsaDeviceResourceList The resource list of the ISA device
541 @param[in] ChildDevicePath The pointer to the child device.
543 @retval EFI_SUCCESS The handle for the child device was created.
544 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
545 @retval EFI_DEVICE_ERROR The handle for the child device can not be created.
549 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
550 IN EFI_HANDLE Controller
,
551 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
552 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
553 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
,
554 OUT EFI_DEVICE_PATH_PROTOCOL
**ChildDevicePath
558 ISA_IO_DEVICE
*IsaIoDevice
;
562 // Initialize the PCI_IO_DEVICE structure
564 IsaIoDevice
= AllocateZeroPool (sizeof (ISA_IO_DEVICE
));
565 if (IsaIoDevice
== NULL
) {
566 return EFI_OUT_OF_RESOURCES
;
569 IsaIoDevice
->Signature
= ISA_IO_DEVICE_SIGNATURE
;
570 IsaIoDevice
->Handle
= NULL
;
571 IsaIoDevice
->PciIo
= PciIo
;
574 // Initialize the ISA I/O instance structure
576 InitializeIsaIoInstance (IsaIoDevice
, IsaDeviceResourceList
);
579 // Build the child device path
581 Node
.DevPath
.Type
= ACPI_DEVICE_PATH
;
582 Node
.DevPath
.SubType
= ACPI_DP
;
583 SetDevicePathNodeLength (&Node
.DevPath
, sizeof (ACPI_HID_DEVICE_PATH
));
584 Node
.Acpi
.HID
= IsaDeviceResourceList
->Device
.HID
;
585 Node
.Acpi
.UID
= IsaDeviceResourceList
->Device
.UID
;
587 IsaIoDevice
->DevicePath
= AppendDevicePathNode (
592 if (IsaIoDevice
->DevicePath
== NULL
) {
593 Status
= EFI_OUT_OF_RESOURCES
;
597 *ChildDevicePath
= IsaIoDevice
->DevicePath
;
600 // Create a child handle and install Device Path and ISA I/O protocols
602 Status
= gBS
->InstallMultipleProtocolInterfaces (
603 &IsaIoDevice
->Handle
,
604 &gEfiDevicePathProtocolGuid
,
605 IsaIoDevice
->DevicePath
,
606 &gEfiIsaIoProtocolGuid
,
610 if (EFI_ERROR (Status
)) {
614 Status
= gBS
->OpenProtocol (
616 &gEfiPciIoProtocolGuid
,
618 This
->DriverBindingHandle
,
620 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
622 if (EFI_ERROR (Status
)) {
623 gBS
->UninstallMultipleProtocolInterfaces (
625 &gEfiDevicePathProtocolGuid
,
626 IsaIoDevice
->DevicePath
,
627 &gEfiIsaIoProtocolGuid
,
635 if (EFI_ERROR (Status
)) {
636 if (IsaIoDevice
->DevicePath
!= NULL
) {
637 gBS
->FreePool (IsaIoDevice
->DevicePath
);
640 gBS
->FreePool (IsaIoDevice
);