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
;
460 EFI_USB_IO_PROTOCOL
*UsbIo
;
463 // Get our context back.
465 Status
= gBS
->OpenProtocol (
467 &gEfiUsbAtapiProtocolGuid
,
468 (VOID
**) &Cbi0AtapiProtocol
,
469 This
->DriverBindingHandle
,
471 EFI_OPEN_PROTOCOL_GET_PROTOCOL
473 if (EFI_ERROR (Status
)) {
474 return EFI_UNSUPPORTED
;
477 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol
);
479 UsbIo
= UsbCbiDev
->UsbIo
;
481 Cbi0ReportStatusCode (
482 UsbCbiDev
->DevicePath
,
484 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
488 // Uninstall protocol
490 Status
= gBS
->UninstallProtocolInterface (
492 &gEfiUsbAtapiProtocolGuid
,
493 &UsbCbiDev
->UsbAtapiProtocol
495 if (EFI_ERROR (Status
)) {
499 Status
= gBS
->CloseProtocol (
501 &gEfiUsbIoProtocolGuid
,
502 This
->DriverBindingHandle
,
506 // Free all allocated resources
508 if (UsbCbiDev
->ControllerNameTable
) {
509 FreeUnicodeStringTable (UsbCbiDev
->ControllerNameTable
);
512 gBS
->FreePool (UsbCbiDev
);
521 IN USB_CBI_DEVICE
*UsbCbiDev
527 Cbi0 Recovery Reset routine
531 UsbCbiDev - Cbi0RecoveryReset
535 EFI_SUCCESS - Success
539 UINT8 ResetCommand
[12];
541 EFI_USB_IO_PROTOCOL
*UsbIo
;
542 UINT8 EndpointAddress
;
546 UsbIo
= UsbCbiDev
->UsbIo
;
548 Cbi0ReportStatusCode (
549 UsbCbiDev
->DevicePath
,
551 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
554 // CBI reset command protocol
556 SetMem (ResetCommand
, sizeof (ResetCommand
), 0xff);
557 ResetCommand
[0] = 0x1d;
558 ResetCommand
[1] = 0x04;
561 // (in millisecond unit)
563 Timeout
= STALL_1_SECOND
;
565 Status
= Cbi0AtapiCommand (
566 &UsbCbiDev
->UsbAtapiProtocol
,
574 if (EFI_ERROR (Status
)) {
578 gBS
->Stall (100 * 1000);
580 // clear bulk in endpoint stall feature
582 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
583 Status
= UsbClearEndpointHalt (
588 if (EFI_ERROR (Status
)) {
592 // clear bulk out endpoint stall feature
594 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
595 Status
= UsbClearEndpointHalt (
601 // according to CBI spec, no need to clear interrupt endpoint feature.
609 IN USB_CBI_DEVICE
*UsbCbiDev
,
611 IN UINT8 CommandSize
,
617 Send ATAPI command through CBI0 interface.
620 UsbCbiDev - USB_CBI_DEVICE
621 Command - Command to send
622 CommandSize - Command size
623 Timeout - Time out value in milliseconds
625 EFI_SUCCESS - Success
626 EFI_DEVICE_ERROR - Fail
633 EFI_USB_IO_PROTOCOL
*UsbIo
;
634 EFI_USB_DEVICE_REQUEST Request
;
636 UsbIo
= UsbCbiDev
->UsbIo
;
638 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
641 // Device request see CBI specification
643 Request
.RequestType
= 0x21;
644 Request
.Request
= 0x00;
647 Request
.Length
= CommandSize
;
649 Status
= UsbIo
->UsbControlTransfer (
658 if (EFI_ERROR (Status
)) {
659 return EFI_DEVICE_ERROR
;
668 IN USB_CBI_DEVICE
*UsbCbiDev
,
670 IN OUT VOID
*DataBuffer
,
671 IN EFI_USB_DATA_DIRECTION Direction
,
677 Get/Send Data through CBI0 interface
680 UsbCbiDev - USB_CBI_DEVICE
682 DataBuffer - Data buffer
683 Direction - IN/OUT/NODATA
684 Timeout - Time out value in milliseconds
692 EFI_USB_IO_PROTOCOL
*UsbIo
;
693 UINT8 EndpointAddress
;
696 UINT32 MaxPacketLength
;
699 UINTN TransferredSize
;
701 UsbIo
= UsbCbiDev
->UsbIo
;
704 BufferPtr
= (UINT8
*) DataBuffer
;
707 // retrieve the the max packet length of the given endpoint
709 if (Direction
== EfiUsbDataIn
) {
710 MaxPacketLength
= UsbCbiDev
->BulkInEndpointDescriptor
.MaxPacketSize
;
711 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
713 MaxPacketLength
= UsbCbiDev
->BulkOutEndpointDescriptor
.MaxPacketSize
;
714 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
719 if (Remain
> 16 * MaxPacketLength
) {
720 Increment
= 16 * MaxPacketLength
;
725 Status
= UsbIo
->UsbBulkTransfer (
733 TransferredSize
+= Increment
;
735 if (EFI_ERROR (Status
)) {
739 BufferPtr
+= Increment
;
747 if (Direction
== EfiUsbDataIn
) {
748 Cbi0ReportStatusCode (
749 UsbCbiDev
->DevicePath
,
750 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
751 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_INPUT_ERROR
)
754 Cbi0ReportStatusCode (
755 UsbCbiDev
->DevicePath
,
756 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
757 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_OUTPUT_ERROR
)
761 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
762 Status
= Cbi0RecoveryReset (UsbCbiDev
);
765 *DataSize
= (UINT32
) TransferredSize
;
772 IN USB_CBI_DEVICE
*UsbCbiDev
,
773 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
779 Get transfer status through BOT interface
782 UsbCbiDev - USB_CBI_DEVICE
783 InterruptDataBlock - Interrupt Data Block for interrupt transfer
784 Timeout - Time out value in milliseconds
791 UINT8 EndpointAddress
;
792 UINTN InterruptDataBlockLength
;
796 ZeroMem (InterruptDataBlock
, sizeof (INTERRUPT_DATA_BLOCK
));
798 EndpointAddress
= UsbCbiDev
->InterruptEndpointDescriptor
.EndpointAddress
;
799 InterruptDataBlockLength
= sizeof (INTERRUPT_DATA_BLOCK
);
801 Status
= UsbCbiDev
->UsbIo
->UsbSyncInterruptTransfer (
805 &InterruptDataBlockLength
,
809 if (EFI_ERROR (Status
)) {
810 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
812 // just endpoint stall happens
814 UsbClearEndpointHalt (
819 gBS
->Stall (100 * 1000);
828 // Cbi0 Atapi Protocol Implementation
833 Cbi0MassStorageReset (
834 IN EFI_USB_ATAPI_PROTOCOL
*This
,
835 IN BOOLEAN ExtendedVerification
843 This - Protocol instance pointer.
844 ExtendedVerification - TRUE if we need to do strictly reset.
847 EFI_SUCCESS - Command succeeded.
848 EFI_DEVICE_ERROR - Command failed.
853 EFI_USB_IO_PROTOCOL
*UsbIo
;
854 USB_CBI_DEVICE
*UsbCbiDev
;
856 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
857 UsbIo
= UsbCbiDev
->UsbIo
;
859 if (ExtendedVerification
) {
861 // UsbIo->UsbPortReset (UsbIo);
865 Status
= Cbi0RecoveryReset (UsbCbiDev
);
873 IN EFI_USB_ATAPI_PROTOCOL
*This
,
875 IN UINT8 CommandSize
,
877 IN UINT32 BufferLength
,
878 IN EFI_USB_DATA_DIRECTION Direction
,
879 IN UINT16 TimeOutInMilliSeconds
884 Send ATAPI command using BOT protocol.
887 This - Protocol instance pointer.
888 Command - Command buffer
889 CommandSize - Size of Command Buffer
890 DataBuffer - Data buffer
891 BufferLength - Length of Data buffer
892 Direction - Data direction of this command
893 TimeOutInMilliSeconds - Timeout value in ms
896 EFI_SUCCESS - Command succeeded.
897 EFI_DEVICE_ERROR - Command failed.
898 EFI_INVALID_PARAMETER - Invalidate parameter
902 USB_CBI_DEVICE
*UsbCbiDev
;
904 INTERRUPT_DATA_BLOCK InterruptDataBlock
;
905 EFI_STATUS DataPhaseStatus
;
907 if (Direction
!= EfiUsbNoData
) {
908 if (DataBuffer
== NULL
|| BufferLength
== 0) {
909 return EFI_INVALID_PARAMETER
;
913 DataPhaseStatus
= EFI_SUCCESS
;
917 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
920 // First send ATAPI command through Cbi
922 Status
= Cbi0CommandPhase (
926 TimeOutInMilliSeconds
928 if (EFI_ERROR (Status
)) {
929 return EFI_DEVICE_ERROR
;
932 // Send/Get Data if there is a Data Stage
938 BufferSize
= BufferLength
;
940 DataPhaseStatus
= Cbi0DataPhase (
945 TimeOutInMilliSeconds
953 if (EFI_ERROR (DataPhaseStatus
)) {
954 return EFI_DEVICE_ERROR
;
960 Status
= Cbi0StatusPhase (
963 TimeOutInMilliSeconds
965 if (EFI_ERROR (Status
)) {
966 return EFI_DEVICE_ERROR
;
969 if (This
->CommandProtocol
!= EFI_USB_SUBCLASS_UFI
) {
971 if (InterruptDataBlock
.bType
== 0) {
973 // indicates command completion
975 switch (InterruptDataBlock
.bValue
& 0x03) {
978 Status
= EFI_SUCCESS
;
982 Status
= EFI_DEVICE_ERROR
;
986 Status
= Cbi0RecoveryReset (UsbCbiDev
);
987 if (EFI_ERROR (Status
)) {
988 UsbCbiDev
->UsbIo
->UsbPortReset (UsbCbiDev
->UsbIo
);
991 Status
= EFI_DEVICE_ERROR
;
995 Status
= EFI_DEVICE_ERROR
;
998 Status
= DataPhaseStatus
;
1003 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
1004 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
1006 Status
= DataPhaseStatus
;
1013 Cbi0ReportStatusCode (
1014 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1015 IN EFI_STATUS_CODE_TYPE CodeType
,
1016 IN EFI_STATUS_CODE_VALUE Value
1020 Routine Description:
1021 Report Status Code in Usb Cbi0 Driver
1024 DevicePath - Use this to get Device Path
1025 CodeType - Status Code Type
1026 CodeValue - Status Code Value
1034 REPORT_STATUS_CODE_WITH_DEVICE_PATH (