📄 bot.c
字号:
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 + -