Code scrub for USB Mass Storage Driver.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7243 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
|
||||
Implementation of the USB mass storage Control/Bulk/Interrupt transport.
|
||||
Implementation of the USB mass storage Control/Bulk/Interrupt transport,
|
||||
according to USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport, Revision 1.1.
|
||||
Notice: it is being obsoleted by the standard body in favor of the BOT
|
||||
(Bulk-Only Transport).
|
||||
|
||||
@@ -18,37 +18,43 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "UsbMass.h"
|
||||
#include "UsbMassCbi.h"
|
||||
|
||||
/**
|
||||
Call the Usb mass storage class transport protocol to
|
||||
reset the device. The reset is defined as a Non-Data
|
||||
command. Don't use UsbCbiExecCommand to send the command
|
||||
to device because that may introduce recursive loop.
|
||||
|
||||
@param Context The USB CBI device protocol
|
||||
@param ExtendedVerification The flag controlling the rule of reset
|
||||
|
||||
@retval EFI_SUCCESS the device is reset
|
||||
@retval Others Failed to reset the device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbCbiResetDevice (
|
||||
IN VOID *Context,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
//
|
||||
// Definition of USB CBI0 Transport Protocol
|
||||
//
|
||||
USB_MASS_TRANSPORT mUsbCbi0Transport = {
|
||||
USB_MASS_STORE_CBI0,
|
||||
UsbCbiInit,
|
||||
UsbCbiExecCommand,
|
||||
UsbCbiResetDevice,
|
||||
NULL,
|
||||
UsbCbiCleanUp
|
||||
};
|
||||
|
||||
//
|
||||
// Definition of USB CBI1 Transport Protocol
|
||||
//
|
||||
USB_MASS_TRANSPORT mUsbCbi1Transport = {
|
||||
USB_MASS_STORE_CBI1,
|
||||
UsbCbiInit,
|
||||
UsbCbiExecCommand,
|
||||
UsbCbiResetDevice,
|
||||
NULL,
|
||||
UsbCbiCleanUp
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the USB mass storage class CBI transport protocol.
|
||||
If Context isn't NULL, it will save its context in it.
|
||||
Initializes USB CBI protocol.
|
||||
|
||||
@param UsbIo The USB IO to use
|
||||
@param Context The variable to save context in
|
||||
This function initializes the USB mass storage class CBI protocol.
|
||||
It will save its context which is a USB_CBI_PROTOCOL structure
|
||||
in the Context if Context isn't NULL.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
@retval EFI_UNSUPPORTED The device isn't supported
|
||||
@retval EFI_SUCCESS The CBI protocol is initialized.
|
||||
@retval Other The Usb cbi init failed.
|
||||
@param UsbIo The USB I/O Protocol instance
|
||||
@param Context The buffer to save the context to
|
||||
|
||||
@retval EFI_SUCCESS The device is successfully initialized.
|
||||
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
||||
@retval Other The USB CBI initialization fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
@@ -64,21 +70,18 @@ UsbCbiInit (
|
||||
UINT8 Index;
|
||||
|
||||
//
|
||||
// Allocate the CBI context
|
||||
// Allocate the CBI context for USB_CBI_PROTOCOL and 3 endpoint descriptors.
|
||||
//
|
||||
UsbCbi = AllocateZeroPool (
|
||||
sizeof (USB_CBI_PROTOCOL) + 3 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
||||
);
|
||||
|
||||
if (UsbCbi == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
ASSERT (UsbCbi != NULL);
|
||||
|
||||
UsbCbi->UsbIo = UsbIo;
|
||||
|
||||
//
|
||||
// Get the interface descriptor and validate that it is a USB mass
|
||||
// storage class CBI interface.
|
||||
// Get the interface descriptor and validate that it
|
||||
// is a USB Mass Storage CBI interface.
|
||||
//
|
||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbCbi->Interface);
|
||||
if (EFI_ERROR (Status)) {
|
||||
@@ -118,7 +121,6 @@ UsbCbiInit (
|
||||
UsbCbi->BulkOutEndpoint = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbCbi + 1) + 1;
|
||||
CopyMem(UsbCbi->BulkOutEndpoint, &EndPoint, sizeof (EndPoint));
|
||||
}
|
||||
|
||||
} else if (USB_IS_INTERRUPT_ENDPOINT (EndPoint.Attributes)) {
|
||||
//
|
||||
// Use the first interrupt endpoint if it is CBI0
|
||||
@@ -132,10 +134,11 @@ UsbCbiInit (
|
||||
}
|
||||
}
|
||||
|
||||
if ((UsbCbi->BulkInEndpoint == NULL)
|
||||
|| (UsbCbi->BulkOutEndpoint == NULL)
|
||||
|| ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0)
|
||||
&& (UsbCbi->InterruptEndpoint == NULL))) {
|
||||
if ((UsbCbi->BulkInEndpoint == NULL) || (UsbCbi->BulkOutEndpoint == NULL)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
if ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0) && (UsbCbi->InterruptEndpoint == NULL)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
@@ -145,6 +148,7 @@ UsbCbiInit (
|
||||
} else {
|
||||
gBS->FreePool (UsbCbi);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
@@ -152,16 +156,18 @@ ON_ERROR:
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send the command to the device using class specific control transfer.
|
||||
|
||||
This function sends command to the device using class specific control transfer.
|
||||
The CBI contains three phases: Command, Data, and Status. This is Command phase.
|
||||
|
||||
@param UsbCbi The USB CBI protocol
|
||||
@param Cmd The high level command to transfer to device
|
||||
@param CmdLen The length of the command
|
||||
@param Timeout The time to wait the command to finish
|
||||
|
||||
@retval EFI_SUCCESS The command is transferred to device
|
||||
@retval EFI_SUCCESS The command is sent to the device.
|
||||
@retval Others The command failed to transfer to device
|
||||
|
||||
**/
|
||||
@@ -181,7 +187,7 @@ UsbCbiSendCommand (
|
||||
|
||||
//
|
||||
// Fill in the device request, CBI use the "Accept Device-Specific
|
||||
// Cmd" (ADSC) class specific request to send commands
|
||||
// Cmd" (ADSC) class specific request to send commands.
|
||||
//
|
||||
Request.RequestType = 0x21;
|
||||
Request.Request = 0;
|
||||
@@ -194,7 +200,7 @@ UsbCbiSendCommand (
|
||||
|
||||
for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) {
|
||||
//
|
||||
// Use the UsbIo to send the command to the device
|
||||
// Use USB I/O Protocol to send the command to the device
|
||||
//
|
||||
TransStatus = 0;
|
||||
DataLen = CmdLen;
|
||||
@@ -226,16 +232,20 @@ UsbCbiSendCommand (
|
||||
|
||||
|
||||
/**
|
||||
Transfer data between the device and host. The CBI contains three phase,
|
||||
command, data, and status. This is data phase.
|
||||
Transfer data between the device and host.
|
||||
|
||||
This function transfers data between the device and host.
|
||||
The CBI contains three phases: Command, Data, and Status. This is Data phase.
|
||||
|
||||
@param UsbCbi The USB CBI device
|
||||
@param DataDir The direction of the data transfer
|
||||
@param Data The buffer to hold the data
|
||||
@param TransLen The expected transfer length
|
||||
@param Timeout The time to wait the command to execute
|
||||
@param Data The buffer to hold the data for input or output.
|
||||
@param TransLen On input, the expected transfer length.
|
||||
On output, the length of data actually transferred.
|
||||
@param Timeout The time to wait for the command to execute
|
||||
|
||||
@retval EFI_SUCCESS The data transfer succeeded
|
||||
@retval EFI_SUCCESS The data transferred successfully.
|
||||
@retval EFI_SUCCESS No data to transfer
|
||||
@retval Others Failed to transfer all the data
|
||||
|
||||
**/
|
||||
@@ -257,7 +267,7 @@ UsbCbiDataTransfer (
|
||||
UINTN Retry;
|
||||
|
||||
//
|
||||
// It's OK if no data to transfer
|
||||
// If no data to transfer, just return EFI_SUCCESS.
|
||||
//
|
||||
if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
|
||||
return EFI_SUCCESS;
|
||||
@@ -279,7 +289,7 @@ UsbCbiDataTransfer (
|
||||
Timeout = Timeout / USB_MASS_1_MILLISECOND;
|
||||
|
||||
//
|
||||
// Transfer the data, if the device returns NAK, retry it.
|
||||
// Transfer the data with a loop. The length of data transferred once is restricted.
|
||||
//
|
||||
while (Remain > 0) {
|
||||
TransStatus = 0;
|
||||
@@ -302,15 +312,15 @@ UsbCbiDataTransfer (
|
||||
if (TransStatus == EFI_USB_ERR_NAK) {
|
||||
//
|
||||
// The device can NAK the host if either the data/buffer isn't
|
||||
// aviable or the command is in-progress. The data can be partly
|
||||
// transferred. The transfer is aborted if several succssive data
|
||||
// transfer commands are NAKed.
|
||||
// aviable or the command is in-progress.
|
||||
// If data are partially transferred, we just ignore NAK and continue.
|
||||
// If all data have been transferred and status is NAK, then we retry for several times.
|
||||
// If retry exceeds the USB_CBI_MAX_RETRY, then return error status.
|
||||
//
|
||||
if (Increment == 0) {
|
||||
if (++Retry > USB_CBI_MAX_RETRY) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
} else {
|
||||
Next += Increment;
|
||||
Remain -= Increment;
|
||||
@@ -342,13 +352,15 @@ ON_EXIT:
|
||||
|
||||
|
||||
/**
|
||||
Get the result of high level command execution from interrupt
|
||||
endpoint. This function returns the USB transfer status, and
|
||||
put the high level command execution result in Result.
|
||||
Gets the result of high level command execution from interrupt endpoint.
|
||||
|
||||
This function returns the USB transfer status, and put the high level
|
||||
command execution result in Result.
|
||||
The CBI contains three phases: Command, Data, and Status. This is Status phase.
|
||||
|
||||
@param UsbCbi The USB CBI protocol
|
||||
@param Timeout The time to wait the command to execute
|
||||
@param Result GC_TODO: add argument description
|
||||
@param Timeout The time to wait for the command to execute
|
||||
@param Result The result of the command execution.
|
||||
|
||||
@retval EFI_SUCCESS The high level command execution result is
|
||||
retrieved in Result.
|
||||
@@ -404,7 +416,7 @@ UsbCbiGetStatus (
|
||||
/**
|
||||
Execute USB mass storage command through the CBI0/CBI1 transport protocol.
|
||||
|
||||
@param Context The USB CBI device
|
||||
@param Context The USB CBI Protocol.
|
||||
@param Cmd The command to transfer to device
|
||||
@param CmdLen The length of the command
|
||||
@param DataDir The direction of data transfer
|
||||
@@ -414,7 +426,7 @@ UsbCbiGetStatus (
|
||||
@param Timeout The time to wait
|
||||
@param CmdStatus The result of the command execution
|
||||
|
||||
@retval EFI_SUCCESS The command is executed OK and result in CmdStatus.
|
||||
@retval EFI_SUCCESS The command is executed successfully.
|
||||
@retval Other Failed to execute the command
|
||||
|
||||
**/
|
||||
@@ -450,7 +462,7 @@ UsbCbiExecCommand (
|
||||
}
|
||||
|
||||
//
|
||||
// Transfer the data, return this status if no interrupt endpoint
|
||||
// Transfer the data. Return this status if no interrupt endpoint
|
||||
// is used to report the transfer status.
|
||||
//
|
||||
TransLen = (UINTN) DataLen;
|
||||
@@ -462,12 +474,12 @@ UsbCbiExecCommand (
|
||||
}
|
||||
|
||||
//
|
||||
// Get the status, if that succeeds, interpret the result
|
||||
// Get the status. If it succeeds, interpret the result.
|
||||
//
|
||||
Status = UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiGetStatus (%r)\n",Status));
|
||||
return EFI_DEVICE_ERROR;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (UsbCbi->Interface.InterfaceSubClass == USB_MASS_STORE_UFI) {
|
||||
@@ -492,7 +504,8 @@ UsbCbiExecCommand (
|
||||
|
||||
case 0x02:
|
||||
//
|
||||
// Phase Error, response with reset. Fall through to Fail.
|
||||
// Phase Error, response with reset.
|
||||
// No break here to fall through to "Fail".
|
||||
//
|
||||
UsbCbiResetDevice (UsbCbi, FALSE);
|
||||
|
||||
@@ -505,7 +518,7 @@ UsbCbiExecCommand (
|
||||
|
||||
case 0x03:
|
||||
//
|
||||
// Persistent Fail, need to send REQUEST SENSE.
|
||||
// Persistent Fail. Need to send REQUEST SENSE.
|
||||
//
|
||||
*CmdStatus = USB_MASS_CMD_PERSISTENT;
|
||||
break;
|
||||
@@ -517,16 +530,18 @@ UsbCbiExecCommand (
|
||||
|
||||
|
||||
/**
|
||||
Call the Usb mass storage class transport protocol to
|
||||
reset the device. The reset is defined as a Non-Data
|
||||
command. Don't use UsbCbiExecCommand to send the command
|
||||
to device because that may introduce recursive loop.
|
||||
Reset the USB mass storage device by CBI protocol.
|
||||
|
||||
@param Context The USB CBI device protocol
|
||||
@param ExtendedVerification The flag controlling the rule of reset
|
||||
This function resets the USB mass storage device by CBI protocol.
|
||||
The reset is defined as a non-data command. Don't use UsbCbiExecCommand
|
||||
to send the command to device because that may introduce recursive loop.
|
||||
|
||||
@retval EFI_SUCCESS the device is reset
|
||||
@retval Others Failed to reset the device
|
||||
@param Context The USB CBI protocol
|
||||
@param ExtendedVerification The flag controlling the rule of reset.
|
||||
Not used here.
|
||||
|
||||
@retval EFI_SUCCESS The device is reset.
|
||||
@retval Others Failed to reset the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
@@ -562,17 +577,17 @@ UsbCbiResetDevice (
|
||||
|
||||
//
|
||||
// Just retrieve the status and ignore that. Then stall
|
||||
// 50ms to wait it complete
|
||||
// 50ms to wait for it to complete.
|
||||
//
|
||||
UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
||||
gBS->Stall (USB_CBI_RESET_DEVICE_STALL);
|
||||
|
||||
//
|
||||
// Clear the Bulk-In and Bulk-Out stall condition and
|
||||
// init data toggle.
|
||||
// Clear the Bulk-In and Bulk-Out stall condition and init data toggle.
|
||||
//
|
||||
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkInEndpoint->EndpointAddress);
|
||||
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkOutEndpoint->EndpointAddress);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -586,30 +601,10 @@ UsbCbiResetDevice (
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbCbiFini (
|
||||
UsbCbiCleanUp (
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
gBS->FreePool (Context);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
USB_MASS_TRANSPORT
|
||||
mUsbCbi0Transport = {
|
||||
USB_MASS_STORE_CBI0,
|
||||
UsbCbiInit,
|
||||
UsbCbiExecCommand,
|
||||
UsbCbiResetDevice,
|
||||
NULL,
|
||||
UsbCbiFini
|
||||
};
|
||||
|
||||
USB_MASS_TRANSPORT
|
||||
mUsbCbi1Transport = {
|
||||
USB_MASS_STORE_CBI1,
|
||||
UsbCbiInit,
|
||||
UsbCbiExecCommand,
|
||||
UsbCbiResetDevice,
|
||||
NULL,
|
||||
UsbCbiFini
|
||||
};
|
||||
|
Reference in New Issue
Block a user