3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file implement the command set of "USB Mass Storage Specification
26 #include "UsbMassImpl.h"
37 return the current TPL, copied from the EDKII glue lib.
51 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
52 gBS
->RestoreTPL (Tpl
);
58 Read an UINT32 from the buffer to avoid byte alignment problems, then
59 convert that to the little endia. The USB mass storage bootability spec
62 @param Buf The buffer contains the first byte of the UINT32
65 @return The UINT32 value read from the buffer in little endia.
76 CopyMem (&Value
, Buf
, sizeof (UINT32
));
77 return USB_BOOT_SWAP32 (Value
);
82 Put an UINT32 in little endia to the buffer. The data is converted to
83 big endia before writing.
85 @param Buf The buffer to write data to
86 @param Data32 The data to write.
98 Data32
= USB_BOOT_SWAP32 (Data32
);
99 CopyMem (Buf
, &Data32
, sizeof (UINT32
));
104 Put an UINT16 in little endia to the buffer. The data is converted to
105 big endia before writing.
107 @param Buf The buffer to write data to
108 @param Data16 The data to write
120 Data16
= (UINT16
) (USB_BOOT_SWAP16 (Data16
));
121 CopyMem (Buf
, &Data16
, sizeof (UINT16
));
126 Request sense information via sending Request Sense
129 @param UsbMass The device to be requested sense data
131 @retval EFI_DEVICE_ERROR Hardware error
132 @retval EFI_SUCCESS Success
136 UsbBootRequestSense (
137 IN USB_MASS_DEVICE
*UsbMass
140 USB_BOOT_REQUEST_SENSE_CMD SenseCmd
;
141 USB_BOOT_REQUEST_SENSE_DATA SenseData
;
142 EFI_BLOCK_IO_MEDIA
*Media
;
143 USB_MASS_TRANSPORT
*Transport
;
147 Transport
= UsbMass
->Transport
;
150 // Request the sense data from the device if command failed
152 ZeroMem (&SenseCmd
, sizeof (USB_BOOT_REQUEST_SENSE_CMD
));
153 ZeroMem (&SenseData
, sizeof (USB_BOOT_REQUEST_SENSE_DATA
));
155 SenseCmd
.OpCode
= USB_BOOT_REQUEST_SENSE_OPCODE
;
156 SenseCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
157 SenseCmd
.AllocLen
= sizeof (USB_BOOT_REQUEST_SENSE_DATA
);
159 Status
= Transport
->ExecCommand (
162 sizeof (USB_BOOT_REQUEST_SENSE_CMD
),
165 sizeof (USB_BOOT_REQUEST_SENSE_DATA
),
166 USB_BOOT_GENERAL_CMD_TIMEOUT
,
169 if (EFI_ERROR (Status
) || CmdResult
!= USB_MASS_CMD_SUCCESS
) {
170 DEBUG ((mUsbMscError
, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status
, CmdResult
));
175 // Interpret the sense data and update the media status if necessary.
177 Media
= &UsbMass
->BlockIoMedia
;
179 switch (USB_BOOT_SENSE_KEY (SenseData
.SenseKey
)) {
181 case USB_BOOT_SENSE_NO_SENSE
:
182 Status
= EFI_NO_RESPONSE
;
185 case USB_BOOT_SENSE_RECOVERED
:
187 // Suppose hardware can handle this case, and recover later by itself
189 Status
= EFI_NOT_READY
;
192 case USB_BOOT_SENSE_NOT_READY
:
193 Status
= EFI_DEVICE_ERROR
;
194 if (SenseData
.ASC
== USB_BOOT_ASC_NO_MEDIA
) {
195 Media
->MediaPresent
= FALSE
;
196 Status
= EFI_NO_MEDIA
;
197 } else if (SenseData
.ASC
== USB_BOOT_ASC_NOT_READY
) {
198 Status
= EFI_NOT_READY
;
202 case USB_BOOT_SENSE_ILLEGAL_REQUEST
:
203 Status
= EFI_INVALID_PARAMETER
;
206 case USB_BOOT_SENSE_UNIT_ATTENTION
:
207 Status
= EFI_DEVICE_ERROR
;
208 if (SenseData
.ASC
== USB_BOOT_ASC_MEDIA_CHANGE
) {
210 // If MediaChange, reset ReadOnly and new MediId
212 Status
= EFI_MEDIA_CHANGED
;
213 Media
->ReadOnly
= FALSE
;
218 case USB_BOOT_SNESE_DATA_PROTECT
:
219 Status
= EFI_WRITE_PROTECTED
;
220 Media
->ReadOnly
= TRUE
;
224 Status
= EFI_DEVICE_ERROR
;
228 DEBUG ((mUsbMscInfo
, "UsbBootRequestSense: (%r) with sense key %x/%x/%x\n",
230 USB_BOOT_SENSE_KEY (SenseData
.SenseKey
),
240 Execute the USB mass storage bootability commands. If execution
241 failed, retrieve the error by REQUEST_SENSE then update the device's
242 status, such as ReadyOnly.
244 @param UsbMass The device to issue commands to
245 @param Cmd The command to execute
246 @param CmdLen The length of the command
247 @param DataDir The direction of data transfer
248 @param Data The buffer to hold the data
249 @param DataLen The length of expected data
250 @param Timeout The timeout used to transfer
252 @retval EFI_SUCCESS The command is excuted OK
253 @retval EFI_DEVICE_ERROR Failed to request sense
254 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
255 @retval EFI_WRITE_PROTECTED The device is write protected
256 @retval EFI_MEDIA_CHANGED The device media has been changed
262 IN USB_MASS_DEVICE
*UsbMass
,
265 IN EFI_USB_DATA_DIRECTION DataDir
,
271 USB_MASS_TRANSPORT
*Transport
;
275 Transport
= UsbMass
->Transport
;
276 Status
= Transport
->ExecCommand (
287 // ExecCommand return success and get the right CmdResult means
288 // the commnad transfer is OK.
290 if ((CmdResult
== USB_MASS_CMD_SUCCESS
) && !EFI_ERROR(Status
)) {
294 DEBUG ((mUsbMscInfo
, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
295 *(UINT8
*)Cmd
,Status
));
297 return UsbBootRequestSense (UsbMass
);
302 Execute the USB mass storage bootability commands. If execution
303 failed, retrieve the error by REQUEST_SENSE then update the device's
304 status, such as ReadyOnly.
306 @param UsbMass The device to issue commands to
307 @param Cmd The command to execute
308 @param CmdLen The length of the command
309 @param DataDir The direction of data transfer
310 @param Data The buffer to hold the data
311 @param DataLen The length of expected data
313 @retval EFI_SUCCESS The command is excuted OK
314 @retval EFI_DEVICE_ERROR Failed to request sense
315 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
316 @retval EFI_WRITE_PROTECTED The device is write protected
317 @retval EFI_MEDIA_CHANGED The device media has been changed
322 UsbBootExecCmdWithRetry (
323 IN USB_MASS_DEVICE
*UsbMass
,
326 IN EFI_USB_DATA_DIRECTION DataDir
,
336 // If the device isn't ready, wait some time. If the device is ready,
337 // retry the command again.
339 Status
= EFI_SUCCESS
;
341 for (Index
= 0; Index
< USB_BOOT_COMMAND_RETRY
; Index
++) {
343 // Execute the command with an increasingly larger timeout value.
345 Status
= UsbBootExecCmd (
352 Timeout
* (Index
+ 1)
354 if (Status
== EFI_SUCCESS
||
355 Status
== EFI_MEDIA_CHANGED
) {
359 // Need retry once more, so reset index
361 if (Status
== EFI_NOT_READY
) {
372 Use the TEST UNIT READY command to check whether it is ready.
373 If it is ready, update the parameters.
375 @param UsbMass The device to test
377 @retval EFI_SUCCESS The device is ready and parameters are updated.
378 @retval Others Device not ready.
383 IN USB_MASS_DEVICE
*UsbMass
386 USB_BOOT_TEST_UNIT_READY_CMD TestCmd
;
388 ZeroMem (&TestCmd
, sizeof (USB_BOOT_TEST_UNIT_READY_CMD
));
390 TestCmd
.OpCode
= USB_BOOT_TEST_UNIT_READY_OPCODE
;
391 TestCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
393 return UsbBootExecCmdWithRetry (
396 sizeof (USB_BOOT_TEST_UNIT_READY_CMD
),
400 USB_BOOT_GENERAL_CMD_TIMEOUT
406 Inquiry Command requests that information regrarding parameters of
407 the Device be sent to the Host.
409 @param UsbMass The device to inquiry.
411 @retval EFI_SUCCESS The device is ready and parameters are updated.
412 @retval Others Device not ready.
417 IN USB_MASS_DEVICE
*UsbMass
420 USB_BOOT_INQUIRY_CMD InquiryCmd
;
421 USB_BOOT_INQUIRY_DATA InquiryData
;
422 EFI_BLOCK_IO_MEDIA
*Media
;
425 Media
= &(UsbMass
->BlockIoMedia
);
428 // Use the Inquiry command to get the RemovableMedia setting.
430 ZeroMem (&InquiryCmd
, sizeof (USB_BOOT_INQUIRY_CMD
));
431 ZeroMem (&InquiryData
, sizeof (USB_BOOT_INQUIRY_DATA
));
433 InquiryCmd
.OpCode
= USB_BOOT_INQUIRY_OPCODE
;
434 InquiryCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
435 InquiryCmd
.AllocLen
= sizeof (InquiryData
);
437 Status
= UsbBootExecCmdWithRetry (
440 sizeof (USB_BOOT_INQUIRY_CMD
),
443 sizeof (USB_BOOT_INQUIRY_DATA
),
444 USB_BOOT_GENERAL_CMD_TIMEOUT
446 if (EFI_ERROR (Status
)) {
450 UsbMass
->Pdt
= (UINT8
) (USB_BOOT_PDT (InquiryData
.Pdt
));
451 Media
->RemovableMedia
= (BOOLEAN
) (USB_BOOT_REMOVABLE (InquiryData
.Removable
));
453 // Default value 512 Bytes, in case no media present at first time
455 Media
->BlockSize
= 0x0200;
462 Get the capacity of the USB mass storage media, including
463 the presentation, block size, and last block number. This
464 function is used to get the disk parameters at the start if
465 it is a non-removable media or to detect the media if it is
468 @param UsbMass The device to retireve disk gemotric.
470 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
471 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
475 UsbBootReadCapacity (
476 IN USB_MASS_DEVICE
*UsbMass
479 USB_BOOT_READ_CAPACITY_CMD CapacityCmd
;
480 USB_BOOT_READ_CAPACITY_DATA CapacityData
;
481 EFI_BLOCK_IO_MEDIA
*Media
;
484 Media
= &UsbMass
->BlockIoMedia
;
487 // Use the READ CAPACITY command to get the block length and last blockno
489 ZeroMem (&CapacityCmd
, sizeof (USB_BOOT_READ_CAPACITY_CMD
));
490 ZeroMem (&CapacityData
, sizeof (USB_BOOT_READ_CAPACITY_DATA
));
492 CapacityCmd
.OpCode
= USB_BOOT_READ_CAPACITY_OPCODE
;
493 CapacityCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
495 Status
= UsbBootExecCmdWithRetry (
498 sizeof (USB_BOOT_READ_CAPACITY_CMD
),
501 sizeof (USB_BOOT_READ_CAPACITY_DATA
),
502 USB_BOOT_GENERAL_CMD_TIMEOUT
504 if (EFI_ERROR (Status
)) {
508 Media
->MediaPresent
= TRUE
;
509 Media
->LastBlock
= UsbBootGetUint32 (CapacityData
.LastLba
);
510 Media
->BlockSize
= UsbBootGetUint32 (CapacityData
.BlockLen
);
512 if (Media
->BlockSize
== 0) {
513 return EFI_NOT_READY
;
516 DEBUG ((mUsbMscInfo
, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",
517 Media
->LastBlock
, Media
->BlockSize
));
524 Retrieves mode sense information via sending Mode Sense
527 @param UsbMass The USB_FLOPPY_DEV instance.
529 @retval EFI_DEVICE_ERROR Hardware error
530 @retval EFI_SUCCESS Success
535 IN USB_MASS_DEVICE
*UsbMass
539 USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd
;
540 USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader
;
541 EFI_BLOCK_IO_MEDIA
*Media
;
543 Media
= &UsbMass
->BlockIoMedia
;
545 ZeroMem (&ModeSenseCmd
, sizeof (USB_SCSI_MODE_SENSE6_CMD
));
546 ZeroMem (&ModeParaHeader
, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
));
549 // ModeSense6 command is defined in [SCSI2Spec-Page151]
551 ModeSenseCmd
.OpCode
= USB_SCSI_MODE_SENSE6_OPCODE
;
552 ModeSenseCmd
.Lun
= (UINT8
) USB_BOOT_LUN (UsbMass
->Lun
);
553 ModeSenseCmd
.PageCode
= 0x3F;
554 ModeSenseCmd
.AllocateLen
= (UINT8
) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
);
556 Status
= UsbBootExecCmdWithRetry (
559 sizeof (USB_SCSI_MODE_SENSE6_CMD
),
562 sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
),
563 USB_BOOT_GENERAL_CMD_TIMEOUT
567 // ModeSense(6) is used to get the information of WriteProtected. While only some of
568 // devices support this command, so have a try here.
570 if (!EFI_ERROR (Status
)) {
571 Media
->ReadOnly
= (BOOLEAN
) ((ModeParaHeader
.DevicePara
& 0x80) ? TRUE
: FALSE
);
579 Get the parameters for the USB mass storage media, including
580 the RemovableMedia, block size, and last block number. This
581 function is used both to initialize the media during the
582 DriverBindingStart and to re-initialize it when the media is
583 changed. Althought the RemoveableMedia is unlikely to change,
586 @param UsbMass The device to retireve disk gemotric.
588 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
589 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
594 IN USB_MASS_DEVICE
*UsbMass
597 EFI_BLOCK_IO_MEDIA
*Media
;
601 Media
= &(UsbMass
->BlockIoMedia
);
602 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
604 Status
= UsbBootInquiry (UsbMass
);
605 if (EFI_ERROR (Status
)) {
606 DEBUG ((mUsbMscError
, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status
));
611 // Don't use the Removable bit in inquirydata to test whether the media
612 // is removable because many flash disks wrongly set this bit.
614 if ((UsbMass
->Pdt
== USB_PDT_CDROM
) || (UsbMass
->Pdt
== USB_PDT_OPTICAL
)) {
616 // CD-Rom device and Non-CD optical device
618 UsbMass
->OpticalStorage
= TRUE
;
620 // Default value 2048 Bytes, in case no media present at first time
622 Media
->BlockSize
= 0x0800;
625 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
627 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
628 // which is from [MassStorageBootabilitySpec-Page7].
629 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
630 // could get the information of WriteProtected.
631 // Since not all device support this command, so skip if fail.
633 UsbScsiModeSense (UsbMass
);
636 return UsbBootReadCapacity (UsbMass
);
641 Detect whether the removable media is present and whether it has changed.
642 The Non-removable media doesn't need it.
644 @param UsbMass The device to retireve disk gemotric.
646 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
647 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
652 IN USB_MASS_DEVICE
*UsbMass
655 EFI_BLOCK_IO_MEDIA OldMedia
;
656 EFI_BLOCK_IO_MEDIA
*Media
;
661 Media
= &UsbMass
->BlockIoMedia
;
665 &(UsbMass
->BlockIoMedia
),
666 sizeof (EFI_BLOCK_IO_MEDIA
)
669 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
671 Status
= UsbBootIsUnitReady (UsbMass
);
672 if (EFI_ERROR (Status
)) {
673 DEBUG ((mUsbMscError
, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status
));
677 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
679 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
680 // which is from [MassStorageBootabilitySpec-Page7].
681 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
682 // could get the information of WriteProtected.
683 // Since not all device support this command, so skip if fail.
685 UsbScsiModeSense (UsbMass
);
688 Status
= UsbBootReadCapacity (UsbMass
);
689 if (EFI_ERROR (Status
)) {
690 DEBUG ((mUsbMscError
, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status
));
698 // Detect whether it is necessary to reinstall the BlockIO
700 // MediaId may change in RequestSense for MediaChanged
701 // MediaPresent may change in RequestSense for NoMedia
702 // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged
703 // MediaPresent/BlockSize/LastBlock may change in ReadCapacity
705 if ((Media
->MediaId
!= OldMedia
.MediaId
) ||
706 (Media
->MediaPresent
!= OldMedia
.MediaPresent
) ||
707 (Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
708 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
709 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
711 OldTpl
= UsbGetCurrentTpl ();
712 DEBUG ((mUsbMscError
, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", OldTpl
));
714 gBS
->RestoreTPL (TPL_CALLBACK
);
716 gBS
->ReinstallProtocolInterface (
718 &gEfiBlockIoProtocolGuid
,
723 DEBUG ((mUsbMscError
, "UsbBootDetectMedia: TPL after reinstall is %d\n", UsbGetCurrentTpl()));
724 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK
);
726 gBS
->RaiseTPL (OldTpl
);
729 // Update MediaId after reinstall BLOCK_IO_PROTOCOL
731 if (Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
732 if (Media
->MediaPresent
== TRUE
) {
739 if ((Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
740 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
741 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
751 Read some blocks from the device.
753 @param UsbMass The USB mass storage device to read from
754 @param Lba The start block number
755 @param TotalBlock Total block number to read
756 @param Buffer The buffer to read to
758 @retval EFI_SUCCESS Data are read into the buffer
759 @retval Others Failed to read all the data
764 IN USB_MASS_DEVICE
*UsbMass
,
770 USB_BOOT_READ10_CMD ReadCmd
;
777 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
778 Status
= EFI_SUCCESS
;
780 while (TotalBlock
> 0) {
782 // Split the total blocks into smaller pieces to ease the pressure
783 // on the device. We must split the total block because the READ10
784 // command only has 16 bit transfer length (in the unit of block).
786 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
787 ByteSize
= (UINT32
)Count
* BlockSize
;
790 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
792 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
795 // Fill in the command then execute
797 ZeroMem (&ReadCmd
, sizeof (USB_BOOT_READ10_CMD
));
799 ReadCmd
.OpCode
= USB_BOOT_READ10_OPCODE
;
800 ReadCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
801 UsbBootPutUint32 (ReadCmd
.Lba
, Lba
);
802 UsbBootPutUint16 (ReadCmd
.TransferLen
, Count
);
804 Status
= UsbBootExecCmdWithRetry (
807 sizeof (USB_BOOT_READ10_CMD
),
813 if (EFI_ERROR (Status
)) {
818 Buffer
+= Count
* BlockSize
;
827 Write some blocks to the device.
829 @param UsbMass The USB mass storage device to write to
830 @param Lba The start block number
831 @param TotalBlock Total block number to write
832 @param Buffer The buffer to write to
834 @retval EFI_SUCCESS Data are written into the buffer
835 @retval Others Failed to write all the data
840 IN USB_MASS_DEVICE
*UsbMass
,
846 USB_BOOT_WRITE10_CMD WriteCmd
;
853 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
854 Status
= EFI_SUCCESS
;
856 while (TotalBlock
> 0) {
858 // Split the total blocks into smaller pieces to ease the pressure
859 // on the device. We must split the total block because the WRITE10
860 // command only has 16 bit transfer length (in the unit of block).
862 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
863 ByteSize
= (UINT32
)Count
* BlockSize
;
866 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
868 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
871 // Fill in the write10 command block
873 ZeroMem (&WriteCmd
, sizeof (USB_BOOT_WRITE10_CMD
));
875 WriteCmd
.OpCode
= USB_BOOT_WRITE10_OPCODE
;
876 WriteCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
877 UsbBootPutUint32 (WriteCmd
.Lba
, Lba
);
878 UsbBootPutUint16 (WriteCmd
.TransferLen
, Count
);
880 Status
= UsbBootExecCmdWithRetry (
883 sizeof (USB_BOOT_WRITE10_CMD
),
889 if (EFI_ERROR (Status
)) {
894 Buffer
+= Count
* BlockSize
;
903 Use the USB clear feature control transfer to clear the endpoint
906 @param UsbIo The USB IO protocol to use
907 @param EndpointAddr The endpoint to clear stall for
909 @retval EFI_SUCCESS The endpoint stall condtion is clear
910 @retval Others Failed to clear the endpoint stall condtion
914 UsbClearEndpointStall (
915 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
916 IN UINT8 EndpointAddr
919 EFI_USB_DEVICE_REQUEST Request
;
924 Request
.RequestType
= 0x02;
925 Request
.Request
= USB_REQ_CLEAR_FEATURE
;
926 Request
.Value
= USB_FEATURE_ENDPOINT_HALT
;
927 Request
.Index
= EndpointAddr
;
929 Timeout
= USB_BOOT_GENERAL_CMD_TIMEOUT
/ USB_MASS_1_MILLISECOND
;
931 Status
= UsbIo
->UsbControlTransfer (