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.
22 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTDebugLevel
= EFI_D_INFO
;
23 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTErrorLevel
= EFI_D_INFO
;
25 // Function prototypes
29 UsbBotDriverEntryPoint (
30 IN EFI_HANDLE ImageHandle
,
31 IN EFI_SYSTEM_TABLE
*SystemTable
35 // Bot Driver Binding Protocol
39 BotDriverBindingSupported (
40 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
41 IN EFI_HANDLE ControllerHandle
,
42 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
47 BotDriverBindingStart (
48 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
49 IN EFI_HANDLE ControllerHandle
,
50 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
55 BotDriverBindingStop (
56 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
57 IN EFI_HANDLE ControllerHandle
,
58 IN UINTN NumberOfChildren
,
59 IN EFI_HANDLE
*ChildHandleBuffer
63 EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding
= {
64 BotDriverBindingSupported
,
65 BotDriverBindingStart
,
78 IN USB_BOT_DEVICE
*UsbBotDev
,
81 IN UINT32 DataTransferLength
,
82 IN EFI_USB_DATA_DIRECTION Direction
,
89 IN USB_BOT_DEVICE
*UsbBotDev
,
91 IN OUT VOID
*DataBuffer
,
92 IN EFI_USB_DATA_DIRECTION Direction
,
99 IN USB_BOT_DEVICE
*UsbBotDev
,
100 OUT UINT32
*DataResidue
,
104 // USB Atapi protocol prototype
110 IN EFI_USB_ATAPI_PROTOCOL
*This
,
112 IN UINT8 CommandSize
,
114 IN UINT32 BufferLength
,
115 IN EFI_USB_DATA_DIRECTION Direction
,
116 IN UINT16 TimeOutInMilliSeconds
122 BotMassStorageReset (
123 IN EFI_USB_ATAPI_PROTOCOL
*This
,
124 IN BOOLEAN ExtendedVerification
128 BotReportStatusCode (
129 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
130 IN EFI_STATUS_CODE_TYPE CodeType
,
131 IN EFI_STATUS_CODE_VALUE Value
134 STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol
= {
142 BotDriverBindingSupported (
143 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
144 IN EFI_HANDLE ControllerHandle
,
145 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
150 Test to see if this driver supports ControllerHandle. Any ControllerHandle
151 than contains a BlockIo and DiskIo protocol can be supported.
154 This - Protocol instance pointer.
155 ControllerHandle - Handle of device to test
156 RemainingDevicePath - Not used
159 EFI_SUCCESS - This driver supports this device
160 EFI_ALREADY_STARTED - This driver is already running on this device
161 other - This driver does not support this device
166 EFI_USB_IO_PROTOCOL
*UsbIo
;
167 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
170 // Check if the Controller supports USB IO protocol
172 Status
= gBS
->OpenProtocol (
174 &gEfiUsbIoProtocolGuid
,
176 This
->DriverBindingHandle
,
178 EFI_OPEN_PROTOCOL_BY_DRIVER
180 if (EFI_ERROR (Status
)) {
184 // Get the Default interface descriptor, now we only
185 // suppose interface 1
187 Status
= UsbIo
->UsbGetInterfaceDescriptor (
191 if (EFI_ERROR (Status
)) {
195 // Check if it is a BOT type Mass Storage Device
197 if ((InterfaceDescriptor
.InterfaceClass
!= MASS_STORAGE_CLASS
) ||
198 (InterfaceDescriptor
.InterfaceProtocol
!= BOT
)) {
199 Status
= EFI_UNSUPPORTED
;
206 &gEfiUsbIoProtocolGuid
,
207 This
->DriverBindingHandle
,
215 BotDriverBindingStart (
216 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
217 IN EFI_HANDLE ControllerHandle
,
218 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
223 Start this driver on ControllerHandle by opening a Block IO and Disk IO
224 protocol, reading Device Path, and creating a child handle with a
225 Disk IO and device path protocol.
228 This - Protocol instance pointer.
229 ControllerHandle - Handle of device to bind driver to
230 RemainingDevicePath - Not used
233 EFI_SUCCESS - This driver is added to DeviceHandle
234 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
235 EFI_OUT_OF_RESOURCES- Can't allocate the memory resource
236 other - This driver does not support this device
240 USB_BOT_DEVICE
*UsbBotDev
;
242 EFI_USB_ENDPOINT_DESCRIPTOR
*EndpointDescriptor
;
243 EFI_USB_INTERFACE_DESCRIPTOR
*InterfaceDescriptor
;
245 EFI_USB_IO_PROTOCOL
*UsbIo
;
248 // Check if the Controller supports USB IO protocol
252 Status
= gBS
->OpenProtocol (
254 &gEfiUsbIoProtocolGuid
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_BY_DRIVER
260 if (EFI_ERROR (Status
)) {
264 InterfaceDescriptor
= AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
265 if (InterfaceDescriptor
== NULL
) {
268 &gEfiUsbIoProtocolGuid
,
269 This
->DriverBindingHandle
,
272 return EFI_OUT_OF_RESOURCES
;
275 // Get the controller interface descriptor,
277 Status
= UsbIo
->UsbGetInterfaceDescriptor (
281 if (EFI_ERROR (Status
)) {
282 gBS
->FreePool (InterfaceDescriptor
);
286 BotAtapiProtocol
.CommandProtocol
= InterfaceDescriptor
->InterfaceSubClass
;
288 UsbBotDev
= AllocateZeroPool (sizeof (USB_BOT_DEVICE
));
289 if (UsbBotDev
== NULL
) {
290 Status
= EFI_OUT_OF_RESOURCES
;
291 gBS
->FreePool (InterfaceDescriptor
);
295 UsbBotDev
->Signature
= USB_BOT_DEVICE_SIGNATURE
;
296 UsbBotDev
->UsbIo
= UsbIo
;
297 UsbBotDev
->InterfaceDescriptor
= InterfaceDescriptor
;
298 CopyMem (&UsbBotDev
->UsbAtapiProtocol
, &BotAtapiProtocol
, sizeof (BotAtapiProtocol
));
301 // Get the Device Path Protocol on Controller's handle
303 Status
= gBS
->OpenProtocol (
305 &gEfiDevicePathProtocolGuid
,
306 (VOID
**) &UsbBotDev
->DevicePath
,
307 This
->DriverBindingHandle
,
309 EFI_OPEN_PROTOCOL_GET_PROTOCOL
312 if (EFI_ERROR (Status
)) {
316 for (Index
= 0; Index
< InterfaceDescriptor
->NumEndpoints
; Index
++) {
317 EndpointDescriptor
= AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
318 if (EndpointDescriptor
== NULL
) {
319 Status
= EFI_OUT_OF_RESOURCES
;
323 UsbIo
->UsbGetEndpointDescriptor (
330 // We parse bulk endpoint
332 if ((EndpointDescriptor
->Attributes
& 0x03) == 0x02) {
333 if ((EndpointDescriptor
->EndpointAddress
& 0x80) != 0) {
334 UsbBotDev
->BulkInEndpointDescriptor
= EndpointDescriptor
;
336 UsbBotDev
->BulkOutEndpointDescriptor
= EndpointDescriptor
;
342 gBS
->FreePool (EndpointDescriptor
);
345 // Double check we have these endpoint descriptors
347 if (!(UsbBotDev
->BulkInEndpointDescriptor
&&
348 UsbBotDev
->BulkOutEndpointDescriptor
)) {
349 Status
= EFI_DEVICE_ERROR
;
353 // After installing Usb-Atapi protocol onto this handle
354 // it will be called by upper layer drivers such as Fat
356 BotReportStatusCode (
357 UsbBotDev
->DevicePath
,
359 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
363 // Install Usb-Atapi Protocol onto the handle
365 Status
= gBS
->InstallProtocolInterface (
367 &gEfiUsbAtapiProtocolGuid
,
368 EFI_NATIVE_INTERFACE
,
369 &UsbBotDev
->UsbAtapiProtocol
372 if (EFI_ERROR (Status
)) {
376 UsbBotDev
->ControllerNameTable
= NULL
;
379 gUsbBotComponentName
.SupportedLanguages
,
380 &UsbBotDev
->ControllerNameTable
,
381 (CHAR16
*) L
"Usb Bot Mass Storage"
389 &gEfiUsbIoProtocolGuid
,
390 This
->DriverBindingHandle
,
394 if (UsbBotDev
!= NULL
) {
395 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
396 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
399 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
400 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
403 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
404 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
407 gBS
->FreePool (UsbBotDev
);
415 BotDriverBindingStop (
416 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
417 IN EFI_HANDLE ControllerHandle
,
418 IN UINTN NumberOfChildren
,
419 IN EFI_HANDLE
*ChildHandleBuffer
424 Stop this driver on ControllerHandle. Support stoping any child handles
425 created by this driver.
428 This - Protocol instance pointer.
429 ControllerHandle - Handle of device to stop driver on
430 NumberOfChildren - Number of Children in the ChildHandleBuffer
431 ChildHandleBuffer - List of handles for the children we need to stop.
434 EFI_SUCCESS - This driver is removed DeviceHandle
435 EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl
436 other - This driver was not removed from this device
441 EFI_USB_ATAPI_PROTOCOL
*BotAtapiProtocol
;
442 USB_BOT_DEVICE
*UsbBotDev
;
445 // Get our context back.
447 Status
= gBS
->OpenProtocol (
449 &gEfiUsbAtapiProtocolGuid
,
450 (VOID
**) &BotAtapiProtocol
,
451 This
->DriverBindingHandle
,
453 EFI_OPEN_PROTOCOL_GET_PROTOCOL
455 if (EFI_ERROR (Status
)) {
456 return EFI_UNSUPPORTED
;
459 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol
);
462 // After installing Usb-Atapi protocol onto this handle
463 // it will be called by upper layer drivers such as Fat
466 BotReportStatusCode (
467 UsbBotDev
->DevicePath
,
469 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
473 // Uninstall protocol
475 Status
= gBS
->UninstallProtocolInterface (
477 &gEfiUsbAtapiProtocolGuid
,
478 &UsbBotDev
->UsbAtapiProtocol
480 if (EFI_ERROR (Status
)) {
484 Status
= gBS
->CloseProtocol (
486 &gEfiUsbIoProtocolGuid
,
487 This
->DriverBindingHandle
,
491 // Free all allocated resources
493 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
494 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
497 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
498 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
501 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
502 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
505 if (UsbBotDev
->ControllerNameTable
) {
506 FreeUnicodeStringTable (UsbBotDev
->ControllerNameTable
);
509 gBS
->FreePool (UsbBotDev
);
519 IN USB_BOT_DEVICE
*UsbBotDev
524 return UsbClearEndpointHalt (
526 UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
,
535 IN USB_BOT_DEVICE
*UsbBotDev
539 return UsbClearEndpointHalt (
541 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
549 IN USB_BOT_DEVICE
*UsbBotDev
559 UsbBotDev - USB_BOT_DEVICE pointer
562 EFI_SUCCESS - Success the operation
567 EFI_USB_DEVICE_REQUEST Request
;
569 BotReportStatusCode (
570 UsbBotDev
->DevicePath
,
572 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
575 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
578 // See BOT specification
580 Request
.RequestType
= 0x21;
581 Request
.Request
= 0xFF;
583 Status
= UsbBotDev
->UsbIo
->UsbControlTransfer (
593 gBS
->Stall (100 * 1000);
595 ClearBulkInPipe (UsbBotDev
);
596 ClearBulkOutPipe (UsbBotDev
);
602 // Bot Protocol Implementation
607 IN USB_BOT_DEVICE
*UsbBotDev
,
609 IN UINT8 CommandSize
,
610 IN UINT32 DataTransferLength
,
611 IN EFI_USB_DATA_DIRECTION Direction
,
617 Send ATAPI command through BOT interface.
620 UsbBotDev - USB_BOT_DEVICE
621 Command - command packet
622 CommandSize - Command size
623 DataTransferLength - Data Transfer Length
624 Direction - Data IN/OUT/NODATA
625 Timeout - Time out value in milliseconds
635 EFI_USB_IO_PROTOCOL
*UsbIo
;
638 UsbIo
= UsbBotDev
->UsbIo
;
640 ZeroMem (&cbw
, sizeof (CBW
));
643 // Fill the command block, detailed see BOT spec
645 cbw
.dCBWSignature
= CBWSIG
;
647 cbw
.dCBWDataTransferLength
= DataTransferLength
;
654 cbw
.bmCBWFlags
= 0x80;
659 cbw
.bCBWCBLength
= CommandSize
;
661 CopyMem (cbw
.CBWCB
, Command
, CommandSize
);
663 DataSize
= sizeof (CBW
);
665 Status
= UsbIo
->UsbBulkTransfer (
667 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
679 IN USB_BOT_DEVICE
*UsbBotDev
,
681 IN OUT VOID
*DataBuffer
,
682 IN EFI_USB_DATA_DIRECTION Direction
,
688 Get/Send Data through BOT interface
691 UsbBotDev - USB_BOT_DEVICE pointer
693 DataBuffer - Data buffer pointer
694 Direction - IN/OUT/NODATA
695 Timeout - Time out value in milliseconds
704 EFI_USB_IO_PROTOCOL
*UsbIo
;
708 UsbIo
= UsbBotDev
->UsbIo
;
709 BufferPtr
= (UINT8
*) DataBuffer
;
712 // retrieve the the max packet length of the given endpoint
714 if (Direction
== EfiUsbDataIn
) {
715 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
717 EndpointAddr
= UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
;
720 Status
= UsbIo
->UsbBulkTransfer (
729 if (EFI_ERROR (Status
)) {
730 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
731 if (Direction
== EfiUsbDataIn
) {
732 DEBUG((gBOTErrorLevel
, "BOT: Data IN Stall, ClearBulkInPipe\n"));
733 ClearBulkInPipe (UsbBotDev
);
735 DEBUG((gBOTErrorLevel
, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
736 ClearBulkOutPipe (UsbBotDev
);
739 // BotRecoveryReset (UsbBotDev);
749 IN USB_BOT_DEVICE
*UsbBotDev
,
750 OUT UINT32
*DataResidue
,
756 Get transfer status through BOT interface
759 UsbBotDev - USB_BOT_DEVICE pointer
760 Timeout - Time out value in milliseconds
769 EFI_USB_IO_PROTOCOL
*UsbIo
;
775 UsbIo
= UsbBotDev
->UsbIo
;
776 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
779 for (Index
= 0; Index
< 3; Index
++) {
780 ZeroMem (&csw
, sizeof (CSW
));
781 DataSize
= sizeof (CSW
);
784 Status
= UsbIo
->UsbBulkTransfer (
792 if (EFI_ERROR (Status
)) {
793 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
794 DEBUG((gBOTDebugLevel
, "BOT: CSW Stall, ClearBulkInPipe\n"));
795 ClearBulkInPipe (UsbBotDev
);
800 if (csw
.dCSWSignature
== CSWSIG
) {
801 if (csw
.bCSWStatus
== 0 || csw
.bCSWStatus
== 0x01) {
802 if (DataResidue
!= NULL
) {
803 *DataResidue
= csw
.dCSWDataResidue
;
805 if (csw
.bCSWStatus
== 0x01) {
806 return EFI_DEVICE_ERROR
;
809 } else if (csw
.bCSWStatus
== 0x02) {
810 DEBUG((gBOTErrorLevel
, "BOT: Bot Phase error\n"));
811 BotRecoveryReset (UsbBotDev
);
818 return EFI_DEVICE_ERROR
;
825 // Usb Atapi Protocol implementation
830 IN EFI_USB_ATAPI_PROTOCOL
*This
,
832 IN UINT8 CommandSize
,
834 IN UINT32 BufferLength
,
835 IN EFI_USB_DATA_DIRECTION Direction
,
836 IN UINT16 TimeOutInMilliSeconds
841 Send ATAPI command using BOT protocol.
844 This - Protocol instance pointer.
845 Command - Command buffer
846 CommandSize - Size of Command Buffer
847 DataBuffer - Data buffer
848 BufferLength - Length of Data buffer
849 Direction - Data direction of this command
850 TimeoutInMilliSeconds - Timeout value in ms
853 EFI_SUCCESS - Command succeeded.
854 EFI_DEVICE_ERROR - Command failed.
859 EFI_STATUS BotDataStatus
;
860 USB_BOT_DEVICE
*UsbBotDev
;
868 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
869 BotDataStatus
= EFI_SUCCESS
;
872 for (Index
= 0; Index
< 3; Index
++) {
874 // First send ATAPI command through Bot
876 Status
= BotCommandPhase (
885 if (EFI_ERROR (Status
)) {
886 DEBUG((gBOTErrorLevel
, "BotCommandPhase Fail\n"));
890 // Send/Get Data if there is a Data Stage
896 BufferSize
= BufferLength
;
898 BotDataStatus
= BotDataPhase (
903 (UINT16
) (TimeOutInMilliSeconds
)
907 if (EFI_ERROR (BotDataStatus
)) {
908 DEBUG((gBOTErrorLevel
, "BotDataPhase Fail\n"));
920 Status
= BotStatusPhase (
926 if (EFI_ERROR (Status
)) {
927 DEBUG((gBOTErrorLevel
, "BotStatusPhase Fail\n"));
931 if (!EFI_ERROR (BotDataStatus
)) {
936 return BotDataStatus
;
941 BotMassStorageReset (
942 IN EFI_USB_ATAPI_PROTOCOL
*This
,
943 IN BOOLEAN ExtendedVerification
951 This - Protocol instance pointer.
952 ExtendedVerification - TRUE if we need to do strictly reset.
955 EFI_SUCCESS - Command succeeded.
956 EFI_DEVICE_ERROR - Command failed.
961 USB_BOT_DEVICE
*UsbBotDev
;
962 EFI_USB_IO_PROTOCOL
*UsbIo
;
964 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
965 UsbIo
= UsbBotDev
->UsbIo
;
967 if (ExtendedVerification
) {
969 // If we need to do strictly reset, reset its parent hub port
971 Status
= UsbIo
->UsbPortReset (UsbIo
);
972 if (EFI_ERROR (Status
)) {
977 Status
= BotRecoveryReset (UsbBotDev
);
983 BotReportStatusCode (
984 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
985 IN EFI_STATUS_CODE_TYPE CodeType
,
986 IN EFI_STATUS_CODE_VALUE Value
991 Report Status Code in Usb Bot Driver
994 DevicePath - Use this to get Device Path
995 CodeType - Status Code Type
996 CodeValue - Status Code Value
1003 REPORT_STATUS_CODE_WITH_DEVICE_PATH (