3 Discovers all the ISA Controllers and their resources by using the ISA PnP
4 Protocol, produces an instance of the ISA I/O Protocol for every ISA
5 Controller found, loads and initializes all ISA Device Drivers, matches ISA
6 Device Drivers with their respective ISA Controllers in a deterministic
7 manner, and informs a ISA Device Driver when it is to start managing an ISA
10 Copyright (c) 2006 - 2007, Intel Corporation.<BR>
11 All rights reserved. This program and the accompanying materials
12 are licensed and made available under the terms and conditions of the BSD License
13 which accompanies this distribution. The full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include "InternalIsaBus.h"
25 // ISA Bus Driver Global Variables
27 EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver
= {
28 IsaBusControllerDriverSupported
,
29 IsaBusControllerDriverStart
,
30 IsaBusControllerDriverStop
,
37 The user Entry Point for module IsaBus. The user code starts with this function.
39 @param[in] ImageHandle The firmware allocated handle for the EFI image.
40 @param[in] SystemTable A pointer to the EFI System Table.
42 @retval EFI_SUCCESS The entry point is executed successfully.
43 @retval other Some error occurs when executing this entry point.
49 IN EFI_HANDLE ImageHandle
,
50 IN EFI_SYSTEM_TABLE
*SystemTable
56 // Install driver model protocol(s).
58 Status
= EfiLibInstallAllDriverProtocols (
61 &gIsaBusControllerDriver
,
63 &gIsaBusComponentName
,
67 ASSERT_EFI_ERROR (Status
);
76 IsaBusControllerDriverSupported (
77 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
78 IN EFI_HANDLE Controller
,
79 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
85 This function checks to see if a controller can be managed by the ISA Bus
86 Driver. This is done by checking to see if the controller supports the
87 EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration
88 Header to see if the device is a PCI to ISA bridge. The class code of
89 PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h
93 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
94 Controller - The handle of the device to check.
95 RemainingDevicePath - A pointer to the remaining portion of a device path.
99 EFI_SUCCESS - The device is supported by this driver.
100 EFI_UNSUPPORTED - The device is not supported by this driver.
105 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
108 // If RemainingDevicePath is not NULL, it should verify that the first device
109 // path node in RemainingDevicePath is an ACPI Device path node
111 if (RemainingDevicePath
!= NULL
) {
112 if (RemainingDevicePath
->Type
!= ACPI_DEVICE_PATH
) {
113 return EFI_UNSUPPORTED
;
114 } else if (RemainingDevicePath
->SubType
== ACPI_DP
) {
115 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_HID_DEVICE_PATH
)) {
116 return EFI_UNSUPPORTED
;
118 } else if (RemainingDevicePath
->SubType
== ACPI_EXTENDED_DP
) {
119 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH
)) {
120 return EFI_UNSUPPORTED
;
123 return EFI_UNSUPPORTED
;
127 // Test the existence of DEVICE_PATH protocol
129 Status
= gBS
->OpenProtocol (
131 &gEfiDevicePathProtocolGuid
,
133 This
->DriverBindingHandle
,
135 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
137 if (EFI_ERROR (Status
)) {
141 // Get the Isa Acpi protocol
143 Status
= gBS
->OpenProtocol (
145 &gEfiIsaAcpiProtocolGuid
,
147 This
->DriverBindingHandle
,
149 EFI_OPEN_PROTOCOL_BY_DRIVER
151 if (Status
== EFI_ALREADY_STARTED
) {
155 if (EFI_ERROR (Status
)) {
161 &gEfiIsaAcpiProtocolGuid
,
162 This
->DriverBindingHandle
,
171 IsaBusControllerDriverStart (
172 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
173 IN EFI_HANDLE Controller
,
174 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
180 This function tells the ISA Bus Driver to start managing a PCI to ISA
185 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
186 Controller - A handle to the device being started.
187 RemainingDevicePath - A pointer to the remaining portion of a device path.
191 EFI_SUCCESS - The device was started.
192 EFI_UNSUPPORTED - The device is not supported.
193 EFI_DEVICE_ERROR - The device could not be started due to a device error.
194 EFI_ALREADY_STARTED - The device has already been started.
195 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
196 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
202 EFI_PCI_IO_PROTOCOL
*PciIo
;
203 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
204 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
205 EFI_ISA_ACPI_DEVICE_ID
*IsaDevice
;
206 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
207 EFI_GENERIC_MEMORY_TEST_PROTOCOL
*GenMemoryTest
;
210 // Local variables declaration for StatusCode reporting
212 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData
;
213 EFI_DEVICE_PATH_PROTOCOL
*DevicePathData
;
216 // Initialize status code structure
218 AllocFailExtendedData
.DataHeader
.HeaderSize
= sizeof (EFI_STATUS_CODE_DATA
);
219 AllocFailExtendedData
.DataHeader
.Size
= sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA
) - sizeof (EFI_STATUS_CODE_DATA
);
221 &AllocFailExtendedData
.DataHeader
.Type
,
222 &gEfiStatusCodeSpecificDataGuid
,
227 // Open Device Path Protocol
229 Status
= gBS
->OpenProtocol (
231 &gEfiDevicePathProtocolGuid
,
232 (VOID
**) &ParentDevicePath
,
233 This
->DriverBindingHandle
,
235 EFI_OPEN_PROTOCOL_BY_DRIVER
237 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
241 // Open Pci IO Protocol
243 Status
= gBS
->OpenProtocol (
245 &gEfiPciIoProtocolGuid
,
247 This
->DriverBindingHandle
,
249 EFI_OPEN_PROTOCOL_GET_PROTOCOL
251 if (EFI_ERROR (Status
)) {
253 // Close opened protocol
257 &gEfiDevicePathProtocolGuid
,
258 This
->DriverBindingHandle
,
264 // Open ISA Acpi Protocol
266 Status
= gBS
->OpenProtocol (
268 &gEfiIsaAcpiProtocolGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_BY_DRIVER
274 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
276 // Close opened protocol
280 &gEfiDevicePathProtocolGuid
,
281 This
->DriverBindingHandle
,
286 &gEfiPciIoProtocolGuid
,
287 This
->DriverBindingHandle
,
293 // The IsaBus driver will use memory below 16M, which is not tested yet,
294 // so call CompatibleRangeTest to test them. Since memory below 1M should
295 // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M
298 Status
= gBS
->LocateProtocol (
299 &gEfiGenericMemTestProtocolGuid
,
301 (VOID
**) &GenMemoryTest
304 if (!EFI_ERROR (Status
)) {
305 Status
= GenMemoryTest
->CompatibleRangeTest (
312 // Report Status Code here since we will initialize the host controller
314 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
316 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
321 // first init ISA interface
323 IsaAcpi
->InterfaceInit (IsaAcpi
);
326 // Report Status Code here since we will enable the host controller
328 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
330 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
335 // Create each ISA device handle in this ISA bus
339 Status
= IsaAcpi
->DeviceEnumerate (IsaAcpi
, &IsaDevice
);
340 if (EFI_ERROR (Status
)) {
344 // Get current resource of this ISA device
347 Status
= IsaAcpi
->GetCurResource (IsaAcpi
, IsaDevice
, &ResourceList
);
348 if (EFI_ERROR (Status
)) {
353 // Create handle for this ISA device
355 Status
= IsaCreateDevice (
362 //&AllocFailExtendedData.DevicePath
365 if (EFI_ERROR (Status
)) {
369 // Initialize ISA device
371 IsaAcpi
->InitDevice (IsaAcpi
, IsaDevice
);
374 // Set resources for this ISA device
376 Status
= IsaAcpi
->SetResource (IsaAcpi
, IsaDevice
, ResourceList
);
379 // Report Status Code here when failed to resource conflicts
381 if (EFI_ERROR (Status
) && (Status
!= EFI_UNSUPPORTED
)) {
383 // It's hard to tell which resource conflicts
385 AllocFailExtendedData
.Bar
= 0;
386 AllocFailExtendedData
.ReqRes
= NULL
;
387 AllocFailExtendedData
.AllocRes
= NULL
;
388 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
390 (EFI_IO_BUS_LPC
| EFI_IOB_EC_RESOURCE_CONFLICT
),
396 // Set power for this ISA device
398 IsaAcpi
->SetPower (IsaAcpi
, IsaDevice
, TRUE
);
401 // Enable this ISA device
403 IsaAcpi
->EnableDevice (IsaAcpi
, IsaDevice
, TRUE
);
412 IsaBusControllerDriverStop (
413 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
414 IN EFI_HANDLE Controller
,
415 IN UINTN NumberOfChildren
,
416 IN EFI_HANDLE
* ChildHandleBuffer OPTIONAL
422 This function tells the ISA Bus Driver to stop managing a PCI to ISA
427 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
428 Controller - A handle to the device being stopped.
429 NumberOfChindren - The number of child device handles in ChildHandleBuffer.
430 ChildHandleBuffer - An array of child handles to be freed.
435 EFI_SUCCESS - The device was stopped.
436 EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
437 EFI_NOT_STARTED - The device has not been started.
438 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
439 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
446 BOOLEAN AllChildrenStopped
;
447 ISA_IO_DEVICE
*IsaIoDevice
;
448 EFI_ISA_IO_PROTOCOL
*IsaIo
;
450 if (NumberOfChildren
== 0) {
452 // Close the bus driver
454 Status
= gBS
->CloseProtocol (
456 &gEfiPciIoProtocolGuid
,
457 This
->DriverBindingHandle
,
460 if (EFI_ERROR (Status
)) {
464 Status
= gBS
->CloseProtocol (
466 &gEfiDevicePathProtocolGuid
,
467 This
->DriverBindingHandle
,
470 if (EFI_ERROR (Status
)) {
474 Status
= gBS
->CloseProtocol (
476 &gEfiIsaAcpiProtocolGuid
,
477 This
->DriverBindingHandle
,
480 if (EFI_ERROR (Status
)) {
487 // Complete all outstanding transactions to Controller.
488 // Don't allow any new transaction to Controller to be started.
491 // Stop all the children
492 // Find all the ISA devices that were discovered on this PCI to ISA Bridge
493 // with the Start() function.
495 AllChildrenStopped
= TRUE
;
497 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
499 Status
= gBS
->OpenProtocol (
500 ChildHandleBuffer
[Index
],
501 &gEfiIsaIoProtocolGuid
,
503 This
->DriverBindingHandle
,
505 EFI_OPEN_PROTOCOL_GET_PROTOCOL
507 if (!EFI_ERROR (Status
)) {
509 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo
);
511 Status
= gBS
->UninstallMultipleProtocolInterfaces (
512 ChildHandleBuffer
[Index
],
513 &gEfiDevicePathProtocolGuid
,
514 IsaIoDevice
->DevicePath
,
515 &gEfiIsaIoProtocolGuid
,
520 if (!EFI_ERROR (Status
)) {
522 // Close the child handle
524 Status
= gBS
->CloseProtocol (
526 &gEfiPciIoProtocolGuid
,
527 This
->DriverBindingHandle
,
528 ChildHandleBuffer
[Index
]
531 gBS
->FreePool (IsaIoDevice
->DevicePath
);
532 gBS
->FreePool (IsaIoDevice
);
536 if (EFI_ERROR (Status
)) {
537 AllChildrenStopped
= FALSE
;
541 if (!AllChildrenStopped
) {
542 return EFI_DEVICE_ERROR
;
552 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
553 IN EFI_HANDLE Controller
,
554 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
555 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
556 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
,
557 OUT EFI_DEVICE_PATH_PROTOCOL
**ChildDevicePath
563 Create ISA device found by IsaPnpProtocol
567 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
568 Controller - The handle of ISA bus controller(PCI to ISA bridge)
569 PciIo - The Pointer to the PCI protocol
570 ParentDevicePath - Device path of the ISA bus controller
571 IsaDeviceResourceList - The resource list of the ISA device
572 ChildDevicePath - The pointer to the child device.
576 EFI_SUCCESS - Create the child device.
577 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
579 EFI_DEVICE_ERROR - Can not create child device.
584 ISA_IO_DEVICE
*IsaIoDevice
;
588 // Initialize the PCI_IO_DEVICE structure
590 IsaIoDevice
= AllocateZeroPool (sizeof (ISA_IO_DEVICE
));
591 if (IsaIoDevice
== NULL
) {
592 return EFI_OUT_OF_RESOURCES
;
595 IsaIoDevice
->Signature
= ISA_IO_DEVICE_SIGNATURE
;
596 IsaIoDevice
->Handle
= NULL
;
597 IsaIoDevice
->PciIo
= PciIo
;
600 // Initialize the ISA I/O instance structure
602 Status
= InitializeIsaIoInstance (IsaIoDevice
, IsaDeviceResourceList
);
603 if (EFI_ERROR (Status
)) {
604 gBS
->FreePool (IsaIoDevice
);
608 // Build the child device path
610 Node
.DevPath
.Type
= ACPI_DEVICE_PATH
;
611 Node
.DevPath
.SubType
= ACPI_DP
;
612 SetDevicePathNodeLength (&Node
.DevPath
, sizeof (ACPI_HID_DEVICE_PATH
));
613 Node
.Acpi
.HID
= IsaDeviceResourceList
->Device
.HID
;
614 Node
.Acpi
.UID
= IsaDeviceResourceList
->Device
.UID
;
616 IsaIoDevice
->DevicePath
= AppendDevicePathNode (
621 if (IsaIoDevice
->DevicePath
== NULL
) {
622 Status
= EFI_DEVICE_ERROR
;
626 *ChildDevicePath
= IsaIoDevice
->DevicePath
;
629 // Create a child handle and attach the DevicePath,
630 // PCI I/O, and Controller State
632 Status
= gBS
->InstallMultipleProtocolInterfaces (
633 &IsaIoDevice
->Handle
,
634 &gEfiDevicePathProtocolGuid
,
635 IsaIoDevice
->DevicePath
,
636 &gEfiIsaIoProtocolGuid
,
640 if (EFI_ERROR (Status
)) {
644 Status
= gBS
->OpenProtocol (
646 &gEfiPciIoProtocolGuid
,
648 This
->DriverBindingHandle
,
650 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
652 if (EFI_ERROR (Status
)) {
653 gBS
->UninstallMultipleProtocolInterfaces (
655 &gEfiDevicePathProtocolGuid
,
656 IsaIoDevice
->DevicePath
,
657 &gEfiIsaIoProtocolGuid
,
665 if (EFI_ERROR (Status
)) {
666 if (IsaIoDevice
->DevicePath
!= NULL
) {
667 gBS
->FreePool (IsaIoDevice
->DevicePath
);
670 gBS
->FreePool (IsaIoDevice
);