3 Copyright (c) 2007 - 2008, 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
),
167 USB_BOOT_GENERAL_CMD_TIMEOUT
,
170 if (EFI_ERROR (Status
) || CmdResult
!= USB_MASS_CMD_SUCCESS
) {
171 DEBUG ((EFI_D_ERROR
, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status
, CmdResult
));
176 // Interpret the sense data and update the media status if necessary.
178 Media
= &UsbMass
->BlockIoMedia
;
180 switch (USB_BOOT_SENSE_KEY (SenseData
.SenseKey
)) {
182 case USB_BOOT_SENSE_NO_SENSE
:
183 Status
= EFI_NO_RESPONSE
;
186 case USB_BOOT_SENSE_RECOVERED
:
188 // Suppose hardware can handle this case, and recover later by itself
190 Status
= EFI_NOT_READY
;
193 case USB_BOOT_SENSE_NOT_READY
:
194 Status
= EFI_DEVICE_ERROR
;
195 if (SenseData
.ASC
== USB_BOOT_ASC_NO_MEDIA
) {
196 Media
->MediaPresent
= FALSE
;
197 Status
= EFI_NO_MEDIA
;
198 } else if (SenseData
.ASC
== USB_BOOT_ASC_NOT_READY
) {
199 Status
= EFI_NOT_READY
;
203 case USB_BOOT_SENSE_ILLEGAL_REQUEST
:
204 Status
= EFI_INVALID_PARAMETER
;
207 case USB_BOOT_SENSE_UNIT_ATTENTION
:
208 Status
= EFI_DEVICE_ERROR
;
209 if (SenseData
.ASC
== USB_BOOT_ASC_MEDIA_CHANGE
) {
211 // If MediaChange, reset ReadOnly and new MediId
213 Status
= EFI_MEDIA_CHANGED
;
214 Media
->ReadOnly
= FALSE
;
219 case USB_BOOT_SNESE_DATA_PROTECT
:
220 Status
= EFI_WRITE_PROTECTED
;
221 Media
->ReadOnly
= TRUE
;
225 Status
= EFI_DEVICE_ERROR
;
229 DEBUG ((EFI_D_INFO
, "UsbBootRequestSense: (%r) with sense key %x/%x/%x\n",
231 USB_BOOT_SENSE_KEY (SenseData
.SenseKey
),
241 Execute the USB mass storage bootability commands. If execution
242 failed, retrieve the error by REQUEST_SENSE then update the device's
243 status, such as ReadyOnly.
245 @param UsbMass The device to issue commands to
246 @param Cmd The command to execute
247 @param CmdLen The length of the command
248 @param DataDir The direction of data transfer
249 @param Data The buffer to hold the data
250 @param DataLen The length of expected data
251 @param Timeout The timeout used to transfer
253 @retval EFI_SUCCESS The command is excuted OK
254 @retval EFI_DEVICE_ERROR Failed to request sense
255 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
256 @retval EFI_WRITE_PROTECTED The device is write protected
257 @retval EFI_MEDIA_CHANGED The device media has been changed
263 IN USB_MASS_DEVICE
*UsbMass
,
266 IN EFI_USB_DATA_DIRECTION DataDir
,
272 USB_MASS_TRANSPORT
*Transport
;
276 Transport
= UsbMass
->Transport
;
277 Status
= Transport
->ExecCommand (
289 // ExecCommand return success and get the right CmdResult means
290 // the commnad transfer is OK.
292 if ((CmdResult
== USB_MASS_CMD_SUCCESS
) && !EFI_ERROR(Status
)) {
296 DEBUG ((EFI_D_INFO
, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
297 *(UINT8
*)Cmd
,Status
));
299 return UsbBootRequestSense (UsbMass
);
304 Execute the USB mass storage bootability commands. If execution
305 failed, retrieve the error by REQUEST_SENSE then update the device's
306 status, such as ReadyOnly.
308 @param UsbMass The device to issue commands to
309 @param Cmd The command to execute
310 @param CmdLen The length of the command
311 @param DataDir The direction of data transfer
312 @param Data The buffer to hold the data
313 @param DataLen The length of expected data
315 @retval EFI_SUCCESS The command is excuted OK
316 @retval EFI_DEVICE_ERROR Failed to request sense
317 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
318 @retval EFI_WRITE_PROTECTED The device is write protected
319 @retval EFI_MEDIA_CHANGED The device media has been changed
324 UsbBootExecCmdWithRetry (
325 IN USB_MASS_DEVICE
*UsbMass
,
328 IN EFI_USB_DATA_DIRECTION DataDir
,
338 // If the device isn't ready, wait some time. If the device is ready,
339 // retry the command again.
341 Status
= EFI_SUCCESS
;
343 for (Index
= 0; Index
< USB_BOOT_COMMAND_RETRY
; Index
++) {
345 // Execute the command with an increasingly larger timeout value.
347 Status
= UsbBootExecCmd (
356 if (Status
== EFI_SUCCESS
||
357 Status
== EFI_MEDIA_CHANGED
) {
361 // Need retry once more, so reset index
363 if (Status
== EFI_NOT_READY
) {
374 Use the TEST UNIT READY command to check whether it is ready.
375 If it is ready, update the parameters.
377 @param UsbMass The device to test
379 @retval EFI_SUCCESS The device is ready and parameters are updated.
380 @retval Others Device not ready.
385 IN USB_MASS_DEVICE
*UsbMass
388 USB_BOOT_TEST_UNIT_READY_CMD TestCmd
;
390 ZeroMem (&TestCmd
, sizeof (USB_BOOT_TEST_UNIT_READY_CMD
));
392 TestCmd
.OpCode
= USB_BOOT_TEST_UNIT_READY_OPCODE
;
393 TestCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
395 return UsbBootExecCmdWithRetry (
398 sizeof (USB_BOOT_TEST_UNIT_READY_CMD
),
402 USB_BOOT_GENERAL_CMD_TIMEOUT
408 Inquiry Command requests that information regrarding parameters of
409 the Device be sent to the Host.
411 @param UsbMass The device to inquiry.
413 @retval EFI_SUCCESS The device is ready and parameters are updated.
414 @retval Others Device not ready.
419 IN USB_MASS_DEVICE
*UsbMass
422 USB_BOOT_INQUIRY_CMD InquiryCmd
;
423 USB_BOOT_INQUIRY_DATA InquiryData
;
424 EFI_BLOCK_IO_MEDIA
*Media
;
427 Media
= &(UsbMass
->BlockIoMedia
);
430 // Use the Inquiry command to get the RemovableMedia setting.
432 ZeroMem (&InquiryCmd
, sizeof (USB_BOOT_INQUIRY_CMD
));
433 ZeroMem (&InquiryData
, sizeof (USB_BOOT_INQUIRY_DATA
));
435 InquiryCmd
.OpCode
= USB_BOOT_INQUIRY_OPCODE
;
436 InquiryCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
437 InquiryCmd
.AllocLen
= sizeof (InquiryData
);
439 Status
= UsbBootExecCmdWithRetry (
442 sizeof (USB_BOOT_INQUIRY_CMD
),
445 sizeof (USB_BOOT_INQUIRY_DATA
),
446 USB_BOOT_GENERAL_CMD_TIMEOUT
448 if (EFI_ERROR (Status
)) {
452 UsbMass
->Pdt
= (UINT8
) (USB_BOOT_PDT (InquiryData
.Pdt
));
453 Media
->RemovableMedia
= (BOOLEAN
) (USB_BOOT_REMOVABLE (InquiryData
.Removable
));
455 // Default value 512 Bytes, in case no media present at first time
457 Media
->BlockSize
= 0x0200;
464 Get the capacity of the USB mass storage media, including
465 the presentation, block size, and last block number. This
466 function is used to get the disk parameters at the start if
467 it is a non-removable media or to detect the media if it is
470 @param UsbMass The device to retireve disk gemotric.
472 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
473 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
477 UsbBootReadCapacity (
478 IN USB_MASS_DEVICE
*UsbMass
481 USB_BOOT_READ_CAPACITY_CMD CapacityCmd
;
482 USB_BOOT_READ_CAPACITY_DATA CapacityData
;
483 EFI_BLOCK_IO_MEDIA
*Media
;
486 Media
= &UsbMass
->BlockIoMedia
;
489 // Use the READ CAPACITY command to get the block length and last blockno
491 ZeroMem (&CapacityCmd
, sizeof (USB_BOOT_READ_CAPACITY_CMD
));
492 ZeroMem (&CapacityData
, sizeof (USB_BOOT_READ_CAPACITY_DATA
));
494 CapacityCmd
.OpCode
= USB_BOOT_READ_CAPACITY_OPCODE
;
495 CapacityCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
497 Status
= UsbBootExecCmdWithRetry (
500 sizeof (USB_BOOT_READ_CAPACITY_CMD
),
503 sizeof (USB_BOOT_READ_CAPACITY_DATA
),
504 USB_BOOT_GENERAL_CMD_TIMEOUT
506 if (EFI_ERROR (Status
)) {
510 Media
->MediaPresent
= TRUE
;
511 Media
->LastBlock
= UsbBootGetUint32 (CapacityData
.LastLba
);
512 Media
->BlockSize
= UsbBootGetUint32 (CapacityData
.BlockLen
);
514 if (Media
->BlockSize
== 0) {
515 return EFI_NOT_READY
;
518 DEBUG ((EFI_D_INFO
, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",
519 Media
->LastBlock
, Media
->BlockSize
));
526 Retrieves mode sense information via sending Mode Sense
529 @param UsbMass The USB_FLOPPY_DEV instance.
531 @retval EFI_DEVICE_ERROR Hardware error
532 @retval EFI_SUCCESS Success
537 IN USB_MASS_DEVICE
*UsbMass
541 USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd
;
542 USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader
;
543 EFI_BLOCK_IO_MEDIA
*Media
;
545 Media
= &UsbMass
->BlockIoMedia
;
547 ZeroMem (&ModeSenseCmd
, sizeof (USB_SCSI_MODE_SENSE6_CMD
));
548 ZeroMem (&ModeParaHeader
, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
));
551 // ModeSense6 command is defined in [SCSI2Spec-Page151]
553 ModeSenseCmd
.OpCode
= USB_SCSI_MODE_SENSE6_OPCODE
;
554 ModeSenseCmd
.Lun
= (UINT8
) USB_BOOT_LUN (UsbMass
->Lun
);
555 ModeSenseCmd
.PageCode
= 0x3F;
556 ModeSenseCmd
.AllocateLen
= (UINT8
) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
);
558 Status
= UsbBootExecCmdWithRetry (
561 sizeof (USB_SCSI_MODE_SENSE6_CMD
),
564 sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
),
565 USB_BOOT_GENERAL_CMD_TIMEOUT
569 // ModeSense(6) is used to get the information of WriteProtected. While only some of
570 // devices support this command, so have a try here.
572 if (!EFI_ERROR (Status
)) {
573 Media
->ReadOnly
= (BOOLEAN
) ((ModeParaHeader
.DevicePara
& 0x80) ? TRUE
: FALSE
);
581 Get the parameters for the USB mass storage media, including
582 the RemovableMedia, block size, and last block number. This
583 function is used both to initialize the media during the
584 DriverBindingStart and to re-initialize it when the media is
585 changed. Althought the RemoveableMedia is unlikely to change,
588 @param UsbMass The device to retireve disk gemotric.
590 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
591 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
596 IN USB_MASS_DEVICE
*UsbMass
599 EFI_BLOCK_IO_MEDIA
*Media
;
603 Media
= &(UsbMass
->BlockIoMedia
);
604 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
606 Status
= UsbBootInquiry (UsbMass
);
607 if (EFI_ERROR (Status
)) {
608 DEBUG ((EFI_D_ERROR
, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status
));
613 // Don't use the Removable bit in inquirydata to test whether the media
614 // is removable because many flash disks wrongly set this bit.
616 if ((UsbMass
->Pdt
== USB_PDT_CDROM
) || (UsbMass
->Pdt
== USB_PDT_OPTICAL
)) {
618 // CD-Rom device and Non-CD optical device
620 UsbMass
->OpticalStorage
= TRUE
;
622 // Default value 2048 Bytes, in case no media present at first time
624 Media
->BlockSize
= 0x0800;
627 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
629 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
630 // which is from [MassStorageBootabilitySpec-Page7].
631 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
632 // could get the information of WriteProtected.
633 // Since not all device support this command, so skip if fail.
635 UsbScsiModeSense (UsbMass
);
638 return UsbBootReadCapacity (UsbMass
);
643 Detect whether the removable media is present and whether it has changed.
644 The Non-removable media doesn't need it.
646 @param UsbMass The device to retireve disk gemotric.
648 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
649 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
654 IN USB_MASS_DEVICE
*UsbMass
657 EFI_BLOCK_IO_MEDIA OldMedia
;
658 EFI_BLOCK_IO_MEDIA
*Media
;
663 Media
= &UsbMass
->BlockIoMedia
;
667 &(UsbMass
->BlockIoMedia
),
668 sizeof (EFI_BLOCK_IO_MEDIA
)
671 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
673 Status
= UsbBootIsUnitReady (UsbMass
);
674 if (EFI_ERROR (Status
)) {
675 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status
));
679 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
681 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
682 // which is from [MassStorageBootabilitySpec-Page7].
683 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
684 // could get the information of WriteProtected.
685 // Since not all device support this command, so skip if fail.
687 UsbScsiModeSense (UsbMass
);
690 Status
= UsbBootReadCapacity (UsbMass
);
691 if (EFI_ERROR (Status
)) {
692 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status
));
700 // Detect whether it is necessary to reinstall the BlockIO
702 // MediaId may change in RequestSense for MediaChanged
703 // MediaPresent may change in RequestSense for NoMedia
704 // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged
705 // MediaPresent/BlockSize/LastBlock may change in ReadCapacity
707 if ((Media
->MediaId
!= OldMedia
.MediaId
) ||
708 (Media
->MediaPresent
!= OldMedia
.MediaPresent
) ||
709 (Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
710 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
711 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
713 OldTpl
= UsbGetCurrentTpl ();
714 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", OldTpl
));
716 gBS
->RestoreTPL (TPL_CALLBACK
);
718 gBS
->ReinstallProtocolInterface (
720 &gEfiBlockIoProtocolGuid
,
725 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: TPL after reinstall is %d\n", UsbGetCurrentTpl()));
726 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK
);
728 gBS
->RaiseTPL (OldTpl
);
731 // Update MediaId after reinstall BLOCK_IO_PROTOCOL
733 if (Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
734 if (Media
->MediaPresent
== TRUE
) {
741 if ((Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
742 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
743 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
753 Read some blocks from the device.
755 @param UsbMass The USB mass storage device to read from
756 @param Lba The start block number
757 @param TotalBlock Total block number to read
758 @param Buffer The buffer to read to
760 @retval EFI_SUCCESS Data are read into the buffer
761 @retval Others Failed to read all the data
766 IN USB_MASS_DEVICE
*UsbMass
,
772 USB_BOOT_READ10_CMD ReadCmd
;
779 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
780 Status
= EFI_SUCCESS
;
782 while (TotalBlock
> 0) {
784 // Split the total blocks into smaller pieces to ease the pressure
785 // on the device. We must split the total block because the READ10
786 // command only has 16 bit transfer length (in the unit of block).
788 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
789 ByteSize
= (UINT32
)Count
* BlockSize
;
792 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
794 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
797 // Fill in the command then execute
799 ZeroMem (&ReadCmd
, sizeof (USB_BOOT_READ10_CMD
));
801 ReadCmd
.OpCode
= USB_BOOT_READ10_OPCODE
;
802 ReadCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
803 UsbBootPutUint32 (ReadCmd
.Lba
, Lba
);
804 UsbBootPutUint16 (ReadCmd
.TransferLen
, Count
);
806 Status
= UsbBootExecCmdWithRetry (
809 sizeof (USB_BOOT_READ10_CMD
),
815 if (EFI_ERROR (Status
)) {
820 Buffer
+= Count
* BlockSize
;
829 Write some blocks to the device.
831 @param UsbMass The USB mass storage device to write to
832 @param Lba The start block number
833 @param TotalBlock Total block number to write
834 @param Buffer The buffer to write to
836 @retval EFI_SUCCESS Data are written into the buffer
837 @retval Others Failed to write all the data
842 IN USB_MASS_DEVICE
*UsbMass
,
848 USB_BOOT_WRITE10_CMD WriteCmd
;
855 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
856 Status
= EFI_SUCCESS
;
858 while (TotalBlock
> 0) {
860 // Split the total blocks into smaller pieces to ease the pressure
861 // on the device. We must split the total block because the WRITE10
862 // command only has 16 bit transfer length (in the unit of block).
864 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
865 ByteSize
= (UINT32
)Count
* BlockSize
;
868 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
870 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
873 // Fill in the write10 command block
875 ZeroMem (&WriteCmd
, sizeof (USB_BOOT_WRITE10_CMD
));
877 WriteCmd
.OpCode
= USB_BOOT_WRITE10_OPCODE
;
878 WriteCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
879 UsbBootPutUint32 (WriteCmd
.Lba
, Lba
);
880 UsbBootPutUint16 (WriteCmd
.TransferLen
, Count
);
882 Status
= UsbBootExecCmdWithRetry (
885 sizeof (USB_BOOT_WRITE10_CMD
),
891 if (EFI_ERROR (Status
)) {
896 Buffer
+= Count
* BlockSize
;
905 Use the USB clear feature control transfer to clear the endpoint
908 @param UsbIo The USB IO protocol to use
909 @param EndpointAddr The endpoint to clear stall for
911 @retval EFI_SUCCESS The endpoint stall condtion is clear
912 @retval Others Failed to clear the endpoint stall condtion
916 UsbClearEndpointStall (
917 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
918 IN UINT8 EndpointAddr
921 EFI_USB_DEVICE_REQUEST Request
;
926 Request
.RequestType
= 0x02;
927 Request
.Request
= USB_REQ_CLEAR_FEATURE
;
928 Request
.Value
= USB_FEATURE_ENDPOINT_HALT
;
929 Request
.Index
= EndpointAddr
;
931 Timeout
= USB_BOOT_GENERAL_CMD_TIMEOUT
/ USB_MASS_1_MILLISECOND
;
933 Status
= UsbIo
->UsbControlTransfer (