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

📄 cbi0.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
                  &gEfiUsbAtapiProtocolGuid,
                  &UsbCbiDev->UsbAtapiProtocol
                );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->CloseProtocol (
                  ControllerHandle,
                  &gEfiUsbIoProtocolGuid,
                  This->DriverBindingHandle,
                  ControllerHandle
                  );

  //
  // Free all allocated resources
  //
  if (UsbCbiDev->ControllerNameTable) {
    EfiLibFreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);
  }
  
  gBS->FreePool(UsbCbiDev);

  return Status;
}


STATIC
EFI_STATUS
Cbi0RecoveryReset (
  IN  USB_CBI_DEVICE   *UsbCbiDev
  )
{
  UINT8               ResetCommand[12];
  UINT8               i;
  EFI_STATUS          Status;
  EFI_USB_IO_PROTOCOL *UsbIo;
  UINT8               EndpointAddress;
  UINT32              Result;
  UINT16              Timeout;

  UsbIo = UsbCbiDev->UsbIo;

  //
  // CBI reset command protocol
  //
  ResetCommand[0] = 0x1d;
  ResetCommand[1] = 0x04;
  for(i = 2; i < 12; i++) {
    ResetCommand[i] = 0xff;
  }
  
  Timeout = STALL_1_SECOND; // (in millisecond unit)

  Status = Cbi0AtapiCommand (
              &UsbCbiDev->UsbAtapiProtocol,
              ResetCommand,
              12,
              NULL,
              0,
              EfiUsbNoData,
              Timeout
              );
  if (EFI_ERROR(Status)) {
    return Status;
  }
  
  gBS->Stall (100000);
  //
  // clear bulk in endpoint stall feature
  //
  EndpointAddress = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress;
  Status = UsbClearEndpointHalt(
        UsbIo,
        EndpointAddress,
        &Result
        );
  if (EFI_ERROR(Status)) {
    return Status;
  }
  //
  // clear bulk out endpoint stall feature
  //
  EndpointAddress = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress;
  Status = UsbClearEndpointHalt(
    UsbIo,
    EndpointAddress,
    &Result
  );
  //
  // according to CBI spec, no need to clear interrupt endpoint feature.
  //
  return Status;
}

STATIC EFI_STATUS
Cbi0CommandPhase (
  IN  USB_CBI_DEVICE          *UsbCbiDev,
  IN  VOID                    *Command,
  IN  UINT8                   CommandSize,
  IN  UINT16                  Timeout
  )
/*++

  Routine Description:
    Send ATAPI command through CBI0 interface.

  Parameters:

  Return Values:
    EFI_SUCCESS
    Others

--*/
{
  EFI_STATUS              Status;
  UINT32                  Result;
  EFI_USB_IO_PROTOCOL     *UsbIo;
  EFI_USB_DEVICE_REQUEST  Request;

  UsbIo = UsbCbiDev->UsbIo;

  EfiZeroMem (&Request, sizeof(EFI_USB_DEVICE_REQUEST));

  //
  // Device request see CBI specification
  //
  Request.RequestType = 0x21;
  Request.Request = 0x00;
  Request.Value = 0 ;
  Request.Index = 0 ;
  Request.Length = CommandSize;
  
  Status = UsbIo->UsbControlTransfer(
              UsbIo,
              &Request,
              EfiUsbDataOut,
              Timeout,
              Command,
              CommandSize,
              &Result
            );
  if (EFI_ERROR(Status)) {    
    return EFI_DEVICE_ERROR;
  }
  return EFI_SUCCESS;
}


STATIC EFI_STATUS
Cbi0DataPhase (
  IN  USB_CBI_DEVICE                  *UsbCbiDev,
  IN  UINT32                          *DataSize,
  IN  OUT VOID                        *DataBuffer,
  IN  EFI_USB_DATA_DIRECTION          Direction,
  IN  UINT16                          Timeout
  )
/*++

  Routine Description:
    Get/Send Data through CBI0 interface

  Parameters:

  Return Value:
    EFI_SUCCESS
    Others

--*/
{
  EFI_STATUS          Status;
  EFI_USB_IO_PROTOCOL *UsbIo;
  UINT8               EndpointAddress;
  UINTN               Remain;
  UINTN               Increment;
  UINT32              MaxPacketLength;
  UINT8               *BufferPtr;
  UINT32              Result;
  UINTN               TransferredSize;

  UsbIo = UsbCbiDev->UsbIo;

  Remain = *DataSize;
  BufferPtr = (UINT8 *)DataBuffer;
  TransferredSize = 0;
  //
  // retrieve the the max packet length of the given endpoint
  //
  if (Direction == EfiUsbDataIn) {
    MaxPacketLength = (UsbCbiDev->BulkInEndpointDescriptor).MaxPacketSize;
    EndpointAddress = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress;
  } else {
    MaxPacketLength = (UsbCbiDev->BulkOutEndpointDescriptor).MaxPacketSize;
    EndpointAddress = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress;
  }

  while (Remain > 0) {

    if ( Remain > 16 * MaxPacketLength) {
      Increment = 16 * MaxPacketLength;
    } else {
      Increment = Remain;
    }

    Status = UsbIo->UsbBulkTransfer(
                UsbIo,
                EndpointAddress,
                BufferPtr,
                &Increment,
                Timeout,
                &Result
              );
    TransferredSize += Increment;
    
    if(EFI_ERROR(Status)) {
      goto ErrorExit;
    }

    BufferPtr += Increment;
    Remain -= Increment;
  }

  return EFI_SUCCESS;

ErrorExit:
  if((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
    Status = Cbi0RecoveryReset (UsbCbiDev);
    gBS->Stall (100000);
  }
  
  *DataSize = (UINT32)TransferredSize;
  return Status;
}

STATIC EFI_STATUS
Cbi0StatusPhase (
  IN  USB_CBI_DEVICE        *UsbCbiDev,
  OUT INTERRUPT_DATA_BLOCK  *InterruptDataBlock,
  IN  UINT16                Timeout
  )
/*++

  Routine Description:
    Get transfer status through BOT interface

  Parameters:

  Return Value:
    EFI_SUCCESS
    Others

--*/
{
  UINT8                 EndpointAddress;
  UINTN                 InterruptDataBlockLength;
  UINT32                Result;
  EFI_STATUS            Status;
  
  EfiZeroMem (InterruptDataBlock,sizeof (INTERRUPT_DATA_BLOCK));
  
  EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;
  InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);
  
  Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (
                    UsbCbiDev->UsbIo,
                    EndpointAddress,
                    InterruptDataBlock,
                    &InterruptDataBlockLength,
                    Timeout,
                    &Result
                    );
  if (EFI_ERROR(Status)) {
    if((Result & EFI_USB_STALL_ERROR) == EFI_USB_ERR_STALL) {
      //
      //just endpoint stall happens
      //
      UsbClearEndpointHalt(
        UsbCbiDev->UsbIo,
        EndpointAddress,
        &Result
      );
      gBS->Stall (100000);
    }
    return Status;
  }
  
  return EFI_SUCCESS;
}


//
// Cbi0 Atapi Protocol Implementation
//
STATIC
EFI_STATUS
Cbi0MassStorageReset (
  IN  EFI_USB_ATAPI_PROTOCOL      *This,
  IN  BOOLEAN                     ExtendedVerification
  )
/*++

  Routine Description:
    Reset CBI 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;
  EFI_USB_IO_PROTOCOL *UsbIo;
  USB_CBI_DEVICE      *UsbCbiDev;

  UsbCbiDev = USB_CBI_DEVICE_FROM_THIS(This);
  UsbIo = UsbCbiDev->UsbIo;
  
  if (ExtendedVerification) {
//    UsbIo->UsbPortReset(UsbIo);
  }

  Status = Cbi0RecoveryReset (UsbCbiDev);
  return Status;
}


STATIC EFI_STATUS
Cbi0AtapiCommand (
  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;
  USB_CBI_DEVICE          *UsbCbiDev;
  UINT32                  BufferSize;
  INTERRUPT_DATA_BLOCK    InterruptDataBlock;
  EFI_STATUS              DataPhaseStatus;
  
  if (Direction != EfiUsbNoData) {
    if (DataBuffer == NULL || BufferLength == 0) {
      return EFI_INVALID_PARAMETER;
    }
  }
  
  DataPhaseStatus = EFI_SUCCESS;
  //
  // Get the context
  //
  UsbCbiDev = USB_CBI_DEVICE_FROM_THIS(This);

  //
  // First send ATAPI command through Cbi
  //
  Status = Cbi0CommandPhase(
              UsbCbiDev,
              Command,
              CommandSize,
              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;
    
      DataPhaseStatus = Cbi0DataPhase(
                      UsbCbiDev,
                      &BufferSize,
                      DataBuffer,
                      Direction,
                      TimeOutInMilliSeconds
                      );
      break;
    
    case EfiUsbNoData:
      break ;
  }
  
  if (EFI_ERROR(DataPhaseStatus)) {
    return EFI_DEVICE_ERROR;
  }
  
  //
  // Status Phase
  //
  Status = Cbi0StatusPhase(
             UsbCbiDev,
             &InterruptDataBlock,
             TimeOutInMilliSeconds
          );
  if (EFI_ERROR(Status)) {    
    return EFI_DEVICE_ERROR;
  }
  
  if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {
    
    if (InterruptDataBlock.bType == 0) {
    //
    // indicates command completion
    //
      switch (InterruptDataBlock.bValue & 0x03) {
        case 0:
          Status = EFI_SUCCESS;
          break;
        
        case 1:
          Status = EFI_DEVICE_ERROR;
          break;
          
        case 2:
          Status = Cbi0RecoveryReset (UsbCbiDev);
          if (EFI_ERROR(Status)) {
            UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);
          }
          Status = EFI_DEVICE_ERROR;
        
        case 3:
          //
          // issue a Request Sense Command, will implement later...
          //
          Status = EFI_DEVICE_ERROR;
      }
    } else {
      Status = DataPhaseStatus;
    }
  
  } else {
  //
  // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
  //             InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
  //
    Status = DataPhaseStatus;
  }
  return Status;
}

⌨️ 快捷键说明

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