Ejemplo n.º 1
0
/**
  Disconnect from the I2C host controller.

  This routine disconnects from the I2C controller.

  This routine is called by DriverUnload when the I2C host driver
  is being unloaded.
  
  @param [in] DriverBinding        Protocol instance pointer.
  @param [in] Controller           Handle of device to stop driver on.
  @param [in] NumberOfChildren     How many children need to be stopped.
  @param [in] ChildHandleBuffer    Not used.

  @retval EFI_SUCCESS          This driver is removed Controller.
  @retval EFI_DEVICE_ERROR     The device could not be stopped due to a device error.
  @retval other                This driver was not removed from this device.

**/
EFI_STATUS
EFIAPI
I2cHostDriverStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
  IN  EFI_HANDLE Controller,
  IN  UINTN NumberOfChildren,
  IN  EFI_HANDLE *ChildHandleBuffer
  )
{
  I2C_HOST_CONTEXT *I2cHost;
  CONST EFI_I2C_HOST_PROTOCOL *I2cHostProtocol;
  EFI_STATUS Status;

  //
  //  Display entry
  //
  DEBUG (( DEBUG_LOAD, "I2cHostDriverStop entered\r\n" ));

  //
  //  Disconnect any connected drivers and locate the context
  //  structure
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  mDriverProtocol,
                  (VOID**)&I2cHostProtocol,
                  DriverBinding->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE );
  if ( !EFI_ERROR ( Status )) {
    I2cHost = I2C_HOST_CONTEXT_FROM_PROTOCOL ( I2cHostProtocol );

    //
    //  Done with the I2C host protocol
    //
    Status = gBS->CloseProtocol ( Controller,
                                  mDriverProtocol,
                                  DriverBinding->DriverBindingHandle,
                                  Controller );
    if ( !EFI_ERROR ( Status )) {
      //
      //  Remove the I2C host protocol
      //
      Status = gBS->UninstallMultipleProtocolInterfaces (
                    Controller,
                    mDriverProtocol,
                    I2cHostProtocol,
                    NULL );
      if ( !EFI_ERROR ( Status )) {
        //
        //  Stop the driver
        //
        DEBUG (( DEBUG_INIT,
                  "0x%016lx: I2cHost stopped\r\n",
                  (UINT64)(UINTN)I2cHost ));
        I2cHostApiStop ( I2cHost );

        //
        //  Release the I2C controller
        //
        gBS->CloseProtocol ( Controller,
                             &gEfiI2cBusConfigurationManagementProtocolGuid,
                             DriverBinding->DriverBindingHandle,
                             Controller );

        //
        //  Release the context
        //
        DEBUG (( DEBUG_POOL | DEBUG_INFO,
                  "0x%016lx: I2cHost released\r\n",
                  (UINT64)(UINTN)I2cHost ));
        FreePool ( I2cHost );
      }
      else {
        DEBUG (( DEBUG_ERROR,
                  "ERROR - Failed to uninstall I2C host protocol, Status: %r\r\n",
                  Status ));
      }
    }
    else {
      DEBUG (( DEBUG_ERROR,
                "ERROR - Failed to close I2C host protocol, Status: %r\r\n",
                Status ));
    }
  }

  //
  //  Display exit
  //
  DEBUG (( DEBUG_LOAD, "I2cHostDriverStop exiting, Status: %r\r\n", Status ));

  //
  //  Return the stop status
  //
  return Status;
}
Ejemplo n.º 2
0
/**
  Stops a device controller or a bus controller.

  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  As a result, much of the error checking on the parameters to Stop() has been moved
  into this common boot service. It is legal to call Stop() from other locations,
  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
     same driver's Start() function.
  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
     Start() function, and the Start() function must have called OpenProtocol() on
     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.

  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
                                support a bus specific I/O protocol for the driver
                                to use to stop the device.
  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
                                if NumberOfChildren is 0.

  @retval EFI_SUCCESS           The device was stopped.
  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.

**/
EFI_STATUS
EFIAPI
I2cHostDriverStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL       *This,
  IN  EFI_HANDLE                        Controller,
  IN  UINTN                             NumberOfChildren,
  IN  EFI_HANDLE                        *ChildHandleBuffer
  )
{
  EFI_STATUS                  Status;  
  I2C_HOST_CONTEXT            *I2cHostContext;
  EFI_I2C_HOST_PROTOCOL       *I2cHost;
  EFI_TPL                     TplPrevious;

  TplPrevious = EfiGetCurrentTpl ();
  if (TplPrevious > TPL_I2C_SYNC) {
    DEBUG ((EFI_D_ERROR, "I2cHost: TPL %d is too high in Stop.\n", TplPrevious));
    return EFI_DEVICE_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiI2cHostProtocolGuid,
                  (VOID **) &I2cHost,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (I2cHost);

  //
  // Raise TPL for critical section
  //
  TplPrevious = gBS->RaiseTPL (TPL_I2C_SYNC);
  
  //
  // If there is pending request or pending bus configuration, do not stop
  //
  Status = EFI_DEVICE_ERROR;
  if (( !I2cHostContext->I2cBusConfigurationManagementPending )
    && IsListEmpty (&I2cHostContext->RequestList)) {
    
    //
    //  Remove the I2C host protocol
    //
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    Controller,
                    &gEfiI2cHostProtocolGuid,
                    I2cHost,
                    NULL
                    );
  }
  
  //
  // Leave critical section
  //
  gBS->RestoreTPL (TplPrevious);
  if (!EFI_ERROR (Status)) {
    gBS->CloseProtocol (
           Controller,
           &gEfiI2cBusConfigurationManagementProtocolGuid,
           This->DriverBindingHandle,
           Controller
           );

    //
    // Release I2c Host resources
    //
    if (I2cHostContext->I2cBusConfigurationEvent != NULL) {
      gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
      I2cHostContext->I2cBusConfigurationEvent = NULL;
    }
    
    if (I2cHostContext->I2cEvent != NULL) {
      gBS->CloseEvent (I2cHostContext->I2cEvent);
      I2cHostContext->I2cEvent = NULL;
    }
    
    FreePool (I2cHostContext);
  }

  //
  //  Return the stop status
  //
  return Status;
}