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
;
611 cbw
.bmCBWFlags
= (UINT8
) ((Direction
== EfiUsbDataIn
) ? 0x80 : 0);
612 cbw
.bCBWCBLength
= CommandSize
;
614 CopyMem (cbw
.CBWCB
, Command
, CommandSize
);
616 DataSize
= sizeof (CBW
);
618 Status
= UsbIo
->UsbBulkTransfer (
620 UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
,
632 IN USB_BOT_DEVICE
*UsbBotDev
,
634 IN OUT VOID
*DataBuffer
,
635 IN EFI_USB_DATA_DIRECTION Direction
,
641 Get/Send Data through BOT interface
644 UsbBotDev - USB_BOT_DEVICE pointer
646 DataBuffer - Data buffer pointer
647 Direction - IN/OUT/NODATA
648 Timeout - Time out value in milliseconds
657 EFI_USB_IO_PROTOCOL
*UsbIo
;
661 UsbIo
= UsbBotDev
->UsbIo
;
662 BufferPtr
= (UINT8
*) DataBuffer
;
665 // retrieve the the max packet length of the given endpoint
667 if (Direction
== EfiUsbDataIn
) {
668 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
670 EndpointAddr
= UsbBotDev
->BulkOutEndpointDescriptor
->EndpointAddress
;
673 Status
= UsbIo
->UsbBulkTransfer (
682 if (EFI_ERROR (Status
)) {
683 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
684 if (Direction
== EfiUsbDataIn
) {
685 DEBUG((gBOTErrorLevel
, "BOT: Data IN Stall, ClearBulkInPipe\n"));
686 ClearBulkInPipe (UsbBotDev
);
688 DEBUG((gBOTErrorLevel
, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
689 ClearBulkOutPipe (UsbBotDev
);
692 // BotRecoveryReset (UsbBotDev);
702 IN USB_BOT_DEVICE
*UsbBotDev
,
703 OUT UINT32
*DataResidue
,
709 Get transfer status through BOT interface
712 UsbBotDev - USB_BOT_DEVICE pointer
713 Timeout - Time out value in milliseconds
722 EFI_USB_IO_PROTOCOL
*UsbIo
;
728 UsbIo
= UsbBotDev
->UsbIo
;
729 EndpointAddr
= UsbBotDev
->BulkInEndpointDescriptor
->EndpointAddress
;
732 for (Index
= 0; Index
< 3; Index
++) {
733 ZeroMem (&csw
, sizeof (CSW
));
734 DataSize
= sizeof (CSW
);
737 Status
= UsbIo
->UsbBulkTransfer (
745 if (EFI_ERROR (Status
)) {
746 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
747 DEBUG((gBOTDebugLevel
, "BOT: CSW Stall, ClearBulkInPipe\n"));
748 ClearBulkInPipe (UsbBotDev
);
753 if (csw
.dCSWSignature
== CSWSIG
) {
754 if (csw
.bCSWStatus
== 0 || csw
.bCSWStatus
== 0x01) {
755 if (DataResidue
!= NULL
) {
756 *DataResidue
= csw
.dCSWDataResidue
;
758 if (csw
.bCSWStatus
== 0x01) {
759 return EFI_DEVICE_ERROR
;
762 } else if (csw
.bCSWStatus
== 0x02) {
763 DEBUG((gBOTErrorLevel
, "BOT: Bot Phase error\n"));
764 BotRecoveryReset (UsbBotDev
);
771 return EFI_DEVICE_ERROR
;
778 // Usb Atapi Protocol implementation
783 IN EFI_USB_ATAPI_PROTOCOL
*This
,
785 IN UINT8 CommandSize
,
787 IN UINT32 BufferLength
,
788 IN EFI_USB_DATA_DIRECTION Direction
,
789 IN UINT16 TimeOutInMilliSeconds
794 Send ATAPI command using BOT protocol.
797 This - Protocol instance pointer.
798 Command - Command buffer
799 CommandSize - Size of Command Buffer
800 DataBuffer - Data buffer
801 BufferLength - Length of Data buffer
802 Direction - Data direction of this command
803 TimeoutInMilliSeconds - Timeout value in ms
806 EFI_SUCCESS - Command succeeded.
807 EFI_DEVICE_ERROR - Command failed.
812 EFI_STATUS BotDataStatus
;
813 USB_BOT_DEVICE
*UsbBotDev
;
821 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
822 BotDataStatus
= EFI_SUCCESS
;
825 for (Index
= 0; Index
< 3; Index
++) {
827 // First send ATAPI command through Bot
829 Status
= BotCommandPhase (
838 if (EFI_ERROR (Status
)) {
839 DEBUG((gBOTErrorLevel
, "BotCommandPhase Fail\n"));
843 // Send/Get Data if there is a Data Stage
849 BufferSize
= BufferLength
;
851 BotDataStatus
= BotDataPhase (
856 (UINT16
) (TimeOutInMilliSeconds
)
860 if (EFI_ERROR (BotDataStatus
)) {
861 DEBUG((gBOTErrorLevel
, "BotDataPhase Fail\n"));
873 Status
= BotStatusPhase (
879 if (EFI_ERROR (Status
)) {
880 DEBUG((gBOTErrorLevel
, "BotStatusPhase Fail\n"));
884 if (!EFI_ERROR (BotDataStatus
)) {
889 return BotDataStatus
;
894 BotMassStorageReset (
895 IN EFI_USB_ATAPI_PROTOCOL
*This
,
896 IN BOOLEAN ExtendedVerification
904 This - Protocol instance pointer.
905 ExtendedVerification - TRUE if we need to do strictly reset.
908 EFI_SUCCESS - Command succeeded.
909 EFI_DEVICE_ERROR - Command failed.
914 USB_BOT_DEVICE
*UsbBotDev
;
915 EFI_USB_IO_PROTOCOL
*UsbIo
;
917 UsbBotDev
= USB_BOT_DEVICE_FROM_THIS (This
);
918 UsbIo
= UsbBotDev
->UsbIo
;
920 if (ExtendedVerification
) {
922 // If we need to do strictly reset, reset its parent hub port
924 Status
= UsbIo
->UsbPortReset (UsbIo
);
925 if (EFI_ERROR (Status
)) {
930 Status
= BotRecoveryReset (UsbBotDev
);
937 BotReportStatusCode (
938 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
939 IN EFI_STATUS_CODE_TYPE CodeType
,
940 IN EFI_STATUS_CODE_VALUE Value
945 Report Status Code in Usb Bot Driver
948 DevicePath - Use this to get Device Path
949 CodeType - Status Code Type
950 CodeValue - Status Code Value
957 REPORT_STATUS_CODE_WITH_DEVICE_PATH (