3 Copyright (c) 2006 - 2007, Intel Corporation<BR>
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Discovers all the ISA Controllers and their resources by using the ISA PnP
19 Protocol, produces an instance of the ISA I/O Protocol for every ISA
20 Controller found, loads and initializes all ISA Device Drivers, matches ISA
21 Device Drivers with their respective ISA Controllers in a deterministic
22 manner, and informs a ISA Device Driver when it is to start managing an ISA
29 #include "InternalIsaBus.h"
32 // ISA Bus Driver Global Variables
34 EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver
= {
35 IsaBusControllerDriverSupported
,
36 IsaBusControllerDriverStart
,
37 IsaBusControllerDriverStop
,
44 The user Entry Point for module IsaBus. The user code starts with this function.
46 @param[in] ImageHandle The firmware allocated handle for the EFI image.
47 @param[in] SystemTable A pointer to the EFI System Table.
49 @retval EFI_SUCCESS The entry point is executed successfully.
50 @retval other Some error occurs when executing this entry point.
56 IN EFI_HANDLE ImageHandle
,
57 IN EFI_SYSTEM_TABLE
*SystemTable
63 // Install driver model protocol(s).
65 Status
= EfiLibInstallAllDriverProtocols (
68 &gIsaBusControllerDriver
,
70 &gIsaBusComponentName
,
74 ASSERT_EFI_ERROR (Status
);
83 IsaBusControllerDriverSupported (
84 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
85 IN EFI_HANDLE Controller
,
86 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
92 This function checks to see if a controller can be managed by the ISA Bus
93 Driver. This is done by checking to see if the controller supports the
94 EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration
95 Header to see if the device is a PCI to ISA bridge. The class code of
96 PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h
100 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
101 Controller - The handle of the device to check.
102 RemainingDevicePath - A pointer to the remaining portion of a device path.
106 EFI_SUCCESS - The device is supported by this driver.
107 EFI_UNSUPPORTED - The device is not supported by this driver.
112 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
115 // If RemainingDevicePath is not NULL, it should verify that the first device
116 // path node in RemainingDevicePath is an ACPI Device path node
118 if (RemainingDevicePath
!= NULL
) {
119 if (RemainingDevicePath
->Type
!= ACPI_DEVICE_PATH
) {
120 return EFI_UNSUPPORTED
;
121 } else if (RemainingDevicePath
->SubType
== ACPI_DP
) {
122 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_HID_DEVICE_PATH
)) {
123 return EFI_UNSUPPORTED
;
125 } else if (RemainingDevicePath
->SubType
== ACPI_EXTENDED_DP
) {
126 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH
)) {
127 return EFI_UNSUPPORTED
;
130 return EFI_UNSUPPORTED
;
134 // Test the existence of DEVICE_PATH protocol
136 Status
= gBS
->OpenProtocol (
138 &gEfiDevicePathProtocolGuid
,
140 This
->DriverBindingHandle
,
142 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
144 if (EFI_ERROR (Status
)) {
148 // Get the Isa Acpi protocol
150 Status
= gBS
->OpenProtocol (
152 &gEfiIsaAcpiProtocolGuid
,
154 This
->DriverBindingHandle
,
156 EFI_OPEN_PROTOCOL_BY_DRIVER
158 if (Status
== EFI_ALREADY_STARTED
) {
162 if (EFI_ERROR (Status
)) {
168 &gEfiIsaAcpiProtocolGuid
,
169 This
->DriverBindingHandle
,
178 IsaBusControllerDriverStart (
179 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
180 IN EFI_HANDLE Controller
,
181 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
187 This function tells the ISA Bus Driver to start managing a PCI to ISA
192 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
193 Controller - A handle to the device being started.
194 RemainingDevicePath - A pointer to the remaining portion of a device path.
198 EFI_SUCCESS - The device was started.
199 EFI_UNSUPPORTED - The device is not supported.
200 EFI_DEVICE_ERROR - The device could not be started due to a device error.
201 EFI_ALREADY_STARTED - The device has already been started.
202 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
203 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
209 EFI_PCI_IO_PROTOCOL
*PciIo
;
210 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
211 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
212 EFI_ISA_ACPI_DEVICE_ID
*IsaDevice
;
213 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
214 EFI_GENERIC_MEMORY_TEST_PROTOCOL
*GenMemoryTest
;
217 // Local variables declaration for StatusCode reporting
219 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData
;
220 EFI_DEVICE_PATH_PROTOCOL
*DevicePathData
;
223 // Initialize status code structure
225 AllocFailExtendedData
.DataHeader
.HeaderSize
= sizeof (EFI_STATUS_CODE_DATA
);
226 AllocFailExtendedData
.DataHeader
.Size
= sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA
) - sizeof (EFI_STATUS_CODE_DATA
);
228 &AllocFailExtendedData
.DataHeader
.Type
,
229 &gEfiStatusCodeSpecificDataGuid
,
234 // Open Device Path Protocol
236 Status
= gBS
->OpenProtocol (
238 &gEfiDevicePathProtocolGuid
,
239 (VOID
**) &ParentDevicePath
,
240 This
->DriverBindingHandle
,
242 EFI_OPEN_PROTOCOL_BY_DRIVER
244 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
248 // Open Pci IO Protocol
250 Status
= gBS
->OpenProtocol (
252 &gEfiPciIoProtocolGuid
,
254 This
->DriverBindingHandle
,
256 EFI_OPEN_PROTOCOL_GET_PROTOCOL
258 if (EFI_ERROR (Status
)) {
260 // Close opened protocol
264 &gEfiDevicePathProtocolGuid
,
265 This
->DriverBindingHandle
,
271 // Open ISA Acpi Protocol
273 Status
= gBS
->OpenProtocol (
275 &gEfiIsaAcpiProtocolGuid
,
277 This
->DriverBindingHandle
,
279 EFI_OPEN_PROTOCOL_BY_DRIVER
281 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
283 // Close opened protocol
287 &gEfiDevicePathProtocolGuid
,
288 This
->DriverBindingHandle
,
293 &gEfiPciIoProtocolGuid
,
294 This
->DriverBindingHandle
,
300 // The IsaBus driver will use memory below 16M, which is not tested yet,
301 // so call CompatibleRangeTest to test them. Since memory below 1M should
302 // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M
305 Status
= gBS
->LocateProtocol (
306 &gEfiGenericMemTestProtocolGuid
,
308 (VOID
**) &GenMemoryTest
311 if (!EFI_ERROR (Status
)) {
312 Status
= GenMemoryTest
->CompatibleRangeTest (
319 // Report Status Code here since we will initialize the host controller
321 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
323 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
328 // first init ISA interface
330 IsaAcpi
->InterfaceInit (IsaAcpi
);
333 // Report Status Code here since we will enable the host controller
335 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
337 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
342 // Create each ISA device handle in this ISA bus
346 Status
= IsaAcpi
->DeviceEnumerate (IsaAcpi
, &IsaDevice
);
347 if (EFI_ERROR (Status
)) {
351 // Get current resource of this ISA device
354 Status
= IsaAcpi
->GetCurResource (IsaAcpi
, IsaDevice
, &ResourceList
);
355 if (EFI_ERROR (Status
)) {
360 // Create handle for this ISA device
362 Status
= IsaCreateDevice (
369 //&AllocFailExtendedData.DevicePath
372 if (EFI_ERROR (Status
)) {
376 // Initialize ISA device
378 IsaAcpi
->InitDevice (IsaAcpi
, IsaDevice
);
381 // Set resources for this ISA device
383 Status
= IsaAcpi
->SetResource (IsaAcpi
, IsaDevice
, ResourceList
);
386 // Report Status Code here when failed to resource conflicts
388 if (EFI_ERROR (Status
) && (Status
!= EFI_UNSUPPORTED
)) {
390 // It's hard to tell which resource conflicts
392 AllocFailExtendedData
.Bar
= 0;
393 AllocFailExtendedData
.ReqRes
= NULL
;
394 AllocFailExtendedData
.AllocRes
= NULL
;
395 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
397 (EFI_IO_BUS_LPC
| EFI_IOB_EC_RESOURCE_CONFLICT
),
403 // Set power for this ISA device
405 IsaAcpi
->SetPower (IsaAcpi
, IsaDevice
, TRUE
);
408 // Enable this ISA device
410 IsaAcpi
->EnableDevice (IsaAcpi
, IsaDevice
, TRUE
);
419 IsaBusControllerDriverStop (
420 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
421 IN EFI_HANDLE Controller
,
422 IN UINTN NumberOfChildren
,
423 IN EFI_HANDLE
* ChildHandleBuffer OPTIONAL
429 This function tells the ISA Bus Driver to stop managing a PCI to ISA
434 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
435 Controller - A handle to the device being stopped.
436 NumberOfChindren - The number of child device handles in ChildHandleBuffer.
437 ChildHandleBuffer - An array of child handles to be freed.
442 EFI_SUCCESS - The device was stopped.
443 EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
444 EFI_NOT_STARTED - The device has not been started.
445 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
446 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
453 BOOLEAN AllChildrenStopped
;
454 ISA_IO_DEVICE
*IsaIoDevice
;
455 EFI_ISA_IO_PROTOCOL
*IsaIo
;
457 if (NumberOfChildren
== 0) {
459 // Close the bus driver
461 Status
= gBS
->CloseProtocol (
463 &gEfiPciIoProtocolGuid
,
464 This
->DriverBindingHandle
,
467 if (EFI_ERROR (Status
)) {
471 Status
= gBS
->CloseProtocol (
473 &gEfiDevicePathProtocolGuid
,
474 This
->DriverBindingHandle
,
477 if (EFI_ERROR (Status
)) {
481 Status
= gBS
->CloseProtocol (
483 &gEfiIsaAcpiProtocolGuid
,
484 This
->DriverBindingHandle
,
487 if (EFI_ERROR (Status
)) {
494 // Complete all outstanding transactions to Controller.
495 // Don't allow any new transaction to Controller to be started.
498 // Stop all the children
499 // Find all the ISA devices that were discovered on this PCI to ISA Bridge
500 // with the Start() function.
502 AllChildrenStopped
= TRUE
;
504 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
506 Status
= gBS
->OpenProtocol (
507 ChildHandleBuffer
[Index
],
508 &gEfiIsaIoProtocolGuid
,
510 This
->DriverBindingHandle
,
512 EFI_OPEN_PROTOCOL_GET_PROTOCOL
514 if (!EFI_ERROR (Status
)) {
516 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo
);
518 Status
= gBS
->UninstallMultipleProtocolInterfaces (
519 ChildHandleBuffer
[Index
],
520 &gEfiDevicePathProtocolGuid
,
521 IsaIoDevice
->DevicePath
,
522 &gEfiIsaIoProtocolGuid
,
527 if (!EFI_ERROR (Status
)) {
529 // Close the child handle
531 Status
= gBS
->CloseProtocol (
533 &gEfiPciIoProtocolGuid
,
534 This
->DriverBindingHandle
,
535 ChildHandleBuffer
[Index
]
538 gBS
->FreePool (IsaIoDevice
->DevicePath
);
539 gBS
->FreePool (IsaIoDevice
);
543 if (EFI_ERROR (Status
)) {
544 AllChildrenStopped
= FALSE
;
548 if (!AllChildrenStopped
) {
549 return EFI_DEVICE_ERROR
;
559 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
560 IN EFI_HANDLE Controller
,
561 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
562 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
563 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
,
564 OUT EFI_DEVICE_PATH_PROTOCOL
**ChildDevicePath
570 Create ISA device found by IsaPnpProtocol
574 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
575 Controller - The handle of ISA bus controller(PCI to ISA bridge)
576 PciIo - The Pointer to the PCI protocol
577 ParentDevicePath - Device path of the ISA bus controller
578 IsaDeviceResourceList - The resource list of the ISA device
579 ChildDevicePath - The pointer to the child device.
583 EFI_SUCCESS - Create the child device.
584 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
586 EFI_DEVICE_ERROR - Can not create child device.
591 ISA_IO_DEVICE
*IsaIoDevice
;
595 // Initialize the PCI_IO_DEVICE structure
597 IsaIoDevice
= AllocateZeroPool (sizeof (ISA_IO_DEVICE
));
598 if (IsaIoDevice
== NULL
) {
599 return EFI_OUT_OF_RESOURCES
;
602 IsaIoDevice
->Signature
= ISA_IO_DEVICE_SIGNATURE
;
603 IsaIoDevice
->Handle
= NULL
;
604 IsaIoDevice
->PciIo
= PciIo
;
607 // Initialize the ISA I/O instance structure
609 Status
= InitializeIsaIoInstance (IsaIoDevice
, IsaDeviceResourceList
);
610 if (EFI_ERROR (Status
)) {
611 gBS
->FreePool (IsaIoDevice
);
615 // Build the child device path
617 Node
.DevPath
.Type
= ACPI_DEVICE_PATH
;
618 Node
.DevPath
.SubType
= ACPI_DP
;
619 SetDevicePathNodeLength (&Node
.DevPath
, sizeof (ACPI_HID_DEVICE_PATH
));
620 Node
.Acpi
.HID
= IsaDeviceResourceList
->Device
.HID
;
621 Node
.Acpi
.UID
= IsaDeviceResourceList
->Device
.UID
;
623 IsaIoDevice
->DevicePath
= AppendDevicePathNode (
628 if (IsaIoDevice
->DevicePath
== NULL
) {
629 Status
= EFI_DEVICE_ERROR
;
633 *ChildDevicePath
= IsaIoDevice
->DevicePath
;
636 // Create a child handle and attach the DevicePath,
637 // PCI I/O, and Controller State
639 Status
= gBS
->InstallMultipleProtocolInterfaces (
640 &IsaIoDevice
->Handle
,
641 &gEfiDevicePathProtocolGuid
,
642 IsaIoDevice
->DevicePath
,
643 &gEfiIsaIoProtocolGuid
,
647 if (EFI_ERROR (Status
)) {
651 Status
= gBS
->OpenProtocol (
653 &gEfiPciIoProtocolGuid
,
655 This
->DriverBindingHandle
,
657 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
659 if (EFI_ERROR (Status
)) {
660 gBS
->UninstallMultipleProtocolInterfaces (
662 &gEfiDevicePathProtocolGuid
,
663 IsaIoDevice
->DevicePath
,
664 &gEfiIsaIoProtocolGuid
,
672 if (EFI_ERROR (Status
)) {
673 if (IsaIoDevice
->DevicePath
!= NULL
) {
674 gBS
->FreePool (IsaIoDevice
->DevicePath
);
677 gBS
->FreePool (IsaIoDevice
);