📄 cbi1.c
字号:
Stop this driver on ControllerHandle. Support stoping any child handles
created by this driver.
Arguments:
This - Protocol instance pointer.
DeviceHandle - Handle of device to stop driver on
NumberOfChildren - Number of Children in the ChildHandleBuffer
ChildHandleBuffer - List of handles for the children we need to stop.
Returns:
EFI_SUCCES - This driver is removed DeviceHandle
other - This driver was not removed from this device
--*/
{
EFI_STATUS Status;
EFI_USB_ATAPI_PROTOCOL *CBI1AtapiProtocol;
USB_CBI_DEVICE *UsbCbiDev;
//
// Get our context back.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUsbAtapiProtocolGuid,
&CBI1AtapiProtocol,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
UsbCbiDev = USB_CBI_DEVICE_FROM_THIS(CBI1AtapiProtocol);
Status = gBS->UninstallProtocolInterface (
ControllerHandle,
&gEfiUsbAtapiProtocolGuid,
&UsbCbiDev->UsbAtapiProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
gBS->FreePool(UsbCbiDev);
return Status;
}
//
// CBI1 command
//
static EFI_STATUS
CBI1CommandPhase (
IN USB_CBI_DEVICE *UsbCbiDev,
IN VOID *Command,
IN UINT8 CommandSize,
OUT UINT32 *Result
)
/*++
In order to make consistence, CBI transportation protocol does only use
the first 3 parameters. Other parameters are not used here.
--*/
{
EFI_STATUS Status;
// UINT32 Result;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_DEVICE_REQUEST Request;
UINT32 TimeOutInMilliSeconds;
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;
TimeOutInMilliSeconds = 1000;
Status = UsbIo->UsbControlTransfer(
UsbIo,
&Request,
EfiUsbDataOut,
TimeOutInMilliSeconds,
Command,
CommandSize,
Result
);
return Status ;
}
static EFI_STATUS
CBI1DataPhase (
IN USB_CBI_DEVICE *UsbCbiDev,
IN UINT32 DataSize,
IN OUT VOID *DataBuffer,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 Timeout,
OUT UINT32 *Result
)
{
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 EndpointAddr;
UINTN Remain;
UINTN Increment;
UINT32 MaxPacketLen;
UINT8 *BufferPtr;
UsbIo = UsbCbiDev->UsbIo;
Remain = DataSize;
BufferPtr = (UINT8 *)DataBuffer;
//
// retrieve the the max packet length of the given endpoint
//
if ( Direction == EfiUsbDataIn ) {
MaxPacketLen = (UsbCbiDev->BulkInEndpointDescriptor).MaxPacketSize;
EndpointAddr = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress;
} else {
MaxPacketLen = (UsbCbiDev->BulkOutEndpointDescriptor).MaxPacketSize;
EndpointAddr = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress;
}
while ( Remain > 0 ) {
//
// Using 15 packets to avoid Bitstuff error
//
if ( Remain > 15 * MaxPacketLen) {
Increment = 15 * MaxPacketLen;
} else {
Increment = Remain ;
}
Status = UsbIo->UsbBulkTransfer(
UsbIo,
EndpointAddr,
BufferPtr,
&Increment,
Timeout,
Result
);
if(EFI_ERROR(Status)) {
goto ErrorExit;
}
BufferPtr += Increment;
Remain -= Increment ;
}
return EFI_SUCCESS;
ErrorExit:
if(((*Result) & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
//
//just endpoint stall happens
//
UsbClearEndpointHalt(
UsbIo,
EndpointAddr,
Result
);
}
return Status;
}
//
// CBI1 USB ATAPI Protocol
//
static EFI_STATUS
CBI1MassStorageReset (
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.
--*/
{
UINT8 ResetCommand[12];
UINT8 i;
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
USB_CBI_DEVICE *UsbCbiDev;
UINT8 EndpointAddr;
UINT32 Result;
UsbCbiDev = USB_CBI_DEVICE_FROM_THIS(This);
UsbIo = UsbCbiDev->UsbIo;
if (ExtendedVerification) {
UsbIo->UsbPortReset(UsbIo);
}
//
// CBI reset command protocol
//
ResetCommand[0] = 0x1d;
ResetCommand[1] = 0x04;
for(i = 2; i < 12; i++) {
ResetCommand[i] = 0xff;
}
Status = CBI1CommandPhase(
UsbCbiDev,
ResetCommand,
12,
&Result
);
//
// clear bulk in endpoint stall feature
//
EndpointAddr = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress;
UsbClearEndpointHalt(
UsbIo,
EndpointAddr,
&Result
);
//
// clear bulk out endpoint stall feature
//
EndpointAddr = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress;
UsbClearEndpointHalt(
UsbIo,
EndpointAddr,
&Result
);
return EFI_SUCCESS ;
}
static EFI_STATUS
CBI1AtapiCommand (
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 CBI1 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 Result;
UINT8 i,MaxRetryNum;
UsbCbiDev = USB_CBI_DEVICE_FROM_THIS(This);
MaxRetryNum = 3;
for (i = 0 ; i < MaxRetryNum; i ++) {
//
// First send ATAPI command through CBI1
//
Status = CBI1CommandPhase(
UsbCbiDev,
Command,
CommandSize,
&Result
);
if (EFI_ERROR (Status)) {
switch (Result) {
//
// when meeting the first 3 err code,
// no need to perform retry
//
case EFI_USB_NOERROR:
case EFI_USB_ERR_STALL:
case EFI_USB_ERR_SYSTEM:
return EFI_DEVICE_ERROR;
default:
continue;
break;
}
} else {
break;
}
}
if (i == MaxRetryNum) {
return EFI_DEVICE_ERROR;
}
for (i = 0 ; i < MaxRetryNum; i ++) {
//
// Send/Get Data if there is a Data Stage
//
switch(Direction) {
case EfiUsbDataIn: // fall through
case EfiUsbDataOut:
Status = CBI1DataPhase(
UsbCbiDev,
BufferLength,
DataBuffer,
Direction,
TimeOutInMilliSeconds,
&Result
);
if (EFI_ERROR(Status)) {
switch (Result) {
//
// when meeting the first 3 err code,
// no need to perform retry
//
case EFI_USB_NOERROR: // fall through
case EFI_USB_ERR_STALL: // fall through
case EFI_USB_ERR_SYSTEM: // fall through
return EFI_DEVICE_ERROR;
default:
continue;
break;
}
} else {
return EFI_SUCCESS;
}
break;
case EfiUsbNoData:
return EFI_SUCCESS;
}
}
//
// If goes here, means met error.
//
return EFI_DEVICE_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -