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 EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding
= {
26 BotDriverBindingSupported
,
27 BotDriverBindingStart
,
40 IN USB_BOT_DEVICE
*UsbBotDev
,
43 IN UINT32 DataTransferLength
,
44 IN EFI_USB_DATA_DIRECTION Direction
,
51 IN USB_BOT_DEVICE
*UsbBotDev
,
53 IN OUT VOID
*DataBuffer
,
54 IN EFI_USB_DATA_DIRECTION Direction
,
61 IN USB_BOT_DEVICE
*UsbBotDev
,
62 OUT UINT32
*DataResidue
,
66 // USB Atapi protocol prototype
72 IN EFI_USB_ATAPI_PROTOCOL
*This
,
76 IN UINT32 BufferLength
,
77 IN EFI_USB_DATA_DIRECTION Direction
,
78 IN UINT16 TimeOutInMilliSeconds
85 IN EFI_USB_ATAPI_PROTOCOL
*This
,
86 IN BOOLEAN ExtendedVerification
92 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
93 IN EFI_STATUS_CODE_TYPE CodeType
,
94 IN EFI_STATUS_CODE_VALUE Value
97 STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol
= {
105 BotDriverBindingSupported (
106 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
107 IN EFI_HANDLE ControllerHandle
,
108 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
113 Test to see if this driver supports ControllerHandle. Any ControllerHandle
114 than contains a BlockIo and DiskIo protocol can be supported.
117 This - Protocol instance pointer.
118 ControllerHandle - Handle of device to test
119 RemainingDevicePath - Not used
122 EFI_SUCCESS - This driver supports this device
123 EFI_ALREADY_STARTED - This driver is already running on this device
124 other - This driver does not support this device
129 EFI_USB_IO_PROTOCOL
*UsbIo
;
130 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
133 // Check if the Controller supports USB IO protocol
135 Status
= gBS
->OpenProtocol (
137 &gEfiUsbIoProtocolGuid
,
139 This
->DriverBindingHandle
,
141 EFI_OPEN_PROTOCOL_BY_DRIVER
143 if (EFI_ERROR (Status
)) {
147 // Get the Default interface descriptor, now we only
148 // suppose interface 1
150 Status
= UsbIo
->UsbGetInterfaceDescriptor (
154 if (EFI_ERROR (Status
)) {
158 // Check if it is a BOT type Mass Storage Device
160 if ((InterfaceDescriptor
.InterfaceClass
!= MASS_STORAGE_CLASS
) ||
161 (InterfaceDescriptor
.InterfaceProtocol
!= BOT
)) {
162 Status
= EFI_UNSUPPORTED
;
169 &gEfiUsbIoProtocolGuid
,
170 This
->DriverBindingHandle
,
178 BotDriverBindingStart (
179 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
180 IN EFI_HANDLE ControllerHandle
,
181 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
186 Start this driver on ControllerHandle by opening a Block IO and Disk IO
187 protocol, reading Device Path, and creating a child handle with a
188 Disk IO and device path protocol.
191 This - Protocol instance pointer.
192 ControllerHandle - Handle of device to bind driver to
193 RemainingDevicePath - Not used
196 EFI_SUCCESS - This driver is added to DeviceHandle
197 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
198 EFI_OUT_OF_RESOURCES- Can't allocate the memory resource
199 other - This driver does not support this device
203 USB_BOT_DEVICE
*UsbBotDev
;
205 EFI_USB_ENDPOINT_DESCRIPTOR
*EndpointDescriptor
;
206 EFI_USB_INTERFACE_DESCRIPTOR
*InterfaceDescriptor
;
208 EFI_USB_IO_PROTOCOL
*UsbIo
;
211 // Check if the Controller supports USB IO protocol
215 Status
= gBS
->OpenProtocol (
217 &gEfiUsbIoProtocolGuid
,
219 This
->DriverBindingHandle
,
221 EFI_OPEN_PROTOCOL_BY_DRIVER
223 if (EFI_ERROR (Status
)) {
227 InterfaceDescriptor
= AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
228 if (InterfaceDescriptor
== NULL
) {
231 &gEfiUsbIoProtocolGuid
,
232 This
->DriverBindingHandle
,
235 return EFI_OUT_OF_RESOURCES
;
238 // Get the controller interface descriptor,
240 Status
= UsbIo
->UsbGetInterfaceDescriptor (
244 if (EFI_ERROR (Status
)) {
245 gBS
->FreePool (InterfaceDescriptor
);
249 BotAtapiProtocol
.CommandProtocol
= InterfaceDescriptor
->InterfaceSubClass
;
251 UsbBotDev
= AllocateZeroPool (sizeof (USB_BOT_DEVICE
));
252 if (UsbBotDev
== NULL
) {
253 Status
= EFI_OUT_OF_RESOURCES
;
254 gBS
->FreePool (InterfaceDescriptor
);
258 UsbBotDev
->Signature
= USB_BOT_DEVICE_SIGNATURE
;
259 UsbBotDev
->UsbIo
= UsbIo
;
260 UsbBotDev
->InterfaceDescriptor
= InterfaceDescriptor
;
261 CopyMem (&UsbBotDev
->UsbAtapiProtocol
, &BotAtapiProtocol
, sizeof (BotAtapiProtocol
));
264 // Get the Device Path Protocol on Controller's handle
266 Status
= gBS
->OpenProtocol (
268 &gEfiDevicePathProtocolGuid
,
269 (VOID
**) &UsbBotDev
->DevicePath
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_GET_PROTOCOL
275 if (EFI_ERROR (Status
)) {
279 for (Index
= 0; Index
< InterfaceDescriptor
->NumEndpoints
; Index
++) {
280 EndpointDescriptor
= AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
281 if (EndpointDescriptor
== NULL
) {
282 Status
= EFI_OUT_OF_RESOURCES
;
286 UsbIo
->UsbGetEndpointDescriptor (
293 // We parse bulk endpoint
295 if ((EndpointDescriptor
->Attributes
& 0x03) == 0x02) {
296 if ((EndpointDescriptor
->EndpointAddress
& 0x80) != 0) {
297 UsbBotDev
->BulkInEndpointDescriptor
= EndpointDescriptor
;
299 UsbBotDev
->BulkOutEndpointDescriptor
= EndpointDescriptor
;
305 gBS
->FreePool (EndpointDescriptor
);
308 // Double check we have these endpoint descriptors
310 if (!(UsbBotDev
->BulkInEndpointDescriptor
&&
311 UsbBotDev
->BulkOutEndpointDescriptor
)) {
312 Status
= EFI_DEVICE_ERROR
;
316 // After installing Usb-Atapi protocol onto this handle
317 // it will be called by upper layer drivers such as Fat
319 BotReportStatusCode (
320 UsbBotDev
->DevicePath
,
322 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
326 // Install Usb-Atapi Protocol onto the handle
328 Status
= gBS
->InstallProtocolInterface (
330 &gEfiUsbAtapiProtocolGuid
,
331 EFI_NATIVE_INTERFACE
,
332 &UsbBotDev
->UsbAtapiProtocol
335 if (EFI_ERROR (Status
)) {
339 UsbBotDev
->ControllerNameTable
= NULL
;
342 gUsbBotComponentName
.SupportedLanguages
,
343 &UsbBotDev
->ControllerNameTable
,
344 (CHAR16
*) L
"Usb Bot Mass Storage"
352 &gEfiUsbIoProtocolGuid
,
353 This
->DriverBindingHandle
,
357 if (UsbBotDev
!= NULL
) {
358 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
359 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
362 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
363 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
366 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
367 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
370 gBS
->FreePool (UsbBotDev
);
378 BotDriverBindingStop (
379 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
380 IN EFI_HANDLE ControllerHandle
,
381 IN UINTN NumberOfChildren
,
382 IN EFI_HANDLE
*ChildHandleBuffer
387 Stop this driver on ControllerHandle. Support stoping any child handles
388 created by this driver.
391 This - Protocol instance pointer.
392 ControllerHandle - Handle of device to stop driver on
393 NumberOfChildren - Number of Children in the ChildHandleBuffer
394 ChildHandleBuffer - List of handles for the children we need to stop.
397 EFI_SUCCESS - This driver is removed DeviceHandle
398 EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl
399 other - This driver was not removed from this device
404 EFI_USB_ATAPI_PROTOCOL
*BotAtapiProtocol
;
405 USB_BOT_DEVICE
*UsbBotDev
;
408 // Get our context back.
410 Status
= gBS
->OpenProtocol (
412 &gEfiUsbAtapiProtocolGuid
,
413 (VOID
**) &BotAtapiProtocol
,
414 This
->DriverBindingHandle
,
416 EFI_OPEN_PROTOCOL_GET_PROTOCOL
418 if (EFI_ERROR (Status
)) {
419 return EFI_UNSUPPORTED
;
422 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol
);
425 // After installing Usb-Atapi protocol onto this handle
426 // it will be called by upper layer drivers such as Fat
429 BotReportStatusCode (
430 UsbBotDev
->DevicePath
,
432 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
436 // Uninstall protocol
438 Status
= gBS
->UninstallProtocolInterface (
440 &gEfiUsbAtapiProtocolGuid
,
441 &UsbBotDev
->UsbAtapiProtocol
443 if (EFI_ERROR (Status
)) {
447 Status
= gBS
->CloseProtocol (
449 &gEfiUsbIoProtocolGuid
,
450 This
->DriverBindingHandle
,
454 // Free all allocated resources
456 if (UsbBotDev
->InterfaceDescriptor
!= NULL
) {
457 gBS
->FreePool (UsbBotDev
->InterfaceDescriptor
);
460 if (UsbBotDev
->BulkInEndpointDescriptor
!= NULL
) {
461 gBS
->FreePool (UsbBotDev
->BulkInEndpointDescriptor
);
464 if (UsbBotDev
->BulkOutEndpointDescriptor
!= NULL
) {
465 gBS
->FreePool (UsbBotDev
->BulkOutEndpointDescriptor
);
468 if (UsbBotDev
->ControllerNameTable
) {
469 FreeUnicodeStringTable (UsbBotDev
->ControllerNameTable
);
472 gBS
->FreePool (UsbBotDev
);
482 IN USB_BOT_DEVICE
*UsbBotDev
487 return UsbClearEndpointHalt (
489 UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
,
498 IN USB_BOT_DEVICE
*UsbBotDev
502 return UsbClearEndpointHalt (
504 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
512 IN USB_BOT_DEVICE
*UsbBotDev
522 UsbBotDev - USB_BOT_DEVICE pointer
525 EFI_SUCCESS - Success the operation
530 EFI_USB_DEVICE_REQUEST Request
;
532 BotReportStatusCode (
533 UsbBotDev
->DevicePath
,
535 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
538 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
541 // See BOT specification
543 Request
.RequestType
= 0x21;
544 Request
.Request
= 0xFF;
546 Status
= UsbBotDev
->UsbIo
->UsbControlTransfer (
556 gBS
->Stall (100 * 1000);
558 ClearBulkInPipe (UsbBotDev
);
559 ClearBulkOutPipe (UsbBotDev
);
565 // Bot Protocol Implementation
570 IN USB_BOT_DEVICE
*UsbBotDev
,
572 IN UINT8 CommandSize
,
573 IN UINT32 DataTransferLength
,
574 IN EFI_USB_DATA_DIRECTION Direction
,
580 Send ATAPI command through BOT interface.
583 UsbBotDev - USB_BOT_DEVICE
584 Command - command packet
585 CommandSize - Command size
586 DataTransferLength - Data Transfer Length
587 Direction - Data IN/OUT/NODATA
588 Timeout - Time out value in milliseconds
598 EFI_USB_IO_PROTOCOL
*UsbIo
;
601 UsbIo
= UsbBotDev
->UsbIo
;
603 ZeroMem (&cbw
, sizeof (CBW
));
606 // Fill the command block, detailed see BOT spec
608 cbw
.dCBWSignature
= CBWSIG
;
610 cbw
.dCBWDataTransferLength
= DataTransferLength
;
617 cbw
.bmCBWFlags
= 0x80;
622 cbw
.bCBWCBLength
= CommandSize
;
624 CopyMem (cbw
.CBWCB
, Command
, CommandSize
);
626 DataSize
= sizeof (CBW
);
628 Status
= UsbIo
->UsbBulkTransfer (
630 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
642 IN USB_BOT_DEVICE
*UsbBotDev
,
644 IN OUT VOID
*DataBuffer
,
645 IN EFI_USB_DATA_DIRECTION Direction
,
651 Get/Send Data through BOT interface
654 UsbBotDev - USB_BOT_DEVICE pointer
656 DataBuffer - Data buffer pointer
657 Direction - IN/OUT/NODATA
658 Timeout - Time out value in milliseconds
667 EFI_USB_IO_PROTOCOL
*UsbIo
;
671 UsbIo
= UsbBotDev
->UsbIo
;
672 BufferPtr
= (UINT8
*) DataBuffer
;
675 // retrieve the the max packet length of the given endpoint
677 if (Direction
== EfiUsbDataIn
) {
678 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
680 EndpointAddr
= UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
;
683 Status
= UsbIo
->UsbBulkTransfer (
692 if (EFI_ERROR (Status
)) {
693 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
694 if (Direction
== EfiUsbDataIn
) {
695 DEBUG((gBOTErrorLevel
, "BOT: Data IN Stall, ClearBulkInPipe\n"));
696 ClearBulkInPipe (UsbBotDev
);
698 DEBUG((gBOTErrorLevel
, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
699 ClearBulkOutPipe (UsbBotDev
);
702 // BotRecoveryReset (UsbBotDev);
712 IN USB_BOT_DEVICE
*UsbBotDev
,
713 OUT UINT32
*DataResidue
,
719 Get transfer status through BOT interface
722 UsbBotDev - USB_BOT_DEVICE pointer
723 Timeout - Time out value in milliseconds
732 EFI_USB_IO_PROTOCOL
*UsbIo
;
738 UsbIo
= UsbBotDev
->UsbIo
;
739 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
742 for (Index
= 0; Index
< 3; Index
++) {
743 ZeroMem (&csw
, sizeof (CSW
));
744 DataSize
= sizeof (CSW
);
747 Status
= UsbIo
->UsbBulkTransfer (
755 if (EFI_ERROR (Status
)) {
756 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
757 DEBUG((gBOTDebugLevel
, "BOT: CSW Stall, ClearBulkInPipe\n"));
758 ClearBulkInPipe (UsbBotDev
);
763 if (csw
.dCSWSignature
== CSWSIG
) {
764 if (csw
.bCSWStatus
== 0 || csw
.bCSWStatus
== 0x01) {
765 if (DataResidue
!= NULL
) {
766 *DataResidue
= csw
.dCSWDataResidue
;
768 if (csw
.bCSWStatus
== 0x01) {
769 return EFI_DEVICE_ERROR
;
772 } else if (csw
.bCSWStatus
== 0x02) {
773 DEBUG((gBOTErrorLevel
, "BOT: Bot Phase error\n"));
774 BotRecoveryReset (UsbBotDev
);
781 return EFI_DEVICE_ERROR
;
788 // Usb Atapi Protocol implementation
793 IN EFI_USB_ATAPI_PROTOCOL
*This
,
795 IN UINT8 CommandSize
,
797 IN UINT32 BufferLength
,
798 IN EFI_USB_DATA_DIRECTION Direction
,
799 IN UINT16 TimeOutInMilliSeconds
804 Send ATAPI command using BOT protocol.
807 This - Protocol instance pointer.
808 Command - Command buffer
809 CommandSize - Size of Command Buffer
810 DataBuffer - Data buffer
811 BufferLength - Length of Data buffer
812 Direction - Data direction of this command
813 TimeoutInMilliSeconds - Timeout value in ms
816 EFI_SUCCESS - Command succeeded.
817 EFI_DEVICE_ERROR - Command failed.
822 EFI_STATUS BotDataStatus
;
823 USB_BOT_DEVICE
*UsbBotDev
;
831 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
832 BotDataStatus
= EFI_SUCCESS
;
835 for (Index
= 0; Index
< 3; Index
++) {
837 // First send ATAPI command through Bot
839 Status
= BotCommandPhase (
848 if (EFI_ERROR (Status
)) {
849 DEBUG((gBOTErrorLevel
, "BotCommandPhase Fail\n"));
853 // Send/Get Data if there is a Data Stage
859 BufferSize
= BufferLength
;
861 BotDataStatus
= BotDataPhase (
866 (UINT16
) (TimeOutInMilliSeconds
)
870 if (EFI_ERROR (BotDataStatus
)) {
871 DEBUG((gBOTErrorLevel
, "BotDataPhase Fail\n"));
883 Status
= BotStatusPhase (
889 if (EFI_ERROR (Status
)) {
890 DEBUG((gBOTErrorLevel
, "BotStatusPhase Fail\n"));
894 if (!EFI_ERROR (BotDataStatus
)) {
899 return BotDataStatus
;
904 BotMassStorageReset (
905 IN EFI_USB_ATAPI_PROTOCOL
*This
,
906 IN BOOLEAN ExtendedVerification
914 This - Protocol instance pointer.
915 ExtendedVerification - TRUE if we need to do strictly reset.
918 EFI_SUCCESS - Command succeeded.
919 EFI_DEVICE_ERROR - Command failed.
924 USB_BOT_DEVICE
*UsbBotDev
;
925 EFI_USB_IO_PROTOCOL
*UsbIo
;
927 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
928 UsbIo
= UsbBotDev
->UsbIo
;
930 if (ExtendedVerification
) {
932 // If we need to do strictly reset, reset its parent hub port
934 Status
= UsbIo
->UsbPortReset (UsbIo
);
935 if (EFI_ERROR (Status
)) {
940 Status
= BotRecoveryReset (UsbBotDev
);
947 BotReportStatusCode (
948 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
949 IN EFI_STATUS_CODE_TYPE CodeType
,
950 IN EFI_STATUS_CODE_VALUE Value
955 Report Status Code in Usb Bot Driver
958 DevicePath - Use this to get Device Path
959 CodeType - Status Code Type
960 CodeValue - Status Code Value
967 REPORT_STATUS_CODE_WITH_DEVICE_PATH (