⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bot.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
                  ControllerHandle,
                  &gEfiUsbIoProtocolGuid,
                  This->DriverBindingHandle,
                  ControllerHandle
                  );

  //
  // Free all allocated resources
  //
  if (UsbBotDev->InterfaceDescriptor != NULL) {
    gBS->FreePool (UsbBotDev->InterfaceDescriptor);
  }

  if (UsbBotDev->BulkInEndpointDescriptor != NULL) {
    gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);
  }

  if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {
    gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);
  }

  if (UsbBotDev->ControllerNameTable) {
    EfiLibFreeUnicodeStringTable (UsbBotDev->ControllerNameTable);
  }
  
  gBS->FreePool(UsbBotDev);

  return Status;
}

STATIC
EFI_STATUS
BotRecoveryReset (
  IN  USB_BOT_DEVICE          *UsbBotDev
  )
{
  EFI_STATUS              Status;
  UINT32                  Result;
  EFI_USB_DEVICE_REQUEST  Request;
  EFI_USB_IO_PROTOCOL     *UsbIo;
  UINT8                   EndpointAddr;
  UINT32                  Timeout;

  UsbIo = UsbBotDev->UsbIo;

  EfiZeroMem ( &Request, sizeof(EFI_USB_DEVICE_REQUEST)) ;

  //
  // See BOT specification
  //
  Request.RequestType = 0x21 ;
  Request.Request = 0xFF ;
  Request.Value = 0 ;
  Request.Index = 0 ;
  Request.Length = 0 ;

  Timeout = 3000;

  Status = UsbIo->UsbControlTransfer(
                    UsbIo,
                    &Request,
                    EfiUsbNoData,
                    Timeout,
                    NULL,
                    0,
                    &Result
                  );
  
  //
  // clear bulk in endpoint stall feature
  //
  EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;

  UsbClearEndpointHalt(
    UsbIo,
    EndpointAddr,
    &Result
  );

  //
  // clear bulk out endpoint stall feature
  //
  EndpointAddr = (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress;
  UsbClearEndpointHalt(
    UsbIo,
    EndpointAddr,
    &Result
  );

  return Status;
}

//
// Bot Protocol Implementation
//
static EFI_STATUS
BotCommandPhase (
  IN  USB_BOT_DEVICE          *UsbBotDev,
  IN  VOID                    *Command,
  IN  UINT8                   CommandSize,
  IN  UINT32                  DataTransferLength,
  IN  EFI_USB_DATA_DIRECTION  Direction,
  IN  UINT16                  Timeout
  )
/*++

  Routine Description:
    Send ATAPI command through BOT interface.

  Parameters:

  Return Values:
    EFI_SUCCESS
    Others

--*/
{
  CBW                 cbw;
  EFI_STATUS          Status;
  UINT32              Result;
  EFI_USB_IO_PROTOCOL *UsbIo;
  UINTN               DataSize;

  UsbIo = UsbBotDev->UsbIo;

  EfiZeroMem ( &cbw, sizeof(CBW)) ;

  //
  // Fill the command block, detailed see BOT spec
  //
  cbw.dCBWSignature = CBWSIG ;
  cbw.dCBWTag = 0x01 ;
  cbw.dCBWDataTransferLength = DataTransferLength ;
  cbw.bmCBWFlags = (UINT8)(Direction << 7);
  cbw.bCBWLUN = 0 ;
  cbw.bCBWCBLength = CommandSize ;
  EfiCopyMem( cbw.CBWCB, Command, CommandSize ) ;

  DataSize = sizeof(CBW);

  Status = UsbIo->UsbBulkTransfer(
                    UsbIo,
                    (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress,
                    &cbw,
                    &DataSize,
                    Timeout,
                    &Result
                  );
  if (EFI_ERROR (Status)) {
    //
    // Command phase fail, we need to recovery reset this device
    //
    BotRecoveryReset (UsbBotDev);
    return EFI_DEVICE_ERROR ;    
  }

  return EFI_SUCCESS;
}


static EFI_STATUS
BotDataPhase (
  IN  USB_BOT_DEVICE                  *UsbBotDev,
  IN  UINT32                          *DataSize,
  IN  OUT VOID                        *DataBuffer,
  IN  EFI_USB_DATA_DIRECTION          Direction,
  IN  UINT16                          Timeout
  )
/*++

  Routine Description:
    Get/Send Data through BOT interface

  Parameters:

  Return Value:
    EFI_SUCCESS
    Others

--*/
{
  EFI_STATUS          Status;
  UINT32              Result;
  EFI_USB_IO_PROTOCOL *UsbIo;
  UINT8               EndpointAddr;
  UINTN               Remain;
  UINTN               Increment;
  UINT32              MaxPacketLen;
  UINT8               *BufferPtr;
  UINTN               TransferredSize;
  UINTN               RetryTimes;
    
  UsbIo = UsbBotDev->UsbIo;

  Remain = *DataSize;
  BufferPtr = (UINT8 *)DataBuffer;
  TransferredSize = 0;

  //
  // retrieve the the max packet length of the given endpoint
  //
  if ( Direction == EfiUsbDataIn ) {
    MaxPacketLen = (UsbBotDev->BulkInEndpointDescriptor)->MaxPacketSize;
    EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;
  } else {
    MaxPacketLen = (UsbBotDev->BulkOutEndpointDescriptor)->MaxPacketSize;
    EndpointAddr = (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress;
  }

  RetryTimes = 10;
  
  while ( Remain > 0 )
  {
    //
    // Using 15 packets to avoid Bitstuff error
    //
    if ( Remain > 16 * MaxPacketLen) {
      Increment = 16 * MaxPacketLen;
    } else {
      Increment = Remain ;
    }

    Status = UsbIo->UsbBulkTransfer(
                        UsbIo,
                        EndpointAddr,
                        BufferPtr,
                        &Increment,
                        Timeout,
                        &Result
                      );

    TransferredSize += Increment;
 
    if (EFI_ERROR (Status)) {
      RetryTimes --;
      if ((RetryTimes == 0) || ((Result & EFI_USB_ERR_TIMEOUT) == 0)) {
        goto ErrorExit;
      }
      TransferredSize -= Increment;
      continue;      
    } else {
      RetryTimes = 10;
    }

    BufferPtr += Increment;
    Remain -= Increment ;
  }

  *DataSize = (UINT32)TransferredSize;
   
  return EFI_SUCCESS;

ErrorExit:
  if((Result & EFI_USB_STALL_ERROR) == EFI_USB_ERR_STALL) {
    //
    //just endpoint stall happens
    //
    UsbClearEndpointHalt(
      UsbIo,
      EndpointAddr,
      &Result
    );
  }

  *DataSize = (UINT32)TransferredSize;

  return Status;

}

static EFI_STATUS
BotStatusPhase (
  IN  USB_BOT_DEVICE        *UsbBotDev,
  OUT UINT8                 *TransferStatus,
  IN  UINT16                Timeout
  )
/*++

  Routine Description:
    Get transfer status through BOT interface

  Parameters:

  Return Value:
    EFI_SUCCESS
    Others

--*/
{
  CSW                     csw;
  EFI_STATUS              Status;
  UINT32                  Result;
  EFI_USB_IO_PROTOCOL     *UsbIo;
  UINT8                   EndpointAddr;
  UINTN                   DataSize;

  UsbIo = UsbBotDev->UsbIo;

  EfiZeroMem( &csw, sizeof(CSW) ) ;

  EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;

  DataSize = sizeof(CSW);
  
  //
  // Get the status field from bulk transfer
  //
  Status = UsbIo->UsbBulkTransfer(
                    UsbIo,
                    EndpointAddr,
                    &csw,
                    &DataSize,
                    Timeout,
                    &Result
                  );
  if(EFI_ERROR(Status)) {    
    if((Result & EFI_USB_STALL_ERROR) == EFI_USB_ERR_STALL) {
      //
      //just endpoint stall happens
      //
      UsbClearEndpointHalt(
        UsbIo,
        EndpointAddr,
        &Result
      );
    }
    return Status;
  }

  if ( csw.dCSWSignature == CSWSIG )
  {
    *TransferStatus = csw.bCSWStatus ;
  }
  else
  {
    return EFI_DEVICE_ERROR ;
  }
  return EFI_SUCCESS;
}


//
// Usb Atapi Protocol implementation
//
static EFI_STATUS
BotAtapiCommand (
  IN  EFI_USB_ATAPI_PROTOCOL      *This,
  IN  VOID                        *Command,
  IN  UINT8                       CommandSize,
  IN  VOID                        *DataBuffer,
  IN  UINT32                      BufferLength,
  IN  EFI_USB_DATA_DIRECTION      Direction,
  IN  UINT16                      TimeOutInMilliSeconds
  )
/*++

  Routine Description:
    Send ATAPI command using BOT protocol.

  Arguments:
    This                  - Protocol instance pointer.
    Command               - Command buffer
    CommandSize           - Size of Command Buffer
    DataBuffer            - Data buffer
    BufferLength          - Length of Data buffer
    Direction             - Data direction of this command
    TimeoutInMilliseconds - Timeout value in ms

  Returns:
    EFI_SUCCES          - Commond succeeded.
    EFI_DEVICE_ERROR    - Command failed.

--*/
{
  EFI_STATUS              Status;
  EFI_STATUS              BotDataStatus = EFI_SUCCESS;
  UINT8                   TransferStatus;
  USB_BOT_DEVICE          *UsbBotDev;
  UINT32                  BufferSize;
  
  //
  // Get the context
  //
  UsbBotDev = USB_BOT_DEVICE_FROM_THIS(This);

  //
  // First send ATAPI command through Bot
  //
  Status = BotCommandPhase(
              UsbBotDev,
              Command,
              CommandSize,
              BufferLength,
              Direction,
              TimeOutInMilliSeconds
           );

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

  //
  // Send/Get Data if there is a Data Stage
  //
  switch (Direction)
  {
  case EfiUsbDataIn:
  case EfiUsbDataOut:
    BufferSize = BufferLength;
    
    BotDataStatus = BotDataPhase(
                      UsbBotDev,
                      &BufferSize,
                      DataBuffer,
                      Direction,
                      TimeOutInMilliSeconds
                    );
    break;
    
  case EfiUsbNoData:
    break ;
  }
  
  //
  // Status Phase
  //
  Status = BotStatusPhase(
             UsbBotDev,
             &TransferStatus,
             TimeOutInMilliSeconds
          );
  if (EFI_ERROR(Status)) {
    return EFI_DEVICE_ERROR;
  }
  
  if (TransferStatus == 0x02) {
    //
    // Phase error
    //
    BotRecoveryReset (UsbBotDev);
    return EFI_DEVICE_ERROR;
  }
  
  if (TransferStatus == 0x01) {
    return EFI_DEVICE_ERROR;
  }
  
  return BotDataStatus;
}

static EFI_STATUS
BotMassStorageReset (
  IN  EFI_USB_ATAPI_PROTOCOL      *This,
  IN  BOOLEAN                     ExtendedVerification
)
/*++

  Routine Description:
    Reset Bot Devices

  Arguments:
    This                    - Protocol instance pointer.
    ExtendedVerification    - TRUE if we need to do strictly reset.

  Returns:
    EFI_SUCCES          - Commond succeeded.
    EFI_DEVICE_ERROR    - Command failed.

--*/
{
  EFI_STATUS              Status;
  USB_BOT_DEVICE          *UsbBotDev;
  EFI_USB_IO_PROTOCOL     *UsbIo;

  UsbBotDev = USB_BOT_DEVICE_FROM_THIS(This);
  UsbIo = UsbBotDev->UsbIo;

  if(ExtendedVerification) {
    //
    // If we need to do strictly reset, reset its parent hub port
    //
    Status = UsbIo->UsbPortReset(UsbIo);
//    if (EFI_ERROR(Status)) {
    return Status;
//    }
  }

  Status = BotRecoveryReset (UsbBotDev);
  
  return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -