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
;
444 EFI_USB_IO_PROTOCOL
*UsbIo
;
447 // Get our context back.
449 Status
= gBS
->OpenProtocol (
451 &gEfiUsbAtapiProtocolGuid
,
452 (VOID
**) &BotAtapiProtocol
,
453 This
->DriverBindingHandle
,
455 EFI_OPEN_PROTOCOL_GET_PROTOCOL
457 if (EFI_ERROR (Status
)) {
458 return EFI_UNSUPPORTED
;
461 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol
);
464 // After installing Usb-Atapi protocol onto this handle
465 // it will be called by upper layer drivers such as Fat
467 UsbIo
= UsbBotDev
->UsbIo
;
469 BotReportStatusCode (
470 UsbBotDev
->DevicePath
,
472 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
476 // Uninstall protocol
478 Status
= gBS
->UninstallProtocolInterface (
480 &gEfiUsbAtapiProtocolGuid
,
481 &UsbBotDev
->UsbAtapiProtocol
483 if (EFI_ERROR (Status
)) {
487 Status
= gBS
->CloseProtocol (
489 &gEfiUsbIoProtocolGuid
,
490 This
->DriverBindingHandle
,
494 // Free all allocated resources
496 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
497 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
500 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
501 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
504 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
505 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
508 if (UsbBotDev
->ControllerNameTable
) {
509 FreeUnicodeStringTable (UsbBotDev
->ControllerNameTable
);
512 gBS
->FreePool (UsbBotDev
);
522 IN USB_BOT_DEVICE
*UsbBotDev
527 return UsbClearEndpointHalt (
529 UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
,
538 IN USB_BOT_DEVICE
*UsbBotDev
542 return UsbClearEndpointHalt (
544 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
552 IN USB_BOT_DEVICE
*UsbBotDev
562 UsbBotDev - USB_BOT_DEVICE pointer
565 EFI_SUCCESS - Success the operation
570 EFI_USB_DEVICE_REQUEST Request
;
572 BotReportStatusCode (
573 UsbBotDev
->DevicePath
,
575 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
578 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
581 // See BOT specification
583 Request
.RequestType
= 0x21;
584 Request
.Request
= 0xFF;
586 Status
= UsbBotDev
->UsbIo
->UsbControlTransfer (
596 gBS
->Stall (100 * 1000);
598 ClearBulkInPipe (UsbBotDev
);
599 ClearBulkOutPipe (UsbBotDev
);
605 // Bot Protocol Implementation
610 IN USB_BOT_DEVICE
*UsbBotDev
,
612 IN UINT8 CommandSize
,
613 IN UINT32 DataTransferLength
,
614 IN EFI_USB_DATA_DIRECTION Direction
,
620 Send ATAPI command through BOT interface.
623 UsbBotDev - USB_BOT_DEVICE
624 Command - command packet
625 CommandSize - Command size
626 DataTransferLength - Data Transfer Length
627 Direction - Data IN/OUT/NODATA
628 Timeout - Time out value in milliseconds
638 EFI_USB_IO_PROTOCOL
*UsbIo
;
641 UsbIo
= UsbBotDev
->UsbIo
;
643 ZeroMem (&cbw
, sizeof (CBW
));
646 // Fill the command block, detailed see BOT spec
648 cbw
.dCBWSignature
= CBWSIG
;
650 cbw
.dCBWDataTransferLength
= DataTransferLength
;
657 cbw
.bmCBWFlags
= 0x80;
662 cbw
.bCBWCBLength
= CommandSize
;
664 CopyMem (cbw
.CBWCB
, Command
, CommandSize
);
666 DataSize
= sizeof (CBW
);
668 Status
= UsbIo
->UsbBulkTransfer (
670 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
682 IN USB_BOT_DEVICE
*UsbBotDev
,
684 IN OUT VOID
*DataBuffer
,
685 IN EFI_USB_DATA_DIRECTION Direction
,
691 Get/Send Data through BOT interface
694 UsbBotDev - USB_BOT_DEVICE pointer
696 DataBuffer - Data buffer pointer
697 Direction - IN/OUT/NODATA
698 Timeout - Time out value in milliseconds
707 EFI_USB_IO_PROTOCOL
*UsbIo
;
711 UsbIo
= UsbBotDev
->UsbIo
;
712 BufferPtr
= (UINT8
*) DataBuffer
;
715 // retrieve the the max packet length of the given endpoint
717 if (Direction
== EfiUsbDataIn
) {
718 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
720 EndpointAddr
= UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
;
723 Status
= UsbIo
->UsbBulkTransfer (
732 if (EFI_ERROR (Status
)) {
733 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
734 if (Direction
== EfiUsbDataIn
) {
735 DEBUG((gBOTErrorLevel
, "BOT: Data IN Stall, ClearBulkInPipe\n"));
736 ClearBulkInPipe (UsbBotDev
);
738 DEBUG((gBOTErrorLevel
, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
739 ClearBulkOutPipe (UsbBotDev
);
742 // BotRecoveryReset (UsbBotDev);
752 IN USB_BOT_DEVICE
*UsbBotDev
,
753 OUT UINT32
*DataResidue
,
759 Get transfer status through BOT interface
762 UsbBotDev - USB_BOT_DEVICE pointer
763 Timeout - Time out value in milliseconds
772 EFI_USB_IO_PROTOCOL
*UsbIo
;
778 UsbIo
= UsbBotDev
->UsbIo
;
779 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
782 for (Index
= 0; Index
< 3; Index
++) {
783 ZeroMem (&csw
, sizeof (CSW
));
784 DataSize
= sizeof (CSW
);
787 Status
= UsbIo
->UsbBulkTransfer (
795 if (EFI_ERROR (Status
)) {
796 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
797 DEBUG((gBOTDebugLevel
, "BOT: CSW Stall, ClearBulkInPipe\n"));
798 ClearBulkInPipe (UsbBotDev
);
803 if (csw
.dCSWSignature
== CSWSIG
) {
804 if (csw
.bCSWStatus
== 0 || csw
.bCSWStatus
== 0x01) {
805 if (DataResidue
!= NULL
) {
806 *DataResidue
= csw
.dCSWDataResidue
;
808 if (csw
.bCSWStatus
== 0x01) {
809 return EFI_DEVICE_ERROR
;
812 } else if (csw
.bCSWStatus
== 0x02) {
813 DEBUG((gBOTErrorLevel
, "BOT: Bot Phase error\n"));
814 BotRecoveryReset (UsbBotDev
);
821 return EFI_DEVICE_ERROR
;
828 // Usb Atapi Protocol implementation
833 IN EFI_USB_ATAPI_PROTOCOL
*This
,
835 IN UINT8 CommandSize
,
837 IN UINT32 BufferLength
,
838 IN EFI_USB_DATA_DIRECTION Direction
,
839 IN UINT16 TimeOutInMilliSeconds
844 Send ATAPI command using BOT protocol.
847 This - Protocol instance pointer.
848 Command - Command buffer
849 CommandSize - Size of Command Buffer
850 DataBuffer - Data buffer
851 BufferLength - Length of Data buffer
852 Direction - Data direction of this command
853 TimeoutInMilliSeconds - Timeout value in ms
856 EFI_SUCCESS - Command succeeded.
857 EFI_DEVICE_ERROR - Command failed.
862 EFI_STATUS BotDataStatus
;
863 USB_BOT_DEVICE
*UsbBotDev
;
871 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
872 BotDataStatus
= EFI_SUCCESS
;
875 for (Index
= 0; Index
< 3; Index
++) {
877 // First send ATAPI command through Bot
879 Status
= BotCommandPhase (
888 if (EFI_ERROR (Status
)) {
889 DEBUG((gBOTErrorLevel
, "BotCommandPhase Fail\n"));
893 // Send/Get Data if there is a Data Stage
899 BufferSize
= BufferLength
;
901 BotDataStatus
= BotDataPhase (
906 (UINT16
) (TimeOutInMilliSeconds
)
910 if (EFI_ERROR (BotDataStatus
)) {
911 DEBUG((gBOTErrorLevel
, "BotDataPhase Fail\n"));
923 Status
= BotStatusPhase (
929 if (EFI_ERROR (Status
)) {
930 DEBUG((gBOTErrorLevel
, "BotStatusPhase Fail\n"));
934 if (!EFI_ERROR (BotDataStatus
)) {
939 return BotDataStatus
;
944 BotMassStorageReset (
945 IN EFI_USB_ATAPI_PROTOCOL
*This
,
946 IN BOOLEAN ExtendedVerification
954 This - Protocol instance pointer.
955 ExtendedVerification - TRUE if we need to do strictly reset.
958 EFI_SUCCESS - Command succeeded.
959 EFI_DEVICE_ERROR - Command failed.
964 USB_BOT_DEVICE
*UsbBotDev
;
965 EFI_USB_IO_PROTOCOL
*UsbIo
;
967 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
968 UsbIo
= UsbBotDev
->UsbIo
;
970 if (ExtendedVerification
) {
972 // If we need to do strictly reset, reset its parent hub port
974 Status
= UsbIo
->UsbPortReset (UsbIo
);
975 if (EFI_ERROR (Status
)) {
980 Status
= BotRecoveryReset (UsbBotDev
);
986 BotReportStatusCode (
987 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
988 IN EFI_STATUS_CODE_TYPE CodeType
,
989 IN EFI_STATUS_CODE_VALUE Value
994 Report Status Code in Usb Bot Driver
997 DevicePath - Use this to get Device Path
998 CodeType - Status Code Type
999 CodeValue - Status Code Value
1006 REPORT_STATUS_CODE_WITH_DEVICE_PATH (