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 // UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor;
359 EndpointExistMask
|= bit (0);
361 CopyMem (&UsbCbiDev
->BulkOutEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
362 // UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor;
363 EndpointExistMask
|= bit (1);
367 // We parse interrupt endpoint
369 if (EndpointDescriptor
.Attributes
== 0x03) {
370 CopyMem (&UsbCbiDev
->InterruptEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
371 // UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor;
372 EndpointExistMask
|= bit (2);
377 // Double check we have all endpoints needed
379 if (EndpointExistMask
!= (bit (0) | bit (1) | bit (2))) {
382 &gEfiUsbIoProtocolGuid
,
383 This
->DriverBindingHandle
,
386 if (UsbCbiDev
!= NULL
) {
387 gBS
->FreePool (UsbCbiDev
);
390 return EFI_UNSUPPORTED
;
393 // After installing Usb-Atapi protocol onto this handle
394 // it will be called by upper layer drivers such as Fat
396 Cbi0ReportStatusCode (
397 UsbCbiDev
->DevicePath
,
399 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
402 Status
= gBS
->InstallProtocolInterface (
404 &gEfiUsbAtapiProtocolGuid
,
405 EFI_NATIVE_INTERFACE
,
406 &UsbCbiDev
->UsbAtapiProtocol
408 if (EFI_ERROR (Status
)) {
411 &gEfiUsbIoProtocolGuid
,
412 This
->DriverBindingHandle
,
415 if (UsbCbiDev
!= NULL
) {
416 gBS
->FreePool (UsbCbiDev
);
422 UsbCbiDev
->ControllerNameTable
= NULL
;
425 gUsbCbi0ComponentName
.SupportedLanguages
,
426 &UsbCbiDev
->ControllerNameTable
,
427 (CHAR16
*) L
"Usb Cbi0 Mass Storage"
436 Cbi0DriverBindingStop (
437 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
438 IN EFI_HANDLE ControllerHandle
,
439 IN UINTN NumberOfChildren
,
440 IN EFI_HANDLE
*ChildHandleBuffer
445 Stop this driver on ControllerHandle. Support stoping any child handles
446 created by this driver.
449 This - Protocol instance pointer.
450 ControllerHandle - Handle of device to stop driver on
451 NumberOfChildren - Number of Children in the ChildHandleBuffer
452 ChildHandleBuffer - List of handles for the children we need to stop.
455 EFI_SUCCESS - This driver is removed DeviceHandle
456 EFI_UNSUPPORTED - This driver was not removed from this device
461 EFI_USB_ATAPI_PROTOCOL
*Cbi0AtapiProtocol
;
462 USB_CBI_DEVICE
*UsbCbiDev
;
463 EFI_USB_IO_PROTOCOL
*UsbIo
;
466 // Get our context back.
468 Status
= gBS
->OpenProtocol (
470 &gEfiUsbAtapiProtocolGuid
,
471 (VOID
**) &Cbi0AtapiProtocol
,
472 This
->DriverBindingHandle
,
474 EFI_OPEN_PROTOCOL_GET_PROTOCOL
476 if (EFI_ERROR (Status
)) {
477 return EFI_UNSUPPORTED
;
480 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol
);
482 UsbIo
= UsbCbiDev
->UsbIo
;
484 Cbi0ReportStatusCode (
485 UsbCbiDev
->DevicePath
,
487 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
491 // Uninstall protocol
493 Status
= gBS
->UninstallProtocolInterface (
495 &gEfiUsbAtapiProtocolGuid
,
496 &UsbCbiDev
->UsbAtapiProtocol
498 if (EFI_ERROR (Status
)) {
502 Status
= gBS
->CloseProtocol (
504 &gEfiUsbIoProtocolGuid
,
505 This
->DriverBindingHandle
,
509 // Free all allocated resources
511 if (UsbCbiDev
->ControllerNameTable
) {
512 FreeUnicodeStringTable (UsbCbiDev
->ControllerNameTable
);
515 gBS
->FreePool (UsbCbiDev
);
524 IN USB_CBI_DEVICE
*UsbCbiDev
530 Cbi0 Recovery Reset routine
534 UsbCbiDev - Cbi0RecoveryReset
538 EFI_SUCCESS - Success
542 UINT8 ResetCommand
[12];
544 EFI_USB_IO_PROTOCOL
*UsbIo
;
545 UINT8 EndpointAddress
;
549 UsbIo
= UsbCbiDev
->UsbIo
;
551 Cbi0ReportStatusCode (
552 UsbCbiDev
->DevicePath
,
554 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
557 // CBI reset command protocol
559 SetMem (ResetCommand
, sizeof (ResetCommand
), 0xff);
560 ResetCommand
[0] = 0x1d;
561 ResetCommand
[1] = 0x04;
564 // (in millisecond unit)
566 Timeout
= STALL_1_SECOND
;
568 Status
= Cbi0AtapiCommand (
569 &UsbCbiDev
->UsbAtapiProtocol
,
577 if (EFI_ERROR (Status
)) {
581 gBS
->Stall (100 * 1000);
583 // clear bulk in endpoint stall feature
585 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
586 Status
= UsbClearEndpointHalt (
591 if (EFI_ERROR (Status
)) {
595 // clear bulk out endpoint stall feature
597 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
598 Status
= UsbClearEndpointHalt (
604 // according to CBI spec, no need to clear interrupt endpoint feature.
612 IN USB_CBI_DEVICE
*UsbCbiDev
,
614 IN UINT8 CommandSize
,
620 Send ATAPI command through CBI0 interface.
623 UsbCbiDev - USB_CBI_DEVICE
624 Command - Command to send
625 CommandSize - Command size
626 Timeout - Time out value in milliseconds
628 EFI_SUCCESS - Success
629 EFI_DEVICE_ERROR - Fail
636 EFI_USB_IO_PROTOCOL
*UsbIo
;
637 EFI_USB_DEVICE_REQUEST Request
;
639 UsbIo
= UsbCbiDev
->UsbIo
;
641 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
644 // Device request see CBI specification
646 Request
.RequestType
= 0x21;
647 Request
.Request
= 0x00;
650 Request
.Length
= CommandSize
;
652 Status
= UsbIo
->UsbControlTransfer (
661 if (EFI_ERROR (Status
)) {
662 return EFI_DEVICE_ERROR
;
671 IN USB_CBI_DEVICE
*UsbCbiDev
,
673 IN OUT VOID
*DataBuffer
,
674 IN EFI_USB_DATA_DIRECTION Direction
,
680 Get/Send Data through CBI0 interface
683 UsbCbiDev - USB_CBI_DEVICE
685 DataBuffer - Data buffer
686 Direction - IN/OUT/NODATA
687 Timeout - Time out value in milliseconds
695 EFI_USB_IO_PROTOCOL
*UsbIo
;
696 UINT8 EndpointAddress
;
699 UINT32 MaxPacketLength
;
702 UINTN TransferredSize
;
704 UsbIo
= UsbCbiDev
->UsbIo
;
707 BufferPtr
= (UINT8
*) DataBuffer
;
710 // retrieve the the max packet length of the given endpoint
712 if (Direction
== EfiUsbDataIn
) {
713 MaxPacketLength
= UsbCbiDev
->BulkInEndpointDescriptor
.MaxPacketSize
;
714 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
716 MaxPacketLength
= UsbCbiDev
->BulkOutEndpointDescriptor
.MaxPacketSize
;
717 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
722 if (Remain
> 16 * MaxPacketLength
) {
723 Increment
= 16 * MaxPacketLength
;
728 Status
= UsbIo
->UsbBulkTransfer (
736 TransferredSize
+= Increment
;
738 if (EFI_ERROR (Status
)) {
742 BufferPtr
+= Increment
;
750 if (Direction
== EfiUsbDataIn
) {
751 Cbi0ReportStatusCode (
752 UsbCbiDev
->DevicePath
,
753 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
754 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_INPUT_ERROR
)
757 Cbi0ReportStatusCode (
758 UsbCbiDev
->DevicePath
,
759 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
760 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_OUTPUT_ERROR
)
764 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
765 Status
= Cbi0RecoveryReset (UsbCbiDev
);
768 *DataSize
= (UINT32
) TransferredSize
;
775 IN USB_CBI_DEVICE
*UsbCbiDev
,
776 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
782 Get transfer status through BOT interface
785 UsbCbiDev - USB_CBI_DEVICE
786 InterruptDataBlock - Interrupt Data Block for interrupt transfer
787 Timeout - Time out value in milliseconds
794 UINT8 EndpointAddress
;
795 UINTN InterruptDataBlockLength
;
799 ZeroMem (InterruptDataBlock
, sizeof (INTERRUPT_DATA_BLOCK
));
801 EndpointAddress
= UsbCbiDev
->InterruptEndpointDescriptor
.EndpointAddress
;
802 InterruptDataBlockLength
= sizeof (INTERRUPT_DATA_BLOCK
);
804 Status
= UsbCbiDev
->UsbIo
->UsbSyncInterruptTransfer (
808 &InterruptDataBlockLength
,
812 if (EFI_ERROR (Status
)) {
813 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
815 // just endpoint stall happens
817 UsbClearEndpointHalt (
822 gBS
->Stall (100 * 1000);
831 // Cbi0 Atapi Protocol Implementation
836 Cbi0MassStorageReset (
837 IN EFI_USB_ATAPI_PROTOCOL
*This
,
838 IN BOOLEAN ExtendedVerification
846 This - Protocol instance pointer.
847 ExtendedVerification - TRUE if we need to do strictly reset.
850 EFI_SUCCESS - Command succeeded.
851 EFI_DEVICE_ERROR - Command failed.
856 EFI_USB_IO_PROTOCOL
*UsbIo
;
857 USB_CBI_DEVICE
*UsbCbiDev
;
859 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
860 UsbIo
= UsbCbiDev
->UsbIo
;
862 if (ExtendedVerification
) {
864 // UsbIo->UsbPortReset (UsbIo);
868 Status
= Cbi0RecoveryReset (UsbCbiDev
);
876 IN EFI_USB_ATAPI_PROTOCOL
*This
,
878 IN UINT8 CommandSize
,
880 IN UINT32 BufferLength
,
881 IN EFI_USB_DATA_DIRECTION Direction
,
882 IN UINT16 TimeOutInMilliSeconds
887 Send ATAPI command using BOT protocol.
890 This - Protocol instance pointer.
891 Command - Command buffer
892 CommandSize - Size of Command Buffer
893 DataBuffer - Data buffer
894 BufferLength - Length of Data buffer
895 Direction - Data direction of this command
896 TimeOutInMilliSeconds - Timeout value in ms
899 EFI_SUCCESS - Command succeeded.
900 EFI_DEVICE_ERROR - Command failed.
901 EFI_INVALID_PARAMETER - Invalidate parameter
905 USB_CBI_DEVICE
*UsbCbiDev
;
907 INTERRUPT_DATA_BLOCK InterruptDataBlock
;
908 EFI_STATUS DataPhaseStatus
;
910 if (Direction
!= EfiUsbNoData
) {
911 if (DataBuffer
== NULL
|| BufferLength
== 0) {
912 return EFI_INVALID_PARAMETER
;
916 DataPhaseStatus
= EFI_SUCCESS
;
920 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
923 // First send ATAPI command through Cbi
925 Status
= Cbi0CommandPhase (
929 TimeOutInMilliSeconds
931 if (EFI_ERROR (Status
)) {
932 return EFI_DEVICE_ERROR
;
935 // Send/Get Data if there is a Data Stage
941 BufferSize
= BufferLength
;
943 DataPhaseStatus
= Cbi0DataPhase (
948 TimeOutInMilliSeconds
956 if (EFI_ERROR (DataPhaseStatus
)) {
957 return EFI_DEVICE_ERROR
;
963 Status
= Cbi0StatusPhase (
966 TimeOutInMilliSeconds
968 if (EFI_ERROR (Status
)) {
969 return EFI_DEVICE_ERROR
;
972 if (This
->CommandProtocol
!= EFI_USB_SUBCLASS_UFI
) {
974 if (InterruptDataBlock
.bType
== 0) {
976 // indicates command completion
978 switch (InterruptDataBlock
.bValue
& 0x03) {
981 Status
= EFI_SUCCESS
;
985 Status
= EFI_DEVICE_ERROR
;
989 Status
= Cbi0RecoveryReset (UsbCbiDev
);
990 if (EFI_ERROR (Status
)) {
991 UsbCbiDev
->UsbIo
->UsbPortReset (UsbCbiDev
->UsbIo
);
994 Status
= EFI_DEVICE_ERROR
;
998 Status
= EFI_DEVICE_ERROR
;
1001 Status
= DataPhaseStatus
;
1006 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
1007 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
1009 Status
= DataPhaseStatus
;
1016 Cbi0ReportStatusCode (
1017 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1018 IN EFI_STATUS_CODE_TYPE CodeType
,
1019 IN EFI_STATUS_CODE_VALUE Value
1023 Routine Description:
1024 Report Status Code in Usb Cbi0 Driver
1027 DevicePath - Use this to get Device Path
1028 CodeType - Status Code Type
1029 CodeValue - Status Code Value
1037 REPORT_STATUS_CODE_WITH_DEVICE_PATH (