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