EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c

Go to the documentation of this file.
00001 
00020 #include "InternalIsaBus.h"
00021 
00022 //
00023 // ISA Bus Driver Global Variables
00024 //
00025 EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver = {
00026   IsaBusControllerDriverSupported,
00027   IsaBusControllerDriverStart,
00028   IsaBusControllerDriverStop,
00029   0xa,
00030   NULL,
00031   NULL
00032 };
00033 
00043 EFI_STATUS
00044 EFIAPI
00045 InitializeIsaBus(
00046   IN EFI_HANDLE           ImageHandle,
00047   IN EFI_SYSTEM_TABLE     *SystemTable
00048   )
00049 {
00050   EFI_STATUS              Status;
00051 
00052   //
00053   // Install driver model protocol(s).
00054   //
00055   Status = EfiLibInstallDriverBindingComponentName2 (
00056              ImageHandle,
00057              SystemTable,
00058              &gIsaBusControllerDriver,
00059              ImageHandle,
00060              &gIsaBusComponentName,
00061              &gIsaBusComponentName2
00062              );
00063   ASSERT_EFI_ERROR (Status);
00064 
00065   return Status;
00066 }
00067 
00086 EFI_STATUS
00087 EFIAPI
00088 IsaBusControllerDriverSupported (
00089   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
00090   IN EFI_HANDLE                   Controller,
00091   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
00092   )
00093 {
00094   EFI_STATUS                Status;
00095   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
00096   EFI_ISA_ACPI_PROTOCOL     *IsaAcpi;
00097 
00098   //
00099   // If RemainingDevicePath is not NULL, it should verify that the first device
00100   // path node in RemainingDevicePath is an ACPI Device path node which is a 
00101   // legal Device Path Node for this bus driver's children.
00102   //
00103   if (RemainingDevicePath != NULL) {
00104     if (RemainingDevicePath->Type != ACPI_DEVICE_PATH) {
00105       return EFI_UNSUPPORTED;
00106     } else if (RemainingDevicePath->SubType == ACPI_DP) {
00107       if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH)) {
00108         return EFI_UNSUPPORTED;
00109       }
00110     } else if (RemainingDevicePath->SubType == ACPI_EXTENDED_DP) {
00111       if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)) {
00112         return EFI_UNSUPPORTED;
00113       }
00114     } else {
00115       return EFI_UNSUPPORTED;
00116     }
00117   }
00118   //
00119   // Try to open EFI DEVICE PATH protocol on the controller
00120   //
00121   Status = gBS->OpenProtocol (
00122                   Controller,
00123                   &gEfiDevicePathProtocolGuid,
00124                   (VOID **) &ParentDevicePath,
00125                   This->DriverBindingHandle,
00126                   Controller,
00127                   EFI_OPEN_PROTOCOL_BY_DRIVER
00128                   );
00129   //
00130   // Although this driver creates all child handles at one time,
00131   // but because all child handles may be not stopped at one time in EFI Driver Binding.Stop(),
00132   // So it is allowed to create child handles again in successive calls to EFI Driver Binding.Start().
00133   //
00134   if (Status == EFI_ALREADY_STARTED) {
00135     return EFI_SUCCESS;
00136   }
00137 
00138   if (EFI_ERROR (Status)) {
00139     return Status;
00140   }
00141 
00142   gBS->CloseProtocol (
00143          Controller,
00144          &gEfiDevicePathProtocolGuid,
00145          This->DriverBindingHandle,
00146          Controller
00147          );
00148 
00149   //
00150   // Try to get Pci IO Protocol because it is assumed
00151   // to have been opened by ISA ACPI driver
00152   //
00153   Status = gBS->OpenProtocol (
00154                   Controller,
00155                   &gEfiPciIoProtocolGuid,
00156                   NULL,
00157                   This->DriverBindingHandle,
00158                   Controller,
00159                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
00160                   );
00161   if (EFI_ERROR (Status)) {
00162     return Status;
00163   }
00164 
00165   //
00166   // Try to open the Isa Acpi protocol on the controller
00167   //
00168   Status = gBS->OpenProtocol (
00169                   Controller,
00170                   &gEfiIsaAcpiProtocolGuid,
00171                   (VOID **) &IsaAcpi,
00172                   This->DriverBindingHandle,
00173                   Controller,
00174                   EFI_OPEN_PROTOCOL_BY_DRIVER
00175                   );
00176   if (EFI_ERROR (Status)) {
00177     return Status;
00178   }
00179 
00180   //
00181   // Add more check to see if the child device is valid by calling IsaAcpi->DeviceEnumerate?
00182   //
00183 
00184   gBS->CloseProtocol (
00185          Controller,
00186          &gEfiIsaAcpiProtocolGuid,
00187          This->DriverBindingHandle,
00188          Controller
00189          );
00190 
00191   return Status;
00192 }
00193 
00221 EFI_STATUS
00222 EFIAPI
00223 IsaBusControllerDriverStart (
00224   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
00225   IN EFI_HANDLE                   Controller,
00226   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
00227   )
00228 {
00229   EFI_STATUS                            Status;
00230   EFI_PCI_IO_PROTOCOL                   *PciIo;
00231   EFI_DEVICE_PATH_PROTOCOL              *ParentDevicePath;
00232   EFI_ISA_ACPI_PROTOCOL                 *IsaAcpi;
00233   EFI_ISA_ACPI_DEVICE_ID                *IsaDevice;
00234   EFI_ISA_ACPI_RESOURCE_LIST            *ResourceList;
00235   EFI_GENERIC_MEMORY_TEST_PROTOCOL      *GenMemoryTest;
00236 
00237   //
00238   // Local variables declaration for StatusCode reporting
00239   //
00240   EFI_DEVICE_PATH_PROTOCOL              *DevicePathData;
00241 
00242   //
00243   // Get Pci IO Protocol
00244   //
00245   Status = gBS->OpenProtocol (
00246                   Controller,
00247                   &gEfiPciIoProtocolGuid,
00248                   (VOID **) &PciIo,
00249                   This->DriverBindingHandle,
00250                   Controller,
00251                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
00252                   );
00253   if (EFI_ERROR (Status)) {
00254     return Status;
00255   }
00256 
00257   //
00258   // Open Device Path Protocol
00259   //
00260   Status = gBS->OpenProtocol (
00261                   Controller,
00262                   &gEfiDevicePathProtocolGuid,
00263                   (VOID **) &ParentDevicePath,
00264                   This->DriverBindingHandle,
00265                   Controller,
00266                   EFI_OPEN_PROTOCOL_BY_DRIVER
00267                   );
00268   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
00269     return Status;
00270   }
00271 
00272   //
00273   // Open ISA Acpi Protocol
00274   //
00275   Status = gBS->OpenProtocol (
00276                   Controller,
00277                   &gEfiIsaAcpiProtocolGuid,
00278                   (VOID **) &IsaAcpi,
00279                   This->DriverBindingHandle,
00280                   Controller,
00281                   EFI_OPEN_PROTOCOL_BY_DRIVER
00282                   );
00283   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
00284     //
00285     // Close opened protocol
00286     //
00287     gBS->CloseProtocol (
00288            Controller,
00289            &gEfiDevicePathProtocolGuid,
00290            This->DriverBindingHandle,
00291            Controller
00292            );
00293     return Status;
00294   }
00295   //
00296   // The IsaBus driver will use memory below 16M, which is not tested yet,
00297   // so call CompatibleRangeTest to test them. Since memory below 1M should
00298   // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M
00299   // ~15M here
00300   //
00301   Status = gBS->LocateProtocol (
00302                   &gEfiGenericMemTestProtocolGuid,
00303                   NULL,
00304                   (VOID **) &GenMemoryTest
00305                   );
00306 
00307   if (!EFI_ERROR (Status)) {
00308     Status = GenMemoryTest->CompatibleRangeTest (
00309                               GenMemoryTest,
00310                               0x100000,
00311                               0xE00000
00312                               );
00313   }
00314   //
00315   // Report Status Code here since we will initialize the host controller
00316   //
00317   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
00318     EFI_PROGRESS_CODE,
00319     (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT),
00320     ParentDevicePath
00321     );
00322 
00323   //
00324   // first init ISA interface
00325   //
00326   IsaAcpi->InterfaceInit (IsaAcpi);
00327 
00328   //
00329   // Report Status Code here since we will enable the host controller
00330   //
00331   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
00332     EFI_PROGRESS_CODE,
00333     (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE),
00334     ParentDevicePath
00335     );
00336 
00337   //
00338   // Create each ISA device handle in this ISA bus
00339   //
00340   IsaDevice = NULL;
00341   do {
00342     Status = IsaAcpi->DeviceEnumerate (IsaAcpi, &IsaDevice);
00343     if (EFI_ERROR (Status)) {
00344       break;
00345     }
00346     //
00347     // Get current resource of this ISA device
00348     //
00349     ResourceList  = NULL;
00350     Status        = IsaAcpi->GetCurResource (IsaAcpi, IsaDevice, &ResourceList);
00351     if (EFI_ERROR (Status)) {
00352       continue;
00353     }
00354 
00355     //
00356     // Create handle for this ISA device
00357     //
00358     // If any child device handle was created in previous call to Start() and not stopped
00359     // in previous call to Stop(), it will not be created again because the
00360     // InstallMultipleProtocolInterfaces() boot service will reject same device path.
00361     //
00362     Status = IsaCreateDevice (
00363                This,
00364                Controller,
00365                PciIo,
00366                ParentDevicePath,
00367                ResourceList,
00368                &DevicePathData
00369                );
00370 
00371     if (EFI_ERROR (Status)) {
00372       continue;
00373     }
00374     //
00375     // Initialize ISA device
00376     //
00377     IsaAcpi->InitDevice (IsaAcpi, IsaDevice);
00378 
00379     //
00380     // Set resources for this ISA device
00381     //
00382     Status = IsaAcpi->SetResource (IsaAcpi, IsaDevice, ResourceList);
00383 
00384     //
00385     // Report Status Code here when failed to resource conflicts
00386     //
00387     if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
00388       //
00389       // It's hard to tell which resource conflicts
00390       //
00391       REPORT_STATUS_CODE_WITH_DEVICE_PATH (
00392          EFI_ERROR_CODE,
00393          (EFI_IO_BUS_LPC | EFI_IOB_EC_RESOURCE_CONFLICT),
00394          DevicePathData
00395          );
00396 
00397     }
00398     //
00399     // Set power for this ISA device
00400     //
00401     IsaAcpi->SetPower (IsaAcpi, IsaDevice, TRUE);
00402 
00403     //
00404     // Enable this ISA device
00405     //
00406     IsaAcpi->EnableDevice (IsaAcpi, IsaDevice, TRUE);
00407 
00408   } while (TRUE);
00409 
00410   return EFI_SUCCESS;
00411 }
00412 
00438 EFI_STATUS
00439 EFIAPI
00440 IsaBusControllerDriverStop (
00441   IN  EFI_DRIVER_BINDING_PROTOCOL  * This,
00442   IN  EFI_HANDLE                   Controller,
00443   IN  UINTN                        NumberOfChildren,
00444   IN  EFI_HANDLE                   * ChildHandleBuffer OPTIONAL
00445   )
00446 {
00447   EFI_STATUS                          Status;
00448   UINTN                               Index;
00449   BOOLEAN                             AllChildrenStopped;
00450   ISA_IO_DEVICE                       *IsaIoDevice;
00451   EFI_ISA_IO_PROTOCOL                 *IsaIo;
00452   EFI_PCI_IO_PROTOCOL                 *PciIo;
00453 
00454   if (NumberOfChildren == 0) {
00455     //
00456     // Close the bus driver
00457     //
00458     Status = gBS->CloseProtocol (
00459                     Controller,
00460                     &gEfiDevicePathProtocolGuid,
00461                     This->DriverBindingHandle,
00462                     Controller
00463                     );
00464     if (EFI_ERROR (Status)) {
00465       return Status;
00466     }
00467 
00468     Status = gBS->CloseProtocol (
00469                     Controller,
00470                     &gEfiIsaAcpiProtocolGuid,
00471                     This->DriverBindingHandle,
00472                     Controller
00473                     );
00474     if (EFI_ERROR (Status)) {
00475       return Status;
00476     }
00477 
00478     return EFI_SUCCESS;
00479   }
00480   //
00481   // Complete all outstanding transactions to Controller.
00482   // Don't allow any new transaction to Controller to be started.
00483   //
00484   //
00485   // Stop all the children
00486   // Find all the ISA devices that were discovered on this PCI to ISA Bridge
00487   // with the Start() function.
00488   //
00489   AllChildrenStopped = TRUE;
00490 
00491   for (Index = 0; Index < NumberOfChildren; Index++) {
00492 
00493     Status = gBS->OpenProtocol (
00494                     ChildHandleBuffer[Index],
00495                     &gEfiIsaIoProtocolGuid,
00496                     (VOID **) &IsaIo,
00497                     This->DriverBindingHandle,
00498                     Controller,
00499                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
00500                     );
00501     if (!EFI_ERROR (Status)) {
00502 
00503       IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo);
00504 
00505       //
00506       // Close the child handle
00507       //
00508 
00509       Status = gBS->CloseProtocol (
00510                       Controller,
00511                       &gEfiPciIoProtocolGuid,
00512                       This->DriverBindingHandle,
00513                       ChildHandleBuffer[Index]
00514                       );
00515       Status = gBS->UninstallMultipleProtocolInterfaces (
00516                       ChildHandleBuffer[Index],
00517                       &gEfiDevicePathProtocolGuid,
00518                       IsaIoDevice->DevicePath,
00519                       &gEfiIsaIoProtocolGuid,
00520                       &IsaIoDevice->IsaIo,
00521                       NULL
00522                       );
00523 
00524       if (!EFI_ERROR (Status)) {
00525         FreePool (IsaIoDevice->DevicePath);
00526         FreePool (IsaIoDevice);
00527       } else {
00528         //
00529         // Re-open PCI IO Protocol on behalf of the child device
00530         // because of failure of destroying the child device handle
00531         //
00532         gBS->OpenProtocol (
00533                Controller,
00534                &gEfiPciIoProtocolGuid,
00535                (VOID **) &PciIo,
00536                This->DriverBindingHandle,
00537                ChildHandleBuffer[Index],
00538                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
00539                );     
00540       }
00541     }
00542 
00543     if (EFI_ERROR (Status)) {
00544       AllChildrenStopped = FALSE;
00545     }
00546   }
00547 
00548   if (!AllChildrenStopped) {
00549     return EFI_DEVICE_ERROR;
00550   }
00551 
00552   return EFI_SUCCESS;
00553 }
00554 
00555 //
00556 // Internal Function
00557 //
00558 
00573 EFI_STATUS
00574 IsaCreateDevice (
00575   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
00576   IN EFI_HANDLE                   Controller,
00577   IN EFI_PCI_IO_PROTOCOL          *PciIo,
00578   IN EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
00579   IN EFI_ISA_ACPI_RESOURCE_LIST   *IsaDeviceResourceList,
00580   OUT EFI_DEVICE_PATH_PROTOCOL    **ChildDevicePath
00581   )
00582 {
00583   EFI_STATUS    Status;
00584   ISA_IO_DEVICE *IsaIoDevice;
00585   EFI_DEV_PATH  Node;
00586 
00587   //
00588   // Initialize the PCI_IO_DEVICE structure
00589   //
00590   IsaIoDevice = AllocateZeroPool (sizeof (ISA_IO_DEVICE));
00591   if (IsaIoDevice == NULL) {
00592     return EFI_OUT_OF_RESOURCES;
00593   }
00594 
00595   IsaIoDevice->Signature  = ISA_IO_DEVICE_SIGNATURE;
00596   IsaIoDevice->Handle     = NULL;
00597   IsaIoDevice->PciIo      = PciIo;
00598 
00599   //
00600   // Initialize the ISA I/O instance structure
00601   //
00602   InitializeIsaIoInstance (IsaIoDevice, IsaDeviceResourceList);
00603 
00604   //
00605   // Build the child device path
00606   //
00607   Node.DevPath.Type     = ACPI_DEVICE_PATH;
00608   Node.DevPath.SubType  = ACPI_DP;
00609   SetDevicePathNodeLength (&Node.DevPath, sizeof (ACPI_HID_DEVICE_PATH));
00610   Node.Acpi.HID = IsaDeviceResourceList->Device.HID;
00611   Node.Acpi.UID = IsaDeviceResourceList->Device.UID;
00612 
00613   IsaIoDevice->DevicePath = AppendDevicePathNode (
00614                               ParentDevicePath,
00615                               &Node.DevPath
00616                               );
00617 
00618   if (IsaIoDevice->DevicePath == NULL) {
00619     Status = EFI_OUT_OF_RESOURCES;
00620     goto Done;
00621   }
00622 
00623   *ChildDevicePath = IsaIoDevice->DevicePath;
00624 
00625   //
00626   // Create a child handle and install Device Path and ISA I/O protocols
00627   //
00628   Status = gBS->InstallMultipleProtocolInterfaces (
00629                   &IsaIoDevice->Handle,
00630                   &gEfiDevicePathProtocolGuid,
00631                   IsaIoDevice->DevicePath,
00632                   &gEfiIsaIoProtocolGuid,
00633                   &IsaIoDevice->IsaIo,
00634                   NULL
00635                   );
00636   if (EFI_ERROR (Status)) {
00637     goto Done;
00638   }
00639 
00640   Status = gBS->OpenProtocol (
00641                   Controller,
00642                   &gEfiPciIoProtocolGuid,
00643                   (VOID **) &PciIo,
00644                   This->DriverBindingHandle,
00645                   IsaIoDevice->Handle,
00646                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
00647                   );
00648   if (EFI_ERROR (Status)) {
00649     gBS->UninstallMultipleProtocolInterfaces (
00650            IsaIoDevice->Handle,
00651            &gEfiDevicePathProtocolGuid,
00652            IsaIoDevice->DevicePath,
00653            &gEfiIsaIoProtocolGuid,
00654            &IsaIoDevice->IsaIo,
00655            NULL
00656            );
00657   }
00658 
00659 Done:
00660 
00661   if (EFI_ERROR (Status)) {
00662     if (IsaIoDevice->DevicePath != NULL) {
00663       FreePool (IsaIoDevice->DevicePath);
00664     }
00665 
00666     FreePool (IsaIoDevice);
00667   }
00668 
00669   return Status;
00670 }
00671 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines