3 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
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
,
45 IsaBusControllerDriverSupported (
46 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
47 IN EFI_HANDLE Controller
,
48 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
54 This function checks to see if a controller can be managed by the ISA Bus
55 Driver. This is done by checking to see if the controller supports the
56 EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration
57 Header to see if the device is a PCI to ISA bridge. The class code of
58 PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h
62 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
63 Controller - The handle of the device to check.
64 RemainingDevicePath - A pointer to the remaining portion of a device path.
68 EFI_SUCCESS - The device is supported by this driver.
69 EFI_UNSUPPORTED - The device is not supported by this driver.
74 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
77 // If RemainingDevicePath is not NULL, it should verify that the first device
78 // path node in RemainingDevicePath is an ACPI Device path node
80 if (RemainingDevicePath
!= NULL
) {
81 if (RemainingDevicePath
->Type
!= ACPI_DEVICE_PATH
) {
82 return EFI_UNSUPPORTED
;
83 } else if (RemainingDevicePath
->SubType
== ACPI_DP
) {
84 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_HID_DEVICE_PATH
)) {
85 return EFI_UNSUPPORTED
;
87 } else if (RemainingDevicePath
->SubType
== ACPI_EXTENDED_DP
) {
88 if (DevicePathNodeLength (RemainingDevicePath
) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH
)) {
89 return EFI_UNSUPPORTED
;
92 return EFI_UNSUPPORTED
;
96 // Test the existence of DEVICE_PATH protocol
98 Status
= gBS
->OpenProtocol (
100 &gEfiDevicePathProtocolGuid
,
102 This
->DriverBindingHandle
,
104 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
106 if (EFI_ERROR (Status
)) {
110 // Get the Isa Acpi protocol
112 Status
= gBS
->OpenProtocol (
114 &gEfiIsaAcpiProtocolGuid
,
116 This
->DriverBindingHandle
,
118 EFI_OPEN_PROTOCOL_BY_DRIVER
120 if (Status
== EFI_ALREADY_STARTED
) {
124 if (EFI_ERROR (Status
)) {
130 &gEfiIsaAcpiProtocolGuid
,
131 This
->DriverBindingHandle
,
140 IsaBusControllerDriverStart (
141 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
142 IN EFI_HANDLE Controller
,
143 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
149 This function tells the ISA Bus Driver to start managing a PCI to ISA
154 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
155 Controller - A handle to the device being started.
156 RemainingDevicePath - A pointer to the remaining portion of a device path.
160 EFI_SUCCESS - The device was started.
161 EFI_UNSUPPORTED - The device is not supported.
162 EFI_DEVICE_ERROR - The device could not be started due to a device error.
163 EFI_ALREADY_STARTED - The device has already been started.
164 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
165 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
171 EFI_PCI_IO_PROTOCOL
*PciIo
;
172 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
173 EFI_ISA_ACPI_PROTOCOL
*IsaAcpi
;
174 EFI_ISA_ACPI_DEVICE_ID
*IsaDevice
;
175 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
176 EFI_GENERIC_MEMORY_TEST_PROTOCOL
*GenMemoryTest
;
179 // Local variables declaration for StatusCode reporting
181 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData
;
182 EFI_DEVICE_PATH_PROTOCOL
*DevicePathData
;
184 BootScriptSaveInformationAsciiString (
185 EFI_ACPI_S3_RESUME_SCRIPT_TABLE
,
186 "IsaBusBindingStartBegin"
190 // Initialize status code structure
192 AllocFailExtendedData
.DataHeader
.HeaderSize
= sizeof (EFI_STATUS_CODE_DATA
);
193 AllocFailExtendedData
.DataHeader
.Size
= sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA
) - sizeof (EFI_STATUS_CODE_DATA
);
195 &AllocFailExtendedData
.DataHeader
.Type
,
196 &gEfiStatusCodeSpecificDataGuid
,
201 // Open Device Path Protocol
203 Status
= gBS
->OpenProtocol (
205 &gEfiDevicePathProtocolGuid
,
206 (VOID
**) &ParentDevicePath
,
207 This
->DriverBindingHandle
,
209 EFI_OPEN_PROTOCOL_BY_DRIVER
211 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
215 // Open Pci IO Protocol
217 Status
= gBS
->OpenProtocol (
219 &gEfiPciIoProtocolGuid
,
221 This
->DriverBindingHandle
,
223 EFI_OPEN_PROTOCOL_GET_PROTOCOL
225 if (EFI_ERROR (Status
)) {
227 // Close opened protocol
231 &gEfiDevicePathProtocolGuid
,
232 This
->DriverBindingHandle
,
238 // Open ISA Acpi Protocol
240 Status
= gBS
->OpenProtocol (
242 &gEfiIsaAcpiProtocolGuid
,
244 This
->DriverBindingHandle
,
246 EFI_OPEN_PROTOCOL_BY_DRIVER
248 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
250 // Close opened protocol
254 &gEfiDevicePathProtocolGuid
,
255 This
->DriverBindingHandle
,
260 &gEfiPciIoProtocolGuid
,
261 This
->DriverBindingHandle
,
267 // The IsaBus driver will use memory below 16M, which is not tested yet,
268 // so call CompatibleRangeTest to test them. Since memory below 1M should
269 // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M
272 Status
= gBS
->LocateProtocol (
273 &gEfiGenericMemTestProtocolGuid
,
275 (VOID
**) &GenMemoryTest
278 if (!EFI_ERROR (Status
)) {
279 Status
= GenMemoryTest
->CompatibleRangeTest (
286 // Report Status Code here since we will initialize the host controller
288 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
290 (EFI_IO_BUS_LPC
| EFI_IOB_PC_INIT
),
295 // first init ISA interface
297 IsaAcpi
->InterfaceInit (IsaAcpi
);
300 // Report Status Code here since we will enable the host controller
302 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
304 (EFI_IO_BUS_LPC
| EFI_IOB_PC_ENABLE
),
309 // Create each ISA device handle in this ISA bus
313 Status
= IsaAcpi
->DeviceEnumerate (IsaAcpi
, &IsaDevice
);
314 if (EFI_ERROR (Status
)) {
318 // Get current resource of this ISA device
321 Status
= IsaAcpi
->GetCurResource (IsaAcpi
, IsaDevice
, &ResourceList
);
322 if (EFI_ERROR (Status
)) {
327 // Create handle for this ISA device
329 Status
= IsaCreateDevice (
336 //&AllocFailExtendedData.DevicePath
339 if (EFI_ERROR (Status
)) {
343 // Initialize ISA device
345 IsaAcpi
->InitDevice (IsaAcpi
, IsaDevice
);
348 // Set resources for this ISA device
350 Status
= IsaAcpi
->SetResource (IsaAcpi
, IsaDevice
, ResourceList
);
353 // Report Status Code here when failed to resource conflicts
355 if (EFI_ERROR (Status
) && (Status
!= EFI_UNSUPPORTED
)) {
357 // It's hard to tell which resource conflicts
359 AllocFailExtendedData
.Bar
= 0;
360 AllocFailExtendedData
.ReqRes
= NULL
;
361 AllocFailExtendedData
.AllocRes
= NULL
;
362 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
364 (EFI_IO_BUS_LPC
| EFI_IOB_EC_RESOURCE_CONFLICT
),
370 // Set power for this ISA device
372 IsaAcpi
->SetPower (IsaAcpi
, IsaDevice
, TRUE
);
375 // Enable this ISA device
377 IsaAcpi
->EnableDevice (IsaAcpi
, IsaDevice
, TRUE
);
381 BootScriptSaveInformationAsciiString (
382 EFI_ACPI_S3_RESUME_SCRIPT_TABLE
,
383 "IsaBusBindingStartEnd"
391 IsaBusControllerDriverStop (
392 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
393 IN EFI_HANDLE Controller
,
394 IN UINTN NumberOfChildren
,
395 IN EFI_HANDLE
* ChildHandleBuffer OPTIONAL
401 This function tells the ISA Bus Driver to stop managing a PCI to ISA
406 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
407 Controller - A handle to the device being stopped.
408 NumberOfChindren - The number of child device handles in ChildHandleBuffer.
409 ChildHandleBuffer - An array of child handles to be freed.
414 EFI_SUCCESS - The device was stopped.
415 EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
416 EFI_NOT_STARTED - The device has not been started.
417 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
418 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
425 BOOLEAN AllChildrenStopped
;
426 ISA_IO_DEVICE
*IsaIoDevice
;
427 EFI_ISA_IO_PROTOCOL
*IsaIo
;
429 if (NumberOfChildren
== 0) {
431 // Close the bus driver
433 Status
= gBS
->CloseProtocol (
435 &gEfiPciIoProtocolGuid
,
436 This
->DriverBindingHandle
,
439 if (EFI_ERROR (Status
)) {
443 Status
= gBS
->CloseProtocol (
445 &gEfiDevicePathProtocolGuid
,
446 This
->DriverBindingHandle
,
449 if (EFI_ERROR (Status
)) {
453 Status
= gBS
->CloseProtocol (
455 &gEfiIsaAcpiProtocolGuid
,
456 This
->DriverBindingHandle
,
459 if (EFI_ERROR (Status
)) {
466 // Complete all outstanding transactions to Controller.
467 // Don't allow any new transaction to Controller to be started.
470 // Stop all the children
471 // Find all the ISA devices that were discovered on this PCI to ISA Bridge
472 // with the Start() function.
474 AllChildrenStopped
= TRUE
;
476 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
478 Status
= gBS
->OpenProtocol (
479 ChildHandleBuffer
[Index
],
480 &gEfiIsaIoProtocolGuid
,
482 This
->DriverBindingHandle
,
484 EFI_OPEN_PROTOCOL_GET_PROTOCOL
486 if (!EFI_ERROR (Status
)) {
488 IsaIoDevice
= ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo
);
490 Status
= gBS
->UninstallMultipleProtocolInterfaces (
491 ChildHandleBuffer
[Index
],
492 &gEfiDevicePathProtocolGuid
,
493 IsaIoDevice
->DevicePath
,
494 &gEfiIsaIoProtocolGuid
,
499 if (!EFI_ERROR (Status
)) {
501 // Close the child handle
503 Status
= gBS
->CloseProtocol (
505 &gEfiPciIoProtocolGuid
,
506 This
->DriverBindingHandle
,
507 ChildHandleBuffer
[Index
]
510 gBS
->FreePool (IsaIoDevice
->DevicePath
);
511 gBS
->FreePool (IsaIoDevice
);
515 if (EFI_ERROR (Status
)) {
516 AllChildrenStopped
= FALSE
;
520 if (!AllChildrenStopped
) {
521 return EFI_DEVICE_ERROR
;
531 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
532 IN EFI_HANDLE Controller
,
533 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
534 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
535 IN EFI_ISA_ACPI_RESOURCE_LIST
*IsaDeviceResourceList
,
536 OUT EFI_DEVICE_PATH_PROTOCOL
**ChildDevicePath
542 Create ISA device found by IsaPnpProtocol
546 This - The EFI_DRIVER_BINDING_PROTOCOL instance.
547 Controller - The handle of ISA bus controller(PCI to ISA bridge)
548 PciIo - The Pointer to the PCI protocol
549 ParentDevicePath - Device path of the ISA bus controller
550 IsaDeviceResourceList - The resource list of the ISA device
551 ChildDevicePath - The pointer to the child device.
555 EFI_SUCCESS - Create the child device.
556 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
558 EFI_DEVICE_ERROR - Can not create child device.
563 ISA_IO_DEVICE
*IsaIoDevice
;
567 // Initialize the PCI_IO_DEVICE structure
569 IsaIoDevice
= AllocateZeroPool (sizeof (ISA_IO_DEVICE
));
570 if (IsaIoDevice
== NULL
) {
571 return EFI_OUT_OF_RESOURCES
;
574 IsaIoDevice
->Signature
= ISA_IO_DEVICE_SIGNATURE
;
575 IsaIoDevice
->Handle
= NULL
;
576 IsaIoDevice
->PciIo
= PciIo
;
579 // Initialize the ISA I/O instance structure
581 Status
= InitializeIsaIoInstance (IsaIoDevice
, IsaDeviceResourceList
);
582 if (EFI_ERROR (Status
)) {
583 gBS
->FreePool (IsaIoDevice
);
587 // Build the child device path
589 Node
.DevPath
.Type
= ACPI_DEVICE_PATH
;
590 Node
.DevPath
.SubType
= ACPI_DP
;
591 SetDevicePathNodeLength (&Node
.DevPath
, sizeof (ACPI_HID_DEVICE_PATH
));
592 Node
.Acpi
.HID
= IsaDeviceResourceList
->Device
.HID
;
593 Node
.Acpi
.UID
= IsaDeviceResourceList
->Device
.UID
;
595 IsaIoDevice
->DevicePath
= AppendDevicePathNode (
600 if (IsaIoDevice
->DevicePath
== NULL
) {
601 Status
= EFI_DEVICE_ERROR
;
605 *ChildDevicePath
= IsaIoDevice
->DevicePath
;
608 // Create a child handle and attach the DevicePath,
609 // PCI I/O, and Controller State
611 Status
= gBS
->InstallMultipleProtocolInterfaces (
612 &IsaIoDevice
->Handle
,
613 &gEfiDevicePathProtocolGuid
,
614 IsaIoDevice
->DevicePath
,
615 &gEfiIsaIoProtocolGuid
,
619 if (EFI_ERROR (Status
)) {
623 Status
= gBS
->OpenProtocol (
625 &gEfiPciIoProtocolGuid
,
627 This
->DriverBindingHandle
,
629 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
631 if (EFI_ERROR (Status
)) {
632 gBS
->UninstallMultipleProtocolInterfaces (
634 &gEfiDevicePathProtocolGuid
,
635 IsaIoDevice
->DevicePath
,
636 &gEfiIsaIoProtocolGuid
,
644 if (EFI_ERROR (Status
)) {
645 if (IsaIoDevice
->DevicePath
!= NULL
) {
646 gBS
->FreePool (IsaIoDevice
->DevicePath
);
649 gBS
->FreePool (IsaIoDevice
);