3 Copyright (c) 2006, 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.
23 // Function prototypes
27 UsbBotDriverEntryPoint (
28 IN EFI_HANDLE ImageHandle
,
29 IN EFI_SYSTEM_TABLE
*SystemTable
33 // Bot Driver Binding Protocol
37 BotDriverBindingSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
39 IN EFI_HANDLE ControllerHandle
,
40 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
45 BotDriverBindingStart (
46 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
47 IN EFI_HANDLE ControllerHandle
,
48 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
53 BotDriverBindingStop (
54 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
55 IN EFI_HANDLE ControllerHandle
,
56 IN UINTN NumberOfChildren
,
57 IN EFI_HANDLE
*ChildHandleBuffer
61 EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding
= {
62 BotDriverBindingSupported
,
63 BotDriverBindingStart
,
76 IN USB_BOT_DEVICE
*UsbBotDev
,
79 IN UINT32 DataTransferLength
,
80 IN EFI_USB_DATA_DIRECTION Direction
,
87 IN USB_BOT_DEVICE
*UsbBotDev
,
89 IN OUT VOID
*DataBuffer
,
90 IN EFI_USB_DATA_DIRECTION Direction
,
97 IN USB_BOT_DEVICE
*UsbBotDev
,
98 OUT UINT8
*TransferStatus
,
103 // USB Atapi protocol prototype
109 IN EFI_USB_ATAPI_PROTOCOL
*This
,
111 IN UINT8 CommandSize
,
113 IN UINT32 BufferLength
,
114 IN EFI_USB_DATA_DIRECTION Direction
,
115 IN UINT16 TimeOutInMilliSeconds
121 BotMassStorageReset (
122 IN EFI_USB_ATAPI_PROTOCOL
*This
,
123 IN BOOLEAN ExtendedVerification
127 BotReportStatusCode (
128 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
129 IN EFI_STATUS_CODE_TYPE CodeType
,
130 IN EFI_STATUS_CODE_VALUE Value
133 STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol
= {
141 BotDriverBindingSupported (
142 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
143 IN EFI_HANDLE ControllerHandle
,
144 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
149 Test to see if this driver supports ControllerHandle. Any ControllerHandle
150 than contains a BlockIo and DiskIo protocol can be supported.
153 This - Protocol instance pointer.
154 ControllerHandle - Handle of device to test
155 RemainingDevicePath - Not used
158 EFI_SUCCESS - This driver supports this device
159 EFI_ALREADY_STARTED - This driver is already running on this device
160 other - This driver does not support this device
165 EFI_USB_IO_PROTOCOL
*UsbIo
;
166 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
169 // Check if the Controller supports USB IO protocol
171 Status
= gBS
->OpenProtocol (
173 &gEfiUsbIoProtocolGuid
,
175 This
->DriverBindingHandle
,
177 EFI_OPEN_PROTOCOL_BY_DRIVER
179 if (EFI_ERROR (Status
)) {
183 // Get the Default interface descriptor, now we only
184 // suppose interface 1
186 Status
= UsbIo
->UsbGetInterfaceDescriptor (
190 if (EFI_ERROR (Status
)) {
194 // Check if it is a BOT type Mass Storage Device
196 if ((InterfaceDescriptor
.InterfaceClass
!= 0x08) ||
197 (InterfaceDescriptor
.InterfaceProtocol
!= BOT
)) {
198 Status
= EFI_UNSUPPORTED
;
205 &gEfiUsbIoProtocolGuid
,
206 This
->DriverBindingHandle
,
214 BotDriverBindingStart (
215 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
216 IN EFI_HANDLE ControllerHandle
,
217 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
222 Start this driver on ControllerHandle by opening a Block IO and Disk IO
223 protocol, reading Device Path, and creating a child handle with a
224 Disk IO and device path protocol.
227 This - Protocol instance pointer.
228 ControllerHandle - Handle of device to bind driver to
229 RemainingDevicePath - Not used
232 EFI_SUCCESS - This driver is added to DeviceHandle
233 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
234 EFI_OUT_OF_RESOURCES- Can't allocate the memory resource
235 other - This driver does not support this device
239 USB_BOT_DEVICE
*UsbBotDev
;
241 EFI_USB_ENDPOINT_DESCRIPTOR
*EndpointDescriptor
;
242 EFI_USB_INTERFACE_DESCRIPTOR
*InterfaceDescriptor
;
244 EFI_USB_IO_PROTOCOL
*UsbIo
;
247 // Check if the Controller supports USB IO protocol
251 Status
= gBS
->OpenProtocol (
253 &gEfiUsbIoProtocolGuid
,
255 This
->DriverBindingHandle
,
257 EFI_OPEN_PROTOCOL_BY_DRIVER
259 if (EFI_ERROR (Status
)) {
263 InterfaceDescriptor
= AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
264 if (InterfaceDescriptor
== NULL
) {
267 &gEfiUsbIoProtocolGuid
,
268 This
->DriverBindingHandle
,
271 return EFI_OUT_OF_RESOURCES
;
274 // Get the controller interface descriptor,
276 Status
= UsbIo
->UsbGetInterfaceDescriptor (
280 if (EFI_ERROR (Status
)) {
281 gBS
->FreePool (InterfaceDescriptor
);
285 BotAtapiProtocol
.CommandProtocol
= InterfaceDescriptor
->InterfaceSubClass
;
287 UsbBotDev
= AllocateZeroPool (sizeof (USB_BOT_DEVICE
));
288 if (UsbBotDev
== NULL
) {
289 Status
= EFI_OUT_OF_RESOURCES
;
290 gBS
->FreePool (InterfaceDescriptor
);
294 UsbBotDev
->Signature
= USB_BOT_DEVICE_SIGNATURE
;
295 UsbBotDev
->UsbIo
= UsbIo
;
296 UsbBotDev
->InterfaceDescriptor
= InterfaceDescriptor
;
297 CopyMem (&UsbBotDev
->UsbAtapiProtocol
, &BotAtapiProtocol
, sizeof (BotAtapiProtocol
));
300 // Get the Device Path Protocol on Controller's handle
302 Status
= gBS
->OpenProtocol (
304 &gEfiDevicePathProtocolGuid
,
305 (VOID
**) &UsbBotDev
->DevicePath
,
306 This
->DriverBindingHandle
,
308 EFI_OPEN_PROTOCOL_GET_PROTOCOL
311 if (EFI_ERROR (Status
)) {
315 for (Index
= 0; Index
< InterfaceDescriptor
->NumEndpoints
; Index
++) {
316 EndpointDescriptor
= AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
317 if (EndpointDescriptor
== NULL
) {
318 Status
= EFI_OUT_OF_RESOURCES
;
322 UsbIo
->UsbGetEndpointDescriptor (
329 // We parse bulk endpoint
331 if ((EndpointDescriptor
->Attributes
& 0x03) == 0x02) {
332 if ((EndpointDescriptor
->EndpointAddress
& 0x80) != 0) {
333 UsbBotDev
->BulkInEndpointDescriptor
= EndpointDescriptor
;
335 UsbBotDev
->BulkOutEndpointDescriptor
= EndpointDescriptor
;
341 gBS
->FreePool (EndpointDescriptor
);
344 // Double check we have these endpoint descriptors
346 if (!(UsbBotDev
->BulkInEndpointDescriptor
&&
347 UsbBotDev
->BulkOutEndpointDescriptor
)) {
348 Status
= EFI_DEVICE_ERROR
;
352 // After installing Usb-Atapi protocol onto this handle
353 // it will be called by upper layer drivers such as Fat
355 BotReportStatusCode (
356 UsbBotDev
->DevicePath
,
358 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
362 // Install Usb-Atapi Protocol onto the handle
364 Status
= gBS
->InstallProtocolInterface (
366 &gEfiUsbAtapiProtocolGuid
,
367 EFI_NATIVE_INTERFACE
,
368 &UsbBotDev
->UsbAtapiProtocol
371 if (EFI_ERROR (Status
)) {
375 UsbBotDev
->ControllerNameTable
= NULL
;
378 gUsbBotComponentName
.SupportedLanguages
,
379 &UsbBotDev
->ControllerNameTable
,
380 (CHAR16
*) L
"Usb Bot Mass Storage"
388 &gEfiUsbIoProtocolGuid
,
389 This
->DriverBindingHandle
,
393 if (UsbBotDev
!= NULL
) {
394 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
395 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
398 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
399 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
402 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
403 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
406 gBS
->FreePool (UsbBotDev
);
414 BotDriverBindingStop (
415 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
416 IN EFI_HANDLE ControllerHandle
,
417 IN UINTN NumberOfChildren
,
418 IN EFI_HANDLE
*ChildHandleBuffer
423 Stop this driver on ControllerHandle. Support stoping any child handles
424 created by this driver.
427 This - Protocol instance pointer.
428 ControllerHandle - Handle of device to stop driver on
429 NumberOfChildren - Number of Children in the ChildHandleBuffer
430 ChildHandleBuffer - List of handles for the children we need to stop.
433 EFI_SUCCESS - This driver is removed DeviceHandle
434 EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl
435 other - This driver was not removed from this device
440 EFI_USB_ATAPI_PROTOCOL
*BotAtapiProtocol
;
441 USB_BOT_DEVICE
*UsbBotDev
;
443 EFI_USB_IO_PROTOCOL
*UsbIo
;
446 // Get our context back.
448 Status
= gBS
->OpenProtocol (
450 &gEfiUsbAtapiProtocolGuid
,
451 (VOID
**) &BotAtapiProtocol
,
452 This
->DriverBindingHandle
,
454 EFI_OPEN_PROTOCOL_GET_PROTOCOL
456 if (EFI_ERROR (Status
)) {
457 return EFI_UNSUPPORTED
;
460 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol
);
463 // After installing Usb-Atapi protocol onto this handle
464 // it will be called by upper layer drivers such as Fat
466 UsbIo
= UsbBotDev
->UsbIo
;
468 BotReportStatusCode (
469 UsbBotDev
->DevicePath
,
471 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
475 // Uninstall protocol
477 Status
= gBS
->UninstallProtocolInterface (
479 &gEfiUsbAtapiProtocolGuid
,
480 &UsbBotDev
->UsbAtapiProtocol
482 if (EFI_ERROR (Status
)) {
486 Status
= gBS
->CloseProtocol (
488 &gEfiUsbIoProtocolGuid
,
489 This
->DriverBindingHandle
,
493 // Free all allocated resources
495 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
496 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
499 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
500 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
503 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
504 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
507 if (UsbBotDev
->ControllerNameTable
) {
508 FreeUnicodeStringTable (UsbBotDev
->ControllerNameTable
);
511 gBS
->FreePool (UsbBotDev
);
519 IN USB_BOT_DEVICE
*UsbBotDev
529 UsbBotDev - USB_BOT_DEVICE pointer
532 EFI_SUCCESS - Success the operation
538 EFI_USB_DEVICE_REQUEST Request
;
539 EFI_USB_IO_PROTOCOL
*UsbIo
;
542 UsbIo
= UsbBotDev
->UsbIo
;
544 BotReportStatusCode (
545 UsbBotDev
->DevicePath
,
547 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
550 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
553 // See BOT specification
555 Request
.RequestType
= 0x21;
556 Request
.Request
= 0xFF;
558 Status
= UsbIo
->UsbControlTransfer (
568 gBS
->Stall (100 * 1000);
570 if (!EFI_ERROR (Status
)) {
572 // clear bulk in endpoint stall feature
574 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
576 Status
= UsbClearEndpointHalt (
583 // clear bulk out endpoint stall feature
585 EndpointAddr
= UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
;
586 Status
= UsbClearEndpointHalt (
596 // Bot Protocol Implementation
601 IN USB_BOT_DEVICE
*UsbBotDev
,
603 IN UINT8 CommandSize
,
604 IN UINT32 DataTransferLength
,
605 IN EFI_USB_DATA_DIRECTION Direction
,
611 Send ATAPI command through BOT interface.
614 UsbBotDev - USB_BOT_DEVICE
615 Command - command packet
616 CommandSize - Command size
617 DataTransferLength - Data Transfer Length
618 Direction - Data IN/OUT/NODATA
619 Timeout - Time out value in milliseconds
629 EFI_USB_IO_PROTOCOL
*UsbIo
;
632 UsbIo
= UsbBotDev
->UsbIo
;
634 ZeroMem (&cbw
, sizeof (CBW
));
637 // Fill the command block, detailed see BOT spec
639 cbw
.dCBWSignature
= CBWSIG
;
641 cbw
.dCBWDataTransferLength
= DataTransferLength
;
642 cbw
.bmCBWFlags
= (UINT8
) (Direction
<< 7);
643 cbw
.bCBWCBLength
= CommandSize
;
645 CopyMem (cbw
.CBWCB
, Command
, CommandSize
);
647 DataSize
= sizeof (CBW
);
649 Status
= UsbIo
->UsbBulkTransfer (
651 (UsbBotDev
->BulkOutEndpointDescriptor
)->EndpointAddress
,
657 if (EFI_ERROR (Status
)) {
659 // Command phase fail, we need to recovery reset this device
661 BotRecoveryReset (UsbBotDev
);
662 return EFI_DEVICE_ERROR
;
671 IN USB_BOT_DEVICE
*UsbBotDev
,
673 IN OUT VOID
*DataBuffer
,
674 IN EFI_USB_DATA_DIRECTION Direction
,
680 Get/Send Data through BOT interface
683 UsbBotDev - USB_BOT_DEVICE pointer
685 DataBuffer - Data buffer pointer
686 Direction - IN/OUT/NODATA
687 Timeout - Time out value in milliseconds
696 EFI_USB_IO_PROTOCOL
*UsbIo
;
702 UINTN TransferredSize
;
708 UsbIo
= UsbBotDev
->UsbIo
;
710 BufferPtr
= (UINT8
*) DataBuffer
;
716 // retrieve the the max packet length of the given endpoint
718 if (Direction
== EfiUsbDataIn
) {
719 MaxPacketLen
= (UsbBotDev
->BulkInEndpointDescriptor
)->MaxPacketSize
;
720 EndpointAddr
= (UsbBotDev
->BulkInEndpointDescriptor
)->EndpointAddress
;
722 MaxPacketLen
= (UsbBotDev
->BulkOutEndpointDescriptor
)->MaxPacketSize
;
723 EndpointAddr
= (UsbBotDev
->BulkOutEndpointDescriptor
)->EndpointAddress
;
726 RetryTimes
= MaxRetry
;
727 BlockSize
= PackageNum
* MaxPacketLen
;
730 // Using 15 packets to aVOID Bitstuff error
732 if (Remain
> PackageNum
* MaxPacketLen
) {
733 Increment
= BlockSize
;
738 Status
= UsbIo
->UsbBulkTransfer (
747 TransferredSize
+= Increment
;
749 if (EFI_ERROR (Status
)) {
751 if ((RetryTimes
== 0) || ((Result
& EFI_USB_ERR_TIMEOUT
) == 0)) {
755 TransferredSize
-= Increment
;
759 // we try MaxTetry times for every bulk transfer
761 RetryTimes
= MaxRetry
;
764 BufferPtr
+= Increment
;
766 if (Increment
< BlockSize
&& TransferredSize
<= *DataSize
) {
768 // we get to the end of transter and transter size is
769 // less than requriedsize
775 *DataSize
= (UINT32
) TransferredSize
;
780 if (Direction
== EfiUsbDataIn
) {
781 BotReportStatusCode (
782 UsbBotDev
->DevicePath
,
783 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
784 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_INPUT_ERROR
)
787 BotReportStatusCode (
788 UsbBotDev
->DevicePath
,
789 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
790 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_OUTPUT_ERROR
)
794 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
796 // just endpoint stall happens
798 UsbClearEndpointHalt (
805 *DataSize
= (UINT32
) TransferredSize
;
814 IN USB_BOT_DEVICE
*UsbBotDev
,
815 OUT UINT8
*TransferStatus
,
821 Get transfer status through BOT interface
824 UsbBotDev - USB_BOT_DEVICE pointer
825 TransferStatus - TransferStatus
826 Timeout - Time out value in milliseconds
836 EFI_USB_IO_PROTOCOL
*UsbIo
;
840 UsbIo
= UsbBotDev
->UsbIo
;
842 ZeroMem (&csw
, sizeof (CSW
));
844 EndpointAddr
= (UsbBotDev
->BulkInEndpointDescriptor
)->EndpointAddress
;
846 DataSize
= sizeof (CSW
);
849 // Get the status field from bulk transfer
851 Status
= UsbIo
->UsbBulkTransfer (
859 if (EFI_ERROR (Status
)) {
860 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
862 // just endpoint stall happens
864 UsbClearEndpointHalt (
871 ZeroMem (&csw
, sizeof (CSW
));
873 EndpointAddr
= (UsbBotDev
->BulkInEndpointDescriptor
)->EndpointAddress
;
875 DataSize
= sizeof (CSW
);
876 Status
= UsbIo
->UsbBulkTransfer (
884 if (EFI_ERROR (Status
)) {
885 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
886 UsbClearEndpointHalt (
897 if (csw
.dCSWSignature
== CSWSIG
) {
898 *TransferStatus
= csw
.bCSWStatus
;
900 return EFI_DEVICE_ERROR
;
906 // Usb Atapi Protocol implementation
911 IN EFI_USB_ATAPI_PROTOCOL
*This
,
913 IN UINT8 CommandSize
,
915 IN UINT32 BufferLength
,
916 IN EFI_USB_DATA_DIRECTION Direction
,
917 IN UINT16 TimeOutInMilliSeconds
922 Send ATAPI command using BOT protocol.
925 This - Protocol instance pointer.
926 Command - Command buffer
927 CommandSize - Size of Command Buffer
928 DataBuffer - Data buffer
929 BufferLength - Length of Data buffer
930 Direction - Data direction of this command
931 TimeoutInMilliSeconds - Timeout value in ms
934 EFI_SUCCESS - Command succeeded.
935 EFI_DEVICE_ERROR - Command failed.
940 EFI_STATUS BotDataStatus
;
941 UINT8 TransferStatus
;
942 USB_BOT_DEVICE
*UsbBotDev
;
945 BotDataStatus
= EFI_SUCCESS
;
951 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
954 // First send ATAPI command through Bot
956 Status
= BotCommandPhase (
962 TimeOutInMilliSeconds
965 if (EFI_ERROR (Status
)) {
966 return EFI_DEVICE_ERROR
;
969 // Send/Get Data if there is a Data Stage
975 BufferSize
= BufferLength
;
977 BotDataStatus
= BotDataPhase (
982 (UINT16
) (TimeOutInMilliSeconds
)
994 Status
= BotStatusPhase (
997 TimeOutInMilliSeconds
1000 if (EFI_ERROR (Status
)) {
1001 return EFI_DEVICE_ERROR
;
1004 if (TransferStatus
== 0x02) {
1008 BotRecoveryReset (UsbBotDev
);
1009 return EFI_DEVICE_ERROR
;
1012 if (TransferStatus
== 0x01) {
1013 return EFI_DEVICE_ERROR
;
1016 return BotDataStatus
;
1021 BotMassStorageReset (
1022 IN EFI_USB_ATAPI_PROTOCOL
*This
,
1023 IN BOOLEAN ExtendedVerification
1027 Routine Description:
1031 This - Protocol instance pointer.
1032 ExtendedVerification - TRUE if we need to do strictly reset.
1035 EFI_SUCCESS - Command succeeded.
1036 EFI_DEVICE_ERROR - Command failed.
1041 USB_BOT_DEVICE
*UsbBotDev
;
1042 EFI_USB_IO_PROTOCOL
*UsbIo
;
1044 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
1045 UsbIo
= UsbBotDev
->UsbIo
;
1047 if (ExtendedVerification
) {
1049 // If we need to do strictly reset, reset its parent hub port
1051 Status
= UsbIo
->UsbPortReset (UsbIo
);
1052 if (EFI_ERROR (Status
)) {
1057 Status
= BotRecoveryReset (UsbBotDev
);
1063 BotReportStatusCode (
1064 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1065 IN EFI_STATUS_CODE_TYPE CodeType
,
1066 IN EFI_STATUS_CODE_VALUE Value
1070 Routine Description:
1071 Report Status Code in Usb Bot Driver
1074 DevicePath - Use this to get Device Path
1075 CodeType - Status Code Type
1076 CodeValue - Status Code Value
1083 REPORT_STATUS_CODE_WITH_DEVICE_PATH (