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 extern EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName
;
24 // Function prototypes
28 UsbCbi0DriverEntryPoint (
29 IN EFI_HANDLE ImageHandle
,
30 IN EFI_SYSTEM_TABLE
*SystemTable
34 // Bot Driver Binding Protocol
39 Cbi0DriverBindingSupported (
40 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
41 IN EFI_HANDLE ControllerHandle
,
42 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
48 Cbi0DriverBindingStart (
49 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
50 IN EFI_HANDLE ControllerHandle
,
51 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
57 Cbi0DriverBindingStop (
58 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
59 IN EFI_HANDLE ControllerHandle
,
60 IN UINTN NumberOfChildren
,
61 IN EFI_HANDLE
*ChildHandleBuffer
65 Cbi0ReportStatusCode (
66 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
67 IN EFI_STATUS_CODE_TYPE CodeType
,
68 IN EFI_STATUS_CODE_VALUE Value
72 EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding
= {
73 Cbi0DriverBindingSupported
,
74 Cbi0DriverBindingStart
,
75 Cbi0DriverBindingStop
,
84 IN USB_CBI_DEVICE
*UsbCbiDev
90 IN USB_CBI_DEVICE
*UsbCbiDev
,
99 IN USB_CBI_DEVICE
*UsbCbiDev
,
101 IN OUT VOID
*DataBuffer
,
102 IN EFI_USB_DATA_DIRECTION Direction
,
109 IN USB_CBI_DEVICE
*UsbCbiDev
,
110 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
115 // USB Atapi protocol prototype
121 IN EFI_USB_ATAPI_PROTOCOL
*This
,
123 IN UINT8 CommandSize
,
125 IN UINT32 BufferLength
,
126 IN EFI_USB_DATA_DIRECTION Direction
,
127 IN UINT16 TimeOutInMilliSeconds
133 Cbi0MassStorageReset (
134 IN EFI_USB_ATAPI_PROTOCOL
*This
,
135 IN BOOLEAN ExtendedVerification
138 STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol
= {
140 Cbi0MassStorageReset
,
147 Cbi0DriverBindingSupported (
148 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
149 IN EFI_HANDLE ControllerHandle
,
150 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
155 Test to see if this driver supports ControllerHandle. Any ControllerHandle
156 than contains a BlockIo and DiskIo protocol can be supported.
159 This - Protocol instance pointer.
160 ControllerHandle - Handle of device to test
161 RemainingDevicePath - Not used
164 EFI_SUCCESS - This driver supports this device
165 EFI_ALREADY_STARTED - This driver is already running on this device
166 other - This driver does not support this device
171 EFI_USB_IO_PROTOCOL
*UsbIo
;
172 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
175 // Check if the Controller supports USB IO protocol
177 Status
= gBS
->OpenProtocol (
179 &gEfiUsbIoProtocolGuid
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (EFI_ERROR (Status
)) {
189 // Get the Default interface descriptor, now we only
190 // suppose interface 1
192 Status
= UsbIo
->UsbGetInterfaceDescriptor (
196 if (EFI_ERROR (Status
)) {
199 &gEfiUsbIoProtocolGuid
,
200 This
->DriverBindingHandle
,
206 // Check if it is a Cbi0 Type Mass Storage Device
208 if((InterfaceDescriptor
.InterfaceClass
!= MASS_STORAGE_CLASS
) ||
209 (InterfaceDescriptor
.InterfaceProtocol
!= CBI0_INTERFACE_PROTOCOL
)) {
210 Status
= EFI_UNSUPPORTED
;
212 Status
= EFI_SUCCESS
;
217 &gEfiUsbIoProtocolGuid
,
218 This
->DriverBindingHandle
,
228 Cbi0DriverBindingStart (
229 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
230 IN EFI_HANDLE ControllerHandle
,
231 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
236 Start this driver on ControllerHandle by opening a Block IO and Disk IO
237 protocol, reading Device Path, and creating a child handle with a
238 Disk IO and device path protocol.
241 This - Protocol instance pointer.
242 ControllerHandle - Handle of device to bind driver to
243 RemainingDevicePath - Not used
246 EFI_SUCCESS - This driver is added to DeviceHandle
247 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
248 other - This driver does not support this device
249 EFI_OUT_OF_RESOURCES- Can't allocate memory
250 EFI_UNSUPPORTED - Endpoint is not as expected
253 USB_CBI_DEVICE
*UsbCbiDev
;
255 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
256 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
258 EFI_USB_IO_PROTOCOL
*UsbIo
;
259 UINT8 EndpointExistMask
;
262 // Check if the Controller supports USB IO protocol
266 Status
= gBS
->OpenProtocol (
268 &gEfiUsbIoProtocolGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_BY_DRIVER
274 if (EFI_ERROR (Status
)) {
278 // Get the controller interface descriptor
280 Status
= UsbIo
->UsbGetInterfaceDescriptor (
284 if (EFI_ERROR (Status
)) {
287 &gEfiUsbIoProtocolGuid
,
288 This
->DriverBindingHandle
,
294 Cbi0AtapiProtocol
.CommandProtocol
= InterfaceDescriptor
.InterfaceSubClass
;
296 UsbCbiDev
= AllocateZeroPool (sizeof (USB_CBI_DEVICE
));
297 if (UsbCbiDev
== NULL
) {
300 &gEfiUsbIoProtocolGuid
,
301 This
->DriverBindingHandle
,
304 return EFI_OUT_OF_RESOURCES
;
307 UsbCbiDev
->Signature
= USB_CBI_DEVICE_SIGNATURE
;
308 UsbCbiDev
->UsbIo
= UsbIo
;
309 CopyMem (&UsbCbiDev
->InterfaceDescriptor
, &InterfaceDescriptor
, sizeof (InterfaceDescriptor
));
310 CopyMem (&UsbCbiDev
->UsbAtapiProtocol
, &Cbi0AtapiProtocol
, sizeof (Cbi0AtapiProtocol
));
313 // Get the Device Path Protocol on Controller's handle
315 Status
= gBS
->OpenProtocol (
317 &gEfiDevicePathProtocolGuid
,
318 (VOID
**) &UsbCbiDev
->DevicePath
,
319 This
->DriverBindingHandle
,
321 EFI_OPEN_PROTOCOL_GET_PROTOCOL
324 if (EFI_ERROR (Status
)) {
327 &gEfiUsbIoProtocolGuid
,
328 This
->DriverBindingHandle
,
331 if (UsbCbiDev
!= NULL
) {
332 gBS
->FreePool (UsbCbiDev
);
338 // Mask used to see whether all three kinds of endpoints exist,
340 // bit0: bulk in endpoint;
341 // bit1: bulk out endpoint;
342 // bit2: interrupt in endpoint;
344 EndpointExistMask
= 0;
345 for (Index
= 0; Index
< InterfaceDescriptor
.NumEndpoints
; Index
++) {
346 UsbIo
->UsbGetEndpointDescriptor (
353 // We parse bulk endpoint
355 if (EndpointDescriptor
.Attributes
== 0x02) {
356 if (EndpointDescriptor
.EndpointAddress
& 0x80) {
357 CopyMem (&UsbCbiDev
->BulkInEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
358 EndpointExistMask
|= bit (0);
360 CopyMem (&UsbCbiDev
->BulkOutEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
361 EndpointExistMask
|= bit (1);
365 // We parse interrupt endpoint
367 if (EndpointDescriptor
.Attributes
== 0x03) {
368 CopyMem (&UsbCbiDev
->InterruptEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
369 EndpointExistMask
|= bit (2);
374 // Double check we have all endpoints needed
376 if (EndpointExistMask
!= (bit (0) | bit (1) | bit (2))) {
379 &gEfiUsbIoProtocolGuid
,
380 This
->DriverBindingHandle
,
383 if (UsbCbiDev
!= NULL
) {
384 gBS
->FreePool (UsbCbiDev
);
387 return EFI_UNSUPPORTED
;
390 // After installing Usb-Atapi protocol onto this handle
391 // it will be called by upper layer drivers such as Fat
393 Cbi0ReportStatusCode (
394 UsbCbiDev
->DevicePath
,
396 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
399 Status
= gBS
->InstallProtocolInterface (
401 &gEfiUsbAtapiProtocolGuid
,
402 EFI_NATIVE_INTERFACE
,
403 &UsbCbiDev
->UsbAtapiProtocol
405 if (EFI_ERROR (Status
)) {
408 &gEfiUsbIoProtocolGuid
,
409 This
->DriverBindingHandle
,
412 if (UsbCbiDev
!= NULL
) {
413 gBS
->FreePool (UsbCbiDev
);
419 UsbCbiDev
->ControllerNameTable
= NULL
;
422 gUsbCbi0ComponentName
.SupportedLanguages
,
423 &UsbCbiDev
->ControllerNameTable
,
424 (CHAR16
*) L
"Usb Cbi0 Mass Storage"
433 Cbi0DriverBindingStop (
434 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
435 IN EFI_HANDLE ControllerHandle
,
436 IN UINTN NumberOfChildren
,
437 IN EFI_HANDLE
*ChildHandleBuffer
442 Stop this driver on ControllerHandle. Support stoping any child handles
443 created by this driver.
446 This - Protocol instance pointer.
447 ControllerHandle - Handle of device to stop driver on
448 NumberOfChildren - Number of Children in the ChildHandleBuffer
449 ChildHandleBuffer - List of handles for the children we need to stop.
452 EFI_SUCCESS - This driver is removed DeviceHandle
453 EFI_UNSUPPORTED - This driver was not removed from this device
458 EFI_USB_ATAPI_PROTOCOL
*Cbi0AtapiProtocol
;
459 USB_CBI_DEVICE
*UsbCbiDev
;
462 // Get our context back.
464 Status
= gBS
->OpenProtocol (
466 &gEfiUsbAtapiProtocolGuid
,
467 (VOID
**) &Cbi0AtapiProtocol
,
468 This
->DriverBindingHandle
,
470 EFI_OPEN_PROTOCOL_GET_PROTOCOL
472 if (EFI_ERROR (Status
)) {
473 return EFI_UNSUPPORTED
;
476 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol
);
478 Cbi0ReportStatusCode (
479 UsbCbiDev
->DevicePath
,
481 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
485 // Uninstall protocol
487 Status
= gBS
->UninstallProtocolInterface (
489 &gEfiUsbAtapiProtocolGuid
,
490 &UsbCbiDev
->UsbAtapiProtocol
492 if (EFI_ERROR (Status
)) {
496 Status
= gBS
->CloseProtocol (
498 &gEfiUsbIoProtocolGuid
,
499 This
->DriverBindingHandle
,
503 // Free all allocated resources
505 if (UsbCbiDev
->ControllerNameTable
) {
506 FreeUnicodeStringTable (UsbCbiDev
->ControllerNameTable
);
509 gBS
->FreePool (UsbCbiDev
);
518 IN USB_CBI_DEVICE
*UsbCbiDev
524 Cbi0 Recovery Reset routine
528 UsbCbiDev - Cbi0RecoveryReset
532 EFI_SUCCESS - Success
536 UINT8 ResetCommand
[12];
538 EFI_USB_IO_PROTOCOL
*UsbIo
;
539 UINT8 EndpointAddress
;
543 UsbIo
= UsbCbiDev
->UsbIo
;
545 Cbi0ReportStatusCode (
546 UsbCbiDev
->DevicePath
,
548 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
551 // CBI reset command protocol
553 SetMem (ResetCommand
, sizeof (ResetCommand
), 0xff);
554 ResetCommand
[0] = 0x1d;
555 ResetCommand
[1] = 0x04;
558 // (in millisecond unit)
560 Timeout
= STALL_1_SECOND
;
562 Status
= Cbi0AtapiCommand (
563 &UsbCbiDev
->UsbAtapiProtocol
,
571 if (EFI_ERROR (Status
)) {
575 gBS
->Stall (100 * 1000);
577 // clear bulk in endpoint stall feature
579 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
580 Status
= UsbClearEndpointHalt (
585 if (EFI_ERROR (Status
)) {
589 // clear bulk out endpoint stall feature
591 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
592 Status
= UsbClearEndpointHalt (
598 // according to CBI spec, no need to clear interrupt endpoint feature.
606 IN USB_CBI_DEVICE
*UsbCbiDev
,
608 IN UINT8 CommandSize
,
614 Send ATAPI command through CBI0 interface.
617 UsbCbiDev - USB_CBI_DEVICE
618 Command - Command to send
619 CommandSize - Command size
620 Timeout - Time out value in milliseconds
622 EFI_SUCCESS - Success
623 EFI_DEVICE_ERROR - Fail
630 EFI_USB_IO_PROTOCOL
*UsbIo
;
631 EFI_USB_DEVICE_REQUEST Request
;
633 UsbIo
= UsbCbiDev
->UsbIo
;
635 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
638 // Device request see CBI specification
640 Request
.RequestType
= 0x21;
641 Request
.Request
= 0x00;
644 Request
.Length
= CommandSize
;
646 Status
= UsbIo
->UsbControlTransfer (
655 if (EFI_ERROR (Status
)) {
656 return EFI_DEVICE_ERROR
;
665 IN USB_CBI_DEVICE
*UsbCbiDev
,
667 IN OUT VOID
*DataBuffer
,
668 IN EFI_USB_DATA_DIRECTION Direction
,
674 Get/Send Data through CBI0 interface
677 UsbCbiDev - USB_CBI_DEVICE
679 DataBuffer - Data buffer
680 Direction - IN/OUT/NODATA
681 Timeout - Time out value in milliseconds
689 EFI_USB_IO_PROTOCOL
*UsbIo
;
690 UINT8 EndpointAddress
;
693 UINT32 MaxPacketLength
;
696 UINTN TransferredSize
;
698 UsbIo
= UsbCbiDev
->UsbIo
;
701 BufferPtr
= (UINT8
*) DataBuffer
;
704 // retrieve the the max packet length of the given endpoint
706 if (Direction
== EfiUsbDataIn
) {
707 MaxPacketLength
= UsbCbiDev
->BulkInEndpointDescriptor
.MaxPacketSize
;
708 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
710 MaxPacketLength
= UsbCbiDev
->BulkOutEndpointDescriptor
.MaxPacketSize
;
711 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
716 if (Remain
> 16 * MaxPacketLength
) {
717 Increment
= 16 * MaxPacketLength
;
722 Status
= UsbIo
->UsbBulkTransfer (
730 TransferredSize
+= Increment
;
732 if (EFI_ERROR (Status
)) {
736 BufferPtr
+= Increment
;
744 if (Direction
== EfiUsbDataIn
) {
745 Cbi0ReportStatusCode (
746 UsbCbiDev
->DevicePath
,
747 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
748 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_INPUT_ERROR
)
751 Cbi0ReportStatusCode (
752 UsbCbiDev
->DevicePath
,
753 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
754 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_OUTPUT_ERROR
)
758 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
759 Status
= Cbi0RecoveryReset (UsbCbiDev
);
762 *DataSize
= (UINT32
) TransferredSize
;
769 IN USB_CBI_DEVICE
*UsbCbiDev
,
770 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
776 Get transfer status through BOT interface
779 UsbCbiDev - USB_CBI_DEVICE
780 InterruptDataBlock - Interrupt Data Block for interrupt transfer
781 Timeout - Time out value in milliseconds
788 UINT8 EndpointAddress
;
789 UINTN InterruptDataBlockLength
;
793 ZeroMem (InterruptDataBlock
, sizeof (INTERRUPT_DATA_BLOCK
));
795 EndpointAddress
= UsbCbiDev
->InterruptEndpointDescriptor
.EndpointAddress
;
796 InterruptDataBlockLength
= sizeof (INTERRUPT_DATA_BLOCK
);
798 Status
= UsbCbiDev
->UsbIo
->UsbSyncInterruptTransfer (
802 &InterruptDataBlockLength
,
806 if (EFI_ERROR (Status
)) {
807 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
809 // just endpoint stall happens
811 UsbClearEndpointHalt (
816 gBS
->Stall (100 * 1000);
825 // Cbi0 Atapi Protocol Implementation
830 Cbi0MassStorageReset (
831 IN EFI_USB_ATAPI_PROTOCOL
*This
,
832 IN BOOLEAN ExtendedVerification
840 This - Protocol instance pointer.
841 ExtendedVerification - TRUE if we need to do strictly reset.
844 EFI_SUCCESS - Command succeeded.
845 EFI_DEVICE_ERROR - Command failed.
850 USB_CBI_DEVICE
*UsbCbiDev
;
852 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
854 if (ExtendedVerification
) {
856 // UsbIo->UsbPortReset (UsbIo);
860 Status
= Cbi0RecoveryReset (UsbCbiDev
);
868 IN EFI_USB_ATAPI_PROTOCOL
*This
,
870 IN UINT8 CommandSize
,
872 IN UINT32 BufferLength
,
873 IN EFI_USB_DATA_DIRECTION Direction
,
874 IN UINT16 TimeOutInMilliSeconds
879 Send ATAPI command using BOT protocol.
882 This - Protocol instance pointer.
883 Command - Command buffer
884 CommandSize - Size of Command Buffer
885 DataBuffer - Data buffer
886 BufferLength - Length of Data buffer
887 Direction - Data direction of this command
888 TimeOutInMilliSeconds - Timeout value in ms
891 EFI_SUCCESS - Command succeeded.
892 EFI_DEVICE_ERROR - Command failed.
893 EFI_INVALID_PARAMETER - Invalidate parameter
897 USB_CBI_DEVICE
*UsbCbiDev
;
899 INTERRUPT_DATA_BLOCK InterruptDataBlock
;
900 EFI_STATUS DataPhaseStatus
;
902 if (Direction
!= EfiUsbNoData
) {
903 if (DataBuffer
== NULL
|| BufferLength
== 0) {
904 return EFI_INVALID_PARAMETER
;
908 DataPhaseStatus
= EFI_SUCCESS
;
912 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
915 // First send ATAPI command through Cbi
917 Status
= Cbi0CommandPhase (
921 TimeOutInMilliSeconds
923 if (EFI_ERROR (Status
)) {
924 return EFI_DEVICE_ERROR
;
927 // Send/Get Data if there is a Data Stage
933 BufferSize
= BufferLength
;
935 DataPhaseStatus
= Cbi0DataPhase (
940 TimeOutInMilliSeconds
948 if (EFI_ERROR (DataPhaseStatus
)) {
949 return EFI_DEVICE_ERROR
;
955 Status
= Cbi0StatusPhase (
958 TimeOutInMilliSeconds
960 if (EFI_ERROR (Status
)) {
961 return EFI_DEVICE_ERROR
;
964 if (This
->CommandProtocol
!= EFI_USB_SUBCLASS_UFI
) {
966 if (InterruptDataBlock
.bType
== 0) {
968 // indicates command completion
970 switch (InterruptDataBlock
.bValue
& 0x03) {
973 Status
= EFI_SUCCESS
;
977 Status
= EFI_DEVICE_ERROR
;
981 Status
= Cbi0RecoveryReset (UsbCbiDev
);
982 if (EFI_ERROR (Status
)) {
983 UsbCbiDev
->UsbIo
->UsbPortReset (UsbCbiDev
->UsbIo
);
986 Status
= EFI_DEVICE_ERROR
;
990 Status
= EFI_DEVICE_ERROR
;
993 Status
= DataPhaseStatus
;
998 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
999 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
1001 Status
= DataPhaseStatus
;
1008 Cbi0ReportStatusCode (
1009 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1010 IN EFI_STATUS_CODE_TYPE CodeType
,
1011 IN EFI_STATUS_CODE_VALUE Value
1015 Routine Description:
1016 Report Status Code in Usb Cbi0 Driver
1019 DevicePath - Use this to get Device Path
1020 CodeType - Status Code Type
1021 CodeValue - Status Code Value
1029 REPORT_STATUS_CODE_WITH_DEVICE_PATH (