/*++\r
\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
Module Name:\r
\r
\r
#include "bot.h"\r
\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTDebugLevel = EFI_D_INFO;\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTErrorLevel = EFI_D_INFO;\r
//\r
// Function prototypes\r
//\r
EFI_STATUS\r
BotDataPhase (\r
IN USB_BOT_DEVICE *UsbBotDev,\r
- IN UINT32 *DataSize,\r
+ IN UINTN *DataSize,\r
IN OUT VOID *DataBuffer,\r
IN EFI_USB_DATA_DIRECTION Direction,\r
IN UINT16 Timeout\r
STATIC\r
EFI_STATUS\r
BotStatusPhase (\r
- IN USB_BOT_DEVICE *UsbBotDev,\r
- OUT UINT8 *TransferStatus,\r
- IN UINT16 Timeout\r
+ IN USB_BOT_DEVICE *UsbBotDev,\r
+ OUT UINT32 *DataResidue, \r
+ IN UINT16 Timeout\r
);\r
-\r
//\r
// USB Atapi protocol prototype\r
//\r
//\r
// Check if it is a BOT type Mass Storage Device\r
//\r
- if ((InterfaceDescriptor.InterfaceClass != 0x08) ||\r
+ if ((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) ||\r
(InterfaceDescriptor.InterfaceProtocol != BOT)) {\r
Status = EFI_UNSUPPORTED;\r
goto Exit;\r
\r
Returns:\r
EFI_SUCCESS - This driver is removed DeviceHandle\r
- EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl \r
+ EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl\r
other - This driver was not removed from this device\r
\r
--*/\r
return Status;\r
}\r
\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+ClearBulkInPipe (\r
+ IN USB_BOT_DEVICE *UsbBotDev\r
+ )\r
+{\r
+ UINT32 Result;\r
+\r
+ return UsbClearEndpointHalt (\r
+ UsbBotDev->UsbIo,\r
+ UsbBotDev->BulkInEndpointDescriptor->EndpointAddress,\r
+ &Result\r
+ );\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+ClearBulkOutPipe (\r
+ IN USB_BOT_DEVICE *UsbBotDev\r
+ )\r
+{\r
+ UINT32 Result;\r
+ return UsbClearEndpointHalt (\r
+ UsbBotDev->UsbIo,\r
+ UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,\r
+ &Result\r
+ );\r
+}\r
+\r
STATIC\r
EFI_STATUS\r
BotRecoveryReset (\r
\r
Returns:\r
EFI_SUCCESS - Success the operation\r
- \r
+\r
--*/\r
{\r
EFI_STATUS Status;\r
- UINT32 Result;\r
EFI_USB_DEVICE_REQUEST Request;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- UINT8 EndpointAddr;\r
-\r
- UsbIo = UsbBotDev->UsbIo;\r
-\r
+ UINT32 Result;\r
BotReportStatusCode (\r
UsbBotDev->DevicePath,\r
EFI_PROGRESS_CODE,\r
Request.RequestType = 0x21;\r
Request.Request = 0xFF;\r
\r
- Status = UsbIo->UsbControlTransfer (\r
- UsbIo,\r
- &Request,\r
- EfiUsbNoData,\r
- TIMEOUT_VALUE,\r
- NULL,\r
- 0,\r
- &Result\r
- );\r
+ Status = UsbBotDev->UsbIo->UsbControlTransfer (\r
+ UsbBotDev->UsbIo,\r
+ &Request,\r
+ EfiUsbNoData,\r
+ TIMEOUT_VALUE,\r
+ NULL,\r
+ 0,\r
+ &Result\r
+ );\r
\r
gBS->Stall (100 * 1000);\r
\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // clear bulk in endpoint stall feature\r
- //\r
- EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
-\r
- Status = UsbClearEndpointHalt (\r
- UsbIo,\r
- EndpointAddr,\r
- &Result\r
- );\r
-\r
- //\r
- // clear bulk out endpoint stall feature\r
- //\r
- EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;\r
- Status = UsbClearEndpointHalt (\r
- UsbIo,\r
- EndpointAddr,\r
- &Result\r
- );\r
- }\r
+ ClearBulkInPipe (UsbBotDev);\r
+ ClearBulkOutPipe (UsbBotDev);\r
\r
return Status;\r
}\r
+\r
//\r
// Bot Protocol Implementation\r
//\r
cbw.dCBWSignature = CBWSIG;\r
cbw.dCBWTag = 0x01;\r
cbw.dCBWDataTransferLength = DataTransferLength;\r
- cbw.bmCBWFlags = (UINT8) (Direction << 7);\r
+ switch (Direction) {\r
+ case EfiUsbDataOut:\r
+ case EfiUsbNoData:\r
+ cbw.bmCBWFlags = 0;\r
+ break;\r
+ case EfiUsbDataIn:\r
+ cbw.bmCBWFlags = 0x80;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
cbw.bCBWCBLength = CommandSize;\r
\r
CopyMem (cbw.CBWCB, Command, CommandSize);\r
\r
Status = UsbIo->UsbBulkTransfer (\r
UsbIo,\r
- (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress,\r
+ UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,\r
&cbw,\r
&DataSize,\r
Timeout,\r
&Result\r
);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Command phase fail, we need to recovery reset this device\r
- //\r
- BotRecoveryReset (UsbBotDev);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
STATIC\r
EFI_STATUS\r
BotDataPhase (\r
IN USB_BOT_DEVICE *UsbBotDev,\r
- IN UINT32 *DataSize,\r
+ IN UINTN *DataSize,\r
IN OUT VOID *DataBuffer,\r
IN EFI_USB_DATA_DIRECTION Direction,\r
IN UINT16 Timeout\r
UINT32 Result;\r
EFI_USB_IO_PROTOCOL *UsbIo;\r
UINT8 EndpointAddr;\r
- UINTN Remain;\r
- UINTN Increment;\r
- UINT32 MaxPacketLen;\r
UINT8 *BufferPtr;\r
- UINTN TransferredSize;\r
- UINTN RetryTimes;\r
- UINTN MaxRetry;\r
- UINTN BlockSize;\r
- UINTN PackageNum;\r
\r
UsbIo = UsbBotDev->UsbIo;\r
- Remain = *DataSize;\r
BufferPtr = (UINT8 *) DataBuffer;\r
- TransferredSize = 0;\r
- MaxRetry = 10;\r
- PackageNum = 128;\r
\r
//\r
// retrieve the the max packet length of the given endpoint\r
//\r
if (Direction == EfiUsbDataIn) {\r
- MaxPacketLen = (UsbBotDev->BulkInEndpointDescriptor)->MaxPacketSize;\r
- EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;\r
+ EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
} else {\r
- MaxPacketLen = (UsbBotDev->BulkOutEndpointDescriptor)->MaxPacketSize;\r
- EndpointAddr = (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress;\r
+ EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;\r
}\r
\r
- RetryTimes = MaxRetry;\r
- BlockSize = PackageNum * MaxPacketLen;\r
- while (Remain > 0) {\r
- //\r
- // Using 15 packets to aVOID Bitstuff error\r
- //\r
- if (Remain > PackageNum * MaxPacketLen) {\r
- Increment = BlockSize;\r
- } else {\r
- Increment = Remain;\r
- }\r
-\r
Status = UsbIo->UsbBulkTransfer (\r
UsbIo,\r
EndpointAddr,\r
BufferPtr,\r
- &Increment,\r
- Timeout,\r
+ DataSize,\r
+ (UINT16)(Timeout),\r
&Result\r
);\r
\r
- TransferredSize += Increment;\r
-\r
if (EFI_ERROR (Status)) {\r
- RetryTimes--;\r
- if ((RetryTimes == 0) || ((Result & EFI_USB_ERR_TIMEOUT) == 0)) {\r
- goto ErrorExit;\r
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
+ if (Direction == EfiUsbDataIn) {\r
+ DEBUG((gBOTErrorLevel, "BOT: Data IN Stall, ClearBulkInPipe\n"));\r
+ ClearBulkInPipe (UsbBotDev);\r
+ } else {\r
+ DEBUG((gBOTErrorLevel, "BOT: Data OUT Stall, ClearBulkInPipe\n"));\r
+ ClearBulkOutPipe (UsbBotDev);\r
+ }\r
}\r
+ // BotRecoveryReset (UsbBotDev);\r
+ }\r
\r
- TransferredSize -= Increment;\r
- continue;\r
- } else {\r
- //\r
- // we try MaxTetry times for every bulk transfer\r
- //\r
- RetryTimes = MaxRetry;\r
- }\r
-\r
- BufferPtr += Increment;\r
- Remain -= Increment;\r
- if (Increment < BlockSize && TransferredSize <= *DataSize) {\r
- //\r
- // we get to the end of transter and transter size is\r
- // less than requriedsize\r
- //\r
- break;\r
- }\r
- }\r
-\r
- *DataSize = (UINT32) TransferredSize;\r
-\r
- return EFI_SUCCESS;\r
-\r
-ErrorExit:\r
- if (Direction == EfiUsbDataIn) {\r
- BotReportStatusCode (\r
- UsbBotDev->DevicePath,\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)\r
- );\r
- } else {\r
- BotReportStatusCode (\r
- UsbBotDev->DevicePath,\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)\r
- );\r
- }\r
-\r
- if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
- //\r
- // just endpoint stall happens\r
- //\r
- UsbClearEndpointHalt (\r
- UsbIo,\r
- EndpointAddr,\r
- &Result\r
- );\r
- }\r
-\r
- *DataSize = (UINT32) TransferredSize;\r
\r
return Status;\r
-\r
}\r
\r
STATIC\r
EFI_STATUS\r
BotStatusPhase (\r
- IN USB_BOT_DEVICE *UsbBotDev,\r
- OUT UINT8 *TransferStatus,\r
- IN UINT16 Timeout\r
+ IN USB_BOT_DEVICE *UsbBotDev,\r
+ OUT UINT32 *DataResidue,\r
+ IN UINT16 Timeout\r
)\r
/*++\r
\r
\r
Parameters:\r
UsbBotDev - USB_BOT_DEVICE pointer\r
- TransferStatus - TransferStatus\r
Timeout - Time out value in milliseconds\r
Return Value:\r
EFI_SUCCESS\r
{\r
CSW csw;\r
EFI_STATUS Status;\r
- UINT32 Result;\r
EFI_USB_IO_PROTOCOL *UsbIo;\r
UINT8 EndpointAddr;\r
UINTN DataSize;\r
+ UINT32 Result;\r
+ UINT8 Index;\r
\r
UsbIo = UsbBotDev->UsbIo;\r
+ EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
\r
- ZeroMem (&csw, sizeof (CSW));\r
-\r
- EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;\r
-\r
- DataSize = sizeof (CSW);\r
-\r
- //\r
- // Get the status field from bulk transfer\r
- //\r
- Status = UsbIo->UsbBulkTransfer (\r
- UsbIo,\r
- EndpointAddr,\r
- &csw,\r
- &DataSize,\r
- Timeout,\r
- &Result\r
- );\r
- if (EFI_ERROR (Status)) {\r
- if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
- //\r
- // just endpoint stall happens\r
- //\r
- UsbClearEndpointHalt (\r
- UsbIo,\r
- EndpointAddr,\r
- &Result\r
- );\r
- }\r
\r
+ for (Index = 0; Index < 3; Index ++) {\r
ZeroMem (&csw, sizeof (CSW));\r
+ DataSize = sizeof (CSW);\r
+ Result = 0;\r
\r
- EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;\r
-\r
- DataSize = sizeof (CSW);\r
Status = UsbIo->UsbBulkTransfer (\r
UsbIo,\r
EndpointAddr,\r
);\r
if (EFI_ERROR (Status)) {\r
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
- UsbClearEndpointHalt (\r
- UsbIo,\r
- EndpointAddr,\r
- &Result\r
- );\r
+ DEBUG((gBOTDebugLevel, "BOT: CSW Stall, ClearBulkInPipe\n"));\r
+ ClearBulkInPipe (UsbBotDev);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (csw.dCSWSignature == CSWSIG) {\r
+ if (csw.bCSWStatus == 0 || csw.bCSWStatus == 0x01) {\r
+ if (DataResidue != NULL) {\r
+ *DataResidue = csw.dCSWDataResidue;\r
+ }\r
+ if (csw.bCSWStatus == 0x01) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ break;\r
+ } else if (csw.bCSWStatus == 0x02) {\r
+ DEBUG((gBOTErrorLevel, "BOT: Bot Phase error\n"));\r
+ BotRecoveryReset (UsbBotDev);\r
}\r
\r
- return Status;\r
}\r
}\r
\r
- if (csw.dCSWSignature == CSWSIG) {\r
- *TransferStatus = csw.bCSWStatus;\r
- } else {\r
+ if (Index == 3) {\r
return EFI_DEVICE_ERROR;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
+\r
//\r
// Usb Atapi Protocol implementation\r
//\r
{\r
EFI_STATUS Status;\r
EFI_STATUS BotDataStatus;\r
- UINT8 TransferStatus;\r
USB_BOT_DEVICE *UsbBotDev;\r
- UINT32 BufferSize;\r
-\r
- BotDataStatus = EFI_SUCCESS;\r
- TransferStatus = 0;\r
+ UINTN BufferSize;\r
+ UINT8 Index;\r
+ UINT32 DataResidue;\r
\r
//\r
// Get the context\r
//\r
- UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
+ UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
+ BotDataStatus = EFI_SUCCESS;\r
+ BufferSize = 0;\r
\r
- //\r
- // First send ATAPI command through Bot\r
- //\r
- Status = BotCommandPhase (\r
- UsbBotDev,\r
- Command,\r
- CommandSize,\r
- BufferLength,\r
- Direction,\r
- TimeOutInMilliSeconds\r
- );\r
+ for (Index = 0; Index < 3; Index ++) {\r
+ //\r
+ // First send ATAPI command through Bot\r
+ //\r
+ Status = BotCommandPhase (\r
+ UsbBotDev,\r
+ Command,\r
+ CommandSize,\r
+ BufferLength,\r
+ Direction,\r
+ 10 * 1000\r
+ );\r
\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Send/Get Data if there is a Data Stage\r
- //\r
- switch (Direction) {\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG((gBOTErrorLevel, "BotCommandPhase Fail\n"));\r
+ return Status;\r
+ }\r
+ //\r
+ // Send/Get Data if there is a Data Stage\r
+ //\r
+ switch (Direction) {\r
\r
- case EfiUsbDataIn:\r
- case EfiUsbDataOut:\r
- BufferSize = BufferLength;\r
-\r
- BotDataStatus = BotDataPhase (\r
- UsbBotDev,\r
- &BufferSize,\r
- DataBuffer,\r
- Direction,\r
- (UINT16) (TimeOutInMilliSeconds)\r
- );\r
+ case EfiUsbDataIn:\r
+ case EfiUsbDataOut:\r
+ BufferSize = BufferLength;\r
\r
- break;\r
+ BotDataStatus = BotDataPhase (\r
+ UsbBotDev,\r
+ &BufferSize,\r
+ DataBuffer,\r
+ Direction,\r
+ (UINT16) (TimeOutInMilliSeconds)\r
+ );\r
\r
- case EfiUsbNoData:\r
- break;\r
- }\r
- \r
- //\r
- // Status Phase\r
- //\r
- Status = BotStatusPhase (\r
- UsbBotDev,\r
- &TransferStatus,\r
- TimeOutInMilliSeconds\r
- );\r
\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ if (EFI_ERROR (BotDataStatus)) {\r
+ DEBUG((gBOTErrorLevel, "BotDataPhase Fail\n"));\r
+ }\r
+ break;\r
\r
- if (TransferStatus == 0x02) {\r
+ case EfiUsbNoData:\r
+ break;\r
+ }\r
+\r
+ DataResidue = 0;\r
//\r
- // Phase error\r
+ // Status Phase\r
//\r
- BotRecoveryReset (UsbBotDev);\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ Status = BotStatusPhase (\r
+ UsbBotDev,\r
+ &DataResidue,\r
+ 10 * 1000\r
+ );\r
\r
- if (TransferStatus == 0x01) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG((gBOTErrorLevel, "BotStatusPhase Fail\n"));\r
+ return Status;\r
+ }\r
\r
+ if (!EFI_ERROR (BotDataStatus)) {\r
+ break;\r
+ }\r
+\r
+ }\r
return BotDataStatus;\r
}\r
\r